.. _merchant_callbacks: Connecting Party Callbacks #################################################### .. contents:: :local: .. role:: ex .. role:: code General information ====================================================== If Connecting Party specified a callback URL, Payment Gateway sends an :ex:`HTTP GET` message to the callback URL whenever transaction reaches final status, no matter if the result is :ex:`approved`, :ex:`declined` or other :ref:`final status`. This gives Connecting Party better control of how the transaction is processed, for example to add appropriate records to Connecting Party internal accounting system. .. warning:: Connecting Party server needs to respond to this :ex:`GET` request with :code:`200 OK` status |rfc_link|, or else Payment Gateway will continue to send the callback 30 times for 14 days applying the progressive timeline. .. |rfc_link| raw:: html RFC Please remember, callbacks are guaranteed to report Connecting Party about transaction status. Connecting Party 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 :code:`status`, :code:`type`, :code:`orderid` and :code:`client_orderid` to prevent duplication of transactions on Connecting Party side. Callback URLs can be specified by Connecting Party in the following ways: * By sending :code:`server_callback_url` or :code:`notify_url` in initial transaction request. If :code:`server_callback_url` is sent, Connecting Party will receive a callback only for the initial transaction (ex. sale approved). If :code:`notify_url` is sent instead, Connecting Party will receive a callback for the initial transaction (ex. sale approved) and for any new transaction types applied to the same transaction (ex. reversal, chargeback). * By specifying the callback URL on endpoint level. Each transaction type can have it's own callback URL. Only the following ports are allowed in callback URL: * for :ex:`HTTP` 80, 8080 * for :ex:`HTTPS` 443, 8443 Customizable Callback URL ======================================================== | Simple callback URL contains all parameters listed in :ref:`Callback Parameters`. | Customizable callback URL is a fully defined URL with all the parameters Connecting Party target page or script would require. Customizable URL allows Connecting Party to define own parameter names, whereas the actual parameters values are defined by use of macros with the following format :code:`${parameter_name}`. Thus gate.payneteasy.com substitutes respective parameter values into final customized URL before calling it. Available macros are listed in :ref:`Callback Macros`. Example of simple callback URL: :code:`https://connectingparty.com/sale_completed.php` Example of customized callback URL: :code:`https://connectingparty.com/sale_completed.php?cardholder_name=${name}&tx_status=${status}&order_id=${merchant_order}` .. _merchant_callback_parameters: Callback Parameters ================================================== .. note:: | The system automatically adds the following parameters to callback URL. | * - these parameters are not defined by default. Please contact tech support to include these fields in callback. .. list-table:: :widths: 30, 70 :header-rows: 1 :class: longtable * - Callback Parameter - Description * - :code:`status` - See :ref:`status_list` for details. * - :code:`merchant_order` - Connecting Party order identifier, same as :ex:`client_orderid`. * - :code:`client_orderid` - Connecting Party order identifier. * - :code:`orderid` - gate.payneteasy.com transaction id. * - :code:`type` - Transaction type, :ex:`sale` :ex:`reversal` :ex:`chargeback` * - :code:`amount` - Actual transaction amount. This value can be changed during the transaction flow. * - :code:`currency` - Transaction currency. * - :code:`descriptor` - Payment descriptor of the gate through which the transaction has been processed. * - :code:`error_code` - Error Code. This field won't be included in callback in case transaction :code:`status=approved`. * - :code:`error_message` - Error Message. This field won't be included in callback in case transaction :code:`status=approved`. * - :code:`name` - Cardholder Name. * - :code:`email` - Payer's email. * - :code:`country` * - Payer’s country (two-letter country code). Please see :ref:`country-state-codes` for a list of valid country codes. * - :code:`state` * - Payer’s state . Please see :ref:`country-state-codes` for a list of valid state codes. Mandatory for USA, Canada and Australia. * - :code:`city` * - Payer’s city. * - :code:`zip_code` * - Payer’s ZIP code. * - :code:`address1` * - Payer’s address line 1. * - :code:`approval-code` - Authorization approval code, if any. * - :code:`last-four-digits` - Last four digits of Payer's credit card number. * - :code:`bin` - Bank BIN of Payer's credit card. * - :code:`card-type` - Type of Payer's credit card (:ex:`VISA`, :ex:`MASTERCARD`, etc). * - :code:`phone` - Payer's phone number. * - :code:`bank-name` - Payer's bank name. * - :code:`card-exp-month` - Card expiration month. * - :code:`card-exp-year` - Card expiration year. * - :code:`gate-partial-reversal` - Processing gate support partial reversal (enabled or disabled). * - :code:`gate-partial-capture` - Processing gate support partial capture (enabled or disabled). * - :code:`reason-code` - Reason code for chargeback or fraud operation. * - :code:`processor-rrn` - Bank Retrieval Reference Number. * - :code:`comment` - Comment in case of Return transaction * - :code:`rapida-balance` - Current balance for Connecting Party registered in Rapida system (only if balance check active) * - :code:`control` - Checksum is used to ensure that it is gate.payneteasy.com (and not a fraudster) that initiates the callback to Connecting Party. This is :ex:`SHA-1` checksum of the concatenation :ex:`status` + :ex:`orderid` + :ex:`merchant_order` + :ex:`merchant_control`. The callback script MUST check this parameter by comparing it to :ex:`SHA-1` checksum of the above concatenation. * - :code:`merchantdata` - The value passed by Connecting Party in initial request. * - :code:`serial-number` - Serial number of the request. * - :code:`processor-tx-id` - Transaction id set by processor. * - :code:`processor-auth-credit-code` - Reserved * - :code:`card-hash-id` - Unique hash of the particular card, does not change. * - :code:`verified-3d-status` - Will return :ex:`AUTHENTICATED` if a transaction was approved by 3DS. * - :code:`processor-credit-rrn` - Retrieval Reference Number set by acquirer. * - :code:`processor-credit-arn` - Acquirer card reference number for credit card. * - :code:`processor-debit-arn` - Acquirer card reference number for debit card. * - :code:`eci` - Electronic Commerce Indicator (Visa). * - :code:`ips-src-payment-product-code` - Code for card set by multinational financial service. (Visa/Mastercard). * - :code:`ips-src-payment-product-name` - Decrypted code for card set by multinational financial service. (Visa/Mastercard). * - :code:`ips-src-payment-type-code` - Type of card code set by multinational financial service. (Visa/Mastercard). * - :code:`ips-src-payment-type-name` - Decrypted code for type of card set by multinational financial service. (Visa/Mastercard). * - :code:`card-country-alpha-three-code` - Three letter country code of source card issuer. See :ref:`Card Country Codes` for details. * - :code:`destination-card-country-alpha-three-code` - Three letter country code of destination card issuer. See :ref:`Card Country Codes` for details. * - :code:`initial-amount` - Amount, set in initiating transaction, without any fees or commissions. This value can't change during the transaction flow. * - :code:`customer-ip` * - The IP address of the customer * - :code:`seller-commission` * - Total commission for processed transaction. * - :code:`acquirer-commission` * - Acquirer commission for processed transaction. * - :code:`exchange-rate` * - Basic exchange rate for currency conversion. * - :code:`effective-exchange-rate` * - Actual exchange rate, applied during currency conversion. * - :code:`motivational-message` * - This is an optional message which contains extended information about the reason for the declined transaction. * - :code:`orig-amount` - Contains the original request amount if it was converted on auxiliary endpoint in Parallel form integration. * - :code:`orig-currency` - Contains the original request currency if it was converted on auxiliary endpoint in Parallel form integration. .. _callback_macros: Callback Macros ============================================== .. list-table:: :widths: 30, 70 :header-rows: 1 :class: longtable * - gate.payneteasy.com Callback Macros name - Description * - :code:`${status}` - Transaction status, ex. :ex:`approved`, :ex:`declined`, :ex:`processing`, etc. * - :code:`${merchant_order}` - Connecting Party order identifier, same as :ex:`client_orderid`. * - :code:`${orderid}` - gate.payneteasy.com transaction id. * - :code:`${type}` - Transaction type, ex. :ex:`sale`, :ex:`return`, :ex:`chargeback`, etc. * - :code:`${amount}` - Transaction amount. * - :code:`${descriptor}` - Payment descriptor of the gate through which the transaction has been processed. * - :code:`${error_message}` - Error message: when :code:`${status}` is declined. * - :code:`${name}` - Cardholder Name. * - :code:`${email}` - Payer's email. * - :code:`${last-four-digits}` - Last four digits of Payer's credit card number. * - :code:`${bin}` - Bank BIN of Payer's credit card. * - :code:`${card-type}` - Type of Payer's credit card (:ex:`VISA`, :ex:`MASTERCARD`, etc). * - :code:`${card-exp-month}` - Card expiration month. * - :code:`${card-exp-year}` - Card expiration year. * - :code:`${gate-partial-reversal}` - Processing gate support partial reversal (enabled or disabled). * - :code:`${gate-partial-capture}` - Processing gate support partial capture (enabled or disabled). * - :code:`${reason-code}` - Reason code for chargeback or fraud operation. * - :code:`${processor-rrn}` - Bank Retrieval Reference Number. * - :code:`${approval-code}` - Bank approval code. * - :code:`${comment}` - Comment in case of Return transaction. * - :code:`${rapida-balance}` - Current balance for Connecting Party registered in Rapida system (only if balance check active). * - :code:`${control}` - Checksum is used to ensure that it is gate.payneteasy.com (and not a fraudster) that initiates the callback to Connecting Party. This is :ex:`SHA-1` checksum of the concatenation :ex:`status` + :ex:`orderid` + :ex:`merchant_order` + :ex:`merchant_control`. The callback script MUST check this parameter by comparing it to :ex:`SHA-1` checksum of the above concatenation. * - :code:`${merchantdata}` - The value passed by Connecting Party in initial request. Callback Request Example ======================================================= .. code-block:: bash https://connectingparty.com/api/integration/check/pay/server?token=some_token &serial-number=b8e5b762-c116-407e-a591-82a458e1 &merchant_order=preauth_1171 &client_orderid=preauth_1171 &processor-tx-id=e0a0572f-2154-737c-8ea7-92410 &orderid=57792 &status=approved &amount=1.50 ¤cy=EUR &descriptor=%D0%90+%D0%94%D0%B5%D0%BD%%D0%B3%D0%B8+-+card+registration &original-gate-descriptor=%D0%90+%D0%940%BD%D1%8C%D0%B3%D0%B8+-+card+registration&gate-partial-capture=enabled &type=preauth &name=CARDHOLDER+NAME &card-exp-month=6 &card-exp-year=2024 &email=22701231%40example.com &processor-rrn=21660934567 &approval-code=265470 &control=bbd11a020f6bsdkfgjh23e24def54991bfb63c5&last-four-digits=0214 &bin=220220&card-type=VISA &phone=%2B71914454778 &bank-name=Rabobank &card-hash-id=235479750 &card-country-alpha-three-code=RUS &ips-src-payment-product-code=VISA &ips-src-payment-product-name=VISA &ips-src-payment-type-code=Unknown &ips-src-payment-type-name=VISA+Unknown &initial-amount=1.50 &transaction-date=2022-06-15+12%3A37%3A02+CEST Callback to Status Parameters Mapping ================================================================================ .. list-table:: :widths: 50, 50 :header-rows: 1 :class: longtable * - Callback parameter Name - Status parameter Name * - :code:`amount` - :code:`amount` * - :code:`approval-code` - :code:`approval-code` * - :code:`bin` - :code:`bin` * - :code:`card-type` - :code:`card-type` * - :code:`last-four-digits` - :code:`last-four-digits` * - :code:`bank-name` - :code:`bank-name` * - :code:`name` - :code:`name` * - :code:`first-name` - :code:`first-name` * - :code:`last-name` - :code:`last-name` * - :code:`country` - :code:`country` * - :code:`state` - :code:`state` * - :code:`city` - :code:`city` * - :code:`zip_code` - :code:`zip_code` * - :code:`address1` - :code:`address1` * - :code:`card-exp-month` - :code:`card-exp-month` * - :code:`card-exp-year` - :code:`card-exp-year` * - :code:`client_orderid` - :code:`merchant-order-id` * - :code:`comment` - :code:`comment` * - :code:`descriptor` - :code:`descriptor` * - :code:`dest-bin` - :code:`dest-bin` * - :code:`dest-card-type` - :code:`dest-card-type` * - :code:`dest-last-four-digits` - :code:`dest-last-four-digits` * - :code:`dest-bank-name` - :code:`dest-bank-name` * - :code:`email` - :code:`email` * - :code:`purpose` - :code:`purpose` * - :code:`error_code` - :code:`error-code` * - :code:`error_message` - :code:`error-message` * - :code:`gate-partial-capture` - :code:`gate-partial-capture` * - :code:`gate-partial-reversal` - :code:`gate-partial-reversal` * - :code:`loyalty-balance` - :code:`loyalty-balance` * - :code:`loyalty-bonus` - :code:`loyalty-bonus` * - :code:`loyalty-message` - :code:`loyalty-message` * - :code:`loyalty-program` - :code:`loyalty-program` * - :code:`merchant_order` - :code:`merchant-order-id` * - :code:`merchantdata` - :code:`merchantdata` * - :code:`orderid` - :code:`paynet-order-id` * - :code:`original-gate-descriptor` - :code:`original-gate-descriptor` * - :code:`phone` - :code:`phone` * - :code:`processor-rrn` - :code:`processor-rrn` * - :code:`processor-tx-id` - :code:`processor-tx-id` * - :code:`rapida-balance` - :code:`rapida-balance` * - :code:`reason-code` - :code:`reason-code` * - :code:`serial-number` - :code:`serial-number` * - :code:`status` - :code:`status` * - :code:`type` - :code:`transaction-type` * - :code:`initial-amount` - :code:`initial-amount` * - :code:`seller-commission` - :code:`seller-commission` * - :code:`acquirer-commission` - :code:`acquirer-commission` * - :code:`exchange-rate` - :code:`exchange-rate` * - :code:`effective-exchange-rate` - :code:`effective-exchange-rate` * - :code:`card-country-alpha-three-code` - :code:`card-country-alpha-three-code` * - :code:`destination-card-country-alpha-three-code` - :code:`destination-card-country-alpha-three-code` Callback Signature Check Example on Java ============================================================================== You may see an example how to check the callback signature using JAVA programming language below: .. highlight:: java :: 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 byte[]. * * @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(); } }