This webhook is used to conclude a transaction. The user needs to be credited after making a successful purchase.
Carry1st Platform will sign the request, using Basic Auth credentials setup in the admin portal.
This webhook URL and Basic Auth credentials will be set in the product configuration in the Carry1st the admin portal.
The Platform will call the webhook URL to credit a user with purchased virtual currency.
The request includes a X-SIGNATURE header, generated by signing the request payload using the basic auth key. To verify the request, sign the request and verify the signature before crediting customers.
Request Signing
The signature is a hex encoded HMAC-SHA256 and is generated and sent using the X-SIGNATURE HTTP request header.
The signature can be generated using the following steps:
Get the payload JSON string as received in request
Trim all whitespace from either end of the data.
Generate a SHA-256 HMAC, using the payload JSON string, and the Basic Auth key. This is a Base64 encoded string of the Basic Auth credentials in the format username:password.
Hex encode the result HMAC. (note: In some cases (like PHP's hash_hmac function), the returned value is hex encoded by default, and this step is not required).
This will result in a 64 character length string.
Verify your string against the X-SIGNATURE header value
#!/bin/bash
KEY="YXBpdXNlcjphcGlwYXNzd29yZA=="
PAYLOAD="{\"reference\":\"C1st_d6213ccf-e838-4c42-9222-4356bb67a7a2\",\"playerId\":\"12345\",\"productBundleId\":1,\"amount\":1000,\"currency\":\"ZAR\",\"tokensPurchased\":11,\"digitalCurrency\":{\"name\":\"Credits\",\"code\":\"CRE\"},\"status\":\"SUCCESSFUL\"}"
echo -en "$PAYLOAD" \
| openssl sha256 -hmac "$KEY" \
| awk '{print $2}'
<?php
$payload = "{\"reference\":\"C1st_d6213ccf-e838-4c42-9222-4356bb67a7a2\",\"playerId\":\"12345\",\"productBundleId\":1,\"amount\":1000,\"currency\":\"ZAR\",\"tokensPurchased\":11,\"digitalCurrency\":{\"name\":\"Credits\",\"code\":\"CRE\"},\"status\":\"SUCCESSFUL\"}";
$key = "YXBpdXNlcjphcGlwYXNzd29yZA==";
echo hash_hmac('sha256', trim($payload), $key);
import java.nio.charset.Charset;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Hex;
public class Signature {
public static void main(String[] args) throws Exception {
String payload = "{\"reference\":\"C1st_d6213ccf-e838-4c42-9222-4356bb67a7a2\",\"playerId\":\"12345\",\"productBundleId\":1,\"amount\":1000,\"currency\":\"ZAR\",\"tokensPurchased\":11,\"digitalCurrency\":{\"name\":\"Credits\",\"code\":\"CRE\"},\"status\":\"SUCCESSFUL\"}";
String key = "YXBpdXNlcjphcGlwYXNzd29yZA==";
Mac hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(Charset.defaultCharset()), "HmacSHA256");
hmac.init(secretKeySpec);
String signature = new String(Hex.encodeHex(hmac.doFinal(String.format(payload).trim().getBytes(Charset.defaultCharset()))));
System.out.println(signature);
}
}
using System;
using System.Text;
using System.Security.Cryptography;
class Signature
{
public static void Main (string[] args)
{
string payload = "{\"reference\":\"C1st_d6213ccf-e838-4c42-9222-4356bb67a7a2\",\"playerId\":\"12345\",\"productBundleId\":1,\"amount\":1000,\"currency\":\"ZAR\",\"tokensPurchased\":11,\"digitalCurrency\":{\"name\":\"Credits\",\"code\":\"CRE\"},\"status\":\"SUCCESSFUL\"}";
string key = "YXBpdXNlcjphcGlwYXNzd29yZA==";
HMACSHA256 hmac = new HMACSHA256 (Encoding.Default.GetBytes (key));
byte[] hash = hmac.ComputeHash (Encoding.Default.GetBytes(payload).Trim()));
string signature = String.Concat(Array.ConvertAll(hash, x => x.ToString("X2")));
Console.Write (signature);
}
}
import hmac
import hashlib
key = 'YXBpdXNlcjphcGlwYXNzd29yZA=='
payload = '{"reference":"C1st_d63f1f41-d1f1-4521-9178-2c28cbe0ec9c","playerId":"selectiveplane71","productBundleId":1,"amount":1000,"currency":"ZAR","tokensPurchased":150,"digitalCurrency":{"name":"Carry1st Credits","code":"C1C"},"status”:”SUCCESSFUL”}'
print hmac.new(key, (payload).strip(), hashlib.sha256).hexdigest()
Field | Format | Description |
---|---|---|
reference | String | The payment unique reference. |
externalReference | String | The merchant unique reference that was passed in payment redirect. |
playerId | String | The user identifier. This should be a unique identifier used to identify the user in the game. |
productBundleId | Number | The bundle identifier as configured in Platform. |
productBundleExternalId | String | The bundle identifier for the Provider |
amount | Integer | The amount paid, in CENTS. |
currency | String | The currency code for amount paid. |
tokensPurchased | Number | The value of tokens purchased from the bundle. |
digitalCurrency | Digital Currency Object | The type of tokens purchased. |
status | String | The status of the transaction. |
POST: https://<webhook_url>
Body:
{
"reference": "C-12345679887665-P",
"externalReference": "EXT_REF",
"playerId": "12345",
"productBundleId": 1,
"productBundleExternalId": "1",
"amount": 1000,
"currency": "ZAR",
"tokensPurchased": 11,
"digitalCurrency": {
"name": "Credits",
"code": "CRE"
},
"status": "SUCCESSFUL"
}
Success Response:
200 - Success
208 - Already redeemed
Error Response:
400
{
"errorMessage": "ERROR_MESSAGE",
"errorCode": "ERROR_CODE"
}
If an error response is received, the request will be retried periodically for a period of 24 hours.
Statuses
Status | Description |
---|---|
NEW | Transaction created, but payment has not been processed. |
PENDING | Payment is processing. |
SUCCESSFUL | Payment has been completed successfully. |
FAILED | Payment has failed. |