Validate a HelcimPay.js Payment

To ensure the integrity of the HelcimPay.js transaction response, it can be validated by comparing the hash returned in the response, with your hash generated from combining the response data and the secret token.

Access the HelcimPay.js Transaction Response

Once the customer has processed their transactions, you can listen to the iFrame's event in order to access the responseMessage with the outcome of the transactions, as well as the hash value for the transaction to validate the response.

// Example CC transaction response

data: {
  "transactionId": "20163175",
  "dateCreated": "2023-07-17 10:34:35",
  "cardBatchId": "2915466",
  "status": "APPROVED",
  "type": "purchase",
  "amount": "15.45",
  "currency": "CAD",
  "avsResponse": "X",
  "cvvResponse": "",
  "approvalCode": "T3E5ST",
  "cardToken": "27128ae9440a0b47e2a068",
  "cardNumber": "4000000028",
  "cardHolderName": "Test",
  "customerCode": "CST1049",
  "invoiceNumber": "INV001045",
  "warning": ""
},
// Hash returned by Helcim
hash: "dbcb570cca52c38d597941adbed03f01be78c43cba89048722925b2f168226a9" 

// Example ACH transaction response

data: {
  data: {
    amount: "100.00",
    approvalCode: "",
    bankAccountNumber: "100200300",
    bankToken: "fcc48b4cb9a8ecd6531b49",
    batchId: "5220",
    currency: "CAD",
    customerCode: "CST1200",
    dateCreated: "2023-04-20 13:56:31",
    invoiceNumber: "INV000020",
    statusAuth: "PENDING",
    statusClearing: "OPENED",
    transactionId: "1020",
    type: "WITHDRAWAL"
  },
  // Hash returned by Helcim
  hash: "dbcb570789b3cba8682c43cba899794103f0122adbed6a26e048722925b2f168"

This data can be sent from your front-end to your secure back-end in order to complete the optional validation and update any other values within your system.

window.addEventListener('message', (event) => {

  const helcimPayJsIdentifierKey = 'helcim-pay-js-' + checkoutToken;

  if(event.data.eventName === helcimPayJsIdentifierKey){

    if(event.data.eventStatus === 'ABORTED'){
      console.error('Transaction failed!', event.data.eventMessage);
    }

    if(event.data.eventStatus === 'SUCCESS'){
      validateResponse(event.data.eventMessage)
        .then(response => console.log(response))
        .catch(err => console.error(err));
    }
  }
});

function validateResponse(eventMessage) {
  const payload = {
    'rawDataResponse': eventMessage.data,
    'checkoutToken': checkoutToken,
    'secretToken': secretToken
  };
  
  return fetch('https://example.com/your-endpoint', payload);
}

Generate and Compare Your Transaction Response Hash

To generate your hash you will JSON encode the transaction response data, append it with the secretToken, then hash them using a secure sha-256 algorithm.

$secretToken = 'sample-secret';
$jsonEncodedData = '{
  "transactionId": "20163175",
  "dateCreated": "2023-07-17 10:34:35",
  "cardBatchId": "2915466",
  "status": "APPROVAL",
  "type": "purchase",
  "amount": "15.45",
  "currency": "CAD",
  "avsResponse": "X",
  "cvvResponse": "",
  "approvalCode": "T3E5ST",
  "cardToken": "27128ae9440a0b47e2a068",
  "cardNumber": "4000000028",
  "cardHolderName": "Test",
  "customerCode": "CST1049",
  "invoiceNumber": "INV001045",
  "warning": ""
}';
$cleanedJsonEncodedData = json_encode(json_decode($jsonEncodedData, true));
$expectedHash = hash('sha256', $cleanedJsonEncodedData . $secretToken); 
// dbcb570cca52c38d597941adbed03f01be78c43cba89048722925b2f168226a9

public function validateHash(array $rawDataResponse, string $secretToken, string $expectedHash) {
  $encodedData = json_encode($rawDataResponse);
  $hashedResponse = hash('sha256', $encodedData . $secretToken);
  return $hashedResponse === $expectedHash;
}
# ❗️ When encoding the JSON object, ensure that extra characters like spaces are removed

import json
import hashlib

secret_token = "your_secretToken"
data_string = '{
	"transactionId": "28425465",
  "dateCreated": "2024-09-10 11:35:19", 
  "cardBatchId": "3915825", 
  "status": "APPROVED", 
  "type": "purchase", 
  "amount": "10", 
  "currency": "USD", 
  "avsResponse": "X", 
  "cvvResponse": "M", 
  "approvalCode": "T1E1ST", 
  "cardToken": "3d1e5ff7eb7599b91494d0", 
  "cardNumber": "5413330011", 
  "cardHolderName": "John Doe", 
  "customerCode": "CST1094", 
  "invoiceNumber": "INV001087", 
  "warning": ""}'
inbound_hash = '42bad6d386ba6717b875ecf0e295f1ed377a9b9146f6633371d536267b8721be'


data_json_encoded_withOUT_spaces = json.dumps(json.loads(data_string), separators=(',', ':'))
generated_hash_withOUT_spaces = hashlib.sha256((data_json_encoded_withOUT_spaces + secret_token).encode()).hexdigest()
print(generated_hash_withOUT_spaces == inbound_hash) 
# HASH: 42bad6d386ba6717b875ecf0e295f1ed377a9b9146f6633371d536267b8721be
 

The hash value returned from your validateHash() function should match the hash value returned in the transaction response from Helcim.