Hosted Payment Page
Hosted Payment page API Reference
Zapper Hosted Payment Page is a quick set-up, PCI DSS compliant service that enables customers to complete transactions on a secure payment page hosted by Zapper.
All encryption is handled internally and cardholder data will not be transmitted between Zapper and the merchant sites.
- 1.Create Session and Receive RedirectUrlThe merchant initiates the payment process by creating a session using Zapper's API. The merchant receives a redirectUrl, which is used to redirect user to the Hosted Payment Page for payment processing.
- 2.Redirect User to Zapper's Hosted Payment PageThe merchant is required to redirect the user to the Hosted Payment Page, where they are presented with payment options, such as QR code or card payment.
- 3.User Completes the PaymentThe user completes the payment process on the Hosted Payment Page.
- 4.Zapper Notifies Merchant via WebhookAfter payment, Zapper sends a payment notification to the merchant's notificationUrl (provided by the merchant when the session is created). The merchant is required to implement a webhook endpoint to receive these payment notifications. It is recommended that the merchant validate the signature.
- 5.Zapper Redirects User Back to Merchant's StoreUpon completing the payment process, Zapper redirects the user back to the merchant's store.
Integration Workflow

post
https://gateway.zapper.com
/api/v3/sessions
Create a new session
curl --location 'https://gateway.zapper.com/api/v3/sessions' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'merchantId: 1234' \
--header 'merchantSiteId: 1234' \
--header 'x-api-key: cb67xxxxxx0546f68806b62a36xxxxxx' \
--data '{
"merchantOrderId": "c93d99c8-20e1-4fc6-95b8-10d50eb9a90e",
"amount": 1000,
"currencyISOCode": "ZAR",
"notificationUrl": "https://merchantstore.com/somePaymentNotificationPath",
"returnUrl": "https://merchantstore.com/someReturnPath",
"cancelUrl": "https://merchantstore.com/someCancelPath",
"requestId": "ad7234d5-4e6b-4acf-8e29-451c056b2bdc",
"origin": "https://merchantstore.com"
}'
get
https://gateway.zapper.com
/api/v3/payments
Get payments by sessionId
curl --location 'https://gateway.zapper.com/api/v3/payments?sessionId=20908573-a1ea-412d-8a25-26e48e58c548' \
--header 'Accept: application/json' \
--header 'merchantId: 8712' \
--header 'merchantSiteId: 8727' \
--header 'x-api-key: cb67xxxxxx0546f68806b62a36xxxxxx'
get
https://gateway.zapper.com
/api/v3/payments/{paymentReference}
Get payment by paymentReference
curl --location 'https://gateway.zapper.com/api/v3/payments/XZR8K9QKWVYE2E159L' \
--header 'Accept: application/json' \
--header 'merchantId: 8712' \
--header 'merchantSiteId: 8727' \
--header 'x-api-key: cb67xxxxxx0546f68806b62a36xxxxxx'
signature | string | The signature property represents a cryptographic value or digital signature associated with a payment notification webhook. |
sessionId | string | The unique identifier for the sessionreference |
amount | integer | The total value of the transaction in the smallest unit of the currency specified (eg in cents) |
currencyISOCode | string | The 3 letter currency code as per ISO 4217. Currently only 'ZAR' is supported. |
merchantOrderId | string | The identifier or reference of the order generated by the merchant. It provides a way to link the session to a specific order or transaction within the merchant's system. |
paymentReference | string | A unique identifier assigned to a specific payment. |
paymentStatus | The status or outcome of a payment transaction | |
userMessage | string | A user friendly message. Only populated when paymentStatus is not 'Success'. |
paymentUTCDate | string | The UTC date and time of the payment. |
status | The API response status. A response other than 'Success' indicates that there was an error on the API level (such as request validation, or errors intepretting the gateway response). Refer to the 'errors' list for more information. | |
errors | The list of errors if the status is not 'Success'. |
Value | Type | Description |
1 | string | Success |
2 | string | Failed |
Value | Type | Description |
1 | string | Success |
2 | string | BadRequest |
3 | string | NotFound |
4 | string | Unauthorized |
5 | string | InternalServer |
Value | Type | Description |
message | string | A human readable error message |
To ensure the authenticity and integrity of the payment notification data, validating the signature is recommended. The PaymentNotificationWebhook is used along with the merchant's x-api-key when creating a SHA256 signature hash. The following are an examples of signature validation:
C#
private bool IsSignatureValid(string signature, ZapperEcomAPIV3Client.PaymentNotificationWebhook paymentNotificationWebhook, string x-api-key)
{
string signatureInput = $"{x-api-key}|{paymentNotificationWebhook.SessionId}|{paymentNotificationWebhook.Amount}|{paymentNotificationWebhook.CurrencyISOCode}|{paymentNotificationWebhook.MerchantOrderId}|{paymentNotificationWebhook.PaymentReference}|{paymentNotificationWebhook.paymentStatus}|{paymentNotificationWebhook.PaymentUTCDate}|{paymentNotificationWebhook.UserMessage}";
using (SHA256 sha = SHA256.Create())
{
byte[] hashBytes = sha.ComputeHash(Encoding.UTF8.GetBytes(signatureInput));
StringBuilder builder = new StringBuilder();
foreach (byte b in hashBytes)
{
builder.Append(b.ToString("x2"));
}
string generatedSignature = builder.ToString();
return generatedSignature.Equals(signature, StringComparison.OrdinalIgnoreCase);
}
}
JavaScript:
const crypto = require('crypto');
function isSignatureValid(signature, paymentNotificationWebhook, x-api-key) {
const signatureInput = `${x-api-key}|${paymentNotificationWebhook.SessionId}|${paymentNotificationWebhook.Amount}|${paymentNotificationWebhook.CurrencyISOCode}|${paymentNotificationWebhook.MerchantOrderId}|${paymentNotificationWebhook.PaymentReference}|${paymentNotificationWebhook.paymentStatus}|${paymentNotificationWebhook.PaymentUTCDate}|${paymentNotificationWebhook.UserMessage || ""}`;
const generatedSignature = sha256Hash(signatureInput);
return generatedSignature.toLowerCase() === signature.toLowerCase();
}
function sha256Hash(value) {
const hash = crypto.createHash('sha256');
const hashBytes = hash.update(value, 'utf-8').digest();
return hashBytes.toString('hex');
}
Java:
private static boolean isSignatureValid(String signature, PaymentNotificationWebhook paymentNotificationWebhook, String x-api-key) {
String signatureInput = x-api-key + "|" +
paymentNotificationWebhook.getSessionId() + "|" +
paymentNotificationWebhook.getAmount() + "|" +
paymentNotificationWebhook.getCurrencyISOCode() + "|" +
paymentNotificationWebhook.getMerchantOrderId() + "|" +
paymentNotificationWebhook.getPaymentReference() + "|" +
paymentNotificationWebhook.getPaymentStatus() + "|" +
paymentNotificationWebhook.getPaymentUTCDate() + "|" +
paymentNotificationWebhook.getUserMessage();
String generatedSignature = sha256Hash(signatureInput);
return generatedSignature.equalsIgnoreCase(signature);
}
private static String sha256Hash(String value) {
MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] hashBytes = digest.digest(value.getBytes(StandardCharsets.UTF_8));
StringBuilder builder = new StringBuilder();
for (byte b : hashBytes) {
builder.append(String.format("%02x", b));
}
return builder.toString();
}
Last modified 1mo ago