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()
FieldFormatDescription
referenceStringThe payment unique reference.
externalReferenceStringThe merchant unique reference that was passed in payment redirect.
playerIdStringThe user identifier. This should be a unique identifier used to identify the user in the game.
productBundleIdNumberThe bundle identifier as configured in Platform.
productBundleExternalIdStringThe bundle identifier for the Provider
amountIntegerThe amount paid, in CENTS.
currencyStringThe currency code for amount paid.
tokensPurchasedNumberThe value of tokens purchased from the bundle.
digitalCurrencyDigital Currency ObjectThe type of tokens purchased.
statusStringThe 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

StatusDescription
NEWTransaction created, but payment has not been processed.
PENDINGPayment is processing.
SUCCESSFULPayment has been completed successfully.
FAILEDPayment has failed.