API Basics
Last update: 2020-06-04 | Edit on GitHub
P2P Invoices API opens a way to operations with invoices from your service or application. Invoice is the unique request for the payment. The user may pay the invoice with any accessible means. API supports issuing and cancelling invoices, making refunds and checking operation status.
To use API, you need public and secret keys. Keys are available after registration on p2p.qiwi.com.
Invoicing Operations Flow
Invoice issue via the form
oplata.qiwi.com deactivate rec user->>p2p:Opening the Payment form
Choose payment method / Paying for invoice p2p->>p2p:Invoice payment opt Redirect to success page p2p->>user:Redirect to success_url page end deactivate user end opt Additional opt Notifications (callback) activate p2p activate rec p2p->>rec:Invoice status notification rec->>p2p:Server response (OK) deactivate rec deactivate p2p end opt Invoice status check activate p2p activate rec rec->>p2p:Check invoice status p2p->>rec:Invoice data deactivate rec deactivate p2p end end
-
User submits an order on the merchant’s website.
-
Merchant redirects the user to Payment Form link. It automatically issues an invoice for the order. Or you may issue an invoice by API and redirects to the Payment Form.
-
The user chooses the most convenient way to pay for the invoice on the Payment Form. By default, the optimal payment method is showed first.
-
The merchant's service receives notification once the invoice is successfully paid by the user. You need to configure notifications on your Personal Page. Notifications contain authorization parameters which merchant needs to verify on its server.
- If needed, via the API merchant can:
- request current status of the invoice,
- cancel invoice (if the user has not initiated payment yet).
- When the invoice payment is confirmed, merchant delivers ordered services/goods.
SDK and CMS
SDK and Libraries
- NODE JS SDK - Node JS package of ready-to-use solutions for server2server integration development.
- PHP SDK - PHP package of ready-to-use solutions for server2server integration development.
- Java SDK - Java package of ready-to-use solutions for server2server integration development.
- .Net SDK - C# .net package of ready-to-use solutions for server2server integration development.
CMS Solutions
- Wordpress - plugin for Woocommerce for work with orders
- Online Leyka - Wordpress plagin for charity
- 1С-Bitrix - plugin for work with orders
- Opencart - plugin for work with orders
- PrestaShop - plugin for work with orders
Authorization
const QiwiBillPaymentsAPI = require('bill-payments-node-js-sdk');
const SECRET_KEY = 'eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjUyNjgxMiwiYXBpX3VzZXJfaWQiOjcxNjI2MTk3LCJzZWNyZXQiOiJmZjBiZmJiM2UxYzc0MjY3YjIyZDIzOGYzMDBkNDhlYjhiNTnONPININONPN090MTg5Z**********************';
const qiwiApi = new QiwiBillPaymentsAPI(SECRET_KEY);
--header "Authorization: Bearer MjMyNDQxMjM6NDUzRmRnZDQ0M*******"
<?php
const SECRET_KEY = 'eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjUyNjgxMiwiYXBpX3VzZXJfaWQiOjcxNjI2MTk3LCJzZWNyZXQiOiJmZjBiZmJiM2UxYzc0MjY3YjIyZDIzOGYzMDBkNDhlYjhiNTnONPININONPN090MTg5Z**********************';
/** @var \Qiwi\Api\BillPayments $billPayments */
$billPayments = new Qiwi\Api\BillPayments(SECRET_KEY);
?>
String secretKey = "eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjUyNjgxMiwiYXBpX3VzZXJfaWQiOjcxNjI2MTk3LCJzZWNyZXQiOiJmZjBiZmJiM2UxYzc0MjY3YjIyZDIzOGYzMDBkNDhlYjhiNTnONPININONPN090MTg5Z**********************";
BillPaymentClient client = BillPaymentClientFactory.createDefault(secretKey);
var secretKey = "eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjUyNjgxMiwiYXBpX3VzZXJfaWQiOjcxNjI2MTk3LCJzZWNyZXQiOiJmZjBiZmJiM2UxYzc0MjY3YjIyZDIzOGYzMDBkNDhlYjhiNTnONPININONPN090MTg5Z**********************";
var client = BillPaymentClientFactory.createDefault(secretKey);
API requests are authorized by the API secret key (SECRET_KEY
). Put this parameter to Authorization header as "Bearer SECRET_KEY".
Public key (PUBLIC_KEY
) is used when issuing invoices via the Payment Form.
Keys are available after registration on p2p.qiwi.com.
Invoice Issue on Payment Form
It is the simplest way of integration. On opening Payment Form, client receives an invoice at the same time. The invoice data sends in URL explicitly. Client gets a Payment Form web page with multiple payment means. When using this method, one cannot be sure that all invoices are issued by the merchant. API invoice creation mitigates this risk.
const QiwiBillPaymentsAPI = require('bill-payments-node-js-sdk');
const SECRET_KEY = 'eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjUyNjgxMiwiYXBpX3VzZXJfaWQiOjcxNjI2MTk3LCJzZWNyZXQiOiJmZjBiZmJiM2UxYzc0MjY3YjIyZDIzOGYzMDBkNDhlYjhiNTnONPININONPN090MTg5Z**********************';
const qiwiApi = new QiwiBillPaymentsAPI(SECRET_KEY);
--header "Authorization: Bearer MjMyNDQxMjM6NDUzRmRnZDQ0M*******"
<?php
$publicKey = '2tbp1WQvsgQeziGY9vTLe9vDZNg7tmCymb4Lh6STQokqKrpCC6qrUUKEDZAJ7mvFnzr1yTebUiQaBLDnebLMMxL8nc6FF5zf******';
$params = [
'publicKey' => $publicKey,
'amount' => 200,
'billId' => 'cc961e8d-d4d6-4f02-b737-2297e51fb48e'
];
/** @var \Qiwi\Api\BillPayments $billPayments */
$link = $billPayments->createPaymentForm($params);
echo $link;
?>
String publicKey = "2tbp1WQvsgQeziGY9vTLe9vDZNg7tmCymb4Lh6STQokqKrpCC6qrUUKEDZAJ7mvFnzr1yTebUiQaBLDnebLMMxL8nc6FF5zfmGQnypdXCbQJqHEJW5RJmKfj8nvgc";
MoneyAmount amount = new MoneyAmount(
BigDecimal.valueOf(499.90),
Currency.getInstance("RUB")
);
String billId = UUID.randomUUID().toString();
String successUrl = "https://merchant.com/payment/success?billId=cc961e8d-d4d6-4f02-b737-2297e51fb48e";
String paymentUrl = client.createPaymentForm(new PaymentInfo(key, amount, billId, successUrl));
var publicKey = "2tbp1WQvsgQeziGY9vTLe9vDZNg7tmCymb4Lh6STQokqKrpCC6qrUUKEDZAJ7mvFnzr1yTebUiQaBLDnebLMMxL8nc6FF5zfmGQnypdXCbQJqHEJW5RJmKfj8nvgc";
var amount = new MoneyAmount
{
ValueDecimal = 499.9m,
CurrencyEnum = CurrencyEnum.Rub
};
var billId = Guid.NewGuid().ToString();
var successUrl = "https://merchant.com/payment/success?billId=cc961e8d-d4d6-4f02-b737-2297e51fb48e";
var paymentUrl = client.createPaymentForm(new PaymentInfo(key, amount, billId, successUrl));
REDIRECT →
URL https://oplata.qiwi.com/create
const publicKey = 'Fnzr1yTebUiQaBLDnebLMMxL8nc6FF5zfmGQnypc*******';
const params = {
publicKey,
amount: 42.24,
billId: 'cc961e8d-d4d6-4f02-b737-2297e51fb48e',
successUrl: 'http://test.ru/',
email: 'm@ya.ru'
};
const link = qiwiApi.createPaymentForm(params);
curl https://oplata.qiwi.com/create?publicKey=Fnzr1yTebUiQaBLDnebLMMxL8nc6FF5zfmGQnypc*******&amount=100&successUrl=http%3A%2F%2Ftest.ru%3F&email=m@ya.ru&customFields[paySourcesFilter]=qw,card&lifetime=2020-12-01T0509
Parameters
Invoice data are put in Payment Form URL.
Parameter | Description | Type | Required |
---|---|---|---|
publicKey | Merchant public key received in p2p.qiwi | String | + |
billId | Unique invoice identifier in merchant's system | URL-Encoded String(200) | - |
amount | Amount of the invoice rounded down on two decimals | Number(6.2) | - |
phone | Phone number of the client to which the invoice is issuing (international format) | URL-Encoded String | - |
E-mail of the client where the invoice payment link will be sent | URL-Encoded String | - | |
account | Client identifier in merchant's system | URL-Encoded String | - |
comment | Invoice commentary | URL-Encoded String(255) | - |
customFields[] | Additional invoice data | URL-encoded String(255) | - |
customFields[paySourcesFilter] | Allow only these payment methods for the client on Payment Form. Possible values: qw - QIWI Wallet card - card payment |
URL-Encoded String(255) | - |
customFields[themeCode] | Personalization for Payments Form | String(255) | - |
lifetime | Expiration date of the pay form link (invoice payment's due date). If the invoice is not paid after that date, the invoice assigns EXPIRED final status and it becomes void.Important! Invoice will be automatically expired when 45 days is passed after the invoicing date |
URL-Encoded StringYYYY-MM-DDThhmm |
- |
successUrl | The URL to which the client will be redirected in case of successful payment. URL must be within merchant's site. | URL-Encoded String | - |
API Operations
1. Invoice Issue by API
It is the reliable method for integration. Parameters are sent by means of server2server requests with authorization. Method allows you to issue an invoice, successful response contains payUrl
link to redirect client on Payment Form.
Request → PUT
const billId = 'cc961e8d-d4d6-4f02-b737-2297e51fb48e';
const fields = {
amount: 1.00,
currency: 'RUB',
comment: 'Hello world',
expirationDateTime: '2018-03-02T08:44:07'
};
qiwiApi.createBill( billId, fields ).then( data => {
//do smth with data
});
curl https://api.qiwi.com/partner/bill/v1/bills/cc961e8d-d4d6-4f02-b737-2297e51fb48e \
-X PUT \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjIwNDIsImFwaV91c2VyX2lkIjo1NjYwMzk3Miwic2VjcmV0IjoiQjIwODlDNkI5Q0NDNTdCNDQzNGHJK43JFJDK595FJFJMjlCRkFFRDM5OE***********************'
-d '{ \
"amount": {
"currency": "RUB",
"value": "1.00"
},
"comment": "Text comment",
"expirationDateTime": "2020-12-10T09:02:00+03:00",
"customer": {
"phone": "78710009999",
"email": "test@tester.com",
"account": "454678"
},
"customFields" : {
"paySourcesFilter":"qw",
"themeCode": "Yvan-YKaSh",
"param1": "64728940"
}
}'
<?php
$billId = 'cc961e8d-d4d6-4f02-b737-2297e51fb48e';
$fields = [
'amount' => 1.00,
'currency' => 'RUB',
'comment' => 'test',
'expirationDateTime' => '2018-03-02T08:44:07',
'email' => 'example@mail.org',
'account' => 'client4563'
];
/** @var \Qiwi\Api\BillPayments $billPayments */
$response = $billPayments->createBill($billId, $fields);
print_r($response);
?>
CreateBillInfo billInfo = new CreateBillInfo(
UUID.randomUUID().toString(),
new MoneyAmount(
BigDecimal.valueOf(199.90),
Currency.getInstance("RUB")
),
"comment",
ZonedDateTime.now().plusDays(45),
new Customer(
"example@mail.org",
UUID.randomUUID().toString(),
"79123456789"
),
"http://merchant.ru/success"
);
BillResponse response = client.createBill(billInfo);
var billInfo = new CreateBillInfo
{
BillId = Guid.NewGuid().ToString(),
Amount = new MoneyAmount
{
ValueDecimal = 199.9m,
CurrencyEnum = CurrencyEnum.Rub
},
Comment = "comment",
ExpirationDateTime = DateTime.Now.AddDays(45),
Customer = new Customer
{
Email = "example@mail.org",
Account = Guid.NewGuid().ToString(),
Phone = "79123456789"
},
SuccessUrl = new Uri("http://merchant.ru/success")
};
var response = client.createBill(billInfo);
URL https://api.qiwi.com/partner/bill/v1/bills/{billid}
- billId - unique invoice identifier generated by the merchant.
HEADERS
- Authorization: Bearer SECRET_KEY
- Accept: application/json
- Content-Type: application/json
Parameter | Description | Type | Required |
---|---|---|---|
billId | Unique invoice identifier in merchant's system | String(200) | + |
amount | Object | Data of the invoice amount | + |
amount.currency | Invoice amount currency code. RUB KZT |
Alpha-3 ISO 4217 code | + |
amount.value | Amount of the invoice rounded down to two decimals | Number(6.2) | + |
expirationDateTime | Invoice due date. Time should be specified with time zone. | YYYY-MM-DDThhmm+\-hh:mm |
+ |
customer | Customer data of the invoice subject | Object | - |
customer.phone | Phone number of the client to which the invoice is issuing (international format) | String | - |
customer.email | E-mail of the client where the invoice payment link will be sent | String | - |
customer.account | Client identifier in merchant's system | String | - |
comment | Invoice commentary | String(255) | - |
customFields | Additional invoice data | Object | - |
customFields.paySourcesFilter | Allow only these payment methods for the client on Payment Form. Possible values: qw - QIWI Wallet card - card payment |
Comma separated string | - |
customFields.themeCode | Personalization for Payments Form | String(255) | - |
Response ←
Successful response body example
{
"siteId": "23044",
"billId": "cc961e8d-d4d6-4f02-b737-2297e51fb48e",
"amount": {
"value": 100,
"currency": "RUB"
},
"status": {
"value": "WAITING",
"changedDateTime": "2020-11-30T16:52:51.932+03:00"
},
"customer": {
"phone": "78710009999",
"email": "test@tester.com",
"account": "454678"
},
"customFields": {
"paySourcesFilter": "qw",
"themeCode": "Yvan-YKaSh"
},
"comment": "Text comment",
"creationDateTime": "2020-11-30T16:52:51.932+03:00",
"expirationDateTime": "2020-12-27T19:39:00+03:00",
"payUrl": "https://oplata.qiwi.com/form/?invoice_uid=d875277b-6f0f-445d-8a83-f62c7c07be77"
}
Error response body
{
"serviceName": "invoicing-api",
"errorCode": "auth.unauthorized",
"description": "Неверные аутентификационные данные",
"userMessage": "",
"datetime": "2018-04-09T18:31:42+03:00",
"traceId" : "48485a395dfsdf34v124"
}
HEADERS
- Content-Type: application/json
Field | Type | Description |
---|---|---|
billId | String | Unique invoice identifier in the merchant's system |
siteId | String | Merchant's site identifier in p2p.qiwi |
amount | Object | Data of the invoice amount |
amount.value | String | The invoice amount. The number is rounded down to two decimals |
amount.currency | String | Currency identifier of the invoice amount (Alpha-3 ISO 4217 code) |
status | Object | Data of the invoice current status |
status.value | String | String representation of the status. Possible statuses |
status.changedDateTime | String | Status refresh date. Date format:YYYY-MM-DDThh:mm:ss±hh |
customer | Object | Customer data of the invoice subject |
customer.phone | String | The customer’s phone (if specified in the invoice) |
customer.email | String | The customer's e-mail (if specified in the invoice) |
customer.account | String | The customer's identifier in the merchant's system (if specified in the invoice) |
customFields | Object | Additional invoice data provided by the merchant |
comment | String | Comment to the invoice |
creationDateTime | String | System date of the invoice creation. Date format:YYYY-MM-DDThh:mm:ss±hh |
payUrl | String | Pay form link |
expirationDateTime | String | Expiration date of the pay form link (invoice payment's due date). Date format:YYYY-MM-DDThh:mm:ss±hh |
2. Checking the Invoice Status
Use this method to get current invoice payment status. We recommend using it after receiving the payment notification.
Request → GET
const billId = 'cc961e8d-d4d6-4f02-b737-2297e51fb48e';
qiwiApi.getBillInfo(billId).then( data => {
//do smth ith data
});
curl https://api.qiwi.com/partner/bill/v1/bills/cc961e8d-d4d6-4f02-b737-2297e51fb48e \
-X GET \
-H 'Accept: application/json' \
-H 'Authorization: Bearer eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjIwNDIsImFwaV91c2VyX2lkIjo1NjYwMzk3Miwic2VjcmV0IjoiQjIwODlDNkI5Q0NDNTdCNDQzNGHJK43JFJDK595FJFJMjlCRkFFRDM5OE***********************'
<?php
$billId = 'cc961e8d-d4d6-4f02-b737-2297e51fb48e';
/** @var \Qiwi\Api\BillPayments $billPayments */
$response = $billPayments->getBillInfo($billId);
print_r($response);
?>
String billId = "fcb40a23-6733-4cf3-bacf-8e425fd1fc71";
BillResponse response = client.getBillInfo(billId);
var billId = "fcb40a23-6733-4cf3-bacf-8e425fd1fc71";
var response = client.getBillInfo(billId);
URL https://api.qiwi.com/partner/bill/v1/bills/{billid}
- billId - unique invoice identifier generated by the merchant.
HEADERS
- Authorization: Bearer SECRET_KEY
- Accept: application/json
Response ←
Successful response body example
{
"siteId": "23044",
"billId": "cc961e8d-d4d6-4f02-b737-2297e51fb48e",
"amount": {
"value": 100,
"currency": "RUB"
},
"status": {
"value": "WAITING",
"changedDateTime": "2020-11-30T16:52:51.932+03:00"
},
"customer": {
"email": "test@tester.com",
"phone": "78710009999",
"account": "454678"
},
"customFields": {
"paySourcesFilter": "qw",
"themeCode": "Yvan-YKaSh"
},
"comment": "Text comment",
"creationDateTime": "2020-11-30T16:52:51.932+03:00",
"expirationDateTime": "2020-12-27T19:39:00+03:00",
"payUrl": "https://oplata.qiwi.com/form/?invoice_uid=d875277b-6f0f-445d-8a83-f62c7c07be77"
}
Error response body example
{
"serviceName": "invoicing",
"errorCode": "auth.unauthorized",
"description": "Неверные аутентификационные данные",
"userMessage": "",
"datetime": "2018-04-09T18:31:42+03:00",
"traceId" : ""
}
HEADERS
- Content-Type: application/json
Field | Type | Description |
---|---|---|
billId | String | Unique invoice identifier in the merchant's system |
siteId | String | Merchant's site identifier in p2p.qiwi |
amount | Object | The invoice amount data |
amount.value | Number | The invoice amount. The number is rounded down to two decimals |
amount.currency | String | Currency identifier of the invoice amount (Alpha-3 ISO 4217 code) |
status | Object | Invoice status data |
status.value | String | Current invoice status |
status.changedDateTime | String | Status refresh date |
customFields | Object | Additional invoice data provided by the merchant |
customer | Object | Customer data of the invoice subject |
customer.phone | String | The customer’s phone (if specified in the invoice) |
customer.email | String | The customer's e-mail (if specified in the invoice) |
customer.account | String | The customer's identifier in the merchant's system (if specified in the invoice) |
comment | String | Comment to the invoice |
creationDateTime | String | System date of the invoice creation. Date format:YYYY-MM-DDThh:mm:ss |
payUrl | String | Pay form link |
expirationDateTime | String | Expiration date of the pay form link (invoice payment's due date). Date format:YYYY-MM-DDThh:mm:ss |
3. Cancelling the Invoice
Use this method to cancel unpaid invoice.
Request → POST
const bill_id = 'cc961e8d-d4d6-4f02-b737-2297e51fb48e';
qiwiApi.cancelBill(billId).then( data => {
//do smth with data
});
curl https://api.qiwi.com/partner/bill/v1/bills/cc961e8d-d4d6-4f02-b737-2297e51fb48e/reject \
-X POST \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjIwNDIsImFwaV91c2VyX2lkIjo1NjYwMzk3Miwic2VjcmV0IjoiQjIwODlDNkI5Q0NDNTdCNDQzNGHJK43JFJDK595FJFJMjlCRkFFRDM5OE***********************'
<?php
$billId = 'cc961e8d-d4d6-4f02-b737-2297e51fb48e';
/** @var \Qiwi\Api\BillPayments $billPayments */
$response = $billPayments->cancelBill($billId);
print_r($response);
?>
String billId = "fcb40a23-6733-4cf3-bacf-8e425fd1fc71";
BillResponse response = client.cancelBill(billId);
var billId = "fcb40a23-6733-4cf3-bacf-8e425fd1fc71";
var response = client.cancelBill(billId);
URL https://api.qiwi.com/partner/bill/v1/bills/{billId}/reject
-
Parameters:
- billId - unique invoice identifier generated by the merchant.
HEADERS
- Authorization: Bearer SECRET_KEY
- Accept: application/json
Response ←
Successful response body example
{
"siteId": "23044",
"billId": "cc961e8d-d4d6-4f02-b737-2297e51fb48e",
"amount": {
"value": 100,
"currency": "RUB"
},
"status": {
"value": "REJECTED",
"changedDateTime": "2020-11-30T16:52:51.932+03:00"
},
"customer": {
"email": "test@tester.com",
"phone": "78710009999",
"account": "454678"
},
"customFields": {
"paySourcesFilter": "qw",
"themeCode": "Yvan-YKaSh"
},
"comment": "Text comment",
"creationDateTime": "2020-11-30T16:52:51.932+03:00",
"expirationDateTime": "2020-12-27T19:39:00+03:00",
"payUrl": "https://oplata.qiwi.com/form/?invoice_uid=6848dd49-e260-4343-b258-62199cffe8c1"
}
Error response body example
{
"serviceName": "invoicing",
"errorCode": "auth.unauthorized",
"description": "Неверные аутентификационные данные",
"userMessage": "",
"datetime": "2018-04-09T18:31:42+03:00",
"traceId" : ""
}
HEADERS
- Content-Type: application/json
Field | Type | Description |
---|---|---|
billId | String | Unique invoice identifier in the merchant's system |
siteId | String | Merchant's site identifier in p2p.qiwi |
amount | Object | The invoice amount data |
amount.value | Number | The invoice amount. The number is rounded down to two decimals |
amount.currency | String | Currency identifier of the invoice amount (Alpha-3 ISO 4217 code) |
status | Object | Invoice status data |
status.value | String | Current invoice status |
status.changedDateTime | String | Status refresh date |
customFields | Object | Additional invoice data provided by the merchant |
customer | Object | Customer data of the invoice subject |
customer.phone | String | The customer’s phone (if specified in the invoice) |
customer.email | String | The customer's e-mail (if specified in the invoice) |
customer.account | String | The customer's identifier in the merchant's system (if specified in the invoice) |
comment | String | Comment to the invoice |
creationDateTime | String | System date of the invoice creation. Date format:YYYY-MM-DDThh:mm:ss |
payUrl | String | Pay form link |
expirationDateTime | String | Expiration date of the pay form link (invoice payment's due date). Date format:YYYY-MM-DDThh:mm:ss |
Invoice Payment Statuses
Status | Description | Final |
---|---|---|
WAITING | Invoice issued awaiting for payment | - |
PAID | Invoice paid | + |
REJECTED | Invoice rejected by customer | + |
EXPIRED | Invoice expired. Invoice not paid | + |
Invoice Payment Notifications
Request ← POST
Notification example
POST /qiwi-notify.php HTTP/1.1
Accept: application/json
Content-type: application/json
X-Api-Signature-SHA256: J4WNfNZd***V5mv2w=
Host: server.ru
{ "bill":
{
"siteId":"23044",
"billId":"1519892138404fhr7i272a2",
"amount":{
"value":"100",
"currency":"RUB"
},
"status":{
"value":"PAID",
"datetime":"2018-03-01T11:16:12"
},
"customer":{},
"customFields":{},
"creationDateTime":"2018-03-01T11:15:39",
"expirationDateTime":"2018-04-01T11:15:39"
},
"version":"1"
}
Notification is an incoming POST-request (callback). The request's body contains JSON-serialized invoice data encoded by UTF-8.
Notifications handler server URL is specified on p2p.qiwi.com in API section.
HEADERS
- X-Api-Signature-SHA256: XXX
- Accept: application/json
- Content-type: application/json
Authorization on Merchant's Server
Upon receiving inbound notification you need to verify it by digital signature from notification HTTP header X-Api-Signature-SHA256
. Signature is verified with HMAC algorithm integrity check with SHA256-hash function.
Signature verification algorithm is as follows:
-
Prepare a string of the following notification's parameters separated by
|
:invoice_parameters = {amount.currency}|{amount.value}|{billId}|{siteId}|{status.value}
where
{*}
is the value of the parameter. All values should be treated as strings. -
Apply HMAC-SHA256 function:
hash = HMAС(SHA256, invoice_parameters, secret_key)
where:
secret_key
– function key;invoice_parameters
– string from step 1.
-
Compare
X-Api-Signature-SHA256
header's value with the result of step 2.
const validSignatureFromNotificationServer =
'07e0ebb10916d97760c196034105d010607a6c6b7d72bfa1c3451448ac484a3b';
const notificationData = {
bill: {
siteId: 'test',
billId: 'test_bill',
amount: { value: 1, currency: 'RUB' },
status: { value: 'PAID', datetime: '2018-03-01T11:16:12+03' },
customer: {},
customFields: {},
creationDateTime: '2018-03-01T11:15:39+03',
expirationDateTime: '2018-04-15T11:15:39+03'
},
version: '1'
};
const merchantSecret = 'test-merchant-secret-for-signature-check';
qiwiApi.checkNotificationSignature(
validSignatureFromNotificationServer, notificationData, merchantSecret
); // true
<?php
$validSignatureFromNotificationServer = '07e0ebb10916d97760c196034105d010607a6c6b7d72bfa1c3451448ac484a3b';
$notificationData = [
'bill' => [
'siteId' => 'test',
'billId' => 'test_bill',
'amount' => ['value' => 1, 'currency' => 'RUB'],
'status' => ['value' => 'PAID']
],
'version' => '3'
];
$merchantSecret = 'test-merchant-secret-for-signature-check';
/** @var \Qiwi\Api\BillPayments $billPayments */
$billPayments->checkNotificationSignature(
$validSignatureFromNotificationServer, $notificationData, $merchantSecret
); // true
?>
String merchantSecret = "test-merchant-secret-for-signature-check";
Notification notification = new Notification(
new Bill(
"test",
"test_bill",
new MoneyAmount(
BigDecimal.ONE,
Currency.getInstance("RUB")
),
BillStatus.PAID
),
"3"
);
String validSignature = "07e0ebb10916d97760c196034105d010607a6c6b7d72bfa1c3451448ac484a3b";
BillPaymentsUtils.checkNotificationSignature(validSignature, notification, merchantSecret); //true
String and key of the signature are encoded in UTF-8.
Data
Invoice data are in the notification's body.
Field | Description | Type |
---|---|---|
bill | Invoice data | Object |
bill.billId | Invoice identifier in the merchant's system | String(200) |
bill.siteId | Merchant's site identifier in p2p.qiwi | String |
bill.amount | The invoice amount data | Object |
amount.value | The invoice amount. The number is rounded down to two decimals | Number(6.2) |
amount.currency | Currency identifier of the invoice amount (Alpha-3 ISO 4217 code) | String(3) |
bill.status | Invoice status data | Object |
status.value | Current invoice status | String |
status.changedDateTime | Status refresh date. Date format:YYYY-MM-DDThh:mm:ssZ |
String |
bill.customFields | Additional invoice data provided by the merchant | Object |
bill.customer | Customer data of the invoice subject (if specified in the invoice) | Object |
customer.phone | The customer’s phone (if specified in the invoice) | String |
customer.email | The customer's e-mail (if specified in the invoice) | String |
customer.account | The customer's identifier in the merchant's system (if specified in the invoice) | String |
bill.comment | Comment to the invoice | String(255) |
bill.creationDateTime | System date of the invoice creation. Date format:YYYY-MM-DDThh:mm:ssZ |
String |
bill.payUrl | Pay form link | String |
bill.expirationDateTime | Expiration date of the pay form link (invoice payment's due date). Date format:YYYY-MM-DDThh:mm:ssZ |
String |
version | Notification service version | String |
Response →
HTTP/1.1 200 OK
Content-Type: application/json
{
"error":"0"
}
HEADERS
- Content-type: application/json
After receiving incoming notification request, you should verify its signature and returns the JSON-response. The processing result code should be returned in response.
Payment Form options
Invoice URL example
curl https://oplata.qiwi.com/form?invoiceUid=a8437e7e-dc48-44f7-9bdb-4d46ca8ef2e4&paySource=qw&successUrl=google.com
You can add parameters to URL from payUrl
field in response to the invoice request.
Parameter | Description | Type |
---|---|---|
paySource | Pre-selected payment method for the client on Payment Form. Possible values: qw - QIWI Walletcard - card paymentmobile - payment from phone balanceWhen specified method is inaccessible, the page automatically selects recommended method for the user. |
String |
successUrl | The URL to which the client will be redirected in case of successful payment. URL must be within merchant's site. | URL-Encoded String |
Personalization
Personalization allows you to create a payment form with your style, customizable logo, background and color of the buttons.
You can create styles in your account on p2p.qiwi.com.
When setting up, you create a code linked to the style (for example, codeStyle
). To use style on the Payment Form, you must pass the variable: "themeCode": "codeStyle"
with respective code of the style in the customFields
parameter of the invoice request or opening Payment Form URL.
Invoice Issue on Payment Form
curl https://oplata.qiwi.com/create?publicKey=Fnzr1yTebUiQaBLDnebLMMxL8nc6FF5zfmGQnypc*******&amount=100&billId=cc961e8d-d4d6-4f02-b737-2297e51fb48e&successUrl=http%3A%2F%2Ftest.ru%3F&customFields%5BthemeCode%5D=codeStyle
Invoice Issue by API
curl https://api.qiwi.com/partner/bill/v1/bills/cc961e8d-d4d6-4f02-b737-2297e51fb48e \
-X PUT \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJ2ZXJzaW9uIjoicmVzdF92MyIsImRhdGEiOnsibWVyY2hhbnRfaWQiOjIwNDIsImFwaV91c2VyX2lkIjo1NjYwMzk3Miwic2VjcmV0IjoiQjIwODlDNkI5Q0NDNTdCNDQzNGHJK43JFJDK595FJFJMjlCRkFFRDM5OE***********************' \
-d '{ \
"amount": { \
"currency": "RUB", \
"value": 100.00 \
}, \
"comment": "Text comment", \
"expirationDateTime": "2018-04-13T14:30:00+03:00", \
"customer": {}, \
"customFields": {"themeCode":"codeStyle"} \
}'
Checkout Popup
Installation:
The library has two methods: create a new invoice and open an existing one.
Create new invoice
Call function QiwiCheckout.createInvoice
.
Parameter | Description | Type | Required |
---|---|---|---|
publicKey | Merchant public key received in p2p.qiwi | String | + |
amount | Amount of the invoice rounded down on two decimals | Number(6.2) | + |
phone | Phone number of the client to which the invoice is issuing (international format) | String | - |
E-mail of the client where the invoice payment link will be sent | String | - | |
account | Client identifier in merchant’s system | String | - |
comment | Invoice commentary | String(255) | - |
customFields | Additional invoice data | Object | - |
lifetime | Expiration date of the pay form link (invoice payment’s due date). If the invoice is not paid after that date, the invoice assigns EXPIRED final status and it becomes void.Important! Invoice will be automatically expired when 45 days is passed after the invoicing date |
URL-encoded string YYYY-MM-DDThhmm |
- |
Create new invoice
params = {
publicKey: '5nAq6abtyCz4tcDj89e5w7Y5i524LAFmzrsN6bQTQ3c******',
amount: 1.23,
phone: '79123456789',
email: 'test@test.com',
account: 'acc789',
comment: 'Оплата',
customFields: {
data: 'data'
},
lifetime: '2019-04-04T1540'
}
QiwiCheckout.createInvoice(params)
.then(data => {
// ...
})
.catch(error => {
// ...
})
Open an existing invoice
Call function QiwiCheckout.openInvoice
.
Parameter | Description | Type | Required |
---|---|---|---|
payUrl | Pay form link | String | + |
Open an existing one
params = {
payUrl: 'https://oplata.qiwi.com/form?invoiceUid=06df838c-0f86-4be3-aced-a950c244b5b1'
}
QiwiCheckout.openInvoice(params)
.then(data => {
// ...
})
.catch(error => {
// ...
})