Card and SBP subscription
Instead of confirming by SMS, the subscriber links a bank card or pays with an SBP QR code. There is no separate method for this: the same CreateSubscription with CustomerType=Card, and SBP is a parameter on the payment page.
Merchant Subscription Service Subscriber
│ │ │
│ 1. CreateSubscription ───►│ │
│ CustomerType=Card │ │
│◄── SubscriptionID + │ │
│ AuthorizeUrl ──────────│ │
│ 2. redirect to AuthorizeUrl ────────────────────────►│
│ │◄── card or SBP QR ───────│
│◄─ SubscriptionStatusNotification (APPROVED) ─────────│CreateSubscriptionwithCustomerType=CardandCustomerId. The response containsAuthorizeUrl,SubscriberAcceptanceChannel=AUTH_PAGEandSubscriptionStatus=Pending.- Redirect the subscriber to
AuthorizeUrl. For an SBP payment append?useSbpQr=True— instead of the card form the SBP flow opens, different for desktop and phone (see below). - The subscriber pays. Card details are not validated in the sandbox: any card number and any PIN work. To get a decline, use a card whose last 4 digits are
0001…0005. - The subscription is activated: status
Active, callbackEventType=APPROVED. On a declined card —ApprovingFailedandEventType=REJECTED.ApproveSubscriptionis not called in this flow.
The SBP flow depends on the device
| Device | What the subscriber sees |
|---|---|
| Desktop | A universal QR code. The subscriber scans it with a phone and confirms the payment in their banking app — no bank is chosen on the page |
| Phone | The bank list. There is nothing to scan the QR with, so the subscriber picks a bank and is taken to its app by a deep link |
The screen is chosen by User-Agent; to see both from one machine append ?view=qr or ?view=banks to the URL.
The payment screen shows the subscription terms: the amount charged now, the recurring amount with its period and an auto-renewal note — without them the payer would only see a one-off amount. The period comes from the BillingPeriodSeconds hook when it is set.
The mock does not distinguish SBP from SberPay — both open the same QR screen. The link is single-use and lives for 15 minutes, like the one-time payment checkout.
The payment screens are bilingual. The language is picked automatically from the subscriber’s Accept-Language header — nothing has to be appended to AuthorizeUrl or to the WAP confirmation page. To open a specific version, add ?lang=en or ?lang=ru (it combines with ?useSbpQr=True and ?view=): an explicit choice beats the header and survives to the end of the flow. A language we do not have falls back to Russian.
<Request>
<SubscriptionProjectID>2001</SubscriptionProjectID>
<CustomerType>Card</CustomerType>
<CustomerId>12345</CustomerId>
<Now>20260625120000</Now>
<Signature>d2f36558ca5455be...</Signature>
</Request>Sandbox
<Response>
<StatusID>0</StatusID>
<StatusName>REQUEST_ACCEPTED</StatusName>
<SubscriptionID>10000002</SubscriptionID>
<SubscriptionStatus>Pending</SubscriptionStatus>
<SubscriberAcceptanceChannel>AUTH_PAGE</SubscriberAcceptanceChannel>
<AuthorizeUrl>https://subs-sandbox.digitalspb.com/Cards/TB/8c0c8870-.../Init</AuthorizeUrl>
<PaidUntil>2026-09-16T12:00:00+03:00</PaidUntil>
<TrialExists>false</TrialExists>
</Response>Sandbox
# the parameter is appended to AuthorizeUrl
https://subs-sandbox.digitalspb.com/Cards/TB/8c0c8870-.../Init?useSbpQr=TrueSandbox
0001 — insufficient funds
0002 — card blocked
0003 — limit exceeded
0004 — declined by bank
0005 — card expired