Curl request on form submission

Im trying to make a form submission hit up an API and then add some code to the page on success. Im not quite sure how to go about it. Im guessing most of this goes in the controller. Basically its a donation form that just captures an amount, name and email address, and then pops up a lightbox powered by javascript if its successful.

Heres a single plain PHP script that works on its own. Whats the best way to inegrate this into Kirby 2?

<?php


$curlObj = curl_init();


$GW_URL = "https://test-bobsal.gateway.mastercard.com/api/rest/version/55/merchant/SECRET/session";

        $postData = array(
               'apiOperation' => 'CREATE_CHECKOUT_SESSION',
               'order' => array(
                       'amount' => '5',
                       'currency' => 'USD',
                       'id' => 'ORDER1003',
                       'description' => 'Donation',
               ),
               'interaction'=> array(
                'operation'=> 'PURCHASE',
                'returnUrl'=> 'https://www.mysite.com/',
                'merchant'=> array(
                    'name'=> 'SECRET',
                    'address'=> array(
                        'line1'=> '200 Sample St',
                        'line2'=> '1234 Example Town'
                    )
                )
                )
        );

    curl_setopt($curlObj, CURLOPT_POSTFIELDS, json_encode($postData));
    curl_setopt($curlObj, CURLOPT_HTTPHEADER, array("Content-Length: " . strlen(json_encode($postData))));
    curl_setopt($curlObj, CURLOPT_HTTPHEADER, array("Content-Type: Application/json;charset=UTF-8"));
    curl_setopt($curlObj, CURLOPT_URL, $GW_URL);
    curl_setopt($curlObj, CURLOPT_USERPWD, "SECRET");
    curl_setopt($curlObj, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($curlObj);

    if (curl_error($curlObj)) {
        $response = "cURL Error: " . curl_errno($curlObj) . " - " . curl_error($curlObj);
    }

    echo $response;

    curl_close($curlObj);



$errorCode = "";
$sessionID = "";
$sessionVr = "";
$result = "";
$successIndicator = "";

$tmpArray = array();

$responseArray = json_decode($response, true);

if ($responseArray == null) {
    print("JSON decode failed. Please review server response (enable debug in config.php).");
    die();
}

if (array_key_exists("result", $responseArray)) {
    $result = $responseArray["result"];
}

if ($result == "FAIL") {
    if (array_key_exists("reason", $responseArray)) {
        $tmpArray = $responseArray["reason"];

        if (array_key_exists("explanation", $tmpArray)) {
            $errorMessage = rawurldecode($tmpArray["explanation"]);
        } elseif (array_key_exists("supportCode", $tmpArray)) {
            $errorMessage = rawurldecode($tmpArray["supportCode"]);
        } else {
            $errorMessage = "Reason unspecified.";
        }

        if (array_key_exists("code", $tmpArray)) {
            $errorCode = "Error (" . $tmpArray["code"] . ")";
        } else {
            $errorCode = "Error (UNSPECIFIED)";
        }
    }
} else {
    if (array_key_exists("successIndicator", $responseArray)) {
        $successIndicator = $responseArray["successIndicator"];
        $_SESSION["successIndicator"] = $successIndicator;
        $tmpArray = $responseArray["session"];
        if (array_key_exists("id", $tmpArray)) {
            $sessionID = rawurldecode($tmpArray["id"]);
            $_SESSION['sessionID'] = $sessionID;
        }
        if (array_key_exists("version", $tmpArray)) {
            $sessionVr = rawurldecode($tmpArray["version"]);
        }
    }
}

echo "Session ID: " .$sessionID ."<br>" ."Session Vr: " .$sessionVr ."<br>" ."Success Indicator: " .$successIndicator ."<br>";


if ($sessionID != "" & $successIndicator != "") {
    echo    "<div style=\"width:300px; margin: auto; border: 0px none #FFF; color: #004D74; font-family: Arial; font-size: 14px;\">" .
          "&nbsp;&nbsp;PAYMENT IS UNDER PROCESSING... <br>" .
        "</div>";

    echo    "<script src=\"https://test-bobsal.gateway.mastercard.com/checkout/version/55/checkout.js\"".
        "            data-error=\"errorCallback\"".
        "            data-cancel=\"cancelCallback\">".
        "</script>";

    echo    "<script type=\"text/javascript\">".

        "    function errorCallback(error) {".
        "        console.log(JSON.stringify(error));".
        "    }".
        "    function cancelCallback() {".
        "        console.log('Payment cancelled');".
        "    }".

        "    Checkout.configure({".
        "        session: {".
        "            id: \"$sessionID\"".
        "        }".
        "    });".
        " Checkout.showLightbox();" .
        "</script>";
}

If you use remote::request($url) instead of cUrl, you’ll make your live easier (the remote class uses cUrl internally).

Since your code includes JS, you probably need a route to combine your logic with a route and an Ajax call.

I do have an api route that i was trying to use start with but in the meantime, the Bank sent me the code above so i was thinking it was best to move it all into the controller…

array(
  'pattern' => 'createsession.json',
  'method' => 'GET|POST',
  'action'  => function() {

    $url = 'https://test-bobsal.gateway.mastercard.com/api/rest/version/55/merchant/secret/session/';

    $postData = array(
        'apiOperation' => 'CREATE_CHECKOUT_SESSION',

        'order' => array(
          'amount' => '5',
          'currency' => 'USD',
          'id' => 'ORDER1003',
          'description' => 'Donation',
        ),

        'interaction' => array(
          'operation' => 'PURCHASE',
          'returnUrl' => 'https://domain.org/thank-you-for-your-donation',
            'merchant' => array(
              'name' => 'ASSAMEH',
                  'address' => array(
                    'line1' => site()->find('address')->streetaddress()->value(),
                    'line2' => site()->find('address')->addresslocality()->value()
                  )
            )
        )
    );

    $params = array(
      'headers' => array(
        'Content-Type: Application/json;charset=UTF-8',
        'Authorization: Basic SECRET',
      ),
      'method' => 'POST',
      'body' => $postData,
    );

    echo remote::post($url, $params);

  }
),

So i can hit that instead, right? and ditch out all that curls, and just use remot::request as you suggested?

I do need to pass it the amount and orderID dynamicaly. How would i do that?

You can send an array of parameters with your request, including the data… We discussed this before here: POST request in a route

Im trying the AJAX guide in the Kirby 2 cook book, but for some reason the page keep reloading when hitting submit and i dont get anything back. Ive setup the jquery ajax stuff and its prevent form submission (i tested this with an alert). Once the alert is closed though, the page reloads. That shouldnt happen should it? Any idea what might be going wrong?

Which one?

The Ajax form validation one. Is there another?

Just to confirm, so you followed the recipe by the word and it failed? Or did you change anything?

I did change a few bits, but the vital cornorstones are there i think. Instead of doing the validation part, i replaced that with the remote php request to the banks API. That should in theory be coming back when echoing the json out in the jQuery request. It just keeps hitting and error instead of success.

Are actually sending a POST request to the API?

I belive so… jQuery bit looks like this…

<script type="text/javascript">

    $('#donatebox').on('submit', function(e) {

    e.preventDefault();

    // define some variables
    var form = $('#donatebox');
    var url  = form.attr('action') + '.json';
    var data = form.serialize();
    alert(url);
    alert(data);
    $.ajax({
        type: 'POST',
        dataType: 'json',
        url: url,
        data: data,

        success:function(response) {

          alert('It works!');

        },

        error:function(response){
          alert('ERROR');
        },


      });

    });
</script>

But that form is sent to your route? I meant the API request…

That happens in the if(r::is('POST')) {) part of the controller and gets returned, so it should be echoed out in the donate.json request… unless im being daft.

Let’s get the workflow straight.

So when I click on the Donate button, you send a POST request via Ajax to your donate.json route, right? And then what’s next?

Yes thats right… as i understand it, that post request to donate.json file triggers the controller to send the post request and return the response…

<?php
echo json_encode($response, ARRAY_FILTER_USE_KEY);

I’m getting more confused with every post. How does the controller come in here?

I sympathise :slight_smile: Ive been going round in circles for hours on this.

The ajax cookbook guide said setup r::isPost stuff to validiate the form and send the forms contents back if succesful. So where it calls the validate in the contoller in the guide, i replaced the validate with the curl request to the api, and put the result into the $resposnse varible and retuned it. I know the curl request is ok becuase it works in a template, it’s just unhappy in the controller. Should i instead be doing that inside the donate.json.php template or use a route for it?

I though if i did that in that contorller, it would be easier to send the form fields through rather then pick them up from the post body and doing stuff in a route or something.

Ah, ok, I forgot that the recipe uses content representations, that’s were the donate.json comes from.

But again, are you sending the API call (remote::request()) as POST request in the params array?

I think so, here is the whole controller…

<?php
return function($site, $pages, $page) {

  // Import Global Controller
  require_once kirby()->roots()->controllers() . '/shared/global.php';

  // Template Code


  // check if request is a POST request
  if(r::is('POST')) {

    $data = r::data();

    $errorCode = "";
    $sessionID = "";
    $sessionVr = "";
    $result = "";
    $successIndicator = "";


    $url = 'https://test-bobsal.gateway.mastercard.com/api/rest/version/55/merchant/secret/session/';

    $postData = array(
        'apiOperation' => 'CREATE_CHECKOUT_SESSION',

        'order' => array(
          'amount' => '5',
          'currency' => 'USD',
          'id' => 'ORDER1003',
          'description' => 'Donation',
        ),

        'interaction' => array(
          'operation' => 'PURCHASE',
          'returnUrl' => 'SECRET',
            'merchant' => array(
              'name' => 'ASSAMEH',
                  'address' => array(
                    'line1' => site()->find('address')->streetaddress()->value(),
                    'line2' => site()->find('address')->addresslocality()->value()
                  )
            )
        )
    );

    $params = array(
      'headers' => array(
        'Content-Type: Application/json;charset=UTF-8',
        'Authorization: Basic SECRET',
      ),
      'method' => 'POST',
      'body' => $postData,
    );


  $responsedata = remote::post($url, $params);

  $response = json_decode($responsedata, true);


}

return compact('query', 'response');



};