Sample Integration

Sample Integration Overview

Example project for demonstrating how to integrate with the Payment Platform to:

  • Process payments using the Hosted Payment Page (HPP) API
  • Securely store cards using the Hosted Secure Card (TOKEN) Registration Page API
  • Process payments and refunds using the Direct/HTTPS POST (XML) Gateway API

Download the Sample Integration.

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:

  • a backend service (server), under the /server folder
  • a frontend application (client), under the /client folder

While 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.

Backend Service (Server) Quick Overview

Uses: TypeScript, Node.js and Express.

Important file: /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:

  • store terminal settings
  • securely persist a shared secret value for a specific terminal
  • generate and validate transaction hash values using the shared secret
  • handle optional background validations to double-check and store transaction results
  • handle transaction refunds
  • prepare, tokenize and store secure cards (tokens) for later use
  • handle payments with cards or previously stored secure cards (tokens)

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.

Frontend Application (Client) Quick Overview

Uses: TypeScript and React.

Important file: /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:

  • store terminal settings and secrets
  • tokenize cards (secure card tokens)
  • process payments and refunds

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.

Hosted Payment Page Example

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');
}

Hosted Secure Card (TOKEN) Registration Page Example

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');
}

Direct/HTTPS POST (XML) Gateway Example

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');
}
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International