3.1. Merchant Callbacks

When ENDPOINT is created for Merchant’s website callback URLs might be defined for any type of transaction type and transaction status.

These callback URLs will be called when the transaction is completed, whether approved, declined or reaching error or unknown state. This gives a Merchant better control how the transaction is processed on Merchant’s side, for example to add appropriate records to Merchant’s internal accounting system.

Please remember, callbacks are guaranteed to report merchant about transaction status. Merchants on their side must provide a means of preventing receiving the same callback twice - in case of network or other technical problems. It is recommended to check status, type, orderid and client_orderid to prevent duplication of transactions on merchant side.

3.1.1. Callback simple URL

If you want to make sure that the customer has paid for the item, you should specify a callback URL. If you do, Apropay sends an HTTP GET message to the callback URL whenever a purchase completed, no matter if the result is approved or declined. Your server needs to answer this GET message 200 OK status RFC, or else Apropay will continue to send the callback 30 times for 14 days applying the progressive timeline. Simple form of Sale or Return callback is just an URL to Merchant’s target page or script without any parameters, for example: https://www.i-cool-merchant.com/sale.php.

You can use only following ports in callback URL: * for HTTP 80, 8080 * for HTTPS 443, 8443

In this case the system automatically adds the following parameters to callback URL.

Also there is a notify_url parameter, which can be used instead of server_callback_url parameter if you want to receive every notification when transaction receives one of the new Types of Transactions, for example reversal or chargeback. In this case there is no need to set callback url manually at the endpoint level for each transaction type.

Callback Parameters

Apropay Callback Parameter Description
status See Status List for details.
merchant_order Merchant order identifier, client_orderid
client_orderid Merchant order identifier
orderid Apropay transaction id
type Transaction type, sale reversal chargeback
amount Actual transaction amount. This value can be changed during the transaction flow.
currency Transaction currency
descriptor Payment descriptor of the gate through which the transaction has been processed.
original-gate-descriptor Descriptor, which is set on gate level in the system.
error_code Error Code
error_message Error Message
name Cardholder Name
email Customer’s email
first-name Customer’s first name
last-name Customer’s last name
country * Customer’s country (two-letter country code). Please see Country Codes for a list of valid country codes.
state * Customer’s state . Please see Country Codes for a list of valid state codes. Mandatory for USA, Canada and Australia.
city * Customer’s city
zip_code * Customer’s ZIP code
address1 * Customer’s address line 1
approval-code Authorization approval code, if any
last-four-digits Last four digits of customer credit card number.
bin Bank BIN of customer credit card.
card-type Type of customer credit card (VISA, MASTERCARD, etc).
phone Customer phone number.
bank-name Customer bank name.
card-exp-month Card expiration month.
card-exp-year Card expiration year.
gate-partial-reversal Processing gate support partial reversal (enabled or disabled).
gate-partial-capture Processing gate support partial capture (enabled or disabled).
reason-code Reason code for chargeback or fraud operation.
processor-rrn Bank Retrieval Reference Number.
comment Comment in case of Return transaction
rapida-balance Current balance for merchants registered in Rapida system (only if balance check active)
control Checksum is used to ensure that it is Apropay (and not a fraudster) that initiates the callback for a particular Merchant. This is SHA-1 checksum of the concatenation status + orderid + merchant_order + merchant_control. The callback script MUST check this parameter by comparing it to SHA-1 checksum of the above concatenation. See Callback authorization through control parameter for more details about generating control checksum.
merchantdata The value passed by merchant in initial request.
serial-number Serial number of the request.
processor-tx-id Transaction id set by processor.
processor-auth-credit-code Reserved
card-hash-id Unique hash of the particular card, does not change.
verified-3d-status Will return AUTHENTICATED if a transaction was approved by 3DS.
processor-credit-rrn Retrieval Reference Number set by acquirer.
processor-credit-arn Acquirer card reference number for credit card.
processor-debit-arn Acquirer card reference number for debit card.
eci Electronic Commerce Indicator (Visa).
ips-src-payment-product-code Code for card set by multinational financial service. (Visa/Mastercard).
ips-src-payment-product-name Decrypted code for card set by multinational financial service. (Visa/Mastercard).
ips-src-payment-type-code Type of card code set by multinational financial service. (Visa/Mastercard).
ips-src-payment-type-name Decrypted code for type of card set by multinational financial service. (Visa/Mastercard)
card-country-alpha-three-code Three letter country code of source card issuer. See Country Codes for details
destination-card-country-alpha-three-code Three letter country code of destination card issuer. See Country Codes for details
initial-amount Amount, set in initiating transaction, without any fees or commissions. This value can’t change during the transaction flow.
seller-commission Total commission for processed transaction. This is optional parameter. Please contact your manager in Apropay, if you would like to receive it.
acquirer-commission Acquirer commission for processed transaction. This is optional parameter. Please contact your manager in Apropay, if you would like to receive it.
exchange-rate Basic exchange rate for currency conversion.
effective-exchange-rate Actual exchange rate, applied during currency conversion.
transaction-date Time and date of transaction’s final status.
motivational-message This is an optional message which contains extended information about the reason for the declined transaction.
orig-amount Contains the original request amount if it was converted on auxiliary endpoint in Parallel form integration.
orig-currency Contains the original request currency if it was converted on auxiliary endpoint in Parallel form integration.

Note

* - these parameters are not defined by default. Please contact tech support to include these fields in callback.

3.1.2. Сustomizable callback URL

Customizable callback URL is a fully defined URL with all the parameters Merchant’s target page or script would require. Customizable URL allows defining Merchant’s own parameter names, whereas the actual parameters values are defined by use of macros with the following format ${parameter_name}. Thus Apropay substitutes respective parameter values into final customized URL before calling it.

Example:

https://www.i-cool-merchant.com/sale_completed.php?cardholder_name= ${name}&tx_status=${status}&order_id=${merchant_order}

Callback Macros

Apropay Callback Macros name Description
${status} Transaction status, approved declined processing
${merchant_order} Merchant order identifier, client_orderid
${orderid} Apropay transaction id
${type} Transaction type, sale return chargeback
${amount} Transaction amount
${descriptor} Payment descriptor of the gate through which the transaction has been processed.
${error_message} Error message: when ${status} meaning declined
${name} Cardholder Name
${email} Customer’s email
${last-four-digits} Last four digits of customer credit card number.
${bin} Bank BIN of customer credit card.
${card-type} Type of customer credit card (VISA, MASTERCARD, etc).
${card-exp-month} Card expiration month.
${card-exp-year} Card expiration year.
${gate-partial-reversal} Processing gate support partial reversal (enabled or disabled).
${gate-partial-capture} Processing gate support partial capture (enabled or disabled).
${reason-code} Reason code for chargebak or fraud operation.
${processor-rrn} Bank Retrieval Reference Number.
${approval-code} Bank approval code.
${comment} Comment in case of Return transaction
${rapida-balance} Current balance for merchants registered in Rapida system (only if balance check active)
${control} Checksum is used to ensure that it is Apropay (and not a fraudster) that initiates the callback for a particular Merchant. This is SHA-1 checksum of the concatenation status + orderid + merchant_order + merchant_control. The callback script MUST check this parameter by comparing it to SHA-1 checksum of the above concatenation. See Callback authorization through control parameter for more details about generating control checksum.
${merchantdata} The value passed by merchant in initial request.

3.1.3. Additional callback for manager

Additional callback can be configured at the endpoint level by using Create Callback utility. To set up new callback, click the “Add Callback” button. There are several parameters can be defined in the window:

  • Transaction type
  • URL address - is the fully defined URL with all the parameters Manager’s target page or script would require. Example: https://www.manager.com/sale_completed
  • Comment if it is required
  • Name and System Parameters. Name - is the manually specified parameter name to be sent in callback, System Parameters - is the one of the selected system parameter values.
pic68 merchant_callback

The table below describes the callback system parameters.

Callback parameter name Comment
endpoint_id ID of the used endpoint
gate_id ID of the used gate
manager_id ID of the manager
merchant_id ID of the merchant
processor_id ID of the used processor
project_id ID of the project
system_currency_rate_coefficient_on_gate Currency conversion rate used in processing of this transaction

3.1.4. Callback authorization through control parameter

The checksum is used to ensure that the callback is sent to the merchant by Apropay, and not by a fraudster. WARNING! If Merchant does not check the “control” parameter in the callback script, a fraudster might use the callback URL to carry out fraudulent activities on the Merchant’s system. This SHA-1 checksum (the “control” parameter) is created by concatenation of the parameters’ values in the following order:

  • status
  • orderid
  • merchant_order
  • merchant_control_key

The complete string example may look as follows:

approved123invoice-1AF4B5DE6-3468-424C-A922-C1DAD7CB4509

Encrypt the string using SHA-1 algorithm. The resultant string yields the “control” parameter which is required for authorizing the callback. For the example the “control” above will take the following value:

5bc8ee48f9ba37c0fd1e0b052a9bc105c6df87e1

3.1.5. Callback to Status Parameters Mapping

The following table contains a correspondence between callback parameters and status response fields.

Callback parameter Name Status parameter Name
amount amount
approval-code approval-code
bin bin
card-type card-type
last-four-digits last-four-digits
bank-name bank-name
name name
first-name first-name
last-name last-name
country country
state state
city city
zip_code zip_code
address1 address1
card-exp-month card-exp-month
card-exp-year card-exp-year
client_orderid merchant-order-id
comment comment
descriptor descriptor
dest-bin dest-bin
dest-card-type dest-card-type
dest-last-four-digits dest-last-four-digits
dest-bank-name dest-bank-name
email email
purpose purpose
error_code error-code
error_message error-message
gate-partial-capture gate-partial-capture
gate-partial-reversal gate-partial-reversal
loyalty-balance loyalty-balance
loyalty-bonus loyalty-bonus
loyalty-message loyalty-message
loyalty-program loyalty-program
merchant_order merchant-order-id
merchantdata merchantdata
orderid paynet-order-id
original-gate-descriptor original-gate-descriptor
phone phone
processor-rrn processor-rrn
processor-tx-id processor-tx-id
rapida-balance rapida-balance
reason-code reason-code
serial-number serial-number
status status
type transaction-type
initial-amount initial-amount
seller-commission seller-commission
acquirer-commission acquirer-commission
exchange-rate exchange-rate
effective-exchange-rate effective-exchange-rate
card-country-alpha-three-code card-country-alpha-three-code
destination-card-country-alpha-three-code destination-card-country-alpha-three-code

3.1.6. Callback Signature check example on Java

You may see an example how to check the callback signature using JAVA programming language below:

import org.junit.Test;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import static org.junit.Assert.assertEquals;

public class TestCallbackSignatureExampleTest {

    @Test
    public void test() {
        String digest3 = calculateCallbackSignature("approved", 123, "invoice-1", "AF4B5DE6-3468-424C-A922-C1DAD7CB4509");
        assertEquals("5bc8ee48f9ba37c0fd1e0b052a9bc105c6df87e1", digest3);
    }

    public String calculateCallbackSignature(String aTransactionStatus, long aOrderId, String aMerchantOrderId, String aMerchantControlKey) {
        String text   = aTransactionStatus + aOrderId + aMerchantOrderId + aMerchantControlKey;
        byte[] buffer = text.getBytes(StandardCharsets.UTF_8);
        byte[] shaSum = sha(buffer);
        return toHexString(shaSum);
    }

    /**
    * Calculates the SHA-1 digest and returns the value as a <code>byte[]</code>.
    *
    * @param data
    *            Data to digest
    * @return SHA-1 digest
    */
    private static byte[] sha(byte[] data) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA");
            return digest.digest(data);
        } catch (NoSuchAlgorithmException e) {
           throw new IllegalStateException("Couldn't calculate SHA-1 digest", e);
        }
    }

    /**
     * Converts bytes to hex string
     */
    private static String toHexString(byte[] data) {
        StringBuilder sb = new StringBuilder();
        for (byte b : data) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }

}