Overview
This topic describes how to create the JavaScript code to do the following:
- Integrate the Apple Pay button into your own payment page.
- Allow the total transaction amount to be changed from inside the Apple Pay payload, based on customer choices.
- Use the finalized payment details to send a
/payment
request for a regular payment or an initial recurring payment.
Prerequisites and Notes
- Include the Nuvei “CDN” library by adding this script tag to your payment page.
This is a light JavaScript wrapper over the Apple API provided by Nuvei, which is used to verify identity with Nuvei servers.<script type="text/javascript" src="https://cdn.safecharge.com/safecharge_resources/v1/sc_api_applepay.min.js"></script>
- Before beginning, it is important to be familiar with how to enable Apple Pay on the web using Apple Pay JS or the Payment Request API.It is strongly recommended reading about these topics on the Apple Pay site by referring to:
- For specific details required in this procedure: How to Display Apple Pay Buttons
- For a general overview: Apple Pay on the Web Interactive Demo
- One of the main differences between the Dynamic JavaScript button solution and the other implementations (Static Apple Pay Button, Static Apple Pay Button using Web SDK, and Payment Page using IFrame), is that it allows you to change the transaction total amount inside the Apple Pay payload, based on customer choices collected in the Apple Pay overlay.
For example, you can calculate the shipping price based on the billing address, or the shipping option selected, or the country/area for delivery, or taxes.
1. Create a Button Handler
Initialize the button handler.
When the button is pressed, invoke the overlay to show relevant fields according to your business requirements, and prompt the customer to enter the relevant details, for example: currency
, amount
, line items
, billing address
, shipping address
, etc.
2. Create a Result Handler
Now that the customer has made all their decisions (e.g which shipping method etc.) and the final payment amount is known, invoke the button handler to call a function (defined in sc_api_applepay.min.js
), which handles the session, collects the decrypted data from the device, and returns the following data:
- The authorized payment token (
mobileToken
) - Optional
address fields
- A completion function.
Define a callback function to receive this data.
3. Frontend to Backend Transfer
From the frontend, send the data gathered by the button handler to your server (backend) (so you can use it to send the /payment
request).
4. Initiate a Session
Sending an /openOrder
API call has two main functions:
- Authenticates you as our merchant using your given credentials.
- Sets up an order in the Nuvei system containing the transaction details, and generates a
sessionToken
, which is referenced later in the payment flow.
Sending an/openOrder
Request
Follow the relevant steps:
4.1 For a Regular Payment
For a regular (non-recurring) payment, send an /openOrder
request using the data received on your server from the frontend (in the previous step), and include:
- The mandatory and other relevant input parameters (as described in the /openOrder topic).
- Include a
checksum
, which is the SHA256 hash of the following concatenated fields, in this order, with no spaces, and no separators between the fields:
merchantId
,merchantSiteId
,clientRequestId
,amount
,currency
,timeStamp
,merchantSecretKey
Example /
openOrder
Request{ "merchantId":"<your merchantId goes here>", "merchantSiteId":"<your merchantSiteId goes here>", "clientUniqueId":"<unique transaction ID in merchant system>", "clientRequestId":"<unique request ID in merchant system>", "currency":"USD", "amount":"200", "timeStamp":"<YYYYMMDDHHmmss>", "checksum":"<calculated checksum>" }
<?php $safecharge = new \SafeCharge\Api\RestClient([ 'environment' => \SafeCharge\Api\Environment::INT, 'merchantId' => '<your merchantId>', 'merchantSiteId' => '<your merchantSiteId>', 'merchantSecretKey' => '<your merchantSecretKey>', ]); $openOrderRequest = $SafeCharge->getPaymentService()->openOrder([ 'clientUniqueId' => '<unique transaction ID in merchant system>', 'clientRequestId' => '<unique request ID in merchant system>', 'currency' => 'USD', 'amount' => '200', ]); ?>
public static void main(String[] args) { // for initialization String merchantId = "<your merchantId>"; String merchantSiteId = "<your merchantSiteId>"; String merchantKey = "<your merchantKey>"; safecharge.initialize(merchantId, merchantSiteId, merchantKey, APIConstants.Environment.INTEGRATION_HOST.getUrl(), Constants.HashAlgorithm.SHA256); //for openOrder String clientUniqueId = "<unique transaction ID in merchant system>"; String clientRequestId = "<unique request ID in merchant system>"; String currency = "USD"; String amount = "200"; Safecharge safecharge = new Safecharge(); SafechargeResponse response = safecharge.openOrder(userTokenId, clientRequestId, clientUniqueId, null, null, null, null, currency, amount, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); }
var safecharge = new Safecharge( "<your merchantKey>", "<your merchantId>", "<your merchantSiteId>", "<your server host value>", HashAlgorithmType.SHA256 ); var response = safecharge.OpenOrder( "USD", "200", clientUniqueId: "<unique transaction ID in merchant system>", clientRequestId: "<unique request ID in merchant system>", );
const safecharge = require('safecharge'); safecharge.initiate(<merchantId>, <merchantSiteId>, <merchantSecretKey>, <env>); safecharge.paymentService.openOrder({ 'clientUniqueId' : '<unique transaction ID in merchant system>', 'clientRequestId' : '<unique request ID in merchant system>', 'currency' : 'USD', 'amount' : '200' }, function (err, result) { console.log(err, result) });
4.2 For a Recurring Payment
For an initial recurring payment, perform the steps in the 4.1 For a Regular Payment section, and also include the following parameters in the request:
userTokenId
: “<unique customer identifier in merchant system>”- For an initial recurring payment include:
isRebilling
: “0“
Example /openOrder
Request for an Initial Recurring Payment
{ "merchantId": "<your merchantId goes here>", "merchantSiteId": "<your merchantSiteId goes here>", "clientUniqueId": "<unique transaction ID in merchant system>", "clientRequestId": "<unique request ID in merchant system>", "userTokenId": "<unique customer identifier in your system>", "isRebilling": "<0 for initial recurring payment>", "currency": "USD", "amount": "200", "timeStamp": "<YYYYMMDDHHmmss>", "checksum": "<calculated checksum>" }
Example /openOrder
Response
{ "sessionToken": "9610a8f6-44cf-4c4f-976a-005da69a2a3b", "orderId": "39272", "merchantId": "427583496191624621", "merchantSiteId": "142033", "clientUniqueId": "12345", "clientRequestId": "1484759782197", "internalRequestId": 866, "status": "SUCCESS", "errCode": 0, "reason": "", "version": "1.0" }
5. Send the Payment Request
On your server, use the data received from the frontend (in the previous step) to send the /payment
request according to the steps in the relevant topic:
- For a “non-recurring” payment, continue with the steps in the Payments topic.
- For an initial recurring payment, continue with the steps in the Initial Recurring Payment topic.
6. Backend to Frontend Transfer
Invoke the button handler to call the completion function to display the transaction result (received from the backend) to the customer, and close the overlay correctly.
The result
parameter returned is set as follows:
result
: “true” means the transaction was successful.result
: “false” means the transaction failed.
You can now test your Apple Pay implementation in the Apple Pay Sandbox environment using the test card details provided.
For details, see the Apple Pay Integration Testing topic.
Appendix
Example JavaScript Code for a Dynamic Apple Pay Button
/* define a button handler */ document.getElementById('apple-pay-button').addEventListener('click', function () { /* create initial apple pay overlay parameters */ let paymentRequest = { merchantSiteId: 183051, // use your own merchant site ID provided by Nuvei env: 'int', // Nuvei API environment - 'int' (integration) or 'prod' (production - default if omitted) applicationData: "RGVtbyBzaXRl", // use your own 64-bit encoded data // merchantCapabilities : ['supports3DS','supportsCredit'] //optional // optional overwrite of the default ['supports3DS'] //optional // supportedNetworks: ['discover', 'visa', 'masterCard'] //optional /* optional could be overwritten, default value is ['amex', 'chinaUnionPay', 'privateLabel', 'discover', 'visa', 'masterCard', 'jcb'], you can request only debit cards or only credit cards otherwise all are allowed */ requiredBillingContactFields: ['postalAddress', 'name', 'phone', 'email'], requiredShippingContactFields: ['postalAddress', 'name', 'phone', 'email'], shippingType: "shipping", // possible values: "delivery", "storePickup", "servicePickup" countryCode: 'GB', currencyCode: 'GBP', shippingMethods: [{ label: 'Standard Delivery', detail: 'Arrives 2-3 business days', amount: '5.83', identifier: 'std' }, { label: 'Ground Shipping', detail: 'Arrives 5-7 business days', amount: '55.83', identifier: 'ground' }, { label: 'Express Shipping', detail: 'Arrives 2-3 business days', amount: '155.83', identifier: 'express' }], lineItems: [{ type: 'final', label: 'Merchandise', amount: '4.95' }, { type: 'final', label: 'Standard Delivery', amount: '5.83' }, { type: 'final', label: 'Tax', amount: '60.16' }], total: { label: 'Your Company', amount: '19.99' } }; /* custom function that sends data to server */ let postTransactionData = function (url, trxData, callback) { let xhr = new XMLHttpRequest(); xhr.open('POST', url, true); xhr.setRequestHeader('Content-type', 'application/json; charset=UTF-8'); xhr.onload = function () { if (xhr.readyState === 4) { let data = {}; try { data = JSON.parse(this.responseText); } catch (e) { } callback (data); } }; let reject = function () { callback({}); }; xhr.onerror = reject; xhr.timeout = 30000; xhr.ontimeout = reject; xhr.send(JSON.stringify(trxData)); }; /* initialize session by calling sfc.applePay.buildSession, a function defined in the external js file provided by Nuvei */ let session = sfc.applePay.buildSession(paymentRequest, (result, completion) => { /* postTransactionData is a function that calls server with provided data using Nuvei API and callback receives status from server */ postTransactionData(uploadUrl, result, function (srvResult) { // depending on status returned, completion method should be called with true or false if (srvResult.transactionStatus && srvResult.transactionStatus === 'APPROVED') { completion(true); } else { completion(false); } }) //session.abort(); }); /* you can define optional handlers of various events in session, for example: onshippingmethodselected, onshippingcontactselected, onpaymentmethodselected, oncancel */ session.onshippingmethodselected = (event) => { console.log('merchant – onshippingmethodselected:', event); setTimeout(() => { session.completeShippingMethodSelection({ newTotal: { label: 'new amount', amount: '115.94' } }) }, 1000); }; session.oncancel = (evt) => { console.log('cancelled', evt) }; /* overlay is triggered*/ session.begin(); });