Сценарий: привязка банковской карты
Card-on-file / custom form: данные карты вводятся на сайте или в приложении продавца и передаются в API внутри <BankCardCustomer>. Карта привязывается контрактом без PIN-подтверждения, дальнейшие списания идут без повторного ввода реквизитов. Сценарий существует только в XML-протоколе — в JSON v3 блока с реквизитами карты нет.
Два жёстких условия. Продавец, через которого проходят карточные данные, обязан иметь сертификацию PCI DSS — без неё используйте обычный сценарий «карта» с редиректом на платёжную форму. Наличие блока BankCard в запросах регулируется типом интеграции и индивидуальными требованиями эквайера — включается индивидуально.
Sandbox
Только тестовые карты с префиксом 1111 (например 1111 2222 3333 4444) — реальные карточные данные не отправляйте никогда. Зарезервированные окончания 0001–0005 эмулируют отказ последующих списаний. Карточные данные песочница не хранит (остаются только последние 4 цифры PAN), CVC не хранится ни в каком виде, реквизиты маскируются в журнале запросов. Песочные контракты чистятся обычным ретеншном, а не двухлетним сроком спеки.
- Привяжите карту:
CreateCustomerContractс<BankCardCustomer>, внутри которого полный блок<BankCard>(PAN, срок действия, CVC, имя держателя), плюсMerchantContractID. Заголовки этого сценария:Service-Method: CreateCustomerContract,Callisto-Protocol-Version: 2,SignatureVersion: 4. Ответ —ContractID,AuthorizationType: SKIPи срок действияExpirationTimeUtc: PIN-подтверждения, как у телефона, нет, шагAuthorizeCustomerContractне нужен. - Списывайте по контракту: обычный
CreateInvoiceс тем же<BankCardCustomer>и<CustomerContractInfo>(MerchantContractID);CreateIfNotExists=trueпозволяет создать контракт заодно с первым инвойсом. В ответе — блокCustomerContractInfoиAuthorizationInfoсAuthorizationUrl— страница подтверждения 3-D Secure (в песочнице подходит любой 4-значный код); сама форма карты остаётся на стороне продавца. Со снятым 3-D Secure состав ответа другой — см. врезку ниже. - Повторная привязка того же активного
MerchantContractIDвозвращаетResultCode230(Business_CustomerContractAlreadyExists— см. ResultCode),ContractIDсуществующего контракта — вResultDescription.
Шаг 1 — CreateCustomerContract с реквизитами карты (XML)
<Request>
<Header><Authentication>
<Login>demo_login</Login>
<NowUtc>20260625120000</NowUtc>
<Signature>abcdef1234...</Signature>
</Authentication></Header>
<CreateCustomerContractRequest>
<ProjectID>1001</ProjectID>
<ClientIP>10.20.30.40</ClientIP>
<BankCardCustomer>
<Source>my_source</Source>
<Country>ru</Country>
<MerchantCustomerId>user_123</MerchantCustomerId>
<Email>test@test.com</Email>
<BankCard>
<PAN>1111222233334444</PAN>
<ExpirationMonth>08</ExpirationMonth>
<ExpirationYear>28</ExpirationYear>
<SecurityCode>123</SecurityCode>
<Cardholder>IVANOV IVAN</Cardholder>
</BankCard>
</BankCardCustomer>
<CustomerContractInfo>
<MerchantContractID>CARD-CONTRACT-001</MerchantContractID>
</CustomerContractInfo>
</CreateCustomerContractRequest>
</Request><Response>
<CreateCustomerContractResponse>
<BankCardCustomer>
<Source>my_source</Source>
<Country>ru</Country>
<MerchantCustomerId>user_123</MerchantCustomerId>
<Email>test@test.com</Email>
</BankCardCustomer>
<CustomerContractInfo>
<ContractID>1c6495bb-0002-005f-f54e-d286731d55b9</ContractID>
<AuthorizationType>SKIP</AuthorizationType>
<ExpirationTimeUtc>27.04.2028 21:00:06</ExpirationTimeUtc>
<MerchantContractID>CARD-CONTRACT-001</MerchantContractID>
</CustomerContractInfo>
</CreateCustomerContractResponse>
<ResultCode>0</ResultCode>
<ResultDescription>OK</ResultDescription>
</Response>Шаг 2 — списание по контракту (XML)
<Request>
<Header><Authentication>
<Login>demo_login</Login>
<NowUtc>20260625120000</NowUtc>
<Signature>abcdef1234...</Signature>
</Authentication></Header>
<CreateInvoiceRequest>
<ProjectID>1001</ProjectID>
<ClientIP>10.20.30.40</ClientIP>
<BankCardCustomer>
<Source>my_source</Source>
<Country>ru</Country>
<MerchantCustomerId>user_123</MerchantCustomerId>
<Email>test@test.com</Email>
</BankCardCustomer>
<InvoiceInfo>
<MerchantOrderID>ORDER-001</MerchantOrderID>
<CustomerPrice amount="99.00" currency="RUB" includingVAT="true"/>
</InvoiceInfo>
<CustomerContractInfo>
<CreateIfNotExists>false</CreateIfNotExists>
<MerchantContractID>CARD-CONTRACT-001</MerchantContractID>
</CustomerContractInfo>
</CreateInvoiceRequest>
</Request>Sandbox
<Response>
<CreateInvoiceResponse>
<BankCardCustomer>
<Source>my_source</Source>
<MerchantCustomerId>user_123</MerchantCustomerId>
<Country>ru</Country>
<Email>test@test.com</Email>
</BankCardCustomer>
<InvoiceInfo>
<CustomerPrice amount="99.00" currency="RUB" includingVAT="true" />
<CreatedTimeUtc>31.08.2026 20:00:10</CreatedTimeUtc>
<ExpirationTimeUtc>31.08.2026 22:00:10</ExpirationTimeUtc>
<InvoiceStatus>WaitPaymentConfirmation</InvoiceStatus>
<PaymentStatus>NOT_PAID</PaymentStatus>
<AuthorizationType>AUTH_PAGE</AuthorizationType>
<IsAuthorized>false</IsAuthorized>
<InvoiceID>3c8d95c6-0006-0062-6727-4ea756dba332</InvoiceID>
<MerchantOrderID>ORDER-001</MerchantOrderID>
</InvoiceInfo>
<BillingInfo>
<BillingChannel>BankRtp</BillingChannel>
</BillingInfo>
<CustomerContractInfo>
<ContractID>1c6495bb-0002-005f-f54e-d286731d55b9</ContractID>
<AuthorizationType>SKIP</AuthorizationType>
<ExpirationTimeUtc>27.04.2028 21:00:06</ExpirationTimeUtc>
<MerchantContractID>CARD-CONTRACT-001</MerchantContractID>
</CustomerContractInfo>
<AuthorizationInfo>
<AuthorizationUrl>https://pay-sandbox.digitalspb.com/checkout/a038a5ce-c580-4ff1-b480-e364b21a7474/pin?last4=4444</AuthorizationUrl>
</AuthorizationInfo>
</CreateInvoiceResponse>
<ResultCode>0</ResultCode>
<ResultDescription>OK</ResultDescription>
</Response>Ответ зависит от настройки card_3ds_enabled. Это единственный сценарий, где 3-D Secure меняет не только число экранов у плательщика, но и состав ответа. Настройка снята — списание проводится синхронно в самом CreateInvoice: блока AuthorizationInfo (а с ним и ссылки оплаты) в ответе нет, AuthorizationType инвойса — SKIP, а InvoiceStatus / PaymentStatus уже показывают исход (Processed / PAID либо Cancelled / NOT_PAID по зарезервированному окончанию карты). Платёжное уведомление уходит как обычно. Разбор обоих ответов и порядок проверки — Сценарий: 3-D Secure.
Вариант — реквизиты карты прямо в CreateInvoice (XML)
В зависимости от подключения блок <BankCard> передаётся не только в CreateCustomerContract, но и в CreateInvoice — внутри того же <BankCardCustomer>, с тем же составом полей, что в шаге 1. Действуют те же условия: сертификация PCI DSS и индивидуальное включение у эквайера (см. врезку в начале страницы).
<Request>
<Header><Authentication>
<Login>demo_login</Login>
<NowUtc>20260625120000</NowUtc>
<Signature>abcdef1234...</Signature>
</Authentication></Header>
<CreateInvoiceRequest>
<ProjectID>1001</ProjectID>
<ClientIP>10.20.30.40</ClientIP>
<BankCardCustomer>
<Source>my_source</Source>
<Country>ru</Country>
<MerchantCustomerId>user_123</MerchantCustomerId>
<Email>test@test.com</Email>
<BankCard>
<PAN>1111222233334444</PAN>
<ExpirationMonth>08</ExpirationMonth>
<ExpirationYear>28</ExpirationYear>
<SecurityCode>123</SecurityCode>
<Cardholder>IVANOV IVAN</Cardholder>
</BankCard>
</BankCardCustomer>
<InvoiceInfo>
<MerchantOrderID>ORDER-002</MerchantOrderID>
<CustomerPrice amount="99.00" currency="RUB" includingVAT="true"/>
</InvoiceInfo>
</CreateInvoiceRequest>
</Request>Регулярные платежи по номеру телефона (контракт с PIN-подтверждением) — отдельный сценарий: Сценарий: рекуррент. Полное описание метода — Создание контракта и справочник createContract.