Step 1 : Post from merchant website
After the user confirms his purchase and has chosen Ozow as his preferred payment method, you will need to post the following variables to https://pay.ozow.com/.
Please note
Variables 18-26 are not commonly used and can be ignored unless you specifically require that functionality.
Post variables
Property | Type | Req. | Description |
---|---|---|---|
1.SiteCode | String (50) | Yes | A unique code for the site currently in use. A site code is generated when adding a site in the Ozow merchant admin section. |
2.CountryCode | String (2) | Yes | The ISO 3166-1 alpha-2 code for the user's country. The country code will determine which banks will be displayed to the customer. Please note only South African (ZA) banks are currently supported by Ozow. |
3.CurrencyCode | String (3) | Yes | The ISO 4217 three-letter code for the transaction currency. Please note only the South African Rand (ZAR) is currently supported by Ozow, so any currency conversion must take place before posting to the Ozow site. |
4.Amount | Decimal (9,2) | Yes | The transaction amount. The amount is in the currency specified by the currency code posted. |
5.TransactionReference | String (50) | Yes | The merchant's reference for the transaction. |
6.BankReference | String (20) | Yes | The reference that will be pre-populated in the "their reference" field in the customers online banking site. This is the payment reference that appears on the merchant’s bank statement and can be used for recon purposes. Only alphanumeric characters, spaces, and dashes are allowed. |
7.Optional1 8. Optional2 9. Optional3 10. Optional4 11. Optional5 | String (50) | No | Optional fields the merchant can post for additional information they would need passed back in the response. These are also stored with the transaction details by Ozow, and can be useful for filtering transactions in the merchant admin section. |
12.Customer | String (100) | No | The customer’s name or identifier. |
13.CancelUrl | String (150) | No | The URL to which the redirect result should be posted to if the customer cancels the payment. This is also the page the customer will be redirected to. This URL can also be set for the applicable merchant site in the merchant admin section. If a value is set in the merchant admin and sent in the post, the posted value will be redirected to if the payment is cancelled. |
14.ErrorUrl | String (150) | No | The URL to which the redirect result should be posted if an error occurs while trying to process the payment. This is also the page the customer will be redirected to. This URL can also be set for the applicable merchant site in the merchant admin section. If a value is set in the merchant admin and sent in the post, the posted value will be redirected to if an error occurred while processing the payment. |
15.SuccessUrl | String (150) | No | The URL to which the redirect result should be posted to if the payment is successful. This is also be the page the customer gets redirected to. This URL can also be set for the applicable merchant site in the merchant admin section. If a value is set in the merchant admin and sent in the post, the posted value will be redirected to if the payment was successful. Please note that it is not sufficient to assume that the payment was successful simply because the customer has been redirected back to this page. It is highly recommended that you check the response fields as well as the transaction status using our check transaction status API call. |
16.NotifyUrl | String (150) | No | The URL that the notification result should be posted to. The result will post regardless of the outcome of the transaction. This URL can also be set for the applicable merchant site in the merchant admin section. If a value is set in the merchant admin and sent in the post, the notification result will be sent to the posted value. Find out more in the notification response section in step 2. |
17.IsTest | bool | Yes | Accepted values are true or false. Send true to test your request posting and response handling. If set to true you will be redirected to select whether you would like a successful or unsuccessful redirect response sent back. Please note that notification responses are sent for test transactions and the online banking payment is skipped. |
18.SelectedBankId | Guid | No | If the 'SelectedBankId' field is populated by the Merchant, the Customer will be redirected to the Ozow login page of the selected bank. However, if the field is left empty, the Customer will be presented with Ozow bank selection screen. Allowed values are: • ABSA – 3284A0AD-BA78-4838-8C2B-102981286A2B • Capitec – 913999FA-3A32-4E3D-82F0-A1DF7E9E4F7B • FNB – 4816019C-3314-4C80-8B6B-B2CD16DCC4EC • Nedbank – D3889DF6-CDAC-4861-9D64-2B100FB7ED07 • Standard Bank – AD8127C6-316D-459C-ADCC-E62A214251FC • Investec – 4B45BE85-B616-4BD1-9027-F8FCF8F9AF7B • African Bank – 33A0840B-0CF4-4B8C-86E0-EC6C4BE8C60E • Tymebank – 28FCC8FA-985B-480B-82FD-7D09BC19C9D0 • Bidvest Bank Grow – E022DFC8-FF4A-4425-A074-C65D07E8F09C • Cash Voucher – 42F71BF8-0E09-43D5-A6EB-4F7370CB5B20 |
19.BankId | Guid | No | The bank that the payment should be made to. Merchant needs to be enabled to send through banking details (18 - 21) in the post, for most merchants this is set up when creating the merchant account. Allowed values are: • ABSA – 3284A0AD-BA78-4838-8C2B-102981286A2B • Capitec – 913999FA-3A32-4E3D-82F0-A1DF7E9E4F7B • FNB – 4816019C-3314-4C80-8B6B-B2CD16DCC4EC • Nedbank – D3889DF6-CDAC-4861-9D64-2B100FB7ED07 • Standard Bank – AD7D8DA4-1723-4066-94BB-6662D845E483 • Investec – 4B45BE85-B616-4BD1-9027-F8FCF8F9AF7B • African Bank – 33A0840B-0CF4-4B8C-86E0-EC6C4BE8C60E • Tymebank – 28FCC8FA-985B-480B-82FD-7D09BC19C9D0 • Bidvest Bank Grow – E022DFC8-FF4A-4425-A074-C65D07E8F09C |
20.BankAccountNumber | String (20) | No | The bank account number the payment should be made to. |
21.BranchCode | String (10) | No | The branch code for the bank account (19). |
22.BankAccountName | String (50) | No | The name to be used for the bank account. Only alphanumeric characters and spaces allowed. |
23.PayeeDisplayName | String (50) | No | The name shown on the site as the entity being paid (not in banking screens). |
24.ExpiryDateUtc | String (19) | No | Payment will not be allowed to be made after this date. Date should be UTC and value should be formatted as yyyy-MM-dd HH:mm e.g. 2015-08-11 16:02 |
25.AllowVariableAmount | bool | No | Allows the user to change the amount passed through before paying. This option must also be enabled for the site in the merchant admin portal to be used. Accepted values are true or false. DO NOT include false in the hash check string, just ignore instead. |
26.VariableAmountMin | Decimal (9,2) | No | If AllowVariableAmount is passed through as true, this will dictate the lowest acceptable amount the user can enter. |
27.VariableAmountMax | Decimal (9,2) | No | If AllowVariableAmount is passed through as true, this will dictate the highest acceptable amount the user can enter. |
28.CustomerIdentifier | String (13) | No | Merchants classified as high-risk must provide a valid South African identity number. It's important to note that this is an optional field for all other merchants. For more details, please reach out to [email protected]. |
29. CustomerCellphoneNumber | String (10) | No | Merchant can provide customer cellphone number for faster login on certain banks. DO NOT include in the hash check string, just ignore instead. |
30.HashCheck | String (250) | Yes | SHA512 hash used to ensure that certain fields in the message have not been altered after the hash was generated. Check the generate hash section below for more details on how to generate the hash. |
Follow these steps to generate the hash check:
- Concatenate the post variables (excluding
HashCheck
andToken
) in the order they appear in the post variables table. - Append your private key to the concatenated string. Your private key can be found in merchant details section of the merchant admin site.
- Convert the concatenated string to lowercase.
- Generate a SHA512 hash of the lowercase concatenated string.
Hash check example
SiteCode: TSTSTE0001
CountryCode: ZA
CurrencyCode: ZAR
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
- TSTSTE0001ZAZAR25.00123ABC123http://demo.ozow.com/cancel.aspxhttp://demo.ozow.com/cancel.ashttp://demo.ozow.com/success.aspxhttp://demo.ozow.com/notify.aspxfalse
- TSTSTE0001ZAZAR25.00123ABC123http://demo.ozow.com/cancel.aspxhttp://demo.ozow.com/cancel.aspxhttp://demo.ozow.com/success.aspxhttp://demo.ozow.com/notify.aspxfalse[YOUR PRIVATE KEY]
- tstste0001zazar25.00123abc123[http://demo.ozow.com/cancel.aspxhttp://demo.ozow.com/cancel.aspxht]http://demo.ozow.com/success.aspx(http://demo.ozow.com/notify.aspxfalse[your private key]
- eedcba106cd8fef3ba6cec5ec80de7d7d7fc90343028bf95b908718c671d0fe885ca08b206d788de009d237a93c18e66edf6ede3f5ca7057e23474106465dcc6
using System.Security.Cryptography;
using System.Text;
using System;
GenerateRequestHash();
void GenerateRequestHash()
{
string siteCode = "[YOUR SITE CODE]";
string countryCode = "ZA";
string currencyCode = "ZAR";
decimal amount = 25.01M;
string transactionReference = "123";
string bankReference = "ABC123";
string cancelUrl = "http://mydomain.com/cancel.html";
string errorUrl = "http://mydomain.com/error.html";
string successUrl = "http://mydomain.com/success.html";
string notifyUrl = "http://mydomain/notify.html";
string privateKey = "[YOUR PRIVATE KEY]";
bool isTest = false;
string inputString = string.Concat(siteCode, countryCode, currencyCode, amount, transactionReference, bankReference, cancelUrl, errorUrl, successUrl, notifyUrl, isTest, privateKey);
string calculatedHashResult = GenerateRequestHashCheck(inputString);
Console.WriteLine($"Hashcheck: {calculatedHashResult}");
}
string GenerateRequestHashCheck(string inputString)
{
var stringToHash = inputString.ToLower();
Console.WriteLine($"Before Hashcheck: {stringToHash}");
return GetSha512Hash(stringToHash);
}
string GetSha512Hash(string stringToHash)
{
using (SHA512 alg = new SHA512CryptoServiceProvider())
{
var bytes = alg.ComputeHash(Encoding.UTF8.GetBytes(stringToHash));
var sb = new StringBuilder();
foreach (var b in bytes)
{
var hex = b.ToString("x2");
sb.Append(hex);
}
return sb.ToString();
}
}
<?php
function generate_request_hash() {
$siteCode = "[YOUR SITE CODE]";
$countryCode = "ZA";
$currencyCode = "ZAR";
$amount = 25.01;
$transactionReference = "123";
$bankReference = "ABC123";
$cancelUrl = "http://mydomain.com/cancel.html";
$errorUrl = "http://mydomain.com/error.html";
$successUrl = "http://mydomain.com/success.html";
$notifyUrl = "http://mydomain/notify.html";
$privateKey = "[YOUR PRIVATE KEY]";
$isTest = "false";
$inputString = $siteCode . $countryCode . $currencyCode . $amount . $transactionReference . $bankReference . $cancelUrl . $errorUrl . $successUrl . $notifyUrl . $isTest . $privateKey;
$calculatedHashResult = generate_request_hash_check($inputString);
echo "Hashcheck: " . $calculatedHashResult . "\n";
}
function generate_request_hash_check($inputString) {
$stringToHash = strtolower($inputString);
echo "Before Hashcheck: " . $stringToHash . "\n";
return get_sha512_hash($stringToHash);
}
function get_sha512_hash($stringToHash) {
$bytes = hash('sha512', $stringToHash, true);
$hex = bin2hex($bytes);
return $hex;
}
generate_request_hash();
?>
const crypto = require("crypto");
function generateRequestHash() {
const siteCode = "[YOUR SITE CODE]";
const countryCode = "ZA";
const currencyCode = "ZAR";
const amount = 25.01;
const transactionReference = "123";
const bankReference = "ABC123";
const cancelUrl = "http://mydomain.com/cancel.html";
const errorUrl = "http://mydomain.com/error.html";
const successUrl = "http://mydomain.com/success.html";
const notifyUrl = "http://mydomain/notify.html";
const privateKey = "[YOUR PRIVATE KEY]";
const isTest = false;
const inputString = `${siteCode}${countryCode}${currencyCode}${amount}${transactionReference}${bankReference}${cancelUrl}${errorUrl}${successUrl}${notifyUrl}${isTest}${privateKey}`;
const calculatedHashResult = generateRequestHashCheck(inputString);
console.log(`Hashcheck: ${calculatedHashResult}`);
}
function generateRequestHashCheck(inputString) {
const stringToHash = inputString.toLowerCase();
console.log(`Before Hashcheck: ${stringToHash}`);
return getSha512Hash(stringToHash);
}
function getSha512Hash(stringToHash) {
const hash = crypto.createHash("sha512");
hash.update(stringToHash);
return hash.digest("hex");
}
generateRequestHash();
import hashlib
import string
def generate_request_hash():
site_code = '[YOUR SITE CODE]'
country_code = 'ZA'
currency_code = 'ZAR'
amount = 25.01
transaction_reference = '123'
bank_reference = 'ABC123'
cancel_url = 'http://mydomain.com/cancel.html'
error_url = 'http://mydomain.com/error.html'
success_url = 'http://mydomain.com/success.html'
notify_url = 'http://mydomain/notify.html'
private_key = '[YOUR PRIVATE KEY]'
is_test = False
input_string = site_code + country_code + currency_code + str(amount) + transaction_reference + bank_reference + cancel_url + error_url + success_url + notify_url + str(is_test) + private_key
input_string = input_string.lower()
calculated_hash_result = generate_request_hash_check(input_string)
print(f"Hashcheck: {calculated_hash_result}")
def generate_request_hash_check(input_string):
print(f"Before Hashcheck: {input_string}")
return get_sha512_hash(input_string)
def get_sha512_hash(input_string):
sha = hashlib.sha512()
sha.update(input_string.encode())
return sha.hexdigest()
generate_request_hash()
Generate payment URL using API
https://api.ozow.com/PostPaymentRequest
This method is called when you want to generate a payment URL that will be included in an email or SMS.
Parameters
Property | Type | Req. | Description |
---|---|---|---|
ApiKey (Http request header value) | String (50) | Yes | Merchant's API key, this value is available in the Ozow merchant admin section. |
Content-Type (Http request header value) | String (50) | Yes | Format of your post data object. Available values: • application/json – post data object is a JSON string • application/xml - post data object is a XML string |
Accept (Http request header value) | String (50) | Yes | Determines the format the response is returned in. Available values: • application/json - Response is returned as JSON • application/xml - Response is returned as XML |
Post data object | String (JSON / XML) | Yes | Applicable post variables found in post variables table above as either a serialised json object or XML element e.g. { "SiteCode": "TSTSTE0001", …, "HashCheck": "6b46c27agfd4656fg3534gfd435”} If you are using this to generate a link that will be used for SMS, email or for QR codes you need to pass an extra Boolean variable in the post data object i.e. GenerateShortUrl with a value of true. This extra field should not be used to generate the hash. e.g. { …, " GenerateShortUrl ": true } |
<?php
$curl = curl_init();
$data = [
"countryCode" => "ZA",
"amount" => "0.01",
"transactionReference" => "Test1",
"bankReference" => "Test1",
"cancelUrl" => "http://test.i-pay.co.za/responsetest.php",
"currencyCode" => "ZAR",
"errorUrl" => "http://test.i-pay.co.za/responsetest.php",
"isTest" => false,
"notifyUrl" => "http://test.i-pay.co.za/responsetest.php",
"siteCode" => "[YOUR SITECODE]",
"successUrl" => "http://test.i-pay.co.za/responsetest.php",
"hashCheck" => "[GENERATED HASH]"
];
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ozow.com/postpaymentrequest',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => array(
'Accept: application/json',
'ApiKey:[API KEY HERE]',
'Content-Type: application/json'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
var client = new RestClient("https://api.ozow.com/postpaymentrequest");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Accept", "application/json");
request.AddHeader("ApiKey", "[API KEY HERE]");
request.AddHeader("Content-Type", "application/json");
var data = new
{
countryCode = "ZA",
amount = "0.01",
transactionReference = "Test1",
bankReference = "Test1",
cancelUrl = "http://test.i-pay.co.za/responsetest.php",
currencyCode = "ZAR",
errorUrl = "http://test.i-pay.co.za/responsetest.php",
isTest = false,
notifyUrl = "http://test.i-pay.co.za/responsetest.php",
siteCode = "[YOUR SITECODE]",
successUrl = "http://test.i-pay.co.za/responsetest.php",
hashCheck = "[GENERATED HASH]"
};
var json = JsonConvert.SerializeObject(data);
request.AddParameter("application/json", json, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);
import json
import requests
url = "https://api.ozow.com/postpaymentrequest"
headers = {
"Accept": "application/json",
"ApiKey": "[API KEY HERE]",
"Content-Type": "application/json"
}
data = {
"countryCode": "ZA",
"amount": "0.01",
"transactionReference": "Test1",
"bankReference": "Test1",
"cancelUrl": "http://test.i-pay.co.za/responsetest.php",
"currencyCode": "ZAR",
"errorUrl": "http://test.i-pay.co.za/responsetest.php",
"isTest": False,
"notifyUrl": "http://test.i-pay.co.za/responsetest.php",
"siteCode": "[YOUR SITECODE]",
"successUrl": "http://test.i-pay.co.za/responsetest.php",
"hashCheck": "[GENERATED HASH]"
}
response = requests.post(url, headers=headers, json=data)
print(response.text)
const data = {
countryCode: "ZA",
amount: "0.01",
transactionReference: "Test1",
bankReference: "Test1",
cancelUrl: "http://test.i-pay.co.za/responsetest.php",
currencyCode: "ZAR",
errorUrl: "http://test.i-pay.co.za/responsetest.php",
isTest: false,
notifyUrl: "http://test.i-pay.co.za/responsetest.php",
siteCode: "[YOUR SITECODE]",
successUrl: "http://test.i-pay.co.za/responsetest.php",
hashCheck: "[GENERATED HASH]"
};
const options = {
method: 'POST',
headers: {
'Accept': 'application/json',
'ApiKey': '[API KEY HERE]',
'Content-Type': 'application/json',
},
body: JSON.stringify(data)
};
fetch('https://api.ozow.com/postpaymentrequest', options)
.then(response => response.text())
.then(data => console.log(data))
.catch(error => console.error(error));
Response
PaymentRequestResult
- A successful call will return a PaymentRequestResult object. The PaymentRequestResult object is described below.
Property | Type | Description |
---|---|---|
PaymentRequestId | String (50) | Ozow's unique identifier for the payment request. |
URL | String (50) | Generated URL that allows payment for the posted variables used to create the payment request. The payment Url you'll receive from the API is dynamic. Please do not hard code it into your integrations as it might change. |
ErrorMessage | String (50) | Error message generated when validating the request |
Sample response JSON
{
"paymentRequestId": "00000000-0000-0000-0000-000000000000",
"url": "https://pay.ozow.com/00000000-0000-0000-0000-000000000000/Secure",
"errorMessage": null
}
Updated 11 months ago