Example project for demonstrating how to integrate with the Payment Platform to:
Full documentation is available in API Specification. You should also use our Sandbox test accounts Sandbox testing.
This sample project consists of two primary components:
/server
folder/client
folderWhile both components contain many files, we attempted to isolate the important pieces of the integration in only two files: one for the server and another one for the client. These files are extensively documented, so we recommend that developers review these files for guidance on integrating to the Payment Platform.
/server/src/server.ts
The server.ts
is the only file that communicates with the Payment Platform. It serves as a bridge between the Payment Platform and the client app. It exposes an API that the client uses to:
Except when running the project in `local` mode (used for development), the backend is also responsible for serving the static files required by the client.
/client/src/modules/payment-gateway.module.ts
The client app was built to simulate the most common scenarios that developers will need when integrating with a Payment Platform.
Its purpose is to demonstrate through a few different scenarios how we can leverage the API exposed by the server to:
The payment-gateway.module.ts
file contains all of the code responsible for interacting with our server and is decoupled (independent) of the user interface we have (that happens to use React). Everything else in the client will, at some point, reach for that module as a way to ultimately use the Payment Platform.
Example code for building the Hosted Payment Page HPP request URL.
The URL can then be used to load the HPP form in an iframe to be displayed to the user.
The iframe can be safely used to pay for transactions.
// User current date time stamp in DD-MM-YYYY:HH:mm:ss:SSS format. const dateTimeStamp = "01-01-2022:08:00:00:000"; // Use your specific terminal ID. const terminalId = "1234"; // Assign the transaction amount. const amount = 1.23; // Assign a unique order ID. const orderId = "ABC123"; // Securely store and use your shared secret value server-side, // do not expose to client-side browsers. const sharedSecret = "MyTestSecret"; // When background validation is enabled, a POST call to `validationUrl` // will be sent containing the details of the transaction in its body. // The `validationUrl` must be a publicly available URL. const backgroundValidationEnabled = true; const validationUrl = `http://localhost:3001/transaction/${orderId}`; // The `receiptPageUrl` will be called with with the resulting transaction as query params const receiptPageUrl = "http://localhost:3001/receipt"; // Concatenate values to be hashed for a Hosted Payment Page request. // Format: "TERMINALID:ORDERID:AMOUNT:DATETIME:RECEIPTPAGEURL:VALIDATIONURL:SECRET" const txnPreHash = [terminalId, orderId, amount, dateTimeStamp, receiptPageUrl] .join(":") // Conditionally add validationUrl if background validation // is enabled in the SelfCare System (Merchant Portal). .concat(backgroundValidationEnabled ? `:${validationUrl}` : "") .concat(`:${sharedSecret}`); // Create SHA512 hash for transaction. const hash = sha512_hash(txnPreHash); // Concatenate Hosted Payment Page URL query parameters const url = "https://testpayments.nuvei.com/merchant/paymentpage" + `?TERMINALID=${terminalId}` + `&ORDERID=${orderId}` + `&CURRENCY=USD` + `&AMOUNT=${amount}` + `&DATETIME=${dateTimeStamp}` + `&RECEIPTPAGEURL=${receiptPageUrl}` + // Include VALIDATIONURL only if Background Validation is // enabled for merchant in the SelfCare System (Merchant Portal) (backgroundValidationEnabled ? `&VALIDATIONURL=${validationUrl}` : "") + `&HASH=${hash}` + `&INIFRAME=Y`; // Then load the url in an iframe
Example SHA512 hashing functions (using Node.js crypto API):
// Create SHA512 hash. function sha512_hash(data) { return crypto.createHash('sha512').update(data).digest('hex'); }
Example code for building the Hosted Secure Card Registration Page request URL.
The URL can then be used to load the Secure Card form in an iframe to be displayed to the user.
The iframe can be safely used to store cards for later use.
// User current date time stamp in DD-MM-YYYY:HH:mm:ss:SSS format. const dateTime = '01-01-2022:08:00:00:000'; // Use your specific terminal ID. const terminalId = '1234'; // Unique Merchant Reference for the card. Length is limited to 48 characters. const merchantRef = 'XYZ987'; // Action can be either 'register' or 'update'. const action = 'register'; // Securely store and use your shared secret value server-side, // do not expose to client-side browsers. const secret = 'MyTestSecret'; // Concatenate values to be hashed for a Hosted Payment Page request. // Format: "TERMINALID:MERCHANTREF:DATETIME:ACTION:SECRET" const txnPreHash = [terminalId, merchantRef, dateTime, action, secret].join(':'); // Create SHA512 hash for transaction. const hash = sha512_hash(txnPreHash); // Persist the relationship between the `terminalId` and the Secure Card `merchantRef`. // Important so we can later retrieve the created secure card token by `merchantRef`. // Concatenate Hosted Payment Page URL query parameters const url = 'https://testpayments.nuvei.com/merchant/securecardpage' + `?TERMINALID=${terminalId}` + `&ACTION=${action}` + `&DATETIME=${dateTime}` + `&MERCHANTREF=${merchantRef}` + `&HASH=${hash}` + `&INIFRAME=Y`; // Then load the url in an iframe
It's important to set the SecureCard URL in the SelfCare System (Merchant Portal).
Upon submitting the form inside the iframe, the cardholder browser will be redirected to that URL after a card is registered or updated.
From there, the implementation can store the secure card token (by terminalId and merchantRef) for later use.
Example SHA512 hashing functions (using Node.js crypto API):
// Create SHA512 hash. function sha512_hash(data) { return crypto.createHash('sha512').update(data).digest('hex'); }
Example of using a stored secure card token:
// User current date time stamp in DD-MM-YYYY:HH:mm:ss:SSS format. const dateTime = '01-01-2022:08:00:00:000'; // Use your specific terminal ID. const terminalId = '1234'; // Assign the transaction amount. const amount = 1.23; // Unique Reference for this Transaction const uniqueRef = `Sign Up - ${Date.now()}`; // Unique Merchant Reference for the card. Length is limited to 48 characters. const merchantRef = 'XYZ987'; // Retrieved stored secure card token with the terminalId and unique merchantRef // Then use its `CARDREFERENCE` (token) - received in the POST call to `SecureCard URL` const { CARDREFERENCE } = getSecureCardToken(terminalId, merchantRef); // (pseudo-code) // Securely store and use your shared secret value server-side, // do not expose to client-side browsers. const secret = 'MyTestSecret'; // Concatenate values to be hashed for a Hosted Payment Page request. // Format: "TERMINALID:ORDERID:AMOUNT:DATETIME:SECRET" const txnPreHash = [terminalId, uniqueRef, amount, dateTime, secret].join(':'); // Create SHA512 hash for transaction. const hash = sha512_hash(txnPreHash); /** * Build XML request for Payment * See "Request Body Fields" under the "Payment" section at * https://docs.gateway.integratedcommerce.io/doku.php%3Fid=developer:api_specification:xml_payment_features.html * * Dependencies used in this example: * - `xmlbuilder2`: https://www.npmjs.com/package/xmlbuilder2 * - `cross-fetch`: https://www.npmjs.com/package/cross-fetch */ const xml = xmlbuilder.create({ version: '1.0', encoding: 'UTF-8' }).ele('PAYMENT'); xml.ele('ORDERID').txt(uniqueRef); xml.ele('TERMINALID').txt(terminalId); xml.ele('AMOUNT').txt(amount); xml.ele('DATETIME').txt(dateTime); xml.ele('CARDNUMBER').txt(CARDREFERENCE); xml.ele('CARDTYPE').txt('SECURECARD'); xml.ele('HASH').txt(hash); xml.ele('CURRENCY').txt('USD'); xml.ele('TERMINALTYPE').txt('2'); // TERMINALTYPE 2 - eCommerce xml.ele('TRANSACTIONTYPE').txt('7'); // TRANSACTIONTYPE 7 - eCommerce xml.end({ prettyPrint: true }); const result = await fetch(`https://testpayments.nuvei.com/merchant/xmlpayment`, { method: 'POST', headers: { Accept: 'application/xml', 'Content-Type': 'application/xml' }, body: xml.toString(), }).then(response => response.text().then(responseAsText => { return xmlbuilder.convert(responseAsText, { format: 'object' }); }), ); // If the result contains a PAYMENTRESPONSE, it means that the transaction // was processed and the PAYMENTRESPONSE will contain more information. // Otherwise, handle any possible errors inside the result, ie.: result.ERROR result.PAYMENTRESPONSE ? console.log(result.PAYMENTRESPONSE) : console.error(result);
Example SHA512 hashing functions (using Node.js crypto API):
// Create SHA512 hash. function sha512_hash(data) { return crypto.createHash('sha512').update(data).digest('hex'); }