QIWI
Feedback
bss@qiwi.com
NAV Navbar
shell php

Payments From Mobile Account

Edit on GitHub

Mobile payments API provides access to operations with customer's mobile account from your application or service. The following operations are supported:

Customer Order Payment Flow

Payment flow processes as follows:

  1. The customer puts an order on the merchant's site.
  2. Merchant makes Initiate Payment request with the authorization parameters.
  3. Customer receives SMS from their mobile network operator immediately on initiating payment. SMS contains the information about corresponding payment invoice.
  4. Customer approves payment by the response SMS. The invoice is automatically rejected when customer rejects the payment.

    Mobile SMS

  5. If the merchant enables notifications to merchant's server, then QIWI system sends a notification (web-hook) of the invoice payment to the merchant's server once invoice is paid. Authorization on the merchant's side is required for notifications.

    If merchant does not use notifications, they can request current payment status of the invoice.

  6. When the invoice payment is confirmed, merchant delivers ordered services/goods.

To use API, complete registration and approval of the agreement.

Authorization

Mobile payments API requests are authorized through HTTP Basic-authorization with API ID and API password Header is Authorization string and its value is Basic Base64(API_ID:API_PASSWORD).

curl "server_address" \
  --header "Authorization: Basic MjMyNDQxMjM6NDUzRmRnZDQ0Mw=="

Service data

Parameter Description Type
API_ID Required. Provider API identifier for authorization Integer
API_PASSWORD Required. API password for authorization String
Shop ID Required. Numeric identifier of the provider's service Integer

Payment Initiation

The request initiates a new payment for a specified mobile phone number. Request type - HTTP PUT.

To confirm payment, customer's mobile network operator send SMS with code to the specified phone number.

Request → PUT

curl "https://api.qiwi.com/api/v2/prv/373712/bills/BILL-1" \
  -X PUT \
  --header "Accept: text/json" \
  --header "Authorization: Basic ***" \
  -d 'user=tel%3A%2B79161111111&amount=10.00&ccy=RUB&comment=test&pay_source=mobile&lifetime=2016-09-25T15:00:00'
HTTP/1.1 200 OK
Content-Type: text/json

{
  "response": {
     "result_code": 0,
     "bill": {
        "bill_id": "BILL-1",
        "amount": "10.00",
        "ccy": "RUB",
        "status": "waiting",
        "error": 0,
        "user": "tel:+79161111111",
        "comment": "Text comment"
     }
  }
}

Parameter|Description|Type ———|——–|——– user | Required. The QIWI Wallet user’s ID, to whom the invoice is issued. It is the user’s phone number with tel: prefix | String(20) «««< HEAD amount | Required. The invoice amount. The number is rounded down with two decimal places | Number(6.2)|Y ======= amount | Required. The invoice amount. The number is rounded down with two decimal places | Number(6.2) »»»> 842a7af… Required column is moved to parameter description ccy | Invoice currency identifier (Alpha-3 ISO 4217 code). Depends on currencies allowed for the merchant in QIWI system | String(3) comment | Required. Comment to the invoice | String(255) lifetime | Required. Date and time up to which the invoice is available for payment, URL-encoded ISO 8601 (YYYY-MM-DDThh:mm:ss), Moscow timezone. If the invoice is not paid by this date it will become void and will be assigned a final status.
Important! Invoice will be automatically expired when 45 days is passed after the invoicing date |dateTime pay_source |Required. A funding source for the payment — the customer's MNO balance | mobile only

The given PHP example implements creation of the invoice. This example demonstrates using merchant's authorization parameters, i.e. shop ID, API ID and password for the API ID. Open the PHP tab on the right.

Response ←

Successful response

HTTP/1.1 200 OK

Content-Type: text/json;charset=utf-8
{
  "response": {
     "result_code": 0,
     "bill": {
        "bill_id": "BILL-1",
        "amount": "10.00",
        "ccy": "RUB",
        "status": "waiting",
        "error": 0,
        "user": "tel:+79031234567",
        "comment": "Text comment"
     }
  }
}

Error Response

HTTP/1.1 500 Internal Server Error
Content-Type: text/json;charset=utf-8

{
 "response": {
  "result_code": 150,
  "description": "Authorization failed"
  }
}
Response field Type Description
result_code Integer Error code
description String Error description. Returned when result_code is non-zero.
bill Object Bill data. Returned when result_code is zero (successful operation). Parameters:
bill.bill_id String Unique invoice identifier generated by the merchant
bill.amount String The invoice amount. The number is rounded down to two decimals
bill.ccy String Currency identifier of the invoice (Alpha-3 ISO 4217 code)
bill.status String Current invoice status
bill.error Integer Always 0, means successful operation
bill.user String The QIWI Wallet user’s ID, to whom the invoice is issued. It is the user’s phone number with tel: prefix.
bill.comment String Comment to the invoice
<?php
//PHP implementation of invoice creation
//Shop identifier
$SHOP_ID = "21379721";
//API ID
$REST_ID = "62573819";
//API Password
$PWD = "**********";
//Invoice ID
$BILL_ID = "99111-ABCD-1-2-1";
$PHONE = "79191234567";

$data = array(
    "user" => "tel:+" . $PHONE,
    "amount" => "1000.00",
    "ccy" => "RUB",
    "comment" => "Goods from basket",
    "lifetime" => "2015-01-30T15:35:00",
    "pay_source" => "mobile"
);

$ch = curl_init('https://api.qiwi.com/api/v2/prv/'.$SHOP_ID.'/bills/'.$BILL_ID);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($data));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $REST_ID.":".$PWD);
curl_setopt($ch, CURLOPT_HTTPHEADER,array (
    "Accept: application/json"
));
$results = curl_exec ($ch) or die(curl_error($ch));
echo $results;
echo curl_error($ch);
curl_close ($ch);
?>

Checking Payment Status

Using this request you can get current payment status of the invoice.

curl "https://api.qiwi.com/api/v2/prv/373712/bills/sdf23452435" \
  --header "Authorization: Basic ***" \
  --header "Accept: text/json"

Request → GET

Response ←

Successful Response

HTTP/1.1 200 OK
Content-Type: text/json

{
  "response": {
     "result_code": 0,
     "bill": {
        "bill_id": "BILL-1",
        "amount": "10.00",
        "originAmount": "10.00"
        "ccy": "RUB",
        "originCcy": "RUB",
        "status": "paid",
        "error": 0,
        "user": "tel:+79031234567",
        "comment": "Text comment"
     }
  }
}

Error response

HTTP/1.1 500 Internal Server Error
Content-Type: text/json

{
 "response": {
  "result_code": 150,
  "description": "Authorization failed"
  }
}
Response field Type Description
result_code Integer Error code
description String Error description. Returned when result_code is non-zero.
bill Object Bill data. Returned when result_code is zero (successful operation). Parameters:
bill.bill_id String Unique invoice identifier generated by the merchant
bill.amount String The invoice amount. The number is rounded down to two decimals
bill.originAmount String The amount taken from the balance when the invoice get paid (see originCcy parameter). The number is rounded down to two decimals. Returned for invoices when the user initiates payment.
bill.ccy String Currency identifier of the invoice (Alpha-3 ISO 4217 code)
bill.originCcy String Currency identifier of the balance from which the invoice is paid (Alpha-3 ISO 4217 code). Returned for invoices when the user initiates payment.
bill.status String Current invoice status
bill.error Integer Always 0, means successful operation
bill.user String The QIWI Wallet user’s ID, to whom the invoice is issued. It is the user’s phone number with tel: prefix.
bill.comment String Comment to the invoice

Operation Statuses

Payment Status

Status Description Final
waiting Payment initiating, pending payment N
paid paid Y
rejected rejected Y
unpaid Payment processing error. Not paid Y
expired Payment expired. Not paid Y

Error Codes

Code Description Fatal
0 Success Unrelated
5 Incorrect data in the request parameters Y
13 Server is busy, try again later N
78 Operation is forbidden Y
150 Authorization error (e.g. invalid login/password) Y
152 Protocol is not enabled or protocol is disabled N
155 This merchant’s identifier (API ID) is blocked Y
210 Invoice not found Y
215 Invoice with this bill_id already exists Y
241 Invoice amount is less than allowed Y
242 Invoice amount is greater than allowed. Also returned to refund request when the amount of refund exceeds the initial invoice amount or the amount left after the previous refunds Y
298 User not registered Y
300 Technical error N
303 Wrong phone number Y
316 Authorization from the blocked merchant N
319 No rights for the operation N
339 IP-addresses blocked Y
341 Required parameter is incorrectly specified or absent in the request Y
700 Monthly limit on operations is exceeded Y
774 QIWI Wallet user account temporarily blocked Y
1001 Currency is not allowed for the merchant Y
1003 No convert rate for these currencies N
1019 Unable to determine wireless operator for MNO balance payment Y
1419 Bill was already payed Y

Notifications

Edit on GitHub

Notification is a POST-request (callback). The request's body contains all relevant data of the invoice serialized as HTTP-request parameters and encoded by UTF-8 plus parameter command=bill.

Request → POST

Example of notification request

user@server:~$ curl "https://example.com/qiwi-notify.php"
  -v -w "%{http_code}"
  -X POST --header "Accept: text/xml"
  --header "Content-Type: application/x-www-form-urlencoded; charset=utf-8"
  --Authorization: "Basic MjA0Mjp0ZXN0Cg=="
  -d "bill_id=BILL-1%26status=paid%26amount=1.00%26user=tel%3A%2B79031811737%26prv_name=TEST%26ccy=RUB%26comment=test%26command=bill"
Parameter Description Type Required
bill_id Merchant invoice number String Y
status Current invoice status String Y
amount The invoice amount. The number is rounded down with two decimal places Number(6.2) Y
user The QIWI Wallet user’s ID, to whom the invoice is issued. It is the user’s phone number with tel: prefix String Y
prv_name Merchant’s site name specified on kassa.qiwi.com in "Settings" section String Y
ccy Invoice currency identifier (Alpha-3 ISO 4217 code) String(3) Y
comment Comment to the invoice String(255) Y
command Always bill by default String Y

Response ←

Example of XML response to notification

HTTP/1.1 200 OK
Content-Type: text/xml

<?xml version="1.0"?>
<result>
<result_code>0</result_code>
</result>

Response must be in XML format.

XML Tag Description
result Grouping tag. Describes notification processing result.
result_code Notification result code (positive integer). We recommend that the result codes returned by the merchant be in accordance with Notification codes table.

Authorization on Merchant's Server

Merchant's server should use basic-authorization or authorization by signature. Merchant may also use client SSL certificate verification (self-signed certificates may be used as well). QIWI Wallet server certificate should be verified in HTTPS requests.

Basic authorization

Example of notification with Basic auth

POST /qiwi-notify.php HTTP/1.1
Accept: text/xml
Content-type: application/x-www-form-urlencoded
Authorization: Basic ***
Host: example.com

command=bill&bill_id=BILL-1&status=paid&error=0&amount=1.00&user=tel%3A%2B79031811737&prv_name=Retail_Store&ccy=RUB&comment=test

The login is taken from Shop ID parameter. To obtain password, click on Change notification password button in Protocols details - REST-protocol section of QIWI partners web site.

Authorization by signature

Example of notification with Signature

POST /qiwi-notify.php HTTP/1.1
Accept: text/xml
Content-type: application/x-www-form-urlencoded
X-Api-Signature: J4WNfNZd***V5mv2w=
Host: example.com

command=bill&bill_id=LocalTest17&status=paid&error=0&amount=0.01&user=tel%3A%2B78000005122&prv_name=Test&ccy=RUB&comment=Some+Descriptor

Example of notification processing with signature check

<?php

function hexToStr($hex){
    $string='';
    for ($i=0; $i < strlen($hex)-1; $i+=2){
        $string .= chr(hexdec($hex[$i].$hex[$i+1]));
    }
    return $string;
}

//Signature generation by key and string
function checkSign($key, $req){
    $sign_hash = hash_hmac("sha1", $req, $key);
    $sign_tr = hexToStr($sign_hash);
    $sign = base64_encode($sign_tr);
    return $sign;
}

//Sort POST-request parameters and return values
function getReqParams(){
    $reqparams = "";
    ksort($_POST);
    foreach ($_POST as $param => $valuep) {
        $reqparams = "$reqparams|$valuep";
    }
    return substr($reqparams,1);
}

//Take signature from the request
function getSign(){
    $HEADERS = getallheaders();
    foreach ($HEADERS as $header => $value) {
       if ($header == 'X-Api-Signature') {
            $SIGN_REQ = $value;
       }
    }
    return $SIGN_REQ;
}

// Sort parameters
$Request = getReqParams();
// Notification password
$NOTIFY_PWD = "***";
// Get sign
$reqres = checkSign($NOTIFY_PWD, $Request);

// Get sign from the request
$SIGN_REQ = getSign();

if ($reqres == $SIGN_REQ) {
    $error = 0;
}
else $error = 151;

//Response
header('Content-Type: text/xml');
$xmlres = <<<XML
<?xml version="1.0"?>
<result>
<result_code>$error</result_code>
</result>
XML;
echo $xmlres;
?>

The HTTP header X-Api-Signature with signature is added to the POST-request. Signature is calculated as HMAC algorithm with SHA1-hash function.

Signature verification algorithm is as follows:

  1. Prepare a string of all parameters values from the notification POST-request sorted in alphabetical order and separated by |:

    {parameter1}|{parameter2}|…

    where {parameter1} is the value of the notification parameter. All values should be treated as strings.

  2. Transform obtained string and password for the notification basic-authorization into bytes encoded in UTF-8.
  3. Apply HMAC-SHA1 function:

    hash = HMAС(SHA1, Notification_password_bytes, Invoice_parameters_bytes) Where:

    • Notification_password_bytes – secret key (bytecoded notification password);
    • Invoice_parameters_bytes – bytecoded POST-request body;
    • hash – hash-function result.
  4. Transform HMAC-hash value into bytes with UTF-8 and Base64-encode it.
  5. Compare X-Api-Signature header's value with the result of step 4.

PHP Implementation Example

The given PHP example implements notification authorization by signature verification. Open the PHP tab on the right.

Notification Codes

Code Description
0 Success
5 The format of the request parameters is incorrect
13 Database connection error
150 Incorrect password
151 Signature authorization failed
300 Server connection error