{
  "info": {
    "name": "i-Free Money Mock Service — Callisto (sandbox)",
    "description": "Песочница разовых платежей Callisto.\n\nЦенность коллекции — pre-request script, который считает подпись HMAC-SHA256 v3 за вас: именно она является барьером входа. Скрипт живёт на уровне коллекции и выполняется перед каждым запросом, заполняя переменные `{{ts_iso}}`, `{{sig_json}}` (для REST JSON v3) и `{{now_utc}}`, `{{sig_xml}}` (для XML v2.6).\n\nДоступы по умолчанию — общие демо-доступы песочницы. Замените `login`, `secret` и `project_id` на свои, когда получите их у администраторов sandbox.\n\nПорядок работы: папка «XML v2.6» содержит сквозной сценарий Quick Start (создать → подтвердить PIN → статус). `invoice_id` подхватывается автоматически из ответа, вручную копировать ничего не нужно.\n\nИмпортируется в Insomnia как есть.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    {
      "key": "base_url",
      "value": "https://pay-sandbox.digitalspb.com",
      "type": "string"
    },
    {
      "key": "login",
      "value": "demo_login",
      "type": "string"
    },
    {
      "key": "secret",
      "value": "demo_password",
      "type": "string"
    },
    {
      "key": "project_id",
      "value": "1001",
      "type": "string"
    },
    {
      "key": "ts_iso",
      "value": "",
      "type": "string"
    },
    {
      "key": "sig_json",
      "value": "",
      "type": "string"
    },
    {
      "key": "now_utc",
      "value": "",
      "type": "string"
    },
    {
      "key": "sig_xml",
      "value": "",
      "type": "string"
    },
    {
      "key": "msisdn",
      "value": "",
      "type": "string"
    },
    {
      "key": "invoice_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "contract_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "merchant_contract_id",
      "value": "",
      "type": "string"
    },
    {
      "key": "merchant_order_id",
      "value": "POSTMAN-ORDER-1"
    },
    {
      "key": "widget_token",
      "value": ""
    },
    {
      "key": "widget_invoice_id",
      "value": ""
    }
  ],
  "event": [
    {
      "listen": "prerequest",
      "script": {
        "type": "text/javascript",
        "exec": [
          "// Подпись HMAC-SHA256 v3 — считается перед каждым запросом коллекции.",
          "//   inner     = HMAC_SHA256(secret, timestamp)",
          "//   signature = HMAC_SHA256(secret, login + inner)",
          "// Разбор формулы и пошаговый пример — в разделе «Подпись запросов» справочника.",
          "const secret = pm.collectionVariables.get('secret');",
          "const login  = pm.collectionVariables.get('login');",
          "",
          "// JSON v3 — метка ISO-8601 UTC в заголовке X-Timestamp.",
          "const iso = new Date().toISOString().replace(/\\.\\d{3}Z$/, 'Z');",
          "// XML v2.6 — та же метка в формате yyyyMMddHHmmss в теле запроса.",
          "const compact = iso.replace(/[-:TZ]/g, '');",
          "",
          "function sign(timestamp) {",
          "  // Внимание на порядок аргументов: у CryptoJS сначала сообщение, потом ключ.",
          "  const inner = CryptoJS.HmacSHA256(timestamp, secret).toString();",
          "  return CryptoJS.HmacSHA256(login + inner, secret).toString();",
          "}",
          "",
          "pm.collectionVariables.set('ts_iso', iso);",
          "pm.collectionVariables.set('sig_json', sign(iso));",
          "pm.collectionVariables.set('now_utc', compact);",
          "pm.collectionVariables.set('sig_xml', sign(compact));",
          "",
          "// Свой абонент на каждый запуск: песочница дедуплицирует инвойсы по клиенту,",
          "// и повторный заказ того же абонента получил бы 409 INVOICE_ALREADY_EXISTS.",
          "if (!pm.collectionVariables.get('msisdn')) {",
          "  pm.collectionVariables.set('msisdn', '79' + String(Date.now()).slice(-9));",
          "}"
        ]
      }
    }
  ],
  "item": [
    {
      "name": "XML v2.6 — сквозной сценарий",
      "description": "Боевой протокол партнёров. Три запроса от нуля до оплаченного инвойса.",
      "item": [
        {
          "name": "1. CreateInvoice",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "const body = pm.response.text();",
                  "pm.test('ResultCode = 0', () => pm.expect(body).to.include('<ResultCode>0</ResultCode>'));",
                  "const m = body.match(/<InvoiceID>([^<]+)<\\/InvoiceID>/);",
                  "if (m) { pm.collectionVariables.set('invoice_id', m[1]); }",
                  "pm.test('InvoiceID получен', () => pm.expect(m, 'нет InvoiceID').to.not.equal(null));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <CreateInvoiceRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <MobilePhoneCustomer><MSISDN>{{msisdn}}</MSISDN></MobilePhoneCustomer>\n    <InvoiceInfo>\n      <MerchantOrderID>POSTMAN-{{$timestamp}}</MerchantOrderID>\n      <CustomerPrice amount=\"99.00\" currency=\"RUB\" includingVAT=\"true\"/>\n    </InvoiceInfo>\n    <!-- Песочные ручки: в боевом контракте этого блока нет -->\n    <TestInfo>\n      <ExpectedBillingResult>Success</ExpectedBillingResult>\n      <CallbackDelaySeconds>0</CallbackDelaySeconds>\n    </TestInfo>\n  </CreateInvoiceRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "MerchantOrderID должен быть уникальным. Подставьте `ERR_210` внутрь него, чтобы получить отказ тарификации — см. «Эмуляция ошибок»."
          }
        },
        {
          "name": "2. AuthorizeInvoice (PIN 1234)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <AuthorizeInvoiceRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <InvoiceInfo>\n      <InvoiceID>{{invoice_id}}</InvoiceID>\n    </InvoiceInfo>\n    <AuthorizeInfo><PinCode>1234</PinCode></AuthorizeInfo>\n  </AuthorizeInvoiceRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "PIN в песочнице фиксированный — 1234. SMS не отправляется."
          }
        },
        {
          "name": "3. GetInvoice",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <GetInvoiceRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <InvoiceInfo>\n      <InvoiceID>{{invoice_id}}</InvoiceID>\n    </InvoiceInfo>\n  </GetInvoiceRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "InvoiceID обязан лежать внутри <InvoiceInfo>. При плоском размещении песочница ответит из заготовки, и статус навсегда останется PROCESSING.\n\nСразу после подтверждения придёт Authorized / PROCESSING, через 6 секунд — Processed / PAID."
          }
        },
        {
          "name": "CancelInvoice",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <CancelInvoiceRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <InvoiceInfo>\n      <InvoiceID>{{invoice_id}}</InvoiceID>\n    </InvoiceInfo>\n  </CancelInvoiceRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "Отменяет неоплаченный счёт. Оплаченный отменить нельзя — для него возврат."
          }
        },
        {
          "name": "RefundInvoice",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <RefundInvoiceRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <InvoiceInfo>\n      <InvoiceID>{{invoice_id}}</InvoiceID>\n    </InvoiceInfo>\n  </RefundInvoiceRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "Возврат применяется только к оплаченному счёту. После него уходит уведомление SendPaymentTransaction со статусом Refund и без блока PaymentTransactionInfo."
          }
        },
        {
          "name": "CreateCustomerContract",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <CreateCustomerContractRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <MobilePhoneCustomer>\n      <MSISDN>{{msisdn}}</MSISDN>\n    </MobilePhoneCustomer>\n    <CustomerContractInfo>\n      <MerchantContractID>{{merchant_contract_id}}</MerchantContractID>\n    </CustomerContractInfo>\n  </CreateCustomerContractRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "Привязка абонента: в ответе ContractID и AuthorizationType. Для карты по сценарию custom form внутрь BankCardCustomer кладётся блок BankCard с тестовым PAN 1111222233334444 — контракт создаётся сразу, с AuthorizationType SKIP."
          }
        },
        {
          "name": "AuthorizeCustomerContract",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <AuthorizeCustomerContractRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <CustomerContractInfo>\n      <ContractID>{{contract_id}}</ContractID>\n    </CustomerContractInfo>\n    <AuthorizationInfo>\n      <PinCode>1234</PinCode>\n    </AuthorizationInfo>\n  </AuthorizeCustomerContractRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "PIN в песочнице фиксированный — 1234. Карточный контракт подтверждать не нужно."
          }
        },
        {
          "name": "CancelCustomerContract",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <CancelCustomerContractRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <CustomerContractInfo>\n      <ContractID>{{contract_id}}</ContractID>\n    </CustomerContractInfo>\n  </CancelCustomerContractRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "После отмены тот же MerchantContractID можно привязать заново."
          }
        },
        {
          "name": "CheckCustomerBillingSupport",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <CheckCustomerBillingSupportRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <MobilePhoneCustomer>\n      <MSISDN>{{msisdn}}</MSISDN>\n    </MobilePhoneCustomer>\n  </CheckCustomerBillingSupportRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "Проверка поддержки тарификации: вызов без побочных эффектов."
          }
        },
        {
          "name": "ProjectCustomerSupport",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "text/xml; charset=utf-8"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Request>\n  <Header>\n    <Authentication>\n      <Login>{{login}}</Login>\n      <NowUtc>{{now_utc}}</NowUtc>\n      <Signature>{{sig_xml}}</Signature>\n    </Authentication>\n  </Header>\n  <ProjectCustomerSupportRequest>\n    <ProjectID>{{project_id}}</ProjectID>\n    <MobilePhoneCustomer>\n      <MSISDN>{{msisdn}}</MSISDN>\n    </MobilePhoneCustomer>\n  </ProjectCustomerSupportRequest>\n</Request>"
            },
            "url": {
              "raw": "{{base_url}}/API/XML/InvoiceManagementService.ashx",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "API",
                "XML",
                "InvoiceManagementService.ashx"
              ]
            },
            "description": "Поддерживается ли абонент проектом."
          }
        }
      ]
    },
    {
      "name": "REST JSON v3",
      "description": "Только песочница: в бою этого протокола нет.",
      "item": [
        {
          "name": "createInvoice",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  pm.collectionVariables.set('invoice_id', pm.response.json().data.invoice_id);",
                  "}",
                  "pm.test('инвойс создан', () => pm.response.to.have.status(201));"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customer\": { \"type\": \"mobile_phone\", \"msisdn\": \"{{msisdn}}\" },\n  \"order\": {\n    \"merchant_order_id\": \"POSTMAN-{{$timestamp}}\",\n    \"price\": { \"amount\": 9900, \"currency\": \"RUB\", \"vat_included\": true }\n  },\n  \"test_info\": { \"expected_billing_result\": \"Success\", \"callback_delay_seconds\": 0 }\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices"
              ]
            },
            "description": "merchant_order_id лежит внутри order, а не на верхнем уровне.\n\nПесочница дедуплицирует по клиенту: пока прежний инвойс этого абонента не закрыт, повторный запрос вернёт 409 INVOICE_ALREADY_EXISTS с id существующего в error.details.invoice_id."
          }
        },
        {
          "name": "authorizeInvoice (PIN 1234)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{ \"pin_code\": \"1234\" }"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices/{{invoice_id}}/authorize",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices",
                "{{invoice_id}}",
                "authorize"
              ]
            },
            "description": "Три попытки. После третьей неверной инвойс не примет авторизацию даже с верным PIN."
          }
        },
        {
          "name": "getInvoice",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices/{{invoice_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices",
                "{{invoice_id}}"
              ]
            }
          }
        },
        {
          "name": "refundInvoice",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{}"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices/{{invoice_id}}/refund",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices",
                "{{invoice_id}}",
                "refund"
              ]
            },
            "description": "Только по оплаченному инвойсу. Иначе 422 INVOICE_NOT_PAID."
          }
        },
        {
          "name": "createContract",
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  pm.collectionVariables.set('contract_id', pm.response.json().data.contract_id);",
                  "}"
                ]
              }
            }
          ],
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customer\": { \"type\": \"mobile_phone\", \"msisdn\": \"{{msisdn}}\" },\n  \"merchant_contract_id\": \"POSTMAN-CONTRACT-{{$timestamp}}\"\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/contracts",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "contracts"
              ]
            },
            "description": "Здесь merchant_contract_id лежит на ВЕРХНЕМ уровне тела. В createInvoice — внутри блока contract. Мок тело не валидирует: поле не на своём месте даёт 200 и пустое эхо."
          }
        },
        {
          "name": "authorizeContract (PIN 1234)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{ \"pin_code\": \"1234\" }"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/contracts/{{contract_id}}/authorize",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "contracts",
                "{{contract_id}}",
                "authorize"
              ]
            }
          }
        },
        {
          "name": "checkCustomerBillingSupport",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{ \"customer\": { \"type\": \"mobile_phone\", \"msisdn\": \"{{msisdn}}\" } }"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/billing/check",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "billing",
                "check"
              ]
            },
            "description": "Вызов без побочных эффектов — удобно для первой проверки подписи."
          }
        },
        {
          "name": "cancelInvoice",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{}"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices/{{invoice_id}}/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices",
                "{{invoice_id}}",
                "cancel"
              ]
            },
            "description": "Отмена неоплаченного счёта. Оплаченный отменить нельзя — 422 INVOICE_NOT_PAID даёт возврат."
          }
        },
        {
          "name": "getInvoiceByMerchantOrderId",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices?merchant_order_id={{merchant_order_id}}",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices"
              ],
              "query": [
                {
                  "key": "merchant_order_id",
                  "value": "{{merchant_order_id}}"
                }
              ]
            },
            "description": "Поиск счёта по номеру заказа. При подписи v4 значение из строки запроса входит в requestPayload."
          }
        },
        {
          "name": "cancelContract",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{}"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/contracts/{{contract_id}}/cancel",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "contracts",
                "{{contract_id}}",
                "cancel"
              ]
            },
            "description": "Отмена контракта. После неё тот же merchant_contract_id можно привязать заново."
          }
        }
      ]
    },
    {
      "name": "Виджет оплаты (разовые платежи)",
      "item": [
        {
          "name": "1. createInvoice — карта (даёт токен виджета)",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "X-Login",
                "value": "{{login}}"
              },
              {
                "key": "X-Timestamp",
                "value": "{{ts_iso}}"
              },
              {
                "key": "X-Signature-Version",
                "value": "3"
              },
              {
                "key": "X-Signature",
                "value": "{{sig_json}}"
              }
            ],
            "body": {
              "mode": "raw",
              "raw": "{\n  \"customer\": { \"type\": \"undefined_bank_card\", \"merchant_customer_id\": \"POSTMAN-{{$timestamp}}\" },\n  \"order\": {\n    \"merchant_order_id\": \"POSTMAN-W-{{$timestamp}}\",\n    \"price\": { \"amount\": \"100.00\", \"currency\": \"RUB\", \"vat_included\": true }\n  }\n}"
            },
            "url": {
              "raw": "{{base_url}}/api/v3/projects/{{project_id}}/invoices",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "api",
                "v3",
                "projects",
                "{{project_id}}",
                "invoices"
              ]
            },
            "description": "Токен виджета (`authorization.token`) выдаётся только карточной ветке: у DCB виджета нет."
          },
          "event": [
            {
              "listen": "test",
              "script": {
                "type": "text/javascript",
                "exec": [
                  "if (pm.response.code === 201) {",
                  "  const data = pm.response.json().data;",
                  "  pm.collectionVariables.set('widget_invoice_id', data.invoice_id);",
                  "  pm.collectionVariables.set('widget_token', data.authorization.token);",
                  "}",
                  "pm.test('карточный счёт создан, токен виджета сохранён', () => pm.response.to.have.status(201));"
                ]
              }
            }
          ]
        },
        {
          "name": "2. sbpWidgetCreateQr",
          "request": {
            "method": "POST",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{widget_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/Card/Handlers/{{widget_invoice_id}}/sbp",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "Card",
                "Handlers",
                "{{widget_invoice_id}}",
                "sbp"
              ]
            },
            "description": "Данные QR по счёту. Идемпотентно: второй вызов отдаёт тот же QR — новая сессия оставила бы плательщика с двумя кодами."
          }
        },
        {
          "name": "3. sbpWidgetStatus",
          "request": {
            "method": "GET",
            "header": [
              {
                "key": "Authorization",
                "value": "Bearer {{widget_token}}"
              }
            ],
            "url": {
              "raw": "{{base_url}}/Card/Handlers/{{widget_invoice_id}}/status",
              "host": [
                "{{base_url}}"
              ],
              "path": [
                "Card",
                "Handlers",
                "{{widget_invoice_id}}",
                "status"
              ]
            },
            "description": "Опрос статуса оплаты: pending → paid | failed | expired."
          }
        }
      ]
    }
  ]
}
