Ozow Hub
On this page14 sections
Build with AI 1 package

A build package is every page for one task, with the API operations they use. Copy the prompt into a coding assistant, or hand it the package itself: slim links to each page, full inlines all of them in one document.

  • Migrate a payin from the Payments API to One APIEverything needed to move an existing redirect payin onto One API, with the legacy guide and its One API counterpart side by side.
    View package

This guide walks you through a redirectRedirect Sending the payer to the Ozow payment page to complete the payment, and returning them to your site afterwards. The alternative is embedding the checkout in your own page, where the payer never leaves it. payinPayin A payment made by a consumer to a merchant. The direction most of this site is about: money coming in. Its counterpart is a payout, which sends money out and is not tied to any payment anyone made you. integration using the Payments API. Your system posts payment information to Ozow, redirects the customer to the Ozow-hosted payment page, and receives a notification response when the payment is complete.

Legacy integration: use One API for new integrations

Payments API is a legacy integration path and will not receive new features. If you are starting a new payin integration, use Redirect: One API instead. This guide exists to support merchants already integrated on Payments API.

Before you start

  • You have completed Prerequisites and onboarding
  • You have your API key, private key, and site codeSite code The unique code for a site registered under a merchant. A site is a place to transact: a website, or a branch of a store. A merchant can have several, and each transaction names the one it belongs to, so sending the wrong code files the payment against the wrong place. from your Ozow Dashboard
  • Your notification URLWebhook A URL of yours that Ozow calls when something happens, rather than you polling to find out. The call carries no credential of yours and arrives at a public URL, so authenticate it before acting on it: a hash field on the Payments API, a Svix signature on One API., success URL, cancel URL, and error URL are set up and publicly accessible via HTTPS

Environments

Environment API endpoint Dashboard
Production https://api.ozow.com/postpaymentrequest dash.ozow.com
Staging https://stagingapi.ozow.com/postpaymentrequest stagingdash.ozow.com

How redirect works


Core integration

Step 1: Generate the hash check

The Payments API uses SHA512SHA-512 A hashing algorithm. Ozow uses it to sign the values in a request or a notification so you can tell that they arrived unaltered and came from us. Hashing is one-way: the hash cannot be turned back into what produced it.Wikipedia hash-based authentication. Before posting a payment request, you must generate a hash check to sign the request.

How to generate the hash check

Critical, field order matters

The fields must be concatenated in exactly the order listed in the request fields table below. Using the wrong order is the most common cause of hash check failures. Only include fields that have a value, empty or unused fields must be excluded from the hash entirely, not included as empty strings.

  1. Concatenate the post variables (excluding HashCheck and Token) in the order they appear in the request fields table below
  2. Append your private key to the concatenated string
  3. Convert the entire string to lowercase
  4. Generate a SHA512 hash of the lowercase string

Note

Boolean values must be represented as the strings true or false in the concatenated string. Some languages may convert booleans to 0 or 1 which will result in a failed hash check.

Important

The amount must be formatted with exactly two decimal places, 100.00 rather than 100 or 100.0. Most languages drop a trailing zero when a number is converted to a string, so format the amount before you concatenate it. This is the most common cause of a failed hash check.

Hash check example

Given the following values:

Field Value
SiteCode TSTSTE0001
CountryCode ZA
CurrencyCode ZARZAR The ISO 4217 code for the South African rand, and the currency every amount on this site is in unless a page says otherwise. Amounts are decimal rand rather than cents, so 100.00 is one hundred rand.
Amount 25.00
TransactionReference 123
BankReference ABC123
CancelUrl http://demo.ozow.com/cancel.aspx
ErrorUrl http://demo.ozow.com/error.aspx
SuccessUrl http://demo.ozow.com/success.aspx
NotifyUrl http://demo.ozow.com/notify.aspx
IsTest false

The concatenated string before hashing would be:

tstste0001zazar25.00123abc123http://demo.ozow.com/cancel.aspxhttp://demo.ozow.com/error.aspxhttp://demo.ozow.com/success.aspxhttp://demo.ozow.com/notify.aspxfalse[your private key]

Resulting hash:

4a2e7db32f76747b0f434edeb62e8b3ebb04125025feae622bc09092296bc965cec49a8cbeeef0e21f3c4c04249de69dd0b330a5b7da21c51a95d360d03f54ba

Code examples

using System.Globalization;
using System.Security.Cryptography;
using System.Text;

void GenerateRequestHash()
{
    string siteCode = "YOUR_SITE_CODE";
    string countryCode = "ZA";
    string currencyCode = "ZAR";
    string amount = 100.00M.ToString("0.00", CultureInfo.InvariantCulture);
    string transactionReference = "ORDER-001";
    string bankReference = "ABC123";
    string cancelUrl = "https://yourstore.com/cancel";
    string errorUrl = "https://yourstore.com/error";
    string successUrl = "https://yourstore.com/success";
    string notifyUrl = "https://yourstore.com/notify";
    string privateKey = "YOUR_PRIVATE_KEY";
    bool isTest = false;

    string inputString = string.Concat(
            siteCode,
            countryCode,
            currencyCode,
            amount,
            transactionReference,
            bankReference,
            cancelUrl,
            errorUrl,
            successUrl,
            notifyUrl,
            isTest,
            privateKey
        )
        .ToLower();

    using SHA512 sha512 = new SHA512CryptoServiceProvider();
    var bytes = sha512.ComputeHash(Encoding.UTF8.GetBytes(inputString));
    var hash = BitConverter.ToString(bytes).Replace("-", "").ToLower();
    Console.WriteLine($"HashCheck: {hash}");
}

Complete field concatenation order

Only include fields that have a value. Empty or unused fields must be excluded.

Position Field Required
1 siteCode Yes
2 countryCode Yes
3 currencyCode Yes
4 amount Yes
5 transactionReference Yes
6 bankReference Yes
7 optional1 No
8 optional2 No
9 optional3 No
10 optional4 No
11 optional5 No
12 customer No
13 cancelUrl No
14 errorUrl No
15 successUrl No
16 notifyUrl No
17 isTest Yes
18 selectedBankId No
19 bankAccountNumber No
20 branchCode No
21 bankAccountName No
22 payeeDisplayName No
23 expiryDateUtc No
24 allowVariableAmount No
25 variableAmountMin No
26 variableAmountMax No
27 customerIdentifier No
28 customerCellphoneNumber No
29 hashCheck Yes: do not include in hash

Step 2: Create a payment request

Post the payment request to the Ozow API to generate a payment URL.

POST Create Payment Request Reference
POST https://api.ozow.com/postpaymentrequest
ApiKey: YOUR_API_KEY
Content-Type: application/json
Accept: application/json
curl -X POST "https://api.ozow.com/postpaymentrequest" \
  -H "Accept: application/json" \
  -H "ApiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "siteCode": "YOUR_SITE_CODE",
    "countryCode": "ZA",
    "currencyCode": "ZAR",
    "amount": "100.00",
    "transactionReference": "ORDER-001",
    "bankReference": "ABC123",
    "cancelUrl": "https://yourstore.com/cancel",
    "errorUrl": "https://yourstore.com/error",
    "successUrl": "https://yourstore.com/success",
    "notifyUrl": "https://yourstore.com/notify",
    "isTest": false,
    "hashCheck": "YOUR_GENERATED_HASH"
  }'

Key request fields

Field Type Required Description
siteCode string Yes Your Ozow site code
countryCode string Yes Must be ZA
currencyCode string Yes Must be ZAR
amount string Yes Payment amount
transactionReference string Yes Your internal order reference
bankReference string Yes The reference that appears on your bank statement for the payment
cancelUrl string Yes URL to redirect the customer to if they cancel
errorUrl string Yes URL to redirect the customer to if an error occurs
successUrl string Yes URL to redirect the customer to on successful payment
notifyUrl string Yes URL Ozow posts the notification response to
isTest boolean Yes Set to false for live payments
hashCheck string Yes The SHA512 hash generated in Step 1

For the full list of request fields see Post Payment Request.

Successful response

{
  "paymentRequestId": "00000000-0000-0000-0000-000000000000",
  "url": "https://pay.ozow.com/00000000-0000-0000-0000-000000000000/Secure",
  "errorMessage": null
}

Important

A rejected request is also an HTTP 200. A failed hash check, a bank reference that is too long, or a site code that is not active come back with status 200, a null url, and the reason in errorMessage. Treat the request as accepted only when url is populated and errorMessage is null.

Rejected response

{
  "paymentRequestId": null,
  "url": null,
  "errorMessage": "The HashCheck value has failed"
}

Step 3: Redirect the customer

Redirect your customer's browser to the url returned in the response. Ozow displays the payment page where the customer selects their preferred payment method and completes the payment.

Once the customer completes, cancels, or encounters an error, Ozow redirects them to the applicable URL you specified in the request; successUrl, cancelUrl, or errorUrl.

Important

Do not use the redirect to successUrl alone as confirmation that a payment was successful. Always confirm payment status via the verified notification response or an API status check.

Note

Pay by BankPay by Bank The payer authorises the payment inside their own banking app or online banking, and the funds move from their bank account. No card is involved and no card details are entered. is available by default. Additional payment methods such as Capitec PayCapitec Pay Capitec's own payment method. The payer gives a cellphone, account or ID number rather than card details, and approves the payment in the Capitec app, so no card number and no banking login is ever entered at checkout. It gets its own button rather than sitting inside the bank list, and it requires Customer Identity Verification.Capitec, Buy Now Pay Later, and PayShap RequestPayShap Request The request side of PayShap. Rather than the payer pushing money, the payee asks for it: the payer receives a request and approves it in their own banking app, and the funds move once they do. Enabled by Ozow on request rather than by default.payshap.co.za are enabled by Ozow on request. Once activated, they appear automatically on the payment page with no additional integration work required.


Step 4: Handle the notification response

Ozow posts a notification to your notifyUrl when a transaction completes. The notification is sent form-encoded with mime-type application/x-www-form-urlencoded.

Example notification

SiteCode=TSTSTE0001&TransactionId=c02dc1c9-a117-45cf-b375-d304cf434a52&TransactionReference=ORDER-001&Amount=100.00&Status=Complete&CurrencyCode=ZAR&IsTest=False&StatusMessage=&Hash=11fa4b11...&SubStatus=Unclassified

Verifying the notification hash

You must verify every notification before acting on it:

  1. Concatenate the fields below in this order, skipping any that are empty
  2. Append your private key to the concatenated string
  3. Convert the entire string to lowercase
  4. Generate a SHA512 hash of the lowercase string
  5. Compare your generated hash to the Hash value in the notification

Notification hash field order

Position Field
1 SiteCode
2 TransactionId
3 TransactionReference
4 Amount, with two decimal places
5 Status
6 Optional1
7 Optional2
8 Optional3
9 Optional4
10 Optional5
11 CurrencyCode
12 IsTest
13 StatusMessage
14 Your private key

Important

This is not the same order as the request hash, and it is not the order the fields appear in the notification body. CurrencyCode comes after the five optional fields here, and SubStatus and Hash are not part of the hash at all. Concatenate in the order above, not in the order you read them off the request.

Important

Never update an order status without first verifying the notification hash. Log and alert on verification failures: do not silently discard them.


Step 5: Confirm the transaction outcome

After verifying the notification hash, check the transaction status and update your order.

Transaction statuses

Status Description
Complete Payment completed successfully
Cancelled Customer cancelled the payment
Error An error occurred: check SubStatus for detail
PendingInvestigation Payment is under review: do not credit until resolved

SubStatus values

When a payment fails, the SubStatus field provides more detail. See Transaction and settlement statuses for the full SubStatus list.

You can also confirm transaction status directly via the API at any time:

By transaction reference

GET Get Transaction By Reference Reference
GET https://api.ozow.com/GetTransactionByReference?siteCode={siteCode}&transactionReference={transactionReference}
ApiKey: YOUR_API_KEY

By transaction ID

GET Get Transaction Reference
GET https://api.ozow.com/GetTransaction?siteCode={siteCode}&transactionId={transactionId}
ApiKey: YOUR_API_KEY

Note

Handle duplicate notifications idempotentlyIdempotency A request is idempotent when sending it twice has the same effect as sending it once. It matters most where a retry after a timeout could otherwise take a payment twice.IETF draft. Ozow may send the same notification more than once. Processing the same notification twice must not result in double-crediting an order.


Step 6: Cancel a payment

The Payments API does not support programmatic cancellation of a payment request via API. A payment can only be cancelled by the customer on the Ozow payment page. If the customer cancels, Ozow redirects them to your cancelUrl.


Optional features

Standalone button

A standalone button lets you surface a specific Ozow payment method as a dedicated button on your checkout page, taking the customer directly to that payment method.

Important

Do not display a standalone button for a payment method until you have received confirmation from Ozow that your account has been enabled for that payment method.

Digital wallets

Apple Pay and Google Pay cannot be offered as standalone buttons using this method. If you want to offer these as dedicated payment options at checkout, use the Wallet SDK.

Implementation

Include the SelectedBankId field in your payment request. The SelectedBankId for each payment method is available on the relevant Payment products page.

Hash field order

selectedBankId is field 18 in the concatenation order. Add it between isTest (field 17) and hashCheck (field 29) in the concatenated string. Only include it if you are using it.

{
  "siteCode": "YOUR_SITE_CODE",
  "countryCode": "ZA",
  "currencyCode": "ZAR",
  "amount": "100.00",
  "transactionReference": "ORDER-001",
  "bankReference": "ABC123",
  "cancelUrl": "https://yourstore.com/cancel",
  "errorUrl": "https://yourstore.com/error",
  "successUrl": "https://yourstore.com/success",
  "notifyUrl": "https://yourstore.com/notify",
  "isTest": false,
  "selectedBankId": "YOUR_BANK_ID",
  "hashCheck": "YOUR_GENERATED_HASH"
}

Customer Identity Verification

If your business operates in a high-risk industry, you are required to implement Customer Identity VerificationCustomer Identity Verification Checking that the payment instrument belongs to the natural person making the payment. Ozow requires it for merchants it has classified as high-risk, on Pay by Bank, Absa Pay, Capitec Pay, Nedbank Direct EFT, FNB Payment Requests and PayShap Request, and can disable those methods where it is not implemented correctly. before going live with Bank API payment methods.

To implement it in Payments API, pass the verified South African ID number or foreign passport number in the customerIdentifier field of the payment request:

{
  "siteCode": "YOUR_SITE_CODE",
  "countryCode": "ZA",
  "currencyCode": "ZAR",
  "amount": "100.00",
  "transactionReference": "ORDER-001",
  "bankReference": "ABC123",
  "cancelUrl": "https://yourstore.com/cancel",
  "errorUrl": "https://yourstore.com/error",
  "successUrl": "https://yourstore.com/success",
  "notifyUrl": "https://yourstore.com/notify",
  "isTest": false,
  "customerIdentifier": "0000000000000",
  "hashCheck": "YOUR_GENERATED_HASH"
}

Hash field order

customerIdentifier is field 27 in the concatenation order. Add it between variableAmountMax (field 26) and customerCellphoneNumber (field 28) in the concatenated string. If you are not using the fields between isTest and customerIdentifier, skip them; only include fields that have a value.

For full details on Customer Identity Verification requirements see Customer Identity Verification.


Next steps

In the API reference

4 entries

Last updated