Payment widget in the sandbox
The payment widget works in the sandbox just as in production: the same embed., mount() / open(), payment methods, events and the /pay redirect route. The full parameter reference lives in the guide. This page covers what to plug in for the sandbox and how to drive a payment to an outcome without a real bank.
What you need
| What | In the sandbox |
|---|---|
| SDK | https://pay-sandbox.digitalspb.com/Card/Sbp/embed.js |
| Credentials and project | The demo credentials from Access & test data |
| Payment methods | The demo project has all four enabled — sbp, alfapay, sberpay, tpay — so the choice screen shows right away. Other projects get only SBP by default; the set is changed on request |
| Widget token | Arrives in the CreateInvoice response and lives for 2 hours |
Step 1. Create the invoice
The invoice is created on the merchant’s server — with the same CreateInvoice as in Flow: bank card. Credentials and the signature never reach the browser.
The token is issued only for the card branch — an UndefinedBankCardCustomer (undefined_bank_card in JSON) or a BankCardCustomer. A DCB invoice by phone number has no widget.
{
"customer": {
"type": "undefined_bank_card",
"source": "my_source",
"country": "RU",
"merchant_customer_id": "user_123"
},
"order": {
"merchant_order_id": "ORDER-001",
"price": { "amount": "99.00", "currency": "RUB", "vat_included": true }
}
}From the response the widget needs the invoice ID and the token: authorization. in JSON, AuthorizationInfo. in XML.
Step 2. Embed the widget
<div id="pay"></div>
<script src="https://pay-sandbox.digitalspb.com/Card/Sbp/embed.js"></script>
<script>
SbpWidget.mount('#pay', {
invoiceId: 'A1B2C3...', // from the CreateInvoice response
token: 'eyJ...', // authorization.token / AuthorizationToken from the same response
lang: 'en', // optional: sandbox pages are bilingual, ru or en
onSuccess: function () { location.href = '/thanks'; },
onFail: function () {},
onExpired: function () {},
onError: function (e) { console.log(e.code, e.message); }
});
</script>For the modal mode use SbpWidget.open() with the same parameters minus the selector. Without embed., the widget opens from a link — in a WebView, for example:
GET https://pay-sandbox.digitalspb.com/Card/Sbp/widget.html?invoiceId={invoiceId}&t={token}&lang=enThe token goes in the t parameter; the sandbox also accepts the old name token.
Step 3. Drive the payment to an outcome
The sandbox has no real banks, so confirmation is replaced with a simulation:
| Method | How to confirm the payment |
|---|---|
| Any | The “Simulate payment” button inside the widget |
| SBP, QR on a desktop | Scan the QR with a phone: in the sandbox the code leads to the sandbox’s own payment confirmation address |
| Alfa Pay, SberPay, T-Pay | The method button opens a bank app imitation with a confirm button |
The widget polls the status every 5 seconds and, once paid, sends a success event — onSuccess fires. The widget event is a UI signal; the invoice state itself is checked as usual: Invoice status, Callbacks.
Your own buttons — the redirect route
The /pay route from §11.7 of the guide works in the sandbox too:
GET https://pay-sandbox.digitalspb.com/Card/Handlers/{invoiceId}/pay?method=alfapay&t={token}alfapay, sberpay and tpay lead to the bank app imitation, sbp to the QR page. An unknown method code returns 400.
What to check besides a successful payment
| What | How to reproduce | What to expect |
|---|---|---|
| Invalid token | Open widget. with someone else’s or a corrupted t | A 401 and the “Link is invalid” screen instead of the payment form |
| Method not enabled | On a project with only SBP enabled, pass methods: ['alfapay'] | The widget shows the whole available set and calls onError with code: 'method_unavailable'; the payment carries on |
| Returning to the page | Start a payment and reload the tab | The payment already started opens; the method is not chosen again |
Differences from production
| In the sandbox | In production |
|---|---|
SDK — https://pay-sandbox.digitalspb.com/Card/Sbp/embed.js | SDK — from the payment domain, https://pay.digitalspb.com/Card/Sbp/embed.js. The default apiBase comes from the script address, so switching environments means switching the embed. address |
| The “Simulate payment” button and the bank app imitation | Not there — the payment is confirmed in a real bank |
The QR handler response carries a sandbox_confirm_url field — the simulation address | No such field; do not build code around it |
| The token is a JWT issued by the sandbox | The platform does not document the token format: pass it to the widget as is, do not parse it |