This is a walk through of the PHP & Javascript code required for collecting a card payment method using .
This code is based on an example found on opayo/integrate-our-drop-checkout .
The results shown are actual running code using the SagePay/Opayo Sandbox account (opayo/test-sandbox).
The code here is using the Opayo developers test environment and will not collect real funds.
warning WARNING: This code is not 100% working code and is still being worked out how to implement fully - handle with care
Opayo fees in the UK are from: [Flex plan:] £32p/m for up to 350 transactions p/m, then 12p per transaction above that.
Written: Aug-2022 PHP: 7+ Sagepay.js: v1
Step 1 : Create a merchant session key (MSK)
sagepay_checkout.php
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "https://pi-test.sagepay.com/api/v1/merchant-session-keys",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => '{ "vendorName": "sandbox" }',
CURLOPT_HTTPHEADER => array(
"Authorization: Basic " . $key,
"Cache-Control: no-cache",
"Content-Type: application/json"
)
));
$responseJson = curl_exec($curl);
$response = json_decode($responseJson, true); // false will allow you to do $response->merchantSessionKey, true will allow you to do $response['merchantSessionKey']
$err = curl_error($curl);
curl_close($curl);
echo "Response<PRE>$responseJson</PRE>";
if ($err) echo "Err<PRE>$err</PRE>";
$msk = $response['merchantSessionKey'];
echo "<LI>MSK:$msk";
{"expiry":"2023-05-30T05:32:54.631+01:00","merchantSessionKey":"61D46443-C451-4CCD-931A-2D05FC9B5974"}
Use the sagepay.js and sagepay-dropin.js scripts to generated a credit-card form fields that is inserted as an iFrame within sp-container. This iframe has been highlighted with the glowing red border for the demo.
This is placed into a <form> that in this case is actioned to post through a new script (mysagepay_processor.php), plus passing through the previously generated merchantSessionKey.
For readability, I have also used a <form target='...'> to allow the output of the php call to be directed to the current page; whether this is a good idea or not is yet to be known.
The obvious flaw in this code is that sage*.js asks for the 'Name:' field, but (1) does not pass this through to the processor via the form, and (2) later on requires a first-name and a last-name. For this reason, we have had to ask for First Name and Last Name as well - not a very good UX. [If this isn't a reason to give up on this drop-in code and move onto a Custom Form then I don't know what is! 🤨]
Note, this seems a very basic set of form fields, missing paypal, google/apple pay, and card logos.
sagepay_checkout.php
echo /**@lang HTML */ "
<p style='color:red'><i class='material-icons' style='vertical-align: middle; color: red'>warning</i> Never use real cards on this test page.</p>
<form action='mysagepay_processor.php' target='formtarget' method='POST'>
<div id=\"sp-container\"'></div>
<br>
<div class='form-group'>
<div class='label-column'>First Name</div>
<div class='input-column'><input type='text' name='FirstNm'></div>
</div>
<div class='form-group'>
<div class='label-column'>Last Name</div>
<div class='input-column'><input type='text' name='LastNm'></div>
</div>
<p><u>Address</u></p>
<div class='form-group'>
<div class='label-column'>Line 1</div>
<div class='input-column'><input type='text' name='AddressLine1'></div>
</div>
<div class='form-group'>
<div class='label-column'>Town/City</div>
<div class='input-column'><input type='text' name='City'></div>
</div>
<div class='form-group'>
<div class='label-column'>Post code</div>
<div class='input-column'><input type='text' name='Postcode'></div>
</div>
<div class='form-group'>
<div class='label-column'>Country</div>
<div class='input-column'><input type='text' name='CountryCode'></div>
</div>
<div id=\"submit-container\">
<button type=\"submit\" onClick='doShowTarget()'>Make Payment</button>
</div>
<br><hr>
MSK:<input type='text' readonly name='merchantSessionKey' value='$msk'>
</form>";
echo /**@lang Javascript */ "
<script src='https://pi-test.sagepay.com/api/v1/js/sagepay.js'></script>
<script src='https://pi-test.opayo.co.uk/api/v1/js/sagepay-dropin.js'></script>
<script>
sagepayCheckout({ merchantSessionKey: '$msk' }).form();
</script>
";
HINT: Use the Test card options listed below (e.g. 4929000000006 - expires 05/23, CVC 123, etc)
warning Never use real cards on this test page.
Clicking Make Payment will make the sagepay.js call the form action page and into the next step target below
The credit card details have been posted through card-identifier to our next step, mysagepay_processor, that now requests a payment, adding in amounts and currency information before posting it to sagepay.com
sagepay_checkout.php
echo "<iframe name='formtarget' id='formtarget' class='hidden'></iframe>";
No code file found