Skip to Content

Hosted Checkout

There are currently two ways to implement the hosted checkout solution:

  1. Using an iframe
  2. Redirection to payment page

Both approaches follow similar steps:

Step 1: Create Checkout Session

Merchants must first create a session for the payment to take place.

  • API: Private
  • Authentication: Live or Test Public Keys
  • Endpoint: /v1/hosted-checkout
  • Method: POST

Example Request

{ "requestId": "order2-1277", "currency": "USD", "amount": 151, "webhookUrl": "https://your-merchant-domain.com/webhook", "successRedirectUrl": "https://your-merchant-domain.com/success", "errorRedirectUrl": "https://your-merchant-domain.com/error", "orderDetails": [ { "name": "Shoes", "currency": "string", "quantity": 1, "description": "string", "price": 0 } ], "deliveryDetails": { "currency": "USD", "fee": 0 } }

Example Response

{ "sessionId": "0193cebd-772f-713a-af5f-cf4f2c8591bf", "url": "https://staging.cashia.com/link/YourMerchantName/0193cebd-772f-713a-af5f-cf4f2c8591bf", "amount": 10, "currency": "KES", "requestId": "order-1234" }

Authentication with HMAC

The hosted checkout endpoint requires HMAC (Hash-based Message Authentication Code) authentication. You need to include specific headers in your request:

Required Headers

  • X-Cashia-Key-ID: Your API Key ID
  • X-Cashia-Timestamp: Current Unix timestamp (seconds since epoch)
  • X-Cashia-Nonce: A unique random string for each request
  • X-Cashia-Signature: HMAC SHA256 signature of the signing string
  • X-Cashia-Hash: HMAC SHA256 hash of the request body (for POST/PUT/PATCH requests)
  • Content-Type: application/json

Generating the Signature

The signature is computed using HMAC SHA256 with your secret key. The signing string format is:

host example: https://host + method + timestamp + nonce + keyId

Important: Do not include any separators or additional characters between the components.

Example Request Body

{ "requestId": "test-14-68a2ff317f34abc3a8a9a9", "amount": 200, "currency": "KES", "successRedirectUrl": "https://your-merchant-domain.com/success", "errorRedirectUrl": "https://your-merchant-domain.com/error", "webhookUrl": "https://your-merchant-domain.com/webhook", "orderDetails": [ { "name": "soda", "currency": "KES", "quantity": 1, "description": "soda", "price": 100 } ], "deliveryDetails": { "currency": "KES", "fee": 0 } }

Postman Pre-request Script

Here’s a Postman pre-request script to automatically generate the required headers:

// Import CryptoJS library for hashing const CryptoJS = require('crypto-js'); // Retrieve the source environment from the collection variable const sourceEnv = pm.variables.get("source_env"); if (!sourceEnv) { throw new Error("The 'source_env' variable is not set in the collection. Please define it as 'staging' or 'local'."); } // Configuration - Generate dynamic values for the headers const secret = pm.environment.get("secret"); // Retrieve the shared secret from environment const keyID = pm.environment.get("key_id"); // Retrieve the Key ID from environment const nonce = Math.random().toString(36).substring(2, 15); // Generate a unique nonce const timestamp = Math.floor(Date.now() / 1000); // Current Unix time in seconds const method = pm.request.method.toUpperCase(); const host = pm.environment.get("host"); // Retrieve the API host from environment // Retrieve and hash the request body if it exists (for POST/PUT/PATCH methods) let requestBody = ''; let bodyHash; if (method === "POST" || method === "PUT" || method === "PATCH") { if (pm.request.body && pm.request.body.mode === 'raw') { requestBody = pm.request.body.raw || ''; } // Hash the request body string bodyHash = CryptoJS.HmacSHA256(requestBody, secret).toString(CryptoJS.enc.Hex); } else { // For GET and other methods with no body, hash an empty string bodyHash = CryptoJS.HmacSHA256('', secret).toString(CryptoJS.enc.Hex); } // Create signing string - must match format exactly: host + method + timestamp + nonce + keyId const signingString = `${host}${method}${timestamp}${nonce}${keyID}`; // Compute HMAC SHA256 Signature const signature = CryptoJS.HmacSHA256(signingString, secret).toString(CryptoJS.enc.Hex); // Set environment variables for use in headers pm.environment.set('timestamp', timestamp); pm.environment.set('nonce', nonce); pm.environment.set('signature', signature); pm.environment.set('body_hash', bodyHash); pm.environment.set('Content-Type', 'application/json');

Postman Headers Configuration

In your Postman request, add these headers:

  • X-Cashia-Key-ID: {{key_id}}
  • X-Cashia-Timestamp: {{timestamp}}
  • X-Cashia-Nonce: {{nonce}}
  • X-Cashia-Signature: {{signature}}
  • X-Cashia-Hash: {{body_hash}}
  • Content-Type: {{Content-Type}}

Implementation Notes

  1. Body Hash: For POST/PUT/PATCH requests, the body must be hashed exactly as it appears in the request (including any whitespace or formatting). Ensure the body string matches exactly between generation and sending.

  2. Nonce: Each request must have a unique nonce. Do not reuse nonces across requests.

  3. Timestamp: The timestamp should be the current Unix time in seconds. The server may reject requests with timestamps that are too old (typically more than 5 minutes).

  4. Host: The host value should match the API host you’re calling (e.g., api.example.com for staging).

Step 2: Use the URL in Your Code

Iframe Approach

With the URL from the above response, render an iframe:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Merchant Checkout Page</title> </head> <body> <div>Merchant Checkout Page</div> <iframe name="cashia" width="400" height="600" src="https://staging.cashia.com/link/YourMerchantName/0193cee1-3206-7e18-b981-37e036b4545f"> </iframe> </body> </html>

Hosted Page Redirect Approach

With the URL from the response, redirect the user to the payment page:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Merchant Checkout Page</title> </head> <body> <div>Merchant Checkout Page</div> <div style="margin-bottom: 20px"></div> <a href="https://staging.cashia.com/link/YourMerchantName/0193cee1-3206-7e18-b981-37e036b4545f" target="_blank"> <div>Click to Pay</div> </a> </body> </html>

Step 3: Redirection to Success/Error Page

Payment processing results in either success or failure/cancellation. The end user must be notified of the payment outcome via successCallbackURL or errorCallbackURL.

During session creation, provide callback URLs for both scenarios. Based on the payment result, the payment gateway will trigger the corresponding callback URL.

Example success callback URL with parameters:

https://your-merchant-domain.com/success?validTimeStamp=1708118400&requestId=order2-1237&status=C

The payment gateway adds requestId and status at the end of the request.

Last updated on