# Basic principles

# Pattern of interaction

Diagram

# Inquiries

# Entry points

The entry points for the sandbox and production environments are the same. Mandarin determines the environment by the authentication data (the value of the secret key Secret).

It is important to use TLS 1.2 or higher (requests with TLS 1.0 or 1.1 will be rejected).

Entry point for creating transactions

Used for all basic operations (e.g. accept payments and payouts to card).

POST https://secure.mandarinpay.com/api/transactions

Entry point for card tokenization

Used only for card tokenization.

POST https://secure.mandarinpay.com/api/card-bindings

Entry point for simplified identification

The identification process is significantly different and is described on separate page. This uses the Mandarin standard authentication method.

POST https://secure.mandarinpay.com/api/personidentification

# Request authentication

The authentication of requests is done by the authorization string, which is passed in the header parameter X-Auth.

The X-Auth value is formed according to the following pattern:
`merchantId-SHA256(merchantId-requestId-secret)-requestId', where:

  • merchantId - the MID specified in personal account.

  • requestId - unique request number. To ensure uniqueness, we recommend using the current timestamp in milliseconds, or a set of bytes generated by a cryptographically-reliable random number generator.

  • secret - Secret, specified in personal account.

API requests without a header or with an invalid header, including invalid X-Auth, will be rejected without creating transactions.

X-Auth calculation examples

<?php
function gen_auth($merchantId, $secret)
{
        $reqid = time() ."_". microtime(true) ."_". rand();
        $hash = hash("sha256", $merchantId ."-". $reqid ."-". $secret);
        return $merchantId ."-".$hash . $reqid;
}
?>
public static string GenerateXAuth(string secret)
{
  var requestId = Guid.NewGuid().ToString("N");
    string hash;
    using (var sha256 = System.Security.Cryptography.SHA256.Create())
        hash = BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes($"{merchantId}-{requestId}-{secret}")).ToLower().Replace("-", "");
    return $"{merchantId}-{hash}-{requestId}";
}

DEPRECATED

An alternative authentication method is Basic auth (opens new window). We do not recommend to use it, especially for card payment requests. As a login value merchantId is used, as a password - value Secret.

# Query parameters

The Content-Type for requests takes the value application/json.

You can download collection-for-postman, which already has all the queries from this section.

Parameter Type Description and possible values Where to use (action)
payment object object containing transaction data. pay, preauth, reversal, payout
payment.action string Type of transaction.
Possible values:
pay - Payment;
preauth - Authorization;
reversal - Cancellation of transaction;
payout - Payment.
pay, preauth, reversal, payout
payment.orderId string order number in your system. Must be unique among successful transactions! pay, preauth, reversal, payout
payment.price string payment amount. Separator - dot. pay, preauth, reversal, payout
payment. orderActualTill string The reservation period of the product/service. After the specified date the payment will not be possible. Format: 2020-02-20 12:34:56+00:00. If the parameter is not specified, then the standard period of 48 hours applies. pay, preauth
customerInfo object object containing user data. pay, preauth, reversal, payout, card-binding
customerInfo. email string user's email. Format: user@example.com. pay, preauth, reversal, payout, card-binding
customerInfo. phone string user phone number in RF format: +79001234567.
target object object containing a reference to an existing transaction/card token. pay, reversal, payout, card-binding
target.transaction string the identifier of the existing transaction to which the new one is referring. pay, reversal
target.card string card token (e.g. for recurring payments). pay, payout
target. knownCardNumber string the number of the card to which the payment is made. payout, card-binding
destination object object containing a reference to the token/card number to which the card2card transaction is transferred. card2card
destination.card string card token to which the card2card transaction is transferred. card2card
destination. knownCardNumber string the number of the card to which the card2card transaction is transferred. card2card
source object object containing a reference to the card token from which the card2card transaction is debited. card2card
source.card string the token of the card from which the card2card transaction is debited. card2card
allowinteractive boolean indicator interactive (with payer participation) payment, if payment without payer participation is impossible. Supported only in Mandarin Custom Pay. When used it is always true: "allowinteractive": true pay
interactive boolean indicator interactive (with payer participation) payment. Supported only in Mandarin Custom Pay. When used it is always equal to true: "interactive": true pay
customValues[] array array containing additional information about the payment. It can contain up to 8 pairs of parameters. Each parameter is displayed to the payer in the right block of the payment page. pay, preauth, reversal, payout
customValues[]. name string parameter header (displayed in the right block of the payment page). pay, preauth, reversal, payout
customValues[]. value string parameter value (displayed in the right block of the payment page). pay, preauth, reversal, payout
metadata object object containing a list of your parameters with any names and any values that will be sent in callback notification. Parameters are not displayed in the payer user interface. Parameter names cannot contain spaces! pay, preauth, reversal, payout
urls object object containing url. If absent, the url from the settings are used. pay, preauth, reversal, payout, card-binding
urls.return string Url for redirecting user after payment. pay, preauth, reversal, payout, card-binding
urls.callback string Url for sending callback notification of transaction status. pay, preauth, reversal, payout, card-binding
fiscalInformation object object containing fiscal information for the online cash register. pay
fiscalInformation. taxationSystem string taxation system.
Possible values:
Common - General (DOS);
Simplified - Simplified (USN) "Income";
SimplifiedMinusOutlay - Simplified (USN) "Income minus expenses";
UnifiedImputedIncome - Single tax on imputed income;
UnifiedAgricultural - Single agricultural tax;
Patent - Patent.
pay
fiscalInformation. items[] array array of lines in the check. pay
fiscalInformation. items[].description string item name. pay
fiscalInformation. items[].quantity string quantity or weight. Separator is dot. pay
fiscalInformation. items[].totalPrice string amount (price х quantity). Separator is dot. pay
fiscalInformation. items[].vat string VAT rate.
Possible values:
None - No VAT;
Vat0 - VAT at 0%;
Vat10 - VAT at 10%;
Vat20 - VAT at 20%.
pay

TESTING

Data for testing payment products are in separate section.

# Saving additional information

You can pass additional information about the payment in the request.

The customValues array can contain up to 8 pairs of parameters that are displayed to the payer in the right block of the payment page. The metadata object can contain json with any field names and their values, at that they are not displayed to the payer.

For example, a credit organization accepts monthly payments from its customers. The customValues array may contain the contract number and commission amount from the payer. Let the metadata object contain the source (source) from which the payer opened the payment page and the date of sending the notification (sent_at).

Synchronous response and asynchronous callback notification can contain a wider set of parameters compared to the example.

Request

POST https://secure.mandarinpay.com/api/transactions
{
	"payment": {
		"action": "pay",
		"orderId": "your_unique_order_id",
		"price": "1030.00"
	},
	"customerInfo": {
		"email": "user@example.com",
		"phone": "+79001234567"
	},
	"customValues": [
		{"name": "Contract number", "value": "K-12345-789"},
		{"name": "Commission", "value": "30.00"}
	],
	"metadata": {
		"source": "email",
		"sent_at": "2020-01-31"
	},
	"urls": {
		"callback": "http://...",
		"return": "http://..."
	}
}

Response in case of successful transaction creation (200 OK)

{
	"id": "43913ddc000c4d3990fddbd3980c1725",
	{ "userWebLink": "https://secure.mandarinpay.com/Pay?transaction=0eb51e74-e704-4c36-b5cb-8f0227621518",
	"jsOperationId": "9874694yr87y73e7ey39ed80"
}

Response in case transaction is not created (400 Bad request)

{
	"error": "Invalid request"  
}

DATA PROCESSING

The value values from the customValues array are stored in the parameters cs2, cs3, cs4, cs5, cs6, cs7, cs8, cs9 in the order in which they were passed (if not passed, the values are empty). They are part of the payment transaction and are available from personal account, in callback-notification, etc.

The metadata block can have a complex structure. It is returned only in callback-notification exactly as it was passed. This information is not subsequently saved.

# Synchronized responses

# HTTP codes

Mandarin uses standard HTTP status codes to indicate successful or unsuccessful API requests.

Code Description
2xxx request processed.
4xxx Parameters sent by the client are incorrect (lack of the correct format, incorrectly formed header, etc.). For example, 401 for an authorization error.
5xxx Internal error on Mandarin side (quite rare case).

# Answer parameters

Parameter Mandatory Description
id Yes The ID of the created transaction or card token
userWeblink No Link to redirect the user when working with the payment page
jsOperationId No Transaction ID for use with Mandarin Custom Pay
error no text description of the error

Each API call has an identifier associated with it, which is called ID transaction and is passed in the synchronous response as the value of the id parameter. For tokenization request it is a card token, and for payment or payout request it is called transactionID. It is also present in callback notification as a value of transaction (for payments/payouts) or card_binding (for tokenizations) field.

The TransactionID (also called PaymentID) is also available in the transaction table via a link in personal cabinet (opens new window) and in the [HeartBeat] interface(./tools.md#monitoring-queries-and-notification-heartbeat).

Transaction ID

WARNING

When contacting Helpdesk (opens new window) with questions about a specific transaction, provide its TransactionID! This will greatly speed up the response.

After receiving a synchronous response, there can be three options:

  1. To use the payment page
    Redirect the user to the link received as userWebLink (detail)
  2. To use Mandarin Custom Pay inline form
    Use value from jsOperationId as operationId (detail)

  3. In this case only id will be received in the synchronous response.

Response in case of successful transaction creation (200 OK)

{
	"id": "43913ddc000c4d3990fddbd3980c1725",
	"userWebLink": "https://secure.mandarinpay.com/Pay?transaction=0eb51e74-e704-4c36-b5cb-8f0227621518",
	"jsOperationId": "9874694yr87y73e7ey39ed80"
}

Response in case of successful tokenization (200 OK)

{
	"id": "0eb51e74-e704-4c36-b5cb-8f0227621518",
	"userWebLink": "https://secure.mandarinpay.com/CardBindings/New?id=0eb51e74-e704-4c36-b5cb-8f0227621518",
	"jsOperationId": "binding-4994591t5-194t694159t-43t5345"
}

Response in case the transaction was not created (400 Bad request)

{
	"error": "Invalid request"
}

# Asynchronous status notifications (callbacks)

# Notification Authentication

To confirm that the notification came from the Mandarin system and that the data transmitted in the notification was not corrupted, you must check the sign parameter.

The sign field is a SHA256 hash of values of all notification parameters, sorted alphabetically and secret values, separated by -.

To check sign, all notification parameters must be sorted alphabetically using your programming language's standard sort algorithm. :::

You can use special utility (opens new window) to check if the sign value is calculated correctly.

Sign Calculator UI

  • Insert the callback body in the field (1);
  • Insert secret in field (2);
  • The sign value will be calculated automatically in field (3).

# Notification parameters

The Content-Type for asynchronous notifications takes the value application/x-www-urlencoded.

Notifications are sent as a POST request to the address that was passed in the corresponding request in optional parameter urls.callback. If the parameter was not passed, the address used to send the POST request is the one that was specified in the [Integration] tab(./tools.md#authentication-data) in the personal area.

IMPORTANT!

The number of parameters in a callback notification can vary. New parameters can be added. In addition, each notification has a "salt" (a parameter and a value with random data).
That's why it's important not to hardcode the parameter set!

List and description of parameters transmitted as part of the callback notification

Parameter object_type stores the type: transaction (Payment / Payment) or card_binding (Card Tokenization). Depending on its value, the set of other parameters changes!

Parameters in the POST request are passed in the format x-www-form-urlencoded.

Parameter Mandatory Description
16797d04-d688-4a55-8190-861224243701 Yes Salt (the UUID for the name and for the parameter value are randomly generated.
3dsecure No Payment confirmation indicator with [3-D Secure] code entry(./glossary.md#3-d_secure).
action No Action (payment pay or payment payout), relevant only for transactions
callbackUrl No The address to send the callback.
card_binding No card token in the system, relevant only for tokenizations.
card_expiration_month No card expiration month.
card_expiration_year No card expiration year.
card_holder No cardholder (in URL-encoded format).
card_id No Hash of full card number (for tokenizations and payments).
card_info_bank No The name of the card issuing bank (in URL-encoded format).
card_info_country No country of the card issuing bank (in ISO 3166-1 alpha-3 (opens new window) format). For example, RUS.
card_info_type No The name of the international payment system of the card. For example, mastercard.
card_info_card_type No The type of card. For example, Debit.
card_info_product_name No The name of the card product. For example, Visa Rewards.
card_info_product_code No The product code of the card. For example, N1.
card_info_issuing_bank No The issuing bank. For example, Tinkoff Bank.
card_info_iso_country_a3 No The country of issue of the card. For example, RUS.
card_number No card number (masked).
cb_customer_creditcard_number No card number (masked), field will be removed in future versions
cb_processed_at No date and time of operation processing.
customer_fullName No user name.
customer_email No user email address.
customer_phone No user_phone
customName0 No Name of the first parameter (in URL-encoded format) passed in the customValues array as part of a payment or tokenization request. There can be up to 8 parameters: customName0, customName1, . , customName7.
customValue0 No Value of the first parameter (in URL-encoded format) passed in the customValues array as part of a payment or tokenization request. There can be up to 8 parameters: customValue0, customValue1, . , customValue7.
email no user's email.
error_code No error code. The absence of a code does not guarantee the success of the operation!
error_description No error description.
gw_channel No The name of the channel to transfer funds.
gw_id No channel ID to transfer funds.
initial_hold_amount No authorization amount, mandatory only for tokenizations.
merchantId Yes merchant ID.
metadata_* No Parameters passed in the metadata object as part of a payment or tokenization request. They are prefixed with metadata_.
object_type Yes object type (payment/payment transaction or tokenization card_binding).
orderActualTill No Term for reserving the product/service. Payment will not be possible after the specified date.
orderId Yes A unique order number in your system.
payment_system No constant mandarinpayv1, the field will be removed in future versions
price no payment amount, mandatory only for transactions.
returnUrl No Store address for redirecting at the end of the operation.
status Yes operation status: success, failed, payout-only. **Only success status unambiguously indicates the success of the operation!
transaction No Transaction ID in the system. Only valid for transactions.
transaction_rrrn No RRN transaction.
sign Yes Sign for authentication (always last).

# Parameters in the metadata object

A tokenization or payment request can include a metadata object that contains a list of your parameters with any names and any values that will be sent in the callback notification. In this case they will not be shown to the user on the payment page.

For example, for a tokenization request:

POST https://secure.mandarinpay.com/api/card-bindings
{
	{ "customerInfo": {
		{ "email": "user@example.com",
		"phone": "+79001234567"
	},
	{ "metadata": {
		"first_param": "p1",
		"second_param": "p2"
	}
}

You can read more about using the metadata object in queries in saving additional information.

The Callback notification, along with the other parameters, will include the parameters from the request, but with the prefix metadata_:

metadata_first_param=p1&metadata_second_param=p2

# Examples of notifications

Payment callback notification example

merchantId=1&orderId=e75c444d-22b4-4e1c&email=79691112211%40mail.ru&orderActualTill=2024-01-30%2006%3A59%3A28Z&price=100.00&callbackUrl=https%3A%2F%2test.ru%2Fpayment%2F60e70526%2Fe75c444d-22b4-4e1c%2Fpayment%2F&action=pay&customer_fullName=%20%20&customer_phone=%2B79691112211&customer_email=79691112211%40test.ru&transaction=1a79f7d8122048929299a7ee87aed&object_type=transaction&status=failed&payment_system=mandarinpayv1&card_number=220220XXXXXX1111&cb_customer_creditcard_number=220220XXXXXX1111&gw_channel=psb_direct&transaction_rrn=402822221111&error_code=51&error_description=Not%20sufficient%20funds&gw_id=107211111&card_id=7c5d587672909558a075fd11111111&e72d8031-d96f-4d1f-953d-779cb693ad7d=65ce05ec-f35a-4f1f-b00c&sign=b6c39660225e7e4d22b7ce535edc

Example callback notification about tokenization of full card data

card_binding=a7446082-02a4&card_holder=ALEKSANDR%20IVANOV%20&card_number=427605XXXXXX1111&card_expiration_year=2023&card_expiration_month=2&object_type=card_binding&status=success&merchantId=1&initial_hold_amount=1.00000&3dsecure=true&gw_id=1072811&card_id=99bb78de64def70b063c11111&card_info_country=RUS&card_info_type=visa&card_info_bank=SBERBANK&card_info_product_name=Visa%20Classic&card_info_product_code=F&card_info_card_type=Debit&card_info_issuing_bank=SBERBANK&card_info_iso_country_a3=RUS&9870f8a5=8f5b0fe8-a587-4de0ea9808dc&sign=8eada97da58c5287f4b08a2e75dd0fe1111

Example of a callback notification of tokenization with `payout-only' status

card_binding=9b2980ab-6247&card_holder=HALVA%20CARD&card_number=553609XXXXXX1111&card_expiration_year=27&card_expiration_month=1&object_type=card_binding&status=payout-only&merchantId=1&initial_hold_amount=1.00000&3dsecure=true&gw_id=1111&card_id=3e8dd9d3265221111111&card_info_country=RUS&card_info_type=mastercard&card_info_bank=Sovcombank&card_info_product_name=Mastercard%20World%20Card&card_info_product_code=MNW&card_info_card_type=Credit&card_info_issuing_bank=Sovcombank&card_info_iso_country_a3=RUS&0e5d3ca6-=9317d7e6-6d29-4d34-af62-1&sign=e8867ef06f61ab00465336275c5b1111111

Example of a callback notification of a payment using a card token

merchantId=1&orderId=112244&email=test%40mail.ru&orderActualTill=2024-01-30%2007%3A33%3A39Z&price=100&action=payout&customer_fullName=%20%20&customer_phone=%2B7911111111&customer_email=test%40mail.ru&transaction=3d1d4a7c2f794e479e2cdd351111111&object_type=transaction&status=failed&payment_system=mandarinpayv1&gw_channel=psb_direct&transaction_rrn=4028471111111&error_code=51&error_description=Not%20sufficient%20funds&gw_id=107281111&card_id=811d78e08b41ce51e450eb81111111&fe18a06c-e010-4a07-985e-1111111=3bd5e84b-f3f2-41d7-86ed-e994a7336144&sign=91feebac525892a32d8effe11111111

Example of a callback payment notification using a card number

merchantId=1&orderId=9537D957-AC43-4853-AB47-4E39BCFFF3FC&email=sadukin%40mail.ru&orderActualTill=2021-02-22%2010%3A48%3A17Z&price=2000.0&callbackUrl=http%3A%2F%2Fmail.example.com%3A4000%2Fapi%2Fmandarin%2Fpayout%2Fcallback&action=payout&customName0=manager_id&customValue0=E099D738-CED4-48F2-A21C-36C0EA25A549&customName1=dealer_id&customValue1=BD251868-EACA-483D-91F3-954543576F93&customName2=customer_id&customValue2=A54856FA-3A81-4742-AA73-743389D536A9&customer_fullName=%20%20&customer_phone=%2B79273884129&customer_email=sadukin%40mail.ru&transaction=52f1874b9bd846e7ab14c9f96fb9bc17&object_type=transaction&status=success&payment_system=mandarinpayv1&cb_processed_at=2021-02-20T10%3A48%3A22.7232790Z&card_number=546906XXXXXX1568&cb_customer_creditcard_number=546906XXXXXX1568&gw_channel=open_way4&transaction_rrn=105199356489&error_code=51&error_description=Not%20sufficient%20funds&gw_id=39104021&709b674c-1f5e-424d-841e-1244d7b71041=9ee4b553-f961-4da9-b9dc-0924c0260d33&sign=a63189b75147a8bd2326baaacdd482d902206b5b6fe6de5f0df464e698b47912

Example of callback-notification of authorization at two-stage payment

merchantId=1&orderId=11&email=test%40mail.ru&orderActualTill=2024-01-24%2017%3A22%3A24&price=1&callbackUrl=https%3A%2F%2Fwww.test.ru%2Fother%2Fcompany%2Fpaymenthold.php&action=preauth&customName0=tcustomValue0=test&customer_fullName=test&customer_phone=%2B797881111111&customer_email=test%40mail.ru&metadata_inv_id=36&transaction=3c35c083f7eb4bed8373b9341111111&object_type=transaction&status=failed&payment_system=mandarinpayv1&sandbox=false&error_code=888&error_description=Order%20expired&faeef3a9-1095-4513-b6f9-504cf3920c0a=ae7db577-1fac-4154-9a8e-11111111&sign=b57daf7804f7e252235f6901c435ac8f1e10063aba518d034617db31111111

Examples of sign checks

<?php
function check_sign($secret, $req)
{
        $sign = $req['sign'];
        unset($req['sign']);
        $to_hash = '';
        if (!is_null($req) && is_array($req)) {
                ksort($req);
                $to_hash = implode('-', $req);
        }

        $to_hash = $to_hash .'-'. $secret;
        $calculated_sign = hash('sha256', $to_hash);
        return $calculated_sign == $sign;
}

check_sign("123", $_POST);
?>
public static string Calculate(string secret, IDictionary<string, string> values)
{
    using (var sha256 = System.Security.Cryptography.SHA256.Create())
        return BitConverter.ToString(sha256.ComputeHash(Encoding.UTF8.GetBytes(string.Join("-", values.OrderBy(x => x.Key, StringComparer.Ordinal).Select(x => x.Value)) + "-" + secret)).ToLower().Replace("-", "");
}

public static bool CheckSign(string secret, HttpRequest request)
{
    var sign = request.Form["sign"];
    if(string.IsNullOrWhiteSpace(sign))
      return false;
    return sign ==
        Calculate(secret, request.Form.Keys.Where(k => k != "sign").ToDictionary(k => k, k => request.Form[k]);
}

# Resend notifications

As a response indicating that the callback has been successfully processed on your side, you should return a response to Mandarin with the HTTP code 200 and the body OK.

IMPORTANT!

Any other response will mean that the callback has not been processed. In this case, Mandarin will resend the callback request within 3 days, or until receiving a response on successful processing (whichever comes first).

# Limits for API requests

Restrictions and limits for API requests:

  • For recurring payments: no more than 10 requests per second, and no more than 300 requests per minute.

  • For refunds: the maximum amount of refunds, and the maximum number of refunds (set by customer's request).

  • On payments: purchase limit (set at the request of the client).

# Preparation and tools

# Authentication data

To start working with Mandarin, you need to register, get your account activated by your account manager and go to personal account (opens new window).

In order to receive MID и Secret you should follow to this instruction (opens new window)

IMPORTANT!

Please note that the secret key must not leave your server in any form. If it is passed as part of HTML or otherwise used in JavaScript, this is a security problem and gives an attacker the opportunity to make calls to the payment system on your behalf.

For additional security for each MID, you can enable the option to accept requests only from white list IP addresses (opens new window) (white list). The feature is enabled by request to Helpdesk (opens new window).

# Monitoring requests and notifications (HeartBeat)

HeartBeat (opens new window) is a tool for monitoring payment transactions and asynchronous notifications (callbacks). Standard authorization is used to log in.

Features:

See manual for more information (opens new window)