Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a412af3e07 | |||
| 9b62a59705 | |||
|
|
d4db68f2e7 | ||
|
|
ea374d2696 | ||
|
|
13c91ad108 | ||
|
|
3cf15b7913 | ||
|
|
a05a6506e8 | ||
|
|
4f52a189c7 | ||
|
|
b7b2a8fd61 | ||
|
|
e2adc8d530 | ||
|
|
c070297211 | ||
|
|
706fcb01b2 | ||
| 7a6b13b12d |
17
_docs/alfabank/README.md
Normal file
17
_docs/alfabank/README.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Alfa Bank SDK Documentation
|
||||
|
||||
Добро пожаловать в структурированную документацию Alfa API.
|
||||
|
||||
## Основные разделы
|
||||
|
||||
### 1. [Pay-in & KYC (Alfa API / Alfa ID)](payin_and_kyc/README.md)
|
||||
Документация по приему платежей, идентификации пользователей через Alfa ID и управлению номинальными счетами.
|
||||
|
||||
### 2. [QR Payout (СБП C2B)](qr_payout/0_full.md)
|
||||
Инструкции по интеграции Системы Быстрых Платежей (СБП) для QR-оплаты.
|
||||
|
||||
## Быстрая навигация
|
||||
- [Карта всех эндпоинтов](endpoints.md)
|
||||
- [Как подключиться](payin_and_kyc/Подключение_к_Alfa_API/how_to_connect.md)
|
||||
- [Песочница](payin_and_kyc/Песочница/sandbox_intro.md)
|
||||
- [Чек-лист готовности](payin_and_kyc/Общая_информация/check-list.md)
|
||||
71
_docs/alfabank/endpoints.md
Normal file
71
_docs/alfabank/endpoints.md
Normal file
@@ -0,0 +1,71 @@
|
||||
# Карта эндпоинтов Alfa API
|
||||
|
||||
| Метод | Путь | Файл | Описание |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `GET` | `/api/endpoint` | [Управление API Key](payin_and_kyc/Портал_разработчика/api_key_managment.md) | |
|
||||
| `GET` | `/api/endpoint` | [TLS-сертификат](payin_and_kyc/Подключение_к_Alfa_API/tls-cert.md) | |
|
||||
| `POST` | `/api/gd/v1/crypto-service/certificates` | [Добавление нового сертификата](payin_and_kyc/Транспортная_подпись_и_шифрование/managing-certificates/post-certificates.md) | |
|
||||
| `GET` | `/api/gd/v1/crypto-service/certificates` | [Получение сертификатов](payin_and_kyc/Транспортная_подпись_и_шифрование/managing-certificates/get-certificates.md) | |
|
||||
| `PATCH` | `/api/gd/v1/crypto-service/certificates/{id}` | [Обновление сертификата](payin_and_kyc/Транспортная_подпись_и_шифрование/managing-certificates/patch-certificates.md) | |
|
||||
| `POST` | `/api/na/jp/v1/beneficiaries` | [Создание запроса на регистрацию бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/add-beneficiary.md) | |
|
||||
| `GET` | `/api/na/jp/v1/beneficiaries/requests/{requestId}/status` | [Получение статуса запроса](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/get-request-status.md) | |
|
||||
| `GET` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}` | [Получение информации о бенефициаре `H2H`](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/get-beneficiary.md) | |
|
||||
| `PUT` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}` | [Создание запроса на изменение информации о бенефициаре](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/change-beneficiary.md) | |
|
||||
| `GET` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}/balance` | [Получение информации о балансе бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/get-balance.md) | |
|
||||
| `POST` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}/requisites` | [Добавление платёжных реквизитов бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/add-requisites.md) | |
|
||||
| `GET` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}/requisites` | [Получение платёжных реквизитов бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/get-requisites.md) | |
|
||||
| `PATCH` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}/requisites/{requisiteId}` | [Изменение признаков платёжных реквизитов бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/change-requisites.md) | |
|
||||
| `POST` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}/scoring` | [Создание запроса на проверку бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/beneficiary-scoring.md) | |
|
||||
| `GET` | `/api/na/jp/v1/beneficiaries/{beneficiaryId}/transactions` | [Получение списка денежных операций бенефициара](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Бенефициары/get-transactions.md) | |
|
||||
| `POST` | `/api/na/jp/v1/deals` | [Регистрация сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/add-deal.md) | |
|
||||
| `PATCH` | `/api/na/jp/v1/deals/action` | [Выполнение действия по сделке](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/deal-actions.md) | |
|
||||
| `POST` | `/api/na/jp/v1/deals/steps` | [Выполнение действия по этапам сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/add-step.md) | |
|
||||
| `PATCH` | `/api/na/jp/v1/deals/steps/contractors` | [Выполнение действия по участникам этапа сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/step-contractors.md) | |
|
||||
| `GET` | `/api/na/jp/v1/deals/{dealId}` | [Получение информации о сделке](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/get-deal.md) | |
|
||||
| `PATCH` | `/api/na/jp/v1/deals/{dealId}/is-valid` | [Проверка возможности осуществления выплат по сделке](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/deal-is-valid.md) | |
|
||||
| `GET` | `/api/na/jp/v1/deals/{dealId}/payoffs` | [Получение списка платежей по сделке](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/get-deal-payoffs.md) | |
|
||||
| `GET` | `/api/na/jp/v1/deals/{dealId}/requests/{requestId}/status` | [Получение статуса запроса на завершение этапа сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/get-deal-request-status.md) | |
|
||||
| `GET` | `/api/na/jp/v1/deals/{dealId}/steps` | [Получение списка этапов сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/get-steps.md) | |
|
||||
| `GET` | `/api/na/jp/v1/deals/{dealId}/steps/{stepId}` | [Получение информации об этапе сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/get-step.md) | |
|
||||
| `GET` | `/api/na/jp/v1/deals/{dealId}/steps/{stepId}/contractors` | [Получение информации об участниках этапа сделки](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/get-contractors.md) | |
|
||||
| `GET` | `/api/na/jp/v1/nominal-accounts` | [Получение списка номинальных счетов](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/get-nominal-accounts.md) | |
|
||||
| `POST` | `/api/na/jp/v1/payoffs` | [Создание запроса на выплату с номинального счёта](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Выплаты/payoff.md) | |
|
||||
| `GET` | `/api/na/jp/v1/unidentified-transactions` | [Получение списка неидентифицированных пополнений номинального счёта](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Идентификация_пополнений/get-unidentified-transactions.md) | |
|
||||
| `POST` | `/api/na/jp/v1/unidentified-transactions/{id}/identify` | [Создание запроса на идентификацию пополнения номинального счёта](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Идентификация_пополнений/identify.md) | |
|
||||
| `GET` | `/api/na/jp/v1/unidentified-transactions/{id}/identify/{identifyId}` | [Получение статуса запроса на идентификацию пополнения номинального счёта](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Идентификация_пополнений/get-identify-request-status.md) | |
|
||||
| `POST` | `/api/na/jp/v1/unidentified-transactions/{id}/refunds` | [Создание запроса на возврат неидентифицированного пополнения](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Идентификация_пополнений/transaction-refund.md) | |
|
||||
| `GET` | `/api/na/jp/v1/unidentified-transactions/{id}/refunds/{refundId}` | [Получение статуса запроса на возврат неидентифицированного пополнения](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Идентификация_пополнений/get-transaction-refund-request-status.md) | |
|
||||
| `POST` | `/api/na/jp/v1/universal-recipients` | [Создание запроса на регистрацию универсального реципиента](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Универсальные_реципиенты/add-universal_recipient.md) | |
|
||||
| `GET` | `/api/na/jp/v1/universal-recipients` | [Получение списка универсальных реципиентов номинального счёта](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Универсальные_реципиенты/get-universal_recipients_list.md) | |
|
||||
| `GET` | `/api/na/jp/v1/universal-recipients/{universalRecipientId}` | [Получение информации об универсальном реципиенте](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Универсальные_реципиенты/get-universal_recipient.md) | |
|
||||
| `POST` | `/api/na/jp/v1/universal-recipients/{universalRecipientId}/requisites` | [Добавление платёжных реквизитов универсального реципиента](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Универсальные_реципиенты/add-requisites.md) | |
|
||||
| `GET` | `/api/na/jp/v1/universal-recipients/{universalRecipientId}/requisites` | [Получение платёжных реквизитов универсального реципиента](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Универсальные_реципиенты/get-requisites.md) | |
|
||||
| `PATCH` | `/api/na/jp/v1/universal-recipients/{universalRecipientId}/requisites/{requisiteId}` | [Изменение признаков платёжных реквизитов универсального реципиента](payin_and_kyc/продукты_и_сервисы/Номинальные_счета/Контрагенты/Универсальные_реципиенты/change-requisites.md) | |
|
||||
| `POST` | `/api/signature-encryption-tests/json` | [Формат исходного сообщения JSON](payin_and_kyc/Песочница/signature-encryption-tests/jws_POST.md) | |
|
||||
| `POST` | `/api/signature-encryption-tests/text` | [Формат исходного сообщения TXT](payin_and_kyc/Песочница/signature-encryption-tests/text_POST.md) | |
|
||||
| `POST` | `/api/signature-encryption-tests/xml` | [Формат исходного сообщения XML](payin_and_kyc/Песочница/signature-encryption-tests/xmldsig_POST.md) | |
|
||||
| `GET` | `/api/v1/endpoint` | [Начало работы в песочнице](payin_and_kyc/Песочница/sandbox_intro.md) | |
|
||||
| `POST` | `/api/v1/webhook-events` | [Партнёрский метод для получения вебхуков](payin_and_kyc/Вебхуки/partner-webhook.md) | |
|
||||
| `POST` | `/api/v1/webhooks` | [Создание вебхука](payin_and_kyc/Вебхуки/create-webhook.md) | |
|
||||
| `POST` | `/api/v1/webhooks-events` | [Проверка работы вебхука](payin_and_kyc/Песочница/check-webhook/checking_the_webhook_eg_transactions.md) | |
|
||||
| `DELETE` | `/api/v1/webhooks/f9f8c674-7a2a-4297-bdb8-ddd3013de3a3?object=ul_transaction_default` | [Удаление вебхука](payin_and_kyc/Вебхуки/delete-webhook.md) | |
|
||||
| `DELETE` | `/api/v1/webhooks/{id}` | [Удаление вебхука](payin_and_kyc/Вебхуки/delete-webhook.md) | |
|
||||
| `PUT` | `/api/v2/webhooks/f9f8c674-7a2a-4297-bdb8-ddd3013de3a3` | [Редактирование вебхука](payin_and_kyc/Вебхуки/edit-webhook.md) | |
|
||||
| `GET` | `/api/v2/webhooks/f9f8c674-7a2a-4297-bdb8-ddd3013de3a3?object=ul_transaction_default` | [Получение вебхука](payin_and_kyc/Вебхуки/get-webhook.md) | |
|
||||
| `GET` | `/api/v2/webhooks/{id}` | [Получение вебхука](payin_and_kyc/Вебхуки/get-webhook.md) | |
|
||||
| `PUT` | `/api/v2/webhooks/{id}` | [Редактирование вебхука](payin_and_kyc/Вебхуки/edit-webhook.md) | |
|
||||
| `GET` | `/api/v2/webhooks?offset=20&limit=10&object=ul_transaction_default` | [Получение списка вебхуков](payin_and_kyc/Вебхуки/get-webhooks-list.md) | |
|
||||
| `PUT` | `/filebox/secure-file-transfer.incoming-files.to-processing/12345678-90AB-CDEF-1234-1234567890AB?X-Amz-Date=20230608T152952Z&X-Amz-Expires=3600&X-Amz-Credential=secure-file-transfer%2F20230608%2Fbaas%2Fs3%2Faws4_request&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Signature=36ef1ccf28bdf6e54710fc3c1dd235c8f383275c2bbb0c9db365da272d3c24a8` | [Загрузка файла](payin_and_kyc/Обмен_файлами/upload.md) | |
|
||||
| `GET` | `/filebox/secure-file-transfer.incoming-files.to-processing/12345678-90ab-cdef-1234-1234567890ab?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Date=20230608T152952Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Credential=secure-file-transfer%2F20230608%2Fdev%2Fs3%2Faws4_request&X-Amz-Signature=e78c051fcff1017a68795620c20e50db33126ab8374c2ee9644ef4743b3625c6` | [Скачивание файла](payin_and_kyc/Обмен_файлами/download.md) | |
|
||||
| `GET` | `/oidc/authorize?response_type=code&client_id=0cee0683-85ae-49f2-a63d-29f97aad1911&redirect_uri=https%3A%2F%2Fwwww.partner.ru%2Fcode&scope=openid&state=abcdef` | [Получение кода авторизации](payin_and_kyc/Alfa_ID/Authorization_Code_Flow/obtaining_an_authorization_code_GET.md) | |
|
||||
| `GET` | `/oidc/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&state={state}` | [Получение кода авторизации](payin_and_kyc/Alfa_ID/Authorization_Code_Flow/obtaining_an_authorization_code_GET.md) | |
|
||||
| `GET` | `/oidc/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&state={state}` | [Получение кода авторизации](payin_and_kyc/Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/obtaining_an_authorization_code.md) | |
|
||||
| `GET` | `/oidc/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={scope}&state={state}` | [Получение кода авторизации](payin_and_kyc/Alfa_ID/Authorization_Code_Flow_for_Holding_Companies/getting_authorization_token.md) | |
|
||||
| `GET` | `/oidc/client-consents` | [Данные по согласиям пользователей](payin_and_kyc/Alfa_ID/expansion/client-consents_GET.md) | |
|
||||
| `POST` | `/oidc/clients/{clientId}/client-secret` | [Client secret](payin_and_kyc/Подключение_к_Alfa_API/client_secret.md) | |
|
||||
| `POST` | `/oidc/revoke` | [Отзыв токена доступа](payin_and_kyc/Alfa_ID/expansion/revoke-token_POST.md) | |
|
||||
| `POST` | `/oidc/token` | [Обновление токена доступа](payin_and_kyc/Alfa_ID/Authorization_Code_Flow/access_token_refresh_POST.md) | |
|
||||
| `POST` | `/oidc/token` | [Как использовать CCF (Client Credentials Flow)](payin_and_kyc/Alfa_ID/client_credentials_flow/how_to_use_ccf.md) | |
|
||||
| `POST` | `/oidc/token` | [Обновление токена доступа](payin_and_kyc/Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/refreshing_access_token_POST.md) | |
|
||||
| `POST` | `/oidc/token` | [Получение токена доступа `H2H` `POST`](payin_and_kyc/Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/geting_access_token_POST.md) | |
|
||||
| `GET` | `/oidc/userinfo` | [Получение профиля представителя пользователя `B2B` `B2C`](payin_and_kyc/Alfa_ID/Authorization_Code_Flow/obtaining_a_user_representative_profile.md) | |
|
||||
30
_docs/alfabank/payin_and_kyc/README.md
Normal file
30
_docs/alfabank/payin_and_kyc/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Pay-in & KYC (Alfa API / Alfa ID)
|
||||
|
||||
Этот раздел содержит документацию по интеграции с банковскими сервисами Alfa-Bank для B2B, B2C и H2H сегментов.
|
||||
|
||||
## Навигация по разделам
|
||||
|
||||
### 🚀 [Начало работы](Подключение_к_Alfa_API/how_to_connect.md)
|
||||
- [Как подключиться](Подключение_к_Alfa_API/how_to_connect.md)
|
||||
- [Подписание договора](Подключение_к_Alfa_API/contract_signing.md)
|
||||
- [Чек-лист готовности](Общая_информация/check-list.md)
|
||||
|
||||
### 🆔 [Alfa ID](Alfa_ID/what_is_alfa_id.md)
|
||||
- [Что такое Alfa ID](Alfa_ID/what_is_alfa_id.md)
|
||||
- [Authorization Code Flow](Alfa_ID/Authorization_Code_Flow/how_to_use_ACF.md)
|
||||
- [H2H Аутентификация](Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md)
|
||||
|
||||
### 💳 [Номинальные счета](продукты_и_сервисы/Номинальные_счета/intro.md)
|
||||
- [Введение](продукты_и_сервисы/Номинальные_счета/intro.md)
|
||||
- [Выплаты](продукты_и_сервисы/Номинальные_счета/Выплаты/intro.md)
|
||||
- [Безопасные сделки](продукты_и_сервисы/Номинальные_счета/Безопасные_сделки/intro.md)
|
||||
- [Идентификация пополнений](продукты_и_сервисы/Номинальные_счета/Идентификация_пополнений/how_it_works_intro.md)
|
||||
|
||||
### 🛠 [Инструменты и Безопасность](Общая_информация/authorization.md)
|
||||
- [Авторизация (API Key / Alfa ID)](Общая_информация/authorization.md)
|
||||
- [Вебхуки](Вебхуки/webhooks_intro.md)
|
||||
- [Транспортная подпись и шифрование](Транспортная_подпись_и_шифрование/signature-encryption-intro.md)
|
||||
- [Песочница](Песочница/sandbox_intro.md)
|
||||
|
||||
---
|
||||
[Все эндпоинты](../endpoints.md)
|
||||
@@ -1,7 +1,6 @@
|
||||
Ниже представлен сконвертированный из HTML текст документации в формате Markdown. Все ссылки сохранены, структура таблиц и примеров кода приведена к удобному для чтения виду.
|
||||
|
||||
---
|
||||
|
||||
|
||||
# Удаление вебхука
|
||||
|
||||
**Теги:** `B2B` `B2C` `H2H`
|
||||
@@ -14,7 +13,7 @@
|
||||
| **Пром** | `DELETE https://baas.alfabank.ru/api/v1/webhooks/{id}` |
|
||||
|
||||
### Scope
|
||||
`scope` события, на которое подписываетесь, с допустимыми значениями можно посмотреть [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/webhooks/webhooks).
|
||||
`scope` события, на которое подписываетесь, с допустимыми значениями можно посмотреть [здесь](webhooks_intro.md).
|
||||
|
||||
---
|
||||
|
||||
@@ -23,7 +22,7 @@
|
||||
### HEADERS
|
||||
| Атрибут | Тип | Обязательность | Описание |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Authorization** | string | **required** | Bearer {access_token}, полученный по [Authorization Code Flow](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf/articles/intro/intro) / [Authorization Code Flow H2H](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf-h2h/articles/intro/intro) |
|
||||
| **Authorization** | string | **required** | Bearer {access_token}, полученный по [Authorization Code Flow](../Alfa_ID/Authorization_Code_Flow/how_to_use_ACF.md) / [Authorization Code Flow H2H](../Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md) |
|
||||
| **Accept** | string | **required** | `application/json` |
|
||||
| **Content-Type** | string | optional | `application/json` |
|
||||
|
||||
@@ -95,4 +94,4 @@ curl -X DELETE https://baas.alfabank.ru/api/v1/webhooks/f9f8c674-7a2a-4297-bdb8-
|
||||
|
||||
---
|
||||
**Навигация:**
|
||||
[← Редактирование вебхука](https://developers.alfabank.ru/products/alfa-api/documentation/articles/webhooks/articles/edit-webhook/v2/edit-webhook) | [Получение вебхука →](https://developers.alfabank.ru/products/alfa-api/documentation/articles/webhooks/articles/get-webhook/v1/get-webhook)
|
||||
[← Редактирование вебхука](edit-webhook.md) | [Получение вебхука →](get-webhook.md)
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
|
||||
Это упрощённый способ авторизации запросов без аутентификации сотрудников вашей организации, который не требует регулярного обновления ключа доступа. Подходит для выполнения операций по своей организации. Контроль безопасности обеспечивается за счёт того, что запросы принимаются только с ваших доверенных серверов.
|
||||
|
||||
Доступные с помощью этого способа авторизации продукты и сервисы можно посмотреть [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/selfservice/articles/api-key/api-key).
|
||||
Доступные с помощью этого способа авторизации продукты и сервисы можно посмотреть [здесь](../API_Key/api-key.md).
|
||||
|
||||
Использование упрощённого способа авторизации будет оптимальным вариантом, если у вас H2H-интеграция, использующая продукты и сервисы, доступные с помощью `API Key` , и вам не требуется аутентификация сотрудников для доступа к продуктам и сервисам Alfa API.
|
||||
|
||||
Подробнее о способах авторизации можно прочитать в статьях ниже.
|
||||
|
||||
[Alfa ID](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/intro/intro)[API Key](https://developers.alfabank.ru/products/alfa-api/documentation/articles/api-key/api-key)
|
||||
[Alfa ID](../Alfa_ID/what_is_alfa_id.md) [API Key](../API_Key/api-key.md)
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
Шифрование канала происходит исходя из выбора метода шифрования. Это может быть:
|
||||
|
||||
•шифрование с применением сертификата RSA (как применить RSA-сертификат смотрите в разделе [Требования к сертификату](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/tls/tls));•шифрование с применением сертификатов ГОСТ (раздел в подготовке).Выбор того или иного метода шифрования канала определяется критичностью данных:
|
||||
•шифрование с применением сертификата RSA (как применить RSA-сертификат смотрите в разделе [Требования к сертификату](../Подключение_к_Alfa_API/tls-cert.md));•шифрование с применением сертификатов ГОСТ (раздел в подготовке).Выбор того или иного метода шифрования канала определяется критичностью данных:
|
||||
|
||||
•если персональные данные не передаются, то TLS RSA будет самым простым, дешёвым и гибким инструментом интеграции;•если персональные данные передаются, то обязательно использование сертификата ГОСТ. Партнёр API может выбирать, что использовать - TLS ГОСТ или вариант с ФПСУ ГОСТ.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
## Чек-лист готовности к тестовой интеграции
|
||||
|
||||
1. **Заключите соглашение и договор**
|
||||
Заключите соглашение о конфиденциальности и неразглашении информации, договор на информационно-технологическое взаимодействие с банком и подпишите приложения к нему. Подробнее в шаге 1 [инструкции по подключению](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/instruction/instruction).
|
||||
Заключите соглашение о конфиденциальности и неразглашении информации, договор на информационно-технологическое взаимодействие с банком и подпишите приложения к нему. Подробнее в шаге 1 [инструкции по подключению](../Подключение_к_Alfa_API/how_to_connect.md).
|
||||
|
||||
2. **Получите тестовые client_id и scope**
|
||||
Подробнее в шаге 2 [инструкции по подготовке к работе с песочницей](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/instruction/instruction).
|
||||
Подробнее в шаге 2 [инструкции по подготовке к работе с песочницей](../Подключение_к_Alfa_API/how_to_connect.md).
|
||||
|
||||
3. **Установите тестовый TLS-сертификат, сертификаты Минцифры и проверьте доступ до Swagger UI**
|
||||
Подробнее в шагах 3-5 [инструкции по подготовке к работе с песочницей](https://developers.alfabank.ru/products/alfa-api/documentation/articles/sandbox/sandbox).
|
||||
Подробнее в шагах 3-5 [инструкции по подготовке к работе с песочницей](../Песочница/sandbox_intro.md).
|
||||
|
||||
4. **Получите тестовый client_secret**
|
||||
Подробнее [на странице Client secret](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/clientsecret/clientsecret).
|
||||
Подробнее [на странице Client secret](../Подключение_к_Alfa_API/client_secret.md).
|
||||
|
||||
5. **Реализуйте и протестируйте интеграцию Alfa ID и Alfa API в песочнице**
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
|
||||
|
||||
2. **Создайте интеграцию в проме на Портале разработчика**
|
||||
Подробнее [на странице Создание интеграции в проме](https://developers.alfabank.ru/products/alfa-api/documentation/articles/selfservice/articles/prod/prod)
|
||||
Подробнее [на странице Создание интеграции в проме](../Портал_разработчика/creating_prod_integration.md)
|
||||
|
||||
3. **Выпустите TLS-сертификат**
|
||||
Подробнее [на странице TLS-сертификат](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/tls/tls)
|
||||
Подробнее [на странице TLS-сертификат](../Подключение_к_Alfa_API/tls-cert.md)
|
||||
|
||||
4. **Получите client_secret**
|
||||
Подробнее [на странице Client secret](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/clientsecret/clientsecret)
|
||||
Подробнее [на странице Client secret](../Подключение_к_Alfa_API/client_secret.md)
|
||||
|
||||
5. **Начните использовать Alfa ID и Alfa API**
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
Перед началом работы рекомендуем внимательно ознакомиться с нашей документацией, которая содержит всю необходимую информацию для успешной интеграции.
|
||||
|
||||
[Подключение к Alfa API](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/connection)
|
||||
[Подключение к Alfa API](../Подключение_к_Alfa_API/how_to_connect.md)
|
||||
|
||||
[Песочница](https://developers.alfabank.ru/products/alfa-api/documentation/articles/sandbox/sandbox)
|
||||
[Песочница](../Песочница/sandbox_intro.md)
|
||||
|
||||
## Преимущества
|
||||
|
||||
|
||||
@@ -82,4 +82,4 @@ invalid_request
|
||||
Сортировка в пагинации происходит следующим образом: вверху списка возвращаются новые записи, внизу - старые записи.
|
||||
|
||||
---
|
||||
[Версионирование](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/version/version) | [Термины и определения](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/terms/terms)
|
||||
[Версионирование](vensioning.md) | [Термины и определения](terms_and_definitions.md)
|
||||
|
||||
@@ -61,5 +61,5 @@
|
||||
**Scopes** – это общий набор операций и/или клэймов.
|
||||
|
||||
---
|
||||
[Пагинация](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/pagination/pagination) | [Что это и для чего нужно](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/intro/intro)
|
||||
[Пагинация](pagination.md) | [Что это и для чего нужно](Сертификаты_Минцифры/what_it_is_and_what_it_is_for.md)
|
||||
|
||||
|
||||
@@ -57,4 +57,4 @@ B2BB2CH2H# Сертификаты для Android
|
||||
|
||||
Очистите кэш вашего браузераОчистите кэш браузера на устройстве, с которого осуществляется доступ. Это необходимо для корректной работы с ресурсами, защищёнными сертификатами безопасности Минцифры.
|
||||
|
||||
[Что это и для чего нужно](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/intro/intro)[Сертификаты для iOS](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/ios/ios)
|
||||
[Что это и для чего нужно](what_it_is_and_what_it_is_for.md) [Сертификаты для iOS](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/ios/ios)
|
||||
@@ -78,4 +78,4 @@ B2BB2CH2H# Сертификаты для Linux
|
||||
|
||||
Очистите кэш вашего браузераОчистите кэш браузера на устройстве, с которого осуществляется доступ. Это необходимо для корректной работы с ресурсами, защищёнными сертификатами безопасности Минцифры.
|
||||
|
||||
[Сертификаты для MacOS](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/macos/macos)[Как подключить](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/instruction/instruction)
|
||||
[Сертификаты для MacOS](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/macos/macos) [Как подключить](../../Подключение_к_Alfa_API/how_to_connect.md)
|
||||
@@ -19,4 +19,4 @@
|
||||
Ответы на часто задаваемые вопросы можно посмотреть здесь.
|
||||
|
||||
---
|
||||
[Термины и определения](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/terms/terms) | [Сертификаты для Android](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/android/android)
|
||||
[Термины и определения](../terms_and_definitions.md) | [Сертификаты для Android](for_android.md)
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
---
|
||||
|
||||
### Описание процесса
|
||||
* **RSA-сертификат:** Процесс формирования и подписания описан [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/signature-encryption/articles/signature/articles/text-rsa/text-rsa), а шифрования — [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/signature-encryption/articles/encryption/articles/text-rsa/text-rsa).
|
||||
* **ГОСТ-сертификат:** Процесс формирования и подписания описан [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/signature-encryption/articles/signature/articles/text-gost/text-gost), а шифрования — [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/signature-encryption/articles/encryption/articles/text-gost/text-gost).
|
||||
* **RSA-сертификат:** Процесс формирования и подписания описан [здесь](../../Транспортная_подпись_и_шифрование/transport-signature/json-rsa.md), а шифрования — [здесь](../../Транспортная_подпись_и_шифрование/encription/json-rsa.md).
|
||||
* **ГОСТ-сертификат:** Процесс формирования и подписания описан [здесь](../../Транспортная_подпись_и_шифрование/transport-signature/json-ghost.md), а шифрования — [здесь](../../Транспортная_подпись_и_шифрование/encription/json-ghost.md).
|
||||
* **Тестирование:** Подписание запроса и дешифрование ответа происходит с использованием закрытого ключа. Для тестов используйте [закрытый ключ](https://developers.alfabank.ru/assets/developers-portal.docs.alfa-api/articles/sandbox/articles/signature/articles/text/v1/files/sandbox_alfa_test_jwt_2026.zip) (пароль уточняйте у персонального менеджера).
|
||||
|
||||
> **⚠️ Внимание**
|
||||
|
||||
@@ -8,19 +8,19 @@
|
||||
> Если вы ещё не являетесь клиентом Альфа-Банка, то для подключения к Alfa API вам необходимо открыть [счёт](https://alfabank.ru/sme/quick/docstariffs/), оформить [расчётно-кассовое обслуживание](https://alfabank.ru/sme/) и подключить [Альфа-Бизнес](https://alfabank.ru/corporate/rko/internet-bank/#form).
|
||||
|
||||
1. **Подпишите договор**
|
||||
[Подпишите договор](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/onboarding/onboarding).
|
||||
[Подпишите договор](contract_signing.md).
|
||||
|
||||
Комиссия за подключение и использование не взимается. Вопросы по заключению договора можно направлять на почту [alfa_api@alfabank.ru](https://developers.alfabank.rumailto:alfa_api@alfabank.ru).
|
||||
Комиссия за подключение и использование не взимается. Вопросы по заключению договора можно направлять на почту [alfa_api@alfabank.ru](mailto:alfa_api@alfabank.ru).
|
||||
|
||||
2. **Проверьте тестовую интеграцию**
|
||||
Получите тестовые учётные данные и настройте тестовую интеграцию [на Портале разработчика](https://developers.alfabank.ru/products/alfa-api/documentation/articles/selfservice/articles/test/test), реализуйте и протестируйте аутентификацию в Alfa ID и вызов методов Alfa API [в песочнице](https://developers.alfabank.ru/products/alfa-api/documentation/articles/sandbox/sandbox).
|
||||
Получите тестовые учётные данные и настройте тестовую интеграцию [на Портале разработчика](../Портал_разработчика/testing.md), реализуйте и протестируйте аутентификацию в Alfa ID и вызов методов Alfa API [в песочнице](../Песочница/sandbox_intro.md).
|
||||
|
||||
3. **Подготовьтесь к промышленной интеграции**
|
||||
Создайте интеграцию в проме, выпустите TLS-сертификат и `client_secret` . Подробнее [в инструкции](https://developers.alfabank.ru/products/alfa-api/documentation/articles/selfservice/articles/prod/prod).
|
||||
Создайте интеграцию в проме, выпустите TLS-сертификат и `client_secret` . Подробнее [в инструкции](../Портал_разработчика/creating_prod_integration.md).
|
||||
|
||||
4. **Используйте Alfa API**
|
||||
|
||||
Если вы ещё не являетесь клиентом Альфа-Банка, то для подключения к Alfa API вам необходимо открыть [счёт](https://alfabank.ru/sme/quick/docstariffs/), оформить [расчётно-кассовое обслуживание](https://alfabank.ru/sme/) и подключить [Альфа-Бизнес](https://alfabank.ru/corporate/rko/internet-bank/#form).
|
||||
|
||||
---
|
||||
[← Сертификаты для Linux](https://developers.alfabank.ru/products/alfa-api/documentation/articles/specification/articles/certificate/articles/linux/linux) [← Подписание договора](https://developers.alfabank.ru/products/alfa-api/documentation/articles/connection/articles/onboarding/onboarding)
|
||||
[← Сертификаты для Linux](../Общая_информация/Сертификаты_Минцифры/for_linux.md) [← Подписание договора](contract_signing.md)
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
какой email технической поддержки ?
|
||||
|
||||
10:36
|
||||
|
||||
Доставлено
|
||||
|
||||
Для связи с технической поддержкой используйте электронную почту alfa\_api@alfabank.ru.
|
||||
|
||||
10:36
|
||||
|
||||
как происходит flow регистрации бенифициара ?
|
||||
|
||||
10:53
|
||||
|
||||
Доставлено
|
||||
|
||||
Для регистрации бенефициара необходимо выполнить следующие шаги:
|
||||
|
||||
1. 1.
|
||||
|
||||
**Создать запрос на регистрацию бенефициара** с помощью метода:
|
||||
|
||||
- •
|
||||
|
||||
**Песочница**: `POST https://sandbox.alfabank.ru/api/na/jp/v1/beneficiaries`
|
||||
|
||||
- •
|
||||
|
||||
**Пром**: `POST https://baas.alfabank.ru/api/na/jp/v1/beneficiaries`
|
||||
|
||||
|
||||
При этом нужно учитывать, что в зависимости от типа бенефициара поля запроса заполняются по-разному.
|
||||
|
||||
2. 2.
|
||||
|
||||
3. 3.
|
||||
|
||||
|
||||
При успешной регистрации бенефициару присваивается уникальный идентификатор — `beneficiaryId`.
|
||||
|
||||
**Важно:** учёт денежных средств на виртуальных счетах бенефициаров будет вестись корректно только при условии, что владелец номинального счёта не использует другие каналы вывода средств с номинального счёта (например, банк-клиент, платёжные поручения на бумажном носителе, сервисы Alfa API для осуществления переводов и другие).
|
||||
|
||||
Ссылки на документацию:
|
||||
|
||||
- •
|
||||
|
||||
- •
|
||||
|
||||
- •
|
||||
|
||||
|
||||
10:53
|
||||
|
||||
а как же socring ?
|
||||
|
||||
10:55
|
||||
|
||||
Доставлено
|
||||
|
||||
Для проверки актуальности ранее зарегистрированных данных о бенефициаре используются следующие методы:
|
||||
|
||||
1. 1.
|
||||
|
||||
**«Создание запроса на проверку бенефициара»** — инициирует процесс скоринга бенефициара.
|
||||
|
||||
2. 2.
|
||||
|
||||
**«Получение статуса запроса»** — позволяет отслеживать статус ранее созданного запроса на проверку.
|
||||
|
||||
|
||||
**Ссылки на документацию:**
|
||||
|
||||
- •
|
||||
|
||||
- •
|
||||
|
||||
|
||||
10:55
|
||||
|
||||
каким образом можно пополнить номинальный счёт компании ?
|
||||
|
||||
22:24
|
||||
|
||||
Доставлено
|
||||
|
||||
Депонент (бенефициар) может пополнить номинальный счёт удобным ему способом. После этого владелец номинального счёта должен идентифицировать поступившие денежные средства. Для этого владельцу счёта необходимо выполнить следующие шаги:
|
||||
|
||||
1. 1.
|
||||
|
||||
2. 2.
|
||||
|
||||
3. 3.
|
||||
|
||||
|
||||
22:25
|
||||
|
||||
каким образом можно пополнить номинальный счёт компании ?
|
||||
|
||||
22:25
|
||||
|
||||
Доставлено
|
||||
|
||||
Депонент (бенефициар) может пополнить номинальный счёт удобным ему способом. После этого владелец номинального счёта должен идентифицировать поступившие денежные средства. Для этого владельцу счёта необходимо выполнить следующие шаги:
|
||||
|
||||
1. 1.
|
||||
|
||||
2. 2.
|
||||
|
||||
3. 3.
|
||||
|
||||
|
||||
**Важно:** для работы с сервисом необходимо использовать электронную подпись. Допускается использование сертификата, выпущенного с помощью [сервиса «Электронная подпись»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/signature/articles/intro/intro), или сертификата УКЭП, выпущенного в любом аккредитованном УЦ.
|
||||
|
||||
Ссылка на статью с подробным описанием процесса: [Идентификация пополнений номинального счёта](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/intro/intro).
|
||||
|
||||
22:25
|
||||
|
||||
а что это значит "любым удобным способом"? каким например ?
|
||||
|
||||
22:25
|
||||
|
||||
Доставлено
|
||||
|
||||
В предоставленной документации нет конкретного перечня способов пополнения номинального счёта. Однако указано, что депонент (бенефициар) может пополнить номинальный счёт удобным ему способом. После этого владелец номинального счёта должен идентифицировать поступившие денежные средства с помощью специальных методов API.
|
||||
|
||||
Для идентификации пополнений владелец счёта может использовать следующие методы:
|
||||
|
||||
1. 1.
|
||||
|
||||
2. 2.
|
||||
|
||||
3. 3.
|
||||
|
||||
|
||||
Для более детальной информации о возможных способах пополнения номинального счёта рекомендуется обратиться на почту alfa\_api@alfabank.ru.
|
||||
|
||||
22:25
|
||||
@@ -0,0 +1,153 @@
|
||||
---
|
||||
title: "Интеграция с Альфа-Банком: API, документация, примеры кода"
|
||||
source: "https://developers.alfabank.ru/products/alfa-api/documentation/articles/sandbox/articles/nominal-accounts/articles/intro/intro"
|
||||
author:
|
||||
published:
|
||||
created: 2026-04-07
|
||||
description: "Описания API-методов, примеры запросов, инструкции по настройке интеграции для работы с продуктами и сервисами Альфа-Банка"
|
||||
tags:
|
||||
- "clippings"
|
||||
---
|
||||
#### Инструкция по тестированию
|
||||
|
||||
Рекомендации по тестированию [номинальных счетов](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/intro/intro).
|
||||
|
||||
##### Идентификация пополнений
|
||||
|
||||
Для тестирования методов для идентификации пополнений номинального счёта предварительно необходимо создать тестовое неидентифицированное пополнение с помощью метода [«Создание тестового неидентифицированного пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/sandbox/articles/nominal-accounts/articles/unidentified-transaction/v1/unidentified-transaction).
|
||||
|
||||
В результате успешного запроса будет создано тестовое неидентифицированное пополнение c идентификатором `id`, который далее необходимо будет передать в методе [«Создание запроса на идентификацию пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/identify/v1/identify).
|
||||
|
||||
[Создание тестового неидентифицированного пополнения номинального счёта](https://developers.alfabank.ru/products/alfa-api/documentation/articles/sandbox/articles/nominal-accounts/articles/unidentified-transaction/v1/unidentified-transaction)
|
||||
|
||||
API Helper
|
||||
|
||||
Beta
|
||||
|
||||
---
|
||||
|
||||
какой email технической поддержки?
|
||||
|
||||
10:36
|
||||
|
||||
Доставлено
|
||||
|
||||
Для связи с технической поддержкой используйте электронную почту alfa\_api@alfabank.ru.
|
||||
|
||||
10:36
|
||||
|
||||
как происходит flow регистрации бенифициара?
|
||||
|
||||
10:53
|
||||
|
||||
Доставлено
|
||||
|
||||
Для регистрации бенефициара необходимо выполнить следующие шаги:
|
||||
|
||||
1. 1.
|
||||
**Создать запрос на регистрацию бенефициара** с помощью метода:
|
||||
- •
|
||||
**Песочница**: `POST https://sandbox.alfabank.ru/api/na/jp/v1/beneficiaries`
|
||||
- •
|
||||
**Пром**: `POST https://baas.alfabank.ru/api/na/jp/v1/beneficiaries`
|
||||
При этом нужно учитывать, что в зависимости от типа бенефициара поля запроса заполняются по-разному.
|
||||
2. 2.
|
||||
**Получить статус запроса** с помощью метода [«Получение статуса запроса»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/get-request-status/v1/get-request-status).
|
||||
3. 3.
|
||||
**После регистрации бенефициара необходимо указать его платёжные реквизиты** с помощью метода [«Добавление платёжных реквизитов бенефициара»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/add-requisites/v1/add-requisites).
|
||||
|
||||
При успешной регистрации бенефициару присваивается уникальный идентификатор — `beneficiaryId`.
|
||||
|
||||
**Важно:** учёт денежных средств на виртуальных счетах бенефициаров будет вестись корректно только при условии, что владелец номинального счёта не использует другие каналы вывода средств с номинального счёта (например, банк-клиент, платёжные поручения на бумажном носителе, сервисы Alfa API для осуществления переводов и другие).
|
||||
|
||||
Ссылки на документацию:
|
||||
|
||||
- •
|
||||
[Создание запроса на регистрацию бенефициара](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/add-beneficiary/v1/add-beneficiary)
|
||||
- •
|
||||
[Получение статуса запроса](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/get-request-status/v1/get-request-status)
|
||||
- •
|
||||
[Добавление платёжных реквизитов бенефициара](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/add-requisites/v1/add-requisites)
|
||||
|
||||
10:53
|
||||
|
||||
а как же socring?
|
||||
|
||||
10:55
|
||||
|
||||
Доставлено
|
||||
|
||||
Для проверки актуальности ранее зарегистрированных данных о бенефициаре используются следующие методы:
|
||||
|
||||
1. 1.
|
||||
**«Создание запроса на проверку бенефициара»** — инициирует процесс скоринга бенефициара.
|
||||
2. 2.
|
||||
**«Получение статуса запроса»** — позволяет отслеживать статус ранее созданного запроса на проверку.
|
||||
|
||||
**Ссылки на документацию:**
|
||||
|
||||
- •
|
||||
[Создание запроса на проверку бенефициара](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/beneficiary-scoring/v1/beneficiary-scoring)
|
||||
- •
|
||||
[Получение статуса запроса](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/get-request-status/v1/get-request-status)
|
||||
|
||||
10:55
|
||||
|
||||
каким образом можно пополнить номинальный счёт компании?
|
||||
|
||||
22:24
|
||||
|
||||
Доставлено
|
||||
|
||||
Депонент (бенефициар) может пополнить номинальный счёт удобным ему способом. После этого владелец номинального счёта должен идентифицировать поступившие денежные средства. Для этого владельцу счёта необходимо выполнить следующие шаги:
|
||||
|
||||
1. 1.
|
||||
**Получить информацию обо всех неидентифицированных пополнениях** с помощью метода [«Получение списка неидентифицированных пополнений номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-unidentified-transactions/v1/get-unidentified-transactions).
|
||||
2. 2.
|
||||
**Создать запрос на идентификацию денежных средств** с помощью метода [«Создание запроса на идентификацию пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/identify/v1/identify).
|
||||
3. 3.
|
||||
**Получить статус запроса на идентификацию денежных средств** с помощью метода [«Получение статуса запроса на идентификацию пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-identify-request-status/v1/get-identify-request-status).
|
||||
|
||||
22:25
|
||||
|
||||
каким образом можно пополнить номинальный счёт компании?
|
||||
|
||||
22:25
|
||||
|
||||
Доставлено
|
||||
|
||||
Депонент (бенефициар) может пополнить номинальный счёт удобным ему способом. После этого владелец номинального счёта должен идентифицировать поступившие денежные средства. Для этого владельцу счёта необходимо выполнить следующие шаги:
|
||||
|
||||
1. 1.
|
||||
Получить информацию обо всех неидентифицированных пополнениях с помощью метода [«Получение списка неидентифицированных пополнений номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-unidentified-transactions/v1/get-unidentified-transactions).
|
||||
2. 2.
|
||||
Создать запрос на идентификацию денежных средств с помощью метода [«Создание запроса на идентификацию пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/identify/v1/identify).
|
||||
3. 3.
|
||||
Получить статус запроса на идентификацию денежных средств с помощью метода [«Получение статуса запроса на идентификацию пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-identify-request-status/v1/get-identify-request-status).
|
||||
|
||||
**Важно:** для работы с сервисом необходимо использовать электронную подпись. Допускается использование сертификата, выпущенного с помощью [сервиса «Электронная подпись»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/signature/articles/intro/intro), или сертификата УКЭП, выпущенного в любом аккредитованном УЦ.
|
||||
|
||||
Ссылка на статью с подробным описанием процесса: [Идентификация пополнений номинального счёта](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/intro/intro).
|
||||
|
||||
22:25
|
||||
|
||||
а что это значит "любым удобным способом"? каким например?
|
||||
|
||||
22:25
|
||||
|
||||
Доставлено
|
||||
|
||||
В предоставленной документации нет конкретного перечня способов пополнения номинального счёта. Однако указано, что депонент (бенефициар) может пополнить номинальный счёт удобным ему способом. После этого владелец номинального счёта должен идентифицировать поступившие денежные средства с помощью специальных методов API.
|
||||
|
||||
Для идентификации пополнений владелец счёта может использовать следующие методы:
|
||||
|
||||
1. 1.
|
||||
Получить информацию обо всех неидентифицированных пополнениях: [«Получение списка неидентифицированных пополнений номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-unidentified-transactions/v1/get-unidentified-transactions).
|
||||
2. 2.
|
||||
Создать запрос на идентификацию денежных средств: [«Создание запроса на идентификацию пополнения номинального счёта»](https://developers.alfa-bank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/identify/v1/identify).
|
||||
3. 3.
|
||||
Получить статус запроса на идентификацию денежных средств: [«Получение статуса запроса на идентификацию пополнения номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-identify-request-status/v1/get-identify-request-status).
|
||||
|
||||
Для более детальной информации о возможных способах пополнения номинального счёта рекомендуется обратиться на почту alfa\_api@alfabank.ru.
|
||||
|
||||
22:25
|
||||
@@ -0,0 +1,355 @@
|
||||
H2H
|
||||
|
||||
Песочница
|
||||
|
||||
POST https://sandbox.alfabank.ru/api/na/jp/v1/unidentified-transactions
|
||||
|
||||
##### Scope
|
||||
|
||||
`beneficiary-payments`
|
||||
|
||||
[](https://developers.alfabank.ru/assets/developers-portal.docs.alfa-api/articles/sandbox/articles/nominal-accounts/articles/unidentified-transaction/v1/files/unidentified-transaction.yaml)
|
||||
|
||||
##### Описание
|
||||
|
||||
Метод позволяет создать тестовое неидентифицированное пополнение номинального счёта.
|
||||
|
||||
###### Параметры запроса
|
||||
|
||||
Атрибут
|
||||
|
||||
Описание
|
||||
|
||||
Authorization
|
||||
|
||||
Accept
|
||||
|
||||
stringrequired
|
||||
|
||||
application/json
|
||||
|
||||
Content-Type
|
||||
|
||||
stringrequired
|
||||
|
||||
application/json
|
||||
|
||||
Атрибут
|
||||
|
||||
Описание
|
||||
|
||||
documentNumber
|
||||
|
||||
stringrequired
|
||||
|
||||
Номер платёжного поручения
|
||||
|
||||
date
|
||||
|
||||
stringrequired
|
||||
|
||||
Дата и время пополнения по МСК
|
||||
|
||||
amount
|
||||
|
||||
stringrequired
|
||||
|
||||
Сумма пополнения в рублях
|
||||
|
||||
purpose
|
||||
|
||||
stringrequired
|
||||
|
||||
Назначение платежа
|
||||
|
||||
accountNumber
|
||||
|
||||
stringrequired
|
||||
|
||||
Номер номинального счёта
|
||||
|
||||
objectrequired
|
||||
|
||||
Информация о плательщике
|
||||
|
||||
inn
|
||||
|
||||
stringoptional
|
||||
|
||||
ИНН плательщика
|
||||
|
||||
kpp
|
||||
|
||||
stringoptional
|
||||
|
||||
КПП плательщика
|
||||
|
||||
accountNumber
|
||||
|
||||
stringoptional
|
||||
|
||||
Номер счёта плательщика
|
||||
|
||||
name
|
||||
|
||||
stringoptional
|
||||
|
||||
Имя плательщика
|
||||
|
||||
bankAccount
|
||||
|
||||
stringoptional
|
||||
|
||||
Номер счёта банка плательщика
|
||||
|
||||
bankBik
|
||||
|
||||
stringoptional
|
||||
|
||||
БИК банка плательщика
|
||||
|
||||
bankName
|
||||
|
||||
stringoptional
|
||||
|
||||
Наименования банка плательщика
|
||||
|
||||
```bash
|
||||
1curl --location 'https://baas.alfabank.ru/api/na/jp/v1/unidentified-transactions' \
|
||||
2--header 'Authorization: Bearer {access-token}' \
|
||||
3--header 'Content-Type: application/json' \
|
||||
4--header 'Accept: application/json' \
|
||||
5--data '{
|
||||
6 "documentNumber": "3",
|
||||
7 "date": "2026-04-03T13:23:24.439Z",
|
||||
8 "amount": 200.9,
|
||||
9 "purpose": "Входящая транзакция созданная вручную для тестирования на песочнице",
|
||||
10 "accountNumber": "40817810306050000000",
|
||||
11 "payer": {
|
||||
12 "inn": "221284672706",
|
||||
13 "kpp": "641914992",
|
||||
14 "accountNumber": "87149728127096890679",
|
||||
15 "name": "Имя плательщика",
|
||||
16 "bankAccount": "3932755239052037086628",
|
||||
17 "bankBik": "108997635",
|
||||
18 "bankName": "Наименования банка плательщика"
|
||||
19 }
|
||||
20}'
|
||||
```
|
||||
|
||||
###### Параметры ответа
|
||||
|
||||
```json
|
||||
1{
|
||||
2 "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6\"",
|
||||
3 "documentNumber": "3",
|
||||
4 "date": "2025-04-08T10:47:17.927Z",
|
||||
5 "amount": 200.9,
|
||||
6 "purpose": "Входящая транзакция созданная вручную для тестирования на песочнице",
|
||||
7 "accountNumber": "40817810306050000000",
|
||||
8 "payer": {
|
||||
9 "inn": "221284672706",
|
||||
10 "kpp": "641914992",
|
||||
11 "accountNumber": "87149728127096890679",
|
||||
12 "name": "Имя плательщика",
|
||||
13 "bankAccount": "3932755239052037086628",
|
||||
14 "bankBik": "108997635",
|
||||
15 "bankName": "Наименования банка плательщика"
|
||||
16 }
|
||||
17}
|
||||
```
|
||||
|
||||
атрибут
|
||||
|
||||
описание
|
||||
|
||||
id
|
||||
|
||||
stringrequired
|
||||
|
||||
Идентификатор операции пополнения
|
||||
|
||||
documentNumber
|
||||
|
||||
stringrequired
|
||||
|
||||
Номер платёжного поручения
|
||||
|
||||
date
|
||||
|
||||
stringrequired
|
||||
|
||||
Дата и время пополнения по МСК
|
||||
|
||||
amount
|
||||
|
||||
stringrequired
|
||||
|
||||
Сумма пополнения в рублях
|
||||
|
||||
purpose
|
||||
|
||||
stringrequired
|
||||
|
||||
Назначение платежа
|
||||
|
||||
accountNumber
|
||||
|
||||
stringrequired
|
||||
|
||||
Номер номинального счёта
|
||||
|
||||
objectrequired
|
||||
|
||||
Информация о плательщике
|
||||
|
||||
inn
|
||||
|
||||
stringoptional
|
||||
|
||||
ИНН плательщика
|
||||
|
||||
kpp
|
||||
|
||||
stringoptional
|
||||
|
||||
КПП плательщика
|
||||
|
||||
accountNumber
|
||||
|
||||
stringoptional
|
||||
|
||||
Номер счёта плательщика
|
||||
|
||||
name
|
||||
|
||||
stringoptional
|
||||
|
||||
Имя плательщика
|
||||
|
||||
bankAccount
|
||||
|
||||
stringoptional
|
||||
|
||||
Номер счёта банка плательщика
|
||||
|
||||
bankBik
|
||||
|
||||
stringoptional
|
||||
|
||||
БИК банка плательщика
|
||||
|
||||
bankName
|
||||
|
||||
stringoptional
|
||||
|
||||
Наименования банка плательщика
|
||||
|
||||
атрибут
|
||||
|
||||
описание
|
||||
|
||||
error
|
||||
|
||||
stringrequired
|
||||
|
||||
Код ошибки. Принимает возможные значения:
|
||||
|
||||
- •
|
||||
|
||||
`invalid_request` — неверные входные параметры запроса
|
||||
|
||||
|
||||
error\_description
|
||||
|
||||
stringoptional
|
||||
|
||||
Описание ошибки
|
||||
|
||||
атрибут
|
||||
|
||||
описание
|
||||
|
||||
error
|
||||
|
||||
stringrequired
|
||||
|
||||
Код ошибки. Принимает возможные значения:
|
||||
|
||||
- •
|
||||
|
||||
`invalid_token` — предоставленный токен просрочен, отозван, имеет неправильный формат или недействителен по другим причинам
|
||||
|
||||
|
||||
error\_description
|
||||
|
||||
stringoptional
|
||||
|
||||
Описание ошибки
|
||||
|
||||
атрибут
|
||||
|
||||
описание
|
||||
|
||||
error
|
||||
|
||||
stringrequired
|
||||
|
||||
Код ошибки. Принимает возможные значения:
|
||||
|
||||
- •
|
||||
|
||||
`insufficient_scope` — у пользователя нет прав на использование запрашиваемого сервиса, доступ к которому не предусмотрен настройками scope
|
||||
|
||||
|
||||
error\_description
|
||||
|
||||
stringoptional
|
||||
|
||||
Описание ошибки
|
||||
|
||||
атрибут
|
||||
|
||||
описание
|
||||
|
||||
error
|
||||
|
||||
stringrequired
|
||||
|
||||
Код ошибки. Принимает возможные значения:
|
||||
|
||||
- •
|
||||
|
||||
`unknown_endpoint` — эндпоинт не найден или неактивен
|
||||
|
||||
|
||||
error\_description
|
||||
|
||||
stringoptional
|
||||
|
||||
Описание ошибки
|
||||
|
||||
Нет тела ответа
|
||||
|
||||
атрибут
|
||||
|
||||
описание
|
||||
|
||||
error
|
||||
|
||||
stringrequired
|
||||
|
||||
Код ошибки. Принимает возможные значения:
|
||||
|
||||
- •
|
||||
|
||||
`internal_error` — внутренняя ошибка сервиса при выполнении обработки запроса
|
||||
|
||||
|
||||
error\_description
|
||||
|
||||
stringoptional
|
||||
|
||||
Описание ошибки
|
||||
|
||||
Нет тела ответа
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
| Атрибут | Тип | Обязательность | Описание |
|
||||
| :---------------- | :----- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Authorization** | string | required | Bearer {access_token}, полученный по [Authorization Code Flow H2H](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf-h2h/articles/intro/intro) |
|
||||
| **Authorization** | string | required | Bearer {access_token}, полученный по [Authorization Code Flow H2H](../../../../Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md) |
|
||||
| **Accept** | string | required | application/json |
|
||||
|
||||
### PATH (Путь)
|
||||
|
||||
@@ -2,22 +2,22 @@
|
||||
|
||||
_Номинальные счета / Выплаты / Как это работает_
|
||||
|
||||
Для осуществления выплат с номинального счёта предварительно необходимо [зарегистрировать контрагента](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/intro/intro), участвующего в выплате.
|
||||
Для осуществления выплат с номинального счёта предварительно необходимо [зарегистрировать контрагента](../Контрагенты/intro.md), участвующего в выплате.
|
||||
|
||||
## Общий механизм выплат с номинального счёта
|
||||
|
||||
1. **Создайте запрос на выплату**
|
||||
Метод [«Создание запроса на выплату с номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/payoff/v1/payoff)
|
||||
Метод [«Создание запроса на выплату с номинального счёта»](payoff.md)
|
||||
|
||||
2. **Получите статус запроса на выплату**
|
||||
Метод [«Получение статуса запроса на выплату с номинального счёта»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/get-payoff-request-status/v1/get-payoff-request-status)
|
||||
Метод [«Получение статуса запроса на выплату с номинального счёта»](get-payoff-request-status.md)
|
||||
|
||||
3. **Подтвердите или отклоните обработку запроса-дубля на выплату**
|
||||
В случае, если статус запроса на выплату уже был создан ранее, он примет статус `MANUAL_ACCEPTANCE` и его нужно будет подтвердить или отклонить.
|
||||
Метод [«Подтвердить или отклонить запрос-дубль на выплату»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/payoff-accept/v1/payoff-accept)
|
||||
Метод [«Подтвердить или отклонить запрос-дубль на выплату»](payoff-accept.md)
|
||||
|
||||
4. **Получите информацию о платеже по его идентификатору**
|
||||
Метод [«Получение информации о платеже»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/get-payoff/v1/get-payoff)
|
||||
Метод [«Получение информации о платеже»](get-payoff.md)
|
||||
|
||||
---
|
||||
|
||||
@@ -33,13 +33,13 @@ _Номинальные счета / Выплаты / Как это работа
|
||||
Необходимо учитывать:
|
||||
|
||||
- На номинальном счёте должен быть положительный баланс.
|
||||
- Если выплата производится в пользу универсального реципиента, то для него предварительно необходимо зарегистрировать платёжные реквизиты с помощью метода [«Добавление платёжных реквизитов универсального реципиента»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/universal-recipients/articles/add-requisites/v1/add-requisites).
|
||||
- Если выплата производится в пользу универсального реципиента, то для него предварительно необходимо зарегистрировать платёжные реквизиты с помощью метода [«Добавление платёжных реквизитов универсального реципиента»](../Контрагенты/Универсальные_реципиенты/add-requisites.md).
|
||||
|
||||
В качестве платёжных реквизитов получателя могут быть указаны:
|
||||
|
||||
- реквизиты счёта;
|
||||
- номер телефона (СБП);
|
||||
- зашифрованный номер карты (как зашифровать номер карты, описано [здесь](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/cardtoken/cardtoken));
|
||||
- зашифрованный номер карты (как зашифровать номер карты, описано [здесь](../how-to-encrypt-your-card-number-eg-cardtoken.md));
|
||||
- идентификатор платёжных реквизитов контрагента.
|
||||
|
||||
## Выплаты с биллингом на стороне Банка
|
||||
@@ -55,11 +55,11 @@ _Номинальные счета / Выплаты / Как это работа
|
||||
### Механизм возврата денежных средств с налогового виртуального кошелька
|
||||
|
||||
1. **Создайте запрос на возврат денежных средств с налогового виртуального кошелька**
|
||||
Метод [«Создание запроса на возврат денежных средств с налогового виртуального кошелька»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/tax-refund/v1/tax-refund)
|
||||
Метод [«Создание запроса на возврат денежных средств с налогового виртуального кошелька»](tax-refund.md)
|
||||
|
||||
2. **Получите статус запроса на возврат налоговых денежных средств**
|
||||
Метод [«Получение статуса запроса на возврат налоговых денежных средств»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/get-tax-refund-request-status/v1/get-tax-refund-request-status)
|
||||
Метод [«Получение статуса запроса на возврат налоговых денежных средств»](get-tax-refund-request-status.md)
|
||||
|
||||
3. **Подтвердите или отклоните обработку запроса-дубля на возврат денежных средств с налогового виртуального кошелька**
|
||||
В случае, если статус запроса на выплату уже был создан ранее, он примет статус `MANUAL_ACCEPTANCE` и его нужно будет подтвердить или отклонить.
|
||||
Метод [«Подтверждение или отклонение запроса-дубля на возврат денежных средств с налогового виртуального кошелька»](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/tax-refund-accept/v1/tax-refund-accept)
|
||||
Метод [«Подтверждение или отклонение запроса-дубля на возврат денежных средств с налогового виртуального кошелька»](tax-refund-accept.md)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
| Атрибут | Тип | Обязательность | Описание |
|
||||
| :---------------- | :----- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Authorization** | string | required | Bearer {access_token}, полученный по [Authorization Code Flow H2H](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf-h2h/articles/intro/intro) |
|
||||
| **Authorization** | string | required | Bearer {access_token}, полученный по [Authorization Code Flow H2H](../../../../Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md) |
|
||||
| **Accept** | string | required | `application/json` |
|
||||
|
||||
### PATH (Путь)
|
||||
@@ -90,5 +90,5 @@ curl --location --globoff --request PATCH \
|
||||
|
||||
## Навигация
|
||||
|
||||
- **Предыдущий шаг:** [Получение статуса запроса на возврат налоговых денежных средств](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/na-payments/articles/get-tax-refund-request-status/v1/get-tax-refund-request-status)
|
||||
- **Предыдущий шаг:** [Получение статуса запроса на возврат налоговых денежных средств](get-tax-refund-request-status.md)
|
||||
- **Раздел:** Номинальные счета / Выплаты
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
Вот очищенная и структурированная версия документации в формате Markdown:
|
||||
|
||||
# Создание запроса на идентификацию пополнения номинального счёта
|
||||
|
||||
|
||||
**Тип интеграции:** H2H
|
||||
|
||||
## Эндпоинты
|
||||
@@ -27,7 +26,7 @@
|
||||
### HEADERS
|
||||
| Атрибут | Тип | Обяз. | Описание |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Authorization** | string | Да | Bearer {access_token}, полученный по [Authorization Code Flow H2H](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf-h2h/articles/intro/intro) |
|
||||
| **Authorization** | string | Да | Bearer {access_token}, полученный по [Authorization Code Flow H2H](../../../../Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md) |
|
||||
| **Accept** | string | Да | application/json |
|
||||
| **Content-Type** | string | Да | application/json |
|
||||
|
||||
@@ -104,5 +103,5 @@ curl --location --globoff 'https://baas.alfabank.ru/api/na/jp/v1/unidentified-tr
|
||||
|
||||
---
|
||||
**Навигация:**
|
||||
* [Предыдущая: Получение списка неидентифицированных пополнений](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-unidentified-transactions/v1/get-unidentified-transactions)
|
||||
* [Следующая: Получение статуса запроса на идентификацию](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/identify-transactions/articles/get-identify-request-status/v1/get-identify-request-status)
|
||||
* [Предыдущая: Получение списка неидентифицированных пополнений](get-unidentified-transactions.md)
|
||||
* [Следующая: Получение статуса запроса на идентификацию](get-identify-request-status.md)
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
| Атрибут | Тип | Обязательность | Описание |
|
||||
| :---------------- | :------- | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Authorization** | `string` | required | Bearer {access_token}, полученный по [Authorization Code Flow H2H](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf-h2h/articles/intro/intro) |
|
||||
| **Authorization** | `string` | required | Bearer {access_token}, полученный по [Authorization Code Flow H2H](../../../../../Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md) |
|
||||
| **Accept** | `string` | required | `application/json` |
|
||||
|
||||
### PATH
|
||||
@@ -86,5 +86,5 @@ curl --location --globoff --request POST 'https://baas.alfabank.ru/api/na/jp/v1/
|
||||
|
||||
## Навигация
|
||||
|
||||
- **Предыдущий метод:** [Создание запроса на изменение информации о бенефициаре](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/change-beneficiary/v1/change-beneficiary)
|
||||
- **Следующий метод:** [Добавление платёжных реквизитов бенефициара](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/add-requisites/v1/add-requisites)
|
||||
- **Предыдущий метод:** [Создание запроса на изменение информации о бенефициаре](change-beneficiary.md)
|
||||
- **Следующий метод:** [Добавление платёжных реквизитов бенефициара](add-requisites.md)
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
### HEADERS
|
||||
| Атрибут | Тип | Обяз. | Описание |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| **Authorization** | string | Да | Bearer {access_token}, полученный по [Authorization Code Flow H2H](https://developers.alfabank.ru/products/alfa-api/documentation/articles/alfa-id/articles/acf-h2h/articles/intro/intro) |
|
||||
| **Authorization** | string | Да | Bearer {access_token}, полученный по [Authorization Code Flow H2H](../../../../../Alfa_ID/Authorization_Code_Flow_for_H2H_Integrations/How_to_use_ACF_for_H2H.md) |
|
||||
| **Accept** | string | Да | `application/json` |
|
||||
| **Content-Type** | string | Да | `application/json` |
|
||||
|
||||
@@ -99,5 +99,5 @@ curl --location 'https://baas.alfabank.ru/api/na/jp/v1/universal-recipients' \
|
||||
---
|
||||
|
||||
**Навигация:**
|
||||
* Предыдущая статья: [Получение списка денежных операций бенефициара](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/beneficiaries/articles/get-transactions/v1/get-transactions)
|
||||
* Следующая статья: [Получение списка универсальных реципиентов номинального счёта](https://developers.alfabank.ru/products/alfa-api/documentation/articles/nominal-accounts/articles/counterparties/articles/universal-recipients/articles/get-urs/v1/get-urs)
|
||||
* Предыдущая статья: [Получение списка денежных операций бенефициара](../Бенефициары/get-transactions.md)
|
||||
* Следующая статья: [Получение списка универсальных реципиентов номинального счёта](get-universal_recipients_list.md)
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
## Главная
|
||||
### Инструкция по интеграции СБП C2B (Альфа-Банк)
|
||||
|
||||
## Содержание
|
||||
- [Обзор API](#1-обзор-api)
|
||||
- [Процесс аутентификации](#2-процесс-аутентификации)
|
||||
- [Тестирование](#3-тестирование)
|
||||
- [Как провести тестовую оплату](#4-как-провести-тестовую-оплату)
|
||||
- [Получение статуса платежа](#5-получение-статуса-платежа)
|
||||
- [Переход на промышленную среду](#6-переход-на-промышленную-среду)
|
||||
- [Статический QR-код](#статический-qr-код-сбп)
|
||||
- [Динамический QR-код](#интеграция-динамических-qr-кодов-сбп)
|
||||
- [Кассовая платёжная ссылка](#кассовая-платёжная-ссылка-сбп-техническая-документация)
|
||||
|
||||
Добро пожаловать в руководство по прямой интеграции с платежным шлюзом (ПШ) Альфа-Банка для реализации сервиса СБП C2B.
|
||||
|
||||
|
||||
---
|
||||
|
||||
### ⚠️ Важное объявление (Изменение адресов)
|
||||
|
||||
@@ -3,8 +3,8 @@ title: Available property mappers
|
||||
weight: 19
|
||||
---
|
||||
|
||||
In previous sections we've already seen how to [create](/docs/laravel-data/v4/as-a-data-transfer-object/mapping-property-names) data objects where the keys of the
|
||||
payload differ from the property names of the data object. It is also possible to [transform](/docs/laravel-data/v4/as-a-resource/mapping-property-names) data objects to an array/json/... where the keys of the payload differ
|
||||
In previous sections we've already seen how to [create](../as-a-data-transfer-object/mapping-property-names.md) data objects where the keys of the
|
||||
payload differ from the property names of the data object. It is also possible to [transform](../as-a-resource/mapping-property-names.md) data objects to an array/json/... where the keys of the payload differ
|
||||
from the property names of the data object.
|
||||
|
||||
These mappings can be set manually put the package also provide a set of mappers that can be used to automatically map
|
||||
|
||||
@@ -16,7 +16,7 @@ interface Cast
|
||||
|
||||
A cast receives the following:
|
||||
|
||||
- **property** a `DataProperty` object which represents the property for which the value is cast. You can read more about the internal structures of the package [here](/docs/laravel-data/v4/advanced-usage/internal-structures)
|
||||
- **property** a `DataProperty` object which represents the property for which the value is cast. You can read more about the internal structures of the package [here](../advanced-usage/internal-structures.md)
|
||||
- **value** the value that should be cast
|
||||
- **properties** an array of the current properties that will be used to create the data object
|
||||
- **creationContext** the context in which the data object is being created you'll find the following info here:
|
||||
|
||||
@@ -14,7 +14,7 @@ interface RuleInferrer
|
||||
}
|
||||
```
|
||||
|
||||
A collection of previous inferred rules is given, and a `DataProperty` object which represents the property for which the value is transformed. You can read more about the internal structures of the package [here](/docs/laravel-data/v4/advanced-usage/internal-structures).
|
||||
A collection of previous inferred rules is given, and a `DataProperty` object which represents the property for which the value is transformed. You can read more about the internal structures of the package [here](../advanced-usage/internal-structures.md).
|
||||
|
||||
The `ValidationContext` is also injected, this contains the following info:
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ interface Transformer
|
||||
|
||||
The following parameters are provided:
|
||||
|
||||
- **property**: a `DataProperty` object which represents the property for which the value is transformed. You can read more about the internal structures of the package [here](/docs/laravel-data/v4/advanced-usage/internal-structures)
|
||||
- **property**: a `DataProperty` object which represents the property for which the value is transformed. You can read more about the internal structures of the package [here](../advanced-usage/internal-structures.md)
|
||||
- **value**: the value that should be transformed, this will never be `null`
|
||||
- **context**: a `TransformationContext` object which contains the current transformation context with the following properties:
|
||||
- **transformValues** indicates if values should be transformed or not
|
||||
|
||||
@@ -57,7 +57,7 @@ The `handle` method has several arguments:
|
||||
|
||||
- **payload** the non normalized payload
|
||||
- **class** the `DataClass` object for the data
|
||||
object [more info](/docs/laravel-data/v4/advanced-usage/internal-structures)
|
||||
object [more info](../advanced-usage/internal-structures.md)
|
||||
- **properties** the key-value properties which will be used to construct the data object
|
||||
- **creationContext** the context in which the data object is being created you'll find the following info here:
|
||||
- **dataClass** the data class which is being created
|
||||
|
||||
@@ -118,7 +118,7 @@ Tip: we can also remove the `EnumCast` since the package will automatically cast
|
||||
|
||||
## Creating your own casts
|
||||
|
||||
It is possible to create your casts. You can read more about this in the [advanced chapter](/docs/laravel-data/v4/advanced-usage/creating-a-cast).
|
||||
It is possible to create your casts. You can read more about this in the [advanced chapter](../advanced-usage/creating-a-cast.md).
|
||||
|
||||
## Casting arrays or collections of non-data types
|
||||
|
||||
|
||||
@@ -162,7 +162,7 @@ will try to create itself from the following types:
|
||||
- An *array*
|
||||
|
||||
This list can be extended using extra normalizers, find more about
|
||||
it [here](/docs/laravel-data/v4/advanced-usage/normalizers).
|
||||
it [here](../advanced-usage/normalizers.md).
|
||||
|
||||
When a data object cannot be created using magical methods or the default methods, a `CannotCreateData`
|
||||
exception will be thrown.
|
||||
@@ -190,7 +190,7 @@ SongData::factory()->withoutMagicalCreation()->from($song);
|
||||
## Advanced creation using factories
|
||||
|
||||
It is possible to configure how a data object is created, whether it will be validated, which casts to use and more. You
|
||||
can read more about it [here](/docs/laravel-data/v4/as-a-data-transfer-object/factories).
|
||||
can read more about it [here](../as-a-data-transfer-object/factories.md).
|
||||
|
||||
## DTO classes
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ SongData::factory()->collect(Song::all())
|
||||
|
||||
## Disable property name mapping
|
||||
|
||||
We saw [earlier](/docs/laravel-data/v4/as-a-data-transfer-object/mapping-property-names) that it is possible to map
|
||||
We saw [earlier](../as-a-data-transfer-object/mapping-property-names.md) that it is possible to map
|
||||
property names when creating a data object from an array. This can be disabled when using a factory:
|
||||
|
||||
```php
|
||||
@@ -47,7 +47,7 @@ SongData::factory()->withoutValidation()->from(['title' => 'Never gonna give you
|
||||
## Disabling magic methods
|
||||
|
||||
A data object can be created
|
||||
using [magic methods](/docs/laravel-data/v4/as-a-data-transfer-object/creating-a-data-object.md#magical-creation) , this can be disabled
|
||||
using [magic methods](../as-a-data-transfer-object/creating-a-data-object.md.md#magical-creation) , this can be disabled
|
||||
when using a factory:
|
||||
|
||||
```php
|
||||
@@ -136,4 +136,4 @@ class SongData extends Data
|
||||
}
|
||||
```
|
||||
|
||||
You can read more about creation contexts [here](/docs/laravel-data/v4/advanced-usage/pipeline).
|
||||
You can read more about creation contexts [here](../advanced-usage/pipeline.md).
|
||||
|
||||
@@ -37,7 +37,7 @@ class ContractData extends Data
|
||||
}
|
||||
```
|
||||
|
||||
You can also use the `MapName` attribute when you want to combine input (see [transforming data objects](/docs/laravel-data/v4/as-a-resource/mapping-property-names)) and output property name mapping:
|
||||
You can also use the `MapName` attribute when you want to combine input (see [transforming data objects](../as-a-resource/mapping-property-names.md)) and output property name mapping:
|
||||
|
||||
```php
|
||||
#[MapName(SnakeCaseMapper::class)]
|
||||
@@ -91,4 +91,4 @@ SongData::from([
|
||||
]);
|
||||
```
|
||||
|
||||
The package has a set of default mappers available, you can find them [here](/docs/laravel-data/v4/advanced-usage/available-property-mappers).
|
||||
The package has a set of default mappers available, you can find them [here](../advanced-usage/available-property-mappers.md).
|
||||
|
||||
@@ -68,4 +68,4 @@ SongData::factory()
|
||||
->from(['title' => 'Never gonna give you up']); // artist will `null` instead of `Optional`
|
||||
```
|
||||
|
||||
You can read more about this [here](/docs/laravel-data/v4/as-a-data-transfer-object/factories#disabling-optional-values).
|
||||
You can read more about this [here](../as-a-data-transfer-object/factories.md#disabling-optional-values).
|
||||
|
||||
@@ -63,7 +63,7 @@ class UpdateSongController
|
||||
}
|
||||
```
|
||||
|
||||
We have a complete section within these docs dedicated to validation, you can find it [here](/docs/laravel-data/v4/validation/introduction).
|
||||
We have a complete section within these docs dedicated to validation, you can find it [here](../validation/introduction.md).
|
||||
|
||||
## Getting the data object filled with request data from anywhere
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ Which will output the following array:
|
||||
]
|
||||
```
|
||||
|
||||
By default, calling `toArray` on a data object will recursively transform all properties to an array. This means that nested data objects and collections of data objects will also be transformed to arrays. Other complex types like `Carbon`, `DateTime`, `Enums`, etc... will be transformed into a string. We'll see in the [transformers](/docs/laravel-data/v4/as-a-resource/transformers) section how to configure and customize this behavior.
|
||||
By default, calling `toArray` on a data object will recursively transform all properties to an array. This means that nested data objects and collections of data objects will also be transformed to arrays. Other complex types like `Carbon`, `DateTime`, `Enums`, etc... will be transformed into a string. We'll see in the [transformers](../as-a-resource/transformers.md) section how to configure and customize this behavior.
|
||||
|
||||
If you only want to transform a data object to an array without transforming the properties, you can call the `all` method:
|
||||
|
||||
|
||||
@@ -81,4 +81,4 @@ And a transformed version of the data object will look like this:
|
||||
]
|
||||
```
|
||||
|
||||
The package has a set of default mappers available, you can find them [here](/docs/laravel-data/v4/advanced-usage/available-property-mappers).
|
||||
The package has a set of default mappers available, you can find them [here](../advanced-usage/available-property-mappers.md).
|
||||
|
||||
@@ -43,7 +43,7 @@ class ArtistData extends Data{
|
||||
|
||||
Next to a `DateTimeInterfaceTransformer` the package also ships with an `ArrayableTransformer` that transforms an `Arrayable` object to an array.
|
||||
|
||||
It is possible to create transformers for your specific types. You can find more info [here](/docs/laravel-data/v4/advanced-usage/creating-a-transformer).
|
||||
It is possible to create transformers for your specific types. You can find more info [here](../advanced-usage/creating-a-transformer.md).
|
||||
|
||||
## Global transformers
|
||||
|
||||
@@ -114,7 +114,7 @@ Outputting the following array:
|
||||
]
|
||||
```
|
||||
|
||||
The [mapping of property names](/docs/laravel-data/v4/as-a-resource/mapping-property-names) can also be disabled:
|
||||
The [mapping of property names](../as-a-resource/mapping-property-names.md) can also be disabled:
|
||||
|
||||
```php
|
||||
ArtistData::from($artist)->transform(
|
||||
@@ -122,7 +122,7 @@ ArtistData::from($artist)->transform(
|
||||
);
|
||||
```
|
||||
|
||||
It is possible to enable [wrapping](/docs/laravel-data/v4/as-a-resource/wrapping-data) the data object:
|
||||
It is possible to enable [wrapping](../as-a-resource/wrapping-data.md) the data object:
|
||||
|
||||
```php
|
||||
use Spatie\LaravelData\Support\Wrapping\WrapExecutionType;
|
||||
|
||||
@@ -5,7 +5,19 @@ weight: 1
|
||||
|
||||
In this quickstart, we'll guide you through the most important functionalities of the package and how to use them.
|
||||
|
||||
First, you should [install the package](/docs/laravel-data/v4/installation-setup).
|
||||
## Table of Contents
|
||||
- [Using requests](#using-requests)
|
||||
- [Casting data](#casting-data)
|
||||
- [Customizing the creation of a data object](#customizing-the-creation-of-a-data-object)
|
||||
- [Nesting data objects and arrays of data objects](#nesting-data-objects-and-arrays-of-data-objects)
|
||||
- [Usage in controllers](#usage-in-controllers)
|
||||
- [Using transformers](#using-transformers)
|
||||
- [Generating a blueprint](#generating-a-blueprint)
|
||||
- [Lazy properties](#lazy-properties)
|
||||
- [Conclusion](#conclusion)
|
||||
|
||||
First, you should [install the package](../installation-setup.md).
|
||||
|
||||
|
||||
We will create a blog with different posts, so let's start with the `PostData` object. A post has a title, some content, a status and a date when it was published:
|
||||
|
||||
@@ -189,7 +201,7 @@ As you can see, we're missing the `date` rule on the `published_at` property. By
|
||||
- `array` when a property type is `array`
|
||||
- `enum:*` when a property type is a native enum
|
||||
|
||||
You can read more about the process of automated rule generation [here](/docs/laravel-data/v4/as-a-data-transfer-object/request-to-data-object#content-automatically-inferring-rules-for-properties-1).
|
||||
You can read more about the process of automated rule generation [here](../as-a-data-transfer-object/request-to-data-object.md#content-automatically-inferring-rules-for-properties-1).
|
||||
|
||||
We can easily add the date rule by using an attribute to our data object:
|
||||
|
||||
@@ -232,7 +244,7 @@ array:4 [
|
||||
]
|
||||
```
|
||||
|
||||
There are [tons](/docs/laravel-data/v4/advanced-usage/validation-attributes) of validation rule attributes you can add to data properties. There's still much more you can do with validating data objects. Read more about it [here](/docs/laravel-data/v4/as-a-data-transfer-object/request-to-data-object#validating-a-request).
|
||||
There are [tons](../advanced-usage/validation-attributes.md) of validation rule attributes you can add to data properties. There's still much more you can do with validating data objects. Read more about it [here](../as-a-data-transfer-object/request-to-data-object.md#validating-a-request).
|
||||
|
||||
Tip: By default, when creating a data object in a non request context, no validation is executed:
|
||||
|
||||
@@ -275,7 +287,7 @@ It is possible to define casts within the `data.php` config file. By default, th
|
||||
|
||||
This code means that if a class property is of type `DateTime`, `Carbon`, `CarbonImmutable`, ... it will be automatically cast.
|
||||
|
||||
You can create your own casts; read more about it [here](/docs/laravel-data/v4/advanced-usage/creating-a-cast).
|
||||
You can create your own casts; read more about it [here](../advanced-usage/creating-a-cast.md).
|
||||
|
||||
### Local casts
|
||||
|
||||
@@ -356,7 +368,7 @@ class PostData extends Data
|
||||
}
|
||||
```
|
||||
|
||||
You can read more about casting [here](/docs/laravel-data/v4/as-a-data-transfer-object/casts).
|
||||
You can read more about casting [here](../as-a-data-transfer-object/casts.md).
|
||||
|
||||
## Customizing the creation of a data object
|
||||
|
||||
@@ -406,7 +418,7 @@ class PostData extends Data
|
||||
```
|
||||
|
||||
Magic creation methods allow you to create data objects from any type by passing them to the `from` method of a data
|
||||
object, you can read more about it [here](/docs/laravel-data/v4/as-a-data-transfer-object/creating-a-data-object#content-magical-creation).
|
||||
object, you can read more about it [here](../as-a-data-transfer-object/creating-a-data-object.md#content-magical-creation).
|
||||
|
||||
It can be convenient to transform more complex models than our `Post` into data objects because you can decide how a model
|
||||
would be mapped onto a data object.
|
||||
@@ -764,7 +776,7 @@ Which leads to the following JSON:
|
||||
}
|
||||
```
|
||||
|
||||
You can read more about transformers [here](/docs/laravel-data/v4/as-a-resource/transformers).
|
||||
You can read more about transformers [here](../as-a-resource/transformers.md).
|
||||
|
||||
## Generating a blueprint
|
||||
|
||||
@@ -1010,19 +1022,19 @@ You can do quite a lot with lazy properties like including them:
|
||||
- when they are requested in the URL query
|
||||
- by default, with an option to exclude them
|
||||
|
||||
And a lot more. You can read all about it [here](/docs/laravel-data/v4/as-a-resource/lazy-properties).
|
||||
And a lot more. You can read all about it [here](../as-a-resource/lazy-properties.md).
|
||||
|
||||
## Conclusion
|
||||
|
||||
So that's it, a quick overview of this package. We barely scratched the surface of what's possible with the package. There's still a lot more you can do with data objects like:
|
||||
|
||||
- [casting](/docs/laravel-data/v4/advanced-usage/eloquent-casting) them into Eloquent models
|
||||
- [transforming](/docs/laravel-data/v4/advanced-usage/typescript) the structure to typescript
|
||||
- [working](/docs/laravel-data/v4/as-a-data-transfer-object/collections) with `DataCollections`
|
||||
- [optional properties](/docs/laravel-data/v4/as-a-data-transfer-object/optional-properties) not always required when creating a data object
|
||||
- [wrapping](/docs/laravel-data/v4/as-a-resource/wrapping) transformed data into keys
|
||||
- [mapping](/docs/laravel-data/v4/as-a-data-transfer-object/mapping-property-names) property names when creating or transforming a data object
|
||||
- [appending](/docs/laravel-data/v4/as-a-resource/appending-properties) extra data
|
||||
- [including](/docs/laravel-data/v4/as-a-resource/lazy-properties#content-using-query-strings) properties using the URL query string
|
||||
- [casting](../advanced-usage/eloquent-casting.md) them into Eloquent models
|
||||
- [transforming](../advanced-usage/typescript.md) the structure to typescript
|
||||
- [working](../as-a-data-transfer-object/collections.md) with `DataCollections`
|
||||
- [optional properties](../as-a-data-transfer-object/optional-properties.md) not always required when creating a data object
|
||||
- [wrapping](../as-a-resource/wrapping.md) transformed data into keys
|
||||
- [mapping](../as-a-data-transfer-object/mapping-property-names.md) property names when creating or transforming a data object
|
||||
- [appending](../as-a-resource/appending-properties.md) extra data
|
||||
- [including](../as-a-resource/lazy-properties.md#content-using-query-strings) properties using the URL query string
|
||||
- [inertia](https://spatie.be/docs/laravel-data/v4/advanced-usage/use-with-inertia) support for lazy properties
|
||||
- and so much more ... you'll find all the information here in the docs
|
||||
|
||||
@@ -57,4 +57,4 @@ By default, five rule inferrers are enabled:
|
||||
- A `array` type will add the `array` rule
|
||||
- **AttributesRuleInferrer** will make sure that rule attributes we described above will also add their rules
|
||||
|
||||
It is possible to write your rule inferrers. You can find more information [here](/docs/laravel-data/v4/advanced-usage/creating-a-rule-inferrer).
|
||||
It is possible to write your rule inferrers. You can find more information [here](../advanced-usage/creating-a-rule-inferrer.md).
|
||||
|
||||
@@ -56,7 +56,7 @@ Completely disabling validation can be done by setting the `validation_strategy`
|
||||
'validation_strategy' => \Spatie\LaravelData\Support\Creation\ValidationStrategy::Disabled->value,
|
||||
```
|
||||
|
||||
If you require a more fine-grained control over when validation should happen, you can use [data factories](/docs/laravel-data/v4/as-a-data-transfer-object/factories) to manually specify the validation strategy.
|
||||
If you require a more fine-grained control over when validation should happen, you can use [data factories](../as-a-data-transfer-object/factories.md) to manually specify the validation strategy.
|
||||
|
||||
## A quick glance at the validation functionality
|
||||
|
||||
@@ -87,7 +87,7 @@ The package will generate the following validation rules:
|
||||
]
|
||||
```
|
||||
|
||||
The package follows an algorithm to infer rules from the data object. You can read more about it [here](/docs/laravel-data/v4/validation/auto-rule-inferring).
|
||||
The package follows an algorithm to infer rules from the data object. You can read more about it [here](../validation/auto-rule-inferring.md).
|
||||
|
||||
### Validation attributes
|
||||
|
||||
@@ -107,7 +107,7 @@ class SongData extends Data
|
||||
|
||||
When you provide an artist with a length of more than 20 characters, the validation will fail.
|
||||
|
||||
There's a complete [chapter](/docs/laravel-data/v4/validation/using-validation-attributes) dedicated to validation attributes.
|
||||
There's a complete [chapter](../validation/using-validation-attributes.md) dedicated to validation attributes.
|
||||
|
||||
### Manual rules
|
||||
|
||||
@@ -132,7 +132,7 @@ class SongData extends Data
|
||||
}
|
||||
```
|
||||
|
||||
You can read more about manual rules in its [dedicated chapter](/docs/laravel-data/v4/validation/manual-rules).
|
||||
You can read more about manual rules in its [dedicated chapter](../validation/manual-rules.md).
|
||||
|
||||
### Using the container
|
||||
|
||||
@@ -147,7 +147,7 @@ If the request contains data that is not compatible with the data object, a vali
|
||||
|
||||
### Working with the validator
|
||||
|
||||
We provide a few points where you can hook into the validation process. You can read more about it in the [dedicated chapter](/docs/laravel-data/v4/validation/working-with-the-validator).
|
||||
We provide a few points where you can hook into the validation process. You can read more about it in the [dedicated chapter](../validation/working-with-the-validator.md).
|
||||
|
||||
It is for example to:
|
||||
|
||||
@@ -207,7 +207,7 @@ The validation rules for this class will be:
|
||||
]
|
||||
```
|
||||
|
||||
There are a few quirky things to keep in mind when working with nested data objects, you can read all about it [here](/docs/laravel-data/v4/validation/nesting-data).
|
||||
There are a few quirky things to keep in mind when working with nested data objects, you can read all about it [here](../validation/nesting-data.md).
|
||||
|
||||
## Validation of nested data collections
|
||||
|
||||
@@ -241,7 +241,7 @@ In this case the validation rules for `AlbumData` would look like this:
|
||||
]
|
||||
```
|
||||
|
||||
More info about nested data collections can be found [here](/docs/laravel-data/v4/validation/nesting-data).
|
||||
More info about nested data collections can be found [here](../validation/nesting-data.md).
|
||||
|
||||
## Default values
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ weight: 6
|
||||
|
||||
A data object can contain other data objects or collections of data objects. The package will make sure that also for these data objects validation rules will be generated.
|
||||
|
||||
Let's take a look again at the data object from the [nesting](/docs/laravel-data/v4/as-a-data-transfer-object/nesting) section:
|
||||
Let's take a look again at the data object from the [nesting](../as-a-data-transfer-object/nesting.md) section:
|
||||
|
||||
```php
|
||||
class AlbumData extends Data
|
||||
|
||||
@@ -63,4 +63,4 @@ Now the validation rules will look like this:
|
||||
|
||||
## Skipping validation for all properties
|
||||
|
||||
By using [data factories](/docs/laravel-data/v4/as-a-data-transfer-object/factories) or setting the `validation_strategy` in the `data.php` config you can skip validation for all properties of a data class.
|
||||
By using [data factories](../as-a-data-transfer-object/factories.md) or setting the `validation_strategy` in the `data.php` config you can skip validation for all properties of a data class.
|
||||
|
||||
@@ -31,7 +31,7 @@ above data object will look like this:
|
||||
```
|
||||
|
||||
For each Laravel validation rule we've got a matching validation attribute, you can find a list of
|
||||
them [here](/docs/laravel-data/v4/advanced-usage/validation-attributes).
|
||||
them [here](../advanced-usage/validation-attributes.md).
|
||||
|
||||
## Referencing route parameters
|
||||
|
||||
|
||||
@@ -1,49 +1,56 @@
|
||||
{
|
||||
"name": "apoloz/alfa-bank-sdk",
|
||||
"description": "Unofficial Alfa Bank API SDK for PHP using Saloon and Laravel Data",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "apoloz",
|
||||
"email": "anatoliy.poloz@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.2",
|
||||
"saloonphp/saloon": "^3.0",
|
||||
"saloonphp/laravel-plugin": "^3.0",
|
||||
"saloonphp/pagination-plugin": "^2.0",
|
||||
"spatie/laravel-data": "^4.0",
|
||||
"guzzlehttp/guzzle": "^7.0",
|
||||
"phpseclib/phpseclib": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"pestphp/pest": "^2.0",
|
||||
"phpstan/phpstan": "^2.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Apoloz\\AlfaBank\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Apoloz\\AlfaBank\\Laravel\\AlfaBankServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"test": "vendor/bin/pest",
|
||||
"test-coverage": "vendor/bin/pest --coverage"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
}
|
||||
"name": "apoloz/alfa-bank-sdk",
|
||||
"description": "Unofficial Alfa Bank API SDK for PHP using Saloon and Laravel Data",
|
||||
"type": "library",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{
|
||||
"name": "apoloz",
|
||||
"email": "anatoliy.poloz@gmail.com"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": "^8.4",
|
||||
"saloonphp/saloon": "^4.0",
|
||||
"saloonphp/laravel-plugin": "^4.0",
|
||||
"saloonphp/pagination-plugin": "^2.0",
|
||||
"spatie/laravel-data": "^4.0",
|
||||
"guzzlehttp/guzzle": "^7.0",
|
||||
"phpseclib/phpseclib": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^10.0",
|
||||
"pestphp/pest": "^2.0",
|
||||
"phpstan/phpstan": "^2.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Apoloz\\AlfaBank\\": "src/"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [
|
||||
"Apoloz\\AlfaBank\\Laravel\\AlfaBankServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true,
|
||||
"scripts": {
|
||||
"test": "vendor/bin/pest",
|
||||
"test-coverage": "vendor/bin/pest --coverage"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
},
|
||||
"audit": {
|
||||
"ignore": {
|
||||
"PKSA-xnj5-w74d-6wmz": "true",
|
||||
"PKSA-rnpm-45mg-w6ht": "true",
|
||||
"PKSA-5szq-gvrg-ttfq": "true"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class CreateBeneficiaryRequestData extends Data
|
||||
public string $countryOfTaxResidence,
|
||||
#[DataCollectionOf(AddressData::class)]
|
||||
public DataCollection $addresses,
|
||||
public ?bool $isBeneficiary = null,
|
||||
#[DataCollectionOf(DigestSignatureData::class)]
|
||||
public ?DataCollection $digestSignatures = null,
|
||||
public ?string $accountNumber = null,
|
||||
|
||||
@@ -29,6 +29,7 @@ class UnidentifiedTransactionData extends Data
|
||||
public ?string $documentNumber = null,
|
||||
public ?string $date = null,
|
||||
public ?string $purpose = null,
|
||||
public ?string $accountNumber = null,
|
||||
public ?PayerData $payer = null, // Nested DTO for payer details
|
||||
) {}
|
||||
// </SECTION>
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace Apoloz\AlfaBank\Data\Statement;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import necessary DTOs and Spatie Laravel Data components.">
|
||||
// <BELIEF_STATE "This collection DTO relies on `PaginationData` for metadata and `TransactionData` for the individual items. `DataCollection` and `DataCollectionOf` are Spatie Data features for handling typed arrays of DTOs.">
|
||||
use Apoloz\AlfaBank\Data\PaginationData;
|
||||
use Spatie\LaravelData\Attributes\DataCollectionOf;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
@@ -27,9 +26,9 @@ class TransactionCollectionData extends Data
|
||||
// <SECTION name="constructor_properties" intent="Define the properties of the transaction collection.">
|
||||
// <BELIEF_STATE "The collection structure includes pagination metadata (`pagination`) and the actual list of transactions (`transactions`). The `#[DataCollectionOf(TransactionData::class)]` attribute is crucial for ensuring that each item in the `transactions` array is automatically cast to a `TransactionData` DTO.">
|
||||
public function __construct(
|
||||
public PaginationData $pagination,
|
||||
#[DataCollectionOf(TransactionData::class)]
|
||||
public DataCollection $transactions
|
||||
) {}
|
||||
) {
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Apoloz\AlfaBank\Requests\NominalAccounts\Identification;
|
||||
|
||||
use Apoloz\AlfaBank\Data\NominalAccounts\Identification\UnidentifiedTransactionData;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
|
||||
class CreateUnidentifiedTransactionRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
|
||||
protected Method $method = Method::POST;
|
||||
|
||||
public function __construct(
|
||||
protected string $documentNumber,
|
||||
protected string $date,
|
||||
protected float $amount,
|
||||
protected string $purpose,
|
||||
protected string $accountNumber,
|
||||
protected ?array $payer = null,
|
||||
) {}
|
||||
|
||||
public function resolveEndpoint(): string
|
||||
{
|
||||
return '/api/na/jp/v1/unidentified-transactions';
|
||||
}
|
||||
|
||||
public function createDtoFromResponse(Response $response): UnidentifiedTransactionData
|
||||
{
|
||||
return UnidentifiedTransactionData::from($response->json());
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
{
|
||||
return array_filter([
|
||||
'documentNumber' => $this->documentNumber,
|
||||
'date' => $this->date,
|
||||
'amount' => $this->amount,
|
||||
'purpose' => $this->purpose,
|
||||
'accountNumber' => $this->accountNumber,
|
||||
'payer' => $this->payer ?? $this->getDefaultPayer(),
|
||||
], fn ($value) => $value !== null);
|
||||
}
|
||||
|
||||
protected function getDefaultPayer(): array
|
||||
{
|
||||
return [
|
||||
'inn' => '221284672706',
|
||||
'kpp' => '641914992',
|
||||
'accountNumber' => '87149728127096890679',
|
||||
'name' => 'Тестовый плательщик',
|
||||
'bankAccount' => '3932755239052037086628',
|
||||
'bankBik' => '108997635',
|
||||
'bankName' => 'АО "Альфа-Банк"',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -27,8 +27,7 @@ class GetTransactionsRequest extends Request
|
||||
|
||||
public function __construct(
|
||||
protected string $accountNumber,
|
||||
protected string $executeDateFrom,
|
||||
protected string $executeDateTo,
|
||||
protected string $statementDate,
|
||||
?int $limit = 1000,
|
||||
?int $offset = 0
|
||||
) {
|
||||
@@ -53,8 +52,7 @@ class GetTransactionsRequest extends Request
|
||||
{
|
||||
return array_merge([
|
||||
'accountNumber' => $this->accountNumber,
|
||||
'executeDateFrom' => $this->executeDateFrom,
|
||||
'executeDateTo' => $this->executeDateTo,
|
||||
'statementDate' => $this->statementDate,
|
||||
], $this->getPaginationQuery());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
39
src/Sbp/Data/GetQRCdQueryData.php
Normal file
39
src/Sbp/Data/GetQRCdQueryData.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
// MODULE_CONTRACT: Defines the data structure for the response when generating an SBP QR Code.
|
||||
// RESPONSIBILITY: To provide a strongly-typed structure for the API's response to QR code generation requests, including status, potential error messages, and the generated QR code data (image, payload, ID).
|
||||
// INPUTS: Raw array data from the SBP QR Code generation API response.
|
||||
// OUTPUTS: An instantiated DTO with properties mapped from the input array.
|
||||
// LINKS: Sbp/Requests/GetQrCodeRequest.php, README.md#sbp-api
|
||||
*/
|
||||
|
||||
namespace Apoloz\AlfaBank\Sbp\Data;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import the base Spatie\LaravelData class.">
|
||||
// <BELIEF_STATE "This class extends `Spatie\LaravelData\Data` to leverage its robust data mapping and type safety, ensuring consistent and predictable handling of SBP QR Code response payloads.">
|
||||
use Spatie\LaravelData\Data;
|
||||
|
||||
// </SECTION>
|
||||
/**
|
||||
*
|
||||
* "queryData":
|
||||
{
|
||||
"notificationUrl":"https://sbp-payments",
|
||||
"SenderFIO":"Иванов|Иван|Иванович",
|
||||
"SenderID":"0079123456789",
|
||||
"SenderBankBIC":"44525593"
|
||||
}
|
||||
*
|
||||
* */
|
||||
// <SECTION name="class_definition" intent="Define the QR Code response data structure.">
|
||||
// <BELIEF_STATE "The `QrCodeResponseData` DTO encapsulates all possible fields returned by the SBP QR Code generation API. Fields are explicitly typed as nullable to accommodate variations in API responses, particularly for error scenarios where certain data might be absent.">
|
||||
class GetQRCdQueryData extends Data
|
||||
{
|
||||
public function __construct(
|
||||
public string $notificationUrl,
|
||||
public string $SenderFIO,
|
||||
public string $SenderID
|
||||
) {}
|
||||
}
|
||||
@@ -54,8 +54,8 @@ class QrCodeRequestData extends Data
|
||||
public ?string $width = null,
|
||||
public ?string $height = null,
|
||||
|
||||
// <BELIEF_STATE "The `notificationUrl` specifies where the bank should send webhook notifications about payment status changes.">
|
||||
public ?string $notificationUrl = null,
|
||||
// <BELIEF_STATE "The `queryData` specifies where the bank should send webhook notifications about payment status changes.">
|
||||
public GetQRCdQueryData $queryData,
|
||||
|
||||
// Dynamic QR specific fields
|
||||
// <BELIEF_STATE "The `OrderNumber` is specific to dynamic QRs, providing a unique identifier for the order in the merchant's system.">
|
||||
@@ -68,17 +68,6 @@ class QrCodeRequestData extends Data
|
||||
// <BELIEF_STATE "Subscription service identifiers are used for recurring payment scenarios with SBP.">
|
||||
public ?string $subscriptionServiceId = null,
|
||||
public ?string $subscriptionServiceName = null,
|
||||
|
||||
// Optional user data for Dynamic QR (often part of sender identification)
|
||||
// <BELIEF_STATE "Sender details are crucial for identifying the payer in certain SBP scenarios. `#[MapName]` ensures these follow API conventions.">
|
||||
#[MapName('SenderFIO')]
|
||||
public ?string $senderFio = null,
|
||||
|
||||
#[MapName('SenderID')]
|
||||
public ?string $senderId = null,
|
||||
|
||||
#[MapName('SenderBankBIC')]
|
||||
public ?string $senderBankBic = null,
|
||||
) {}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -13,11 +13,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
// <SECTION name="module_imports" intent="Import DTO and Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request requires the `ActivateCashQrRequestData` DTO for its JSON body and utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\CashLink\ActivateCashQrRequestData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -25,7 +26,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for activating a CashLink QR Code, a key management operation in SBP payment systems.">
|
||||
class ActivateCashQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Activating a resource is an action that changes the system state, so POST is the correct verb.">
|
||||
@@ -56,9 +57,9 @@ class ActivateCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Fields from the DTO are mapped, including conditional parameters for order number, payment purpose, QR TTL, and notification URLs.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'ActivateCashQRc',
|
||||
'TermNo' => $this->data->TermNo,
|
||||
'qrcId' => $this->data->qrcId,
|
||||
@@ -67,22 +68,22 @@ class ActivateCashQrRequest extends Request implements HasBody
|
||||
];
|
||||
|
||||
if ($this->data->OrderNumber !== null) {
|
||||
$body['OrderNumber'] = $this->data->OrderNumber;
|
||||
$bodyArray['OrderNumber'] = $this->data->OrderNumber;
|
||||
}
|
||||
if ($this->data->paymentPurpose !== null) {
|
||||
$body['paymentPurpose'] = $this->data->paymentPurpose;
|
||||
$bodyArray['paymentPurpose'] = $this->data->paymentPurpose;
|
||||
}
|
||||
if ($this->data->qrTtl !== null) {
|
||||
$body['qrTtl'] = $this->data->qrTtl;
|
||||
$bodyArray['qrTtl'] = $this->data->qrTtl;
|
||||
}
|
||||
if ($this->data->redirectUrl !== null) {
|
||||
$body['redirectUrl'] = $this->data->redirectUrl;
|
||||
$bodyArray['redirectUrl'] = $this->data->redirectUrl;
|
||||
}
|
||||
if ($this->data->notificationUrl !== null) {
|
||||
$body['queryData'] = ['notificationUrl' => $this->data->notificationUrl];
|
||||
$bodyArray['queryData'] = ['notificationUrl' => $this->data->notificationUrl];
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to change the account for a CashLink QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for modifying a CashLink QR Code, which is a key management operation.">
|
||||
class ChangeAccountForCashQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Modifying a resource via an action is correctly represented by a POST request in the SBP API context.">
|
||||
@@ -53,7 +53,7 @@ class ChangeAccountForCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Return the raw JSON response as an array.">
|
||||
// <BELIEF_STATE "For this specific request, the response is currently returned as a raw array. A dedicated DTO could be created if a structured object is required.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): array
|
||||
public function createDtoFromResponse(Response $response): array
|
||||
{
|
||||
return $response->json();
|
||||
}
|
||||
@@ -61,9 +61,9 @@ class ChangeAccountForCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Fields are conditionally added based on constructor parameters, ensuring the payload precisely matches the API specification.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'ChangeAccForCashQRc',
|
||||
'TermNo' => $this->TermNo,
|
||||
'qrcId' => $this->qrcId,
|
||||
@@ -71,16 +71,16 @@ class ChangeAccountForCashQrRequest extends Request implements HasBody
|
||||
];
|
||||
|
||||
if ($this->NewTermNo !== null) {
|
||||
$body['NewTermNo'] = $this->NewTermNo;
|
||||
$bodyArray['NewTermNo'] = $this->NewTermNo;
|
||||
}
|
||||
if ($this->NewMerchantId !== null) {
|
||||
$body['NewMerchantId'] = $this->NewMerchantId;
|
||||
$bodyArray['NewMerchantId'] = $this->NewMerchantId;
|
||||
}
|
||||
if ($this->redirectUrl !== null) {
|
||||
$body['redirectUrl'] = $this->redirectUrl;
|
||||
$bodyArray['redirectUrl'] = $this->redirectUrl;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to change the terminal number for a CashLink QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for modifying a CashLink QR Code, specifically its associated terminal, which is a key management operation.">
|
||||
class ChangeTermNoForCashQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Modifying a resource via an action is correctly represented by a POST request in the SBP API context.">
|
||||
@@ -49,7 +49,7 @@ class ChangeTermNoForCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Return the raw JSON response as an array.">
|
||||
// <BELIEF_STATE "For this specific request, the response is currently returned as a raw array. A dedicated DTO could be created if a structured object is required.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): array
|
||||
public function createDtoFromResponse(Response $response): array
|
||||
{
|
||||
return $response->json();
|
||||
}
|
||||
@@ -57,13 +57,15 @@ class ChangeTermNoForCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo` and `qrcId` are included in the body to identify the target.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'ChangeTermNoForCashQRc',
|
||||
'TermNo' => $this->TermNo,
|
||||
'qrcId' => $this->qrcId,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to delete a CashLink QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for deleting a CashLink QR Code, which is a critical management operation.">
|
||||
class DeleteCashQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Deleting a resource via an action is correctly represented by a POST request in the SBP API context.">
|
||||
@@ -49,7 +49,7 @@ class DeleteCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Return the raw JSON response as an array.">
|
||||
// <BELIEF_STATE "For this specific request, the response is currently returned as a raw array. A dedicated DTO could be created if a structured object is required.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): array
|
||||
public function createDtoFromResponse(Response $response): array
|
||||
{
|
||||
return $response->json();
|
||||
}
|
||||
@@ -57,13 +57,15 @@ class DeleteCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo` and `qrcId` are included in the body to identify the target.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'DelCashQRc',
|
||||
'TermNo' => $this->TermNo,
|
||||
'qrcId' => $this->qrcId,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to get the history of a CashLink QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the history of a CashLink QR Code, which is useful for auditing and reconciliation.">
|
||||
class GetCashQrHistoryRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP history requests are often performed via POST requests with a JSON body.">
|
||||
@@ -51,7 +51,7 @@ class GetCashQrHistoryRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Return the raw JSON response as an array.">
|
||||
// <BELIEF_STATE "For this specific request, the response is currently returned as a raw array. A dedicated DTO could be created if a structured object is required.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): array
|
||||
public function createDtoFromResponse(Response $response): array
|
||||
{
|
||||
return $response->json();
|
||||
}
|
||||
@@ -59,15 +59,17 @@ class GetCashQrHistoryRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. All constructor properties are directly mapped to the request body to identify the QR Code and the date range.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'GetCashQrcId',
|
||||
'TermNo' => $this->TermNo,
|
||||
'qrcId' => $this->qrcId,
|
||||
'dateFrom' => $this->dateFrom,
|
||||
'dateTo' => $this->dateTo,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,20 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to get the status of a CashLink QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the status of a CashLink QR Code, which is crucial for tracking payment flows.">
|
||||
class GetCashQrStatusRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP status checks are often performed via POST requests with a JSON body.">
|
||||
@@ -49,7 +49,7 @@ class GetCashQrStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Return the raw JSON response as an array.">
|
||||
// <BELIEF_STATE "For this specific request, the response is currently returned as a raw array. A dedicated DTO could be created if a structured object is required.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): array
|
||||
public function createDtoFromResponse(Response $response): array
|
||||
{
|
||||
return $response->json();
|
||||
}
|
||||
@@ -57,13 +57,15 @@ class GetCashQrStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo` and `qrcId` identify the target.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'GetCashQRCstatus',
|
||||
'TermNo' => $this->TermNo,
|
||||
'qrcId' => $this->qrcId,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\CashLink;
|
||||
// <BELIEF_STATE "This POST request requires specific DTOs for its JSON body and its response, along with Saloon's body-handling traits.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\CashLink\RegCashQrRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\CashLink\RegCashQrResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +27,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for generating a CashLink QR Code, a key feature in SBP payment systems.">
|
||||
class RegCashQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Creating a new QR Code resource or initiating a generation action is correctly represented by a POST request.">
|
||||
@@ -57,30 +58,30 @@ class RegCashQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Fields from the DTO are mapped, including conditional parameters for media type, dimensions, redirect URL, and QR Code ID.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'RegCashQRc',
|
||||
'TermNo' => $this->data->TermNo,
|
||||
];
|
||||
|
||||
if ($this->data->mediaType !== null) {
|
||||
$body['mediaType'] = $this->data->mediaType;
|
||||
$bodyArray['mediaType'] = $this->data->mediaType;
|
||||
}
|
||||
if ($this->data->width !== null) {
|
||||
$body['width'] = $this->data->width;
|
||||
$bodyArray['width'] = $this->data->width;
|
||||
}
|
||||
if ($this->data->height !== null) {
|
||||
$body['height'] = $this->data->height;
|
||||
$bodyArray['height'] = $this->data->height;
|
||||
}
|
||||
if ($this->data->redirectUrl !== null) {
|
||||
$body['redirectUrl'] = $this->data->redirectUrl;
|
||||
$bodyArray['redirectUrl'] = $this->data->redirectUrl;
|
||||
}
|
||||
if ($this->data->qrcId !== null) {
|
||||
$body['qrcId'] = $this->data->qrcId;
|
||||
$bodyArray['qrcId'] = $this->data->qrcId;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +25,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for modifying a Digital Ruble CashLink QR Code, which is a key management operation.">
|
||||
class ChangeAccForCashUniQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Modifying a resource via an action is correctly represented by a POST request in the SBP API context.">
|
||||
@@ -57,42 +56,42 @@ class ChangeAccForCashUniQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Fields from the DTO are mapped, including conditional parameters for the new account, merchant, redirect URL, etc.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'ChangeAccForCashUniQr',
|
||||
'TermNo' => $this->data->TermNo,
|
||||
];
|
||||
|
||||
if ($this->data->messageID !== null) {
|
||||
$body['messageID'] = $this->data->messageID;
|
||||
$bodyArray['messageID'] = $this->data->messageID;
|
||||
}
|
||||
if ($this->data->qrcId !== null) {
|
||||
$body['qrcId'] = $this->data->qrcId;
|
||||
$bodyArray['qrcId'] = $this->data->qrcId;
|
||||
}
|
||||
if ($this->data->account !== null) {
|
||||
$body['account'] = $this->data->account;
|
||||
$bodyArray['account'] = $this->data->account;
|
||||
}
|
||||
if ($this->data->accountDR !== null) {
|
||||
$body['accountDR'] = $this->data->accountDR;
|
||||
$bodyArray['accountDR'] = $this->data->accountDR;
|
||||
}
|
||||
if ($this->data->NewTermNo !== null) {
|
||||
$body['NewTermNo'] = $this->data->NewTermNo;
|
||||
$bodyArray['NewTermNo'] = $this->data->NewTermNo;
|
||||
}
|
||||
if ($this->data->NewMerchantId !== null) {
|
||||
$body['NewMerchantId'] = $this->data->NewMerchantId;
|
||||
$bodyArray['NewMerchantId'] = $this->data->NewMerchantId;
|
||||
}
|
||||
if ($this->data->redirectUrl !== null) {
|
||||
$body['redirectUrl'] = $this->data->redirectUrl;
|
||||
$bodyArray['redirectUrl'] = $this->data->redirectUrl;
|
||||
}
|
||||
if ($this->data->paymentPageUrl !== null) {
|
||||
$body['paymentPageUrl'] = $this->data->paymentPageUrl;
|
||||
$bodyArray['paymentPageUrl'] = $this->data->paymentPageUrl;
|
||||
}
|
||||
if ($this->data->fraudScore !== null) {
|
||||
$body['fraudScore'] = $this->data->fraudScore;
|
||||
$bodyArray['fraudScore'] = $this->data->fraudScore;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +25,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for generating a Digital Ruble CashLink QR Code, a key feature in the SBP Digital Ruble operations.">
|
||||
class CreateCashUniQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Creating a new QR Code resource or initiating a generation action is correctly represented by a POST request.">
|
||||
@@ -57,40 +56,40 @@ class CreateCashUniQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Fields from the DTO are mapped, including conditional and nested `queryData` for notification URLs.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'ReqCashUniQr',
|
||||
'TermNo' => $this->data->TermNo,
|
||||
];
|
||||
|
||||
if ($this->data->messageID !== null) {
|
||||
$body['messageID'] = $this->data->messageID;
|
||||
$bodyArray['messageID'] = $this->data->messageID;
|
||||
}
|
||||
if ($this->data->redirectUrl !== null) {
|
||||
$body['redirectUrl'] = $this->data->redirectUrl;
|
||||
$bodyArray['redirectUrl'] = $this->data->redirectUrl;
|
||||
}
|
||||
if ($this->data->paymentPageUrl !== null) {
|
||||
$body['paymentPageUrl'] = $this->data->paymentPageUrl;
|
||||
$bodyArray['paymentPageUrl'] = $this->data->paymentPageUrl;
|
||||
}
|
||||
if ($this->data->mediaType !== null) {
|
||||
$body['mediaType'] = $this->data->mediaType;
|
||||
$bodyArray['mediaType'] = $this->data->mediaType;
|
||||
}
|
||||
if ($this->data->width !== null) {
|
||||
$body['width'] = $this->data->width;
|
||||
$bodyArray['width'] = $this->data->width;
|
||||
}
|
||||
if ($this->data->height !== null) {
|
||||
$body['height'] = $this->data->height;
|
||||
$bodyArray['height'] = $this->data->height;
|
||||
}
|
||||
if ($this->data->qrcId !== null) {
|
||||
$body['qrcId'] = $this->data->qrcId;
|
||||
$bodyArray['qrcId'] = $this->data->qrcId;
|
||||
}
|
||||
|
||||
if ($this->data->notificationUrl !== null) {
|
||||
$body['queryData'] = ['notificationUrl' => $this->data->notificationUrl];
|
||||
$bodyArray['queryData'] = ['notificationUrl' => $this->data->notificationUrl];
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +25,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the status of a Digital Ruble CashLink QR Code, which is crucial for tracking payment flows.">
|
||||
class GetCashUniQrStatusRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP status checks are often performed via POST requests with a JSON body.">
|
||||
@@ -57,9 +56,9 @@ class GetCashUniQrStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo`, `uniQrId`, and `paramsId` identify the target. Optional fields like `messageID` and `payrrn` provide additional context.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'GetCashUniQrStatus',
|
||||
'TermNo' => $this->data->TermNo,
|
||||
'uniQrId' => $this->data->uniQrId,
|
||||
@@ -67,13 +66,13 @@ class GetCashUniQrStatusRequest extends Request implements HasBody
|
||||
];
|
||||
|
||||
if ($this->data->messageID !== null) {
|
||||
$body['messageID'] = $this->data->messageID;
|
||||
$bodyArray['messageID'] = $this->data->messageID;
|
||||
}
|
||||
if ($this->data->payrrn !== null) {
|
||||
$body['payrrn'] = $this->data->payrrn;
|
||||
$bodyArray['payrrn'] = $this->data->payrrn;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -6,15 +6,16 @@ namespace Apoloz\AlfaBank\Sbp\Requests\DigitalRuble;
|
||||
|
||||
use Apoloz\AlfaBank\Sbp\Data\DigitalRuble\CreateUniQrRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\DigitalRuble\UniQrResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
class CreateUniQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
protected Method $method = Method::POST;
|
||||
|
||||
@@ -32,40 +33,40 @@ class CreateUniQrRequest extends Request implements HasBody
|
||||
return UniQrResponseData::from($response->json());
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'ReqUniQr',
|
||||
'TermNo' => $this->data->TermNo,
|
||||
'uniQrType' => $this->data->uniQrType,
|
||||
];
|
||||
|
||||
if ($this->data->amount !== null) {
|
||||
$body['amount'] = $this->data->amount;
|
||||
$bodyArray['amount'] = $this->data->amount;
|
||||
}
|
||||
if ($this->data->paymentPurpose !== null) {
|
||||
$body['paymentPurpose'] = $this->data->paymentPurpose;
|
||||
$bodyArray['paymentPurpose'] = $this->data->paymentPurpose;
|
||||
}
|
||||
if ($this->data->redirectUrl !== null) {
|
||||
$body['redirectUrl'] = $this->data->redirectUrl;
|
||||
$bodyArray['redirectUrl'] = $this->data->redirectUrl;
|
||||
}
|
||||
if ($this->data->paymentPageUrl !== null) {
|
||||
$body['paymentPageUrl'] = $this->data->paymentPageUrl;
|
||||
$bodyArray['paymentPageUrl'] = $this->data->paymentPageUrl;
|
||||
}
|
||||
if ($this->data->mediaType !== null) {
|
||||
$body['mediaType'] = $this->data->mediaType;
|
||||
$bodyArray['mediaType'] = $this->data->mediaType;
|
||||
}
|
||||
if ($this->data->width !== null) {
|
||||
$body['width'] = $this->data->width;
|
||||
$bodyArray['width'] = $this->data->width;
|
||||
}
|
||||
if ($this->data->height !== null) {
|
||||
$body['height'] = $this->data->height;
|
||||
$bodyArray['height'] = $this->data->height;
|
||||
}
|
||||
if ($this->data->qrTtl !== null) {
|
||||
$body['qrTtl'] = $this->data->qrTtl;
|
||||
$bodyArray['qrTtl'] = $this->data->qrTtl;
|
||||
}
|
||||
if ($this->data->messageID !== null) {
|
||||
$body['messageID'] = $this->data->messageID;
|
||||
$bodyArray['messageID'] = $this->data->messageID;
|
||||
}
|
||||
|
||||
$queryData = [];
|
||||
@@ -83,9 +84,9 @@ class CreateUniQrRequest extends Request implements HasBody
|
||||
}
|
||||
|
||||
if (! empty($queryData)) {
|
||||
$body['queryData'] = $queryData;
|
||||
$bodyArray['queryData'] = $queryData;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,20 +12,21 @@ namespace Apoloz\AlfaBank\Sbp\Requests\DigitalRuble;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\DigitalRuble\GetUniQrStatusResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to get the status of Universal QR Codes.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the status of multiple Uni QR Codes, which is part of managing digital ruble transactions.">
|
||||
class GetUniQrStatusRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP status checks are often performed via POST requests with a JSON body.">
|
||||
@@ -49,21 +50,23 @@ class GetUniQrStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `GetUniQrStatusResponseData` DTO provides a type-safe and structured object for the status of Universal QR Codes.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\DigitalRuble\GetUniQrStatusResponseData
|
||||
public function createDtoFromResponse(Response $response): GetUniQrStatusResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\DigitalRuble\GetUniQrStatusResponseData::from($response->json());
|
||||
return GetUniQrStatusResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo` and `uniQrIds` are included in the body to identify the targets.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'GetUniQrStatus',
|
||||
'TermNo' => $this->TermNo,
|
||||
'uniQrIds' => $this->uniQrIds,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -13,20 +13,21 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Management;
|
||||
// <SECTION name="module_imports" intent="Import DTO and Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request requires the `BlockQrRequestData` DTO for its JSON body and utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Management\BlockQrRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to block a QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for blocking an SBP QR Code, which is a critical management operation.">
|
||||
class BlockQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Blocking a resource is an action that changes the system state, so POST is the correct verb.">
|
||||
@@ -49,20 +50,22 @@ class BlockQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `SbpManagementResponseData` DTO provides a structured object for the result of the block operation.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData
|
||||
public function createDtoFromResponse(Response $response): SbpManagementResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData::from($response->json());
|
||||
return SbpManagementResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Using the DTO's `toArray` method ensures the payload is correctly structured.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'BlockQRcId'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,21 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Management;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Management\GetBlockedQrListResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to get a list of blocked QR Codes.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying blocked QR Codes, which is part of managing payment terminals.">
|
||||
class GetBlockedQrListRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP list requests are often performed via POST requests with a JSON body.">
|
||||
@@ -48,20 +49,22 @@ class GetBlockedQrListRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `GetBlockedQrListResponseData` DTO provides a type-safe object for the list of blocked QR Codes.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Management\GetBlockedQrListResponseData
|
||||
public function createDtoFromResponse(Response $response): GetBlockedQrListResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\Management\GetBlockedQrListResponseData::from($response->json());
|
||||
return GetBlockedQrListResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo` is included in the body to identify the terminal.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'GetBlockedQRcIdList',
|
||||
'TermNo' => $this->TermNo,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -13,20 +13,21 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Management;
|
||||
// <SECTION name="module_imports" intent="Import DTO and Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request requires the `BlockQrRequestData` DTO for its JSON body and utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Management\BlockQrRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to unblock a QR Code.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for unblocking an SBP QR Code, which is a critical management operation.">
|
||||
class UnblockQrRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Unblocking a resource is an action that changes the system state, so POST is the correct verb.">
|
||||
@@ -49,20 +50,22 @@ class UnblockQrRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `SbpManagementResponseData` DTO provides a structured object for the result of the unblock operation.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData
|
||||
public function createDtoFromResponse(Response $response): SbpManagementResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData::from($response->json());
|
||||
return SbpManagementResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Using the DTO's `toArray` method ensures the payload is correctly structured.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'UnblockQRcId'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -13,11 +13,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Registry;
|
||||
// <SECTION name="module_imports" intent="Import DTO and Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request requires the `GetBankListResponseData` DTO for its response and utilizes `HasBody` and `HasJsonBody` for proper payload serialization.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Registry\GetBankListResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -25,7 +26,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the list of SBP participating banks, which is essential for routing payments.">
|
||||
class GetBankListRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP list requests are often performed via POST requests with a JSON body.">
|
||||
@@ -57,20 +58,20 @@ class GetBankListRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Optional fields are conditionally added to the body.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'GetBankList',
|
||||
];
|
||||
|
||||
if ($this->messageID !== null) {
|
||||
$body['messageID'] = $this->messageID;
|
||||
$bodyArray['messageID'] = $this->messageID;
|
||||
}
|
||||
if ($this->BankMemberIdFilter !== null) {
|
||||
$body['BankMemberIdFilter'] = $this->BankMemberIdFilter;
|
||||
$bodyArray['BankMemberIdFilter'] = $this->BankMemberIdFilter;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Reversal;
|
||||
// <BELIEF_STATE "This POST request requires specific DTOs for its JSON body and its response, along with Saloon's body-handling traits.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\GetQrcReversalDataRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\GetQrcReversalDataResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +27,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying detailed SBP reversal information, which is crucial for auditing and reconciliation.">
|
||||
class GetQrcReversalDataRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP data requests are often performed via POST requests with a JSON body.">
|
||||
@@ -57,12 +58,14 @@ class GetQrcReversalDataRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Other fields from the DTO are conditionally added, ensuring the payload precisely matches the API specification.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'GetQRCreversalData'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -5,15 +5,16 @@ declare(strict_types=1);
|
||||
namespace Apoloz\AlfaBank\Sbp\Requests\Reversal;
|
||||
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\ReversalHistoryResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
class GetQrcReversalHistoryRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
protected Method $method = Method::POST;
|
||||
|
||||
@@ -32,12 +33,14 @@ class GetQrcReversalHistoryRequest extends Request implements HasBody
|
||||
return ReversalHistoryResponseData::from($response->json());
|
||||
}
|
||||
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'GetQRCreversalHistory',
|
||||
'TermNo' => $this->TermNo,
|
||||
'payrrn' => $this->payrrn,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Reversal;
|
||||
// <BELIEF_STATE "This POST request requires specific DTOs for its JSON body and its response, along with Saloon's body-handling traits.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\GetQrcReversalStatusRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\GetQrcReversalStatusResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +27,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the status of an SBP reversal, which is a critical operation in payment systems.">
|
||||
class GetQrcReversalStatusRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP status checks are often performed via POST requests with a JSON body.">
|
||||
@@ -57,12 +58,14 @@ class GetQrcReversalStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Other fields from the DTO are conditionally added, ensuring the payload precisely matches the API specification.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'GetQRCreversalStatus'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Reversal;
|
||||
// <BELIEF_STATE "This POST request requires specific DTOs for its JSON body and its response, along with Saloon's body-handling traits.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\QrcReversalRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Reversal\QrcReversalResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +27,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for initiating an SBP reversal, which is a critical operation in payment systems.">
|
||||
class QrcReversalRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Initiating a new transaction or action that changes the system state (like a reversal) is correctly represented by a POST request.">
|
||||
@@ -57,12 +58,14 @@ class QrcReversalRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Other fields from the DTO are conditionally added, ensuring the payload precisely matches the API specification.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'QRCreversal'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -14,11 +14,12 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Status;
|
||||
// <BELIEF_STATE "This POST request requires specific DTOs for its JSON body and its response, along with Saloon's body-handling traits.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Status\GetQrcStatusRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Status\GetQrcStatusResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -26,7 +27,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the status of an SBP QR Code, which is crucial for tracking payment flows.">
|
||||
class GetQrcStatusRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP status checks are often performed via POST requests with a JSON body.">
|
||||
@@ -57,12 +58,14 @@ class GetQrcStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. The `TermNo` is mandatory, and `qrcId`, `payrrn`, and `messageID` are optional filters to pinpoint the transaction.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'GetQRCstatus'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,20 +12,21 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Subscription;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Subscription\GetQrSubStatusResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// <BELIEF_STATE "The `Response` object is fully qualified in `createDtoFromResponse` as it is not explicitly imported with a `use` statement at the top. This is acceptable but less explicit.">
|
||||
// use Saloon\Http\Response; // Explicit import would be cleaner
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the request to get the status of a QR Code subscription.">
|
||||
// <BELIEF_STATE "This class encapsulates the logic for querying the status of an SBP subscription, which is crucial for managing recurring payments.">
|
||||
class GetQrSubStatusRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Even though it retrieves data, SBP status checks are often performed via POST requests with a JSON body.">
|
||||
@@ -50,27 +51,27 @@ class GetQrSubStatusRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `GetQrSubStatusResponseData` DTO provides a structured object for the status of the subscription.">
|
||||
public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Subscription\GetQrSubStatusResponseData
|
||||
public function createDtoFromResponse(Response $response): GetQrSubStatusResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\Subscription\GetQrSubStatusResponseData::from($response->json());
|
||||
return GetQrSubStatusResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Other fields are conditionally added, ensuring the payload precisely matches the API specification.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
$body = [
|
||||
$bodyArray = [
|
||||
'command' => 'GetQRCSubStatus',
|
||||
'TermNo' => $this->TermNo,
|
||||
'qrcId' => $this->qrcId,
|
||||
];
|
||||
|
||||
if ($this->RQperiod !== null) {
|
||||
$body['RQperiod'] = $this->RQperiod;
|
||||
$bodyArray['RQperiod'] = $this->RQperiod;
|
||||
}
|
||||
|
||||
return $body;
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -12,11 +12,13 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Subscription;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Subscription\QrcSubPayPetitionResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -24,7 +26,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for initiating a payment through an SBP subscription, which is a key part of recurring payment flows.">
|
||||
class QrcSubPayPetitionRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Initiating a payment action that changes the system state is correctly represented by a POST request.">
|
||||
@@ -50,23 +52,25 @@ class QrcSubPayPetitionRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `QrcSubPayPetitionResponseData` DTO provides a structured object for the result of the payment petition.">
|
||||
public function createDtoFromResponse(Response $response): \Apoloz\AlfaBank\Sbp\Data\Subscription\QrcSubPayPetitionResponseData
|
||||
public function createDtoFromResponse(Response $response): QrcSubPayPetitionResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\Subscription\QrcSubPayPetitionResponseData::from($response->json());
|
||||
return QrcSubPayPetitionResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. All constructor properties are directly mapped to the request body.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return [
|
||||
$bodyArray = [
|
||||
'command' => 'QRCSubPayPetition',
|
||||
'TermNo' => $this->TermNo,
|
||||
'subscriptionToken' => $this->subscriptionToken,
|
||||
'SenderMemberId' => $this->SenderMemberId,
|
||||
'qrcId' => $this->qrcId,
|
||||
];
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -13,11 +13,13 @@ namespace Apoloz\AlfaBank\Sbp\Requests\Subscription;
|
||||
// <SECTION name="module_imports" intent="Import DTO and Saloon components for a JSON body request.">
|
||||
// <BELIEF_STATE "This POST request requires the `RegQrSubRequestData` DTO for its JSON body and utilizes `HasBody` and `HasJsonBody` for proper payload serialization. It currently returns a raw array response.">
|
||||
use Apoloz\AlfaBank\Sbp\Data\Subscription\RegQrSubRequestData;
|
||||
use Apoloz\AlfaBank\Sbp\Data\Subscription\RegQrSubResponseData;
|
||||
use Apoloz\AlfaBank\Utils\CmsSigner;
|
||||
use Saloon\Contracts\Body\HasBody;
|
||||
use Saloon\Enums\Method;
|
||||
use Saloon\Http\Request;
|
||||
use Saloon\Http\Response;
|
||||
use Saloon\Traits\Body\HasJsonBody;
|
||||
use Saloon\Traits\Body\HasStringBody;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
@@ -25,7 +27,7 @@ use Saloon\Traits\Body\HasJsonBody;
|
||||
// <BELIEF_STATE "This class encapsulates the logic for initiating an SBP subscription, which is crucial for recurring payment models.">
|
||||
class RegQrSubRequest extends Request implements HasBody
|
||||
{
|
||||
use HasJsonBody;
|
||||
use HasStringBody;
|
||||
|
||||
// <SECTION name="http_method" intent="Declare the HTTP verb.">
|
||||
// <BELIEF_STATE "Registering a new resource or initiating an action that changes the system state is correctly represented by a POST request.">
|
||||
@@ -48,20 +50,22 @@ class RegQrSubRequest extends Request implements HasBody
|
||||
|
||||
// <SECTION name="response_caster" intent="Map the JSON response to a DTO.">
|
||||
// <BELIEF_STATE "Casting the response to a `RegQrSubResponseData` DTO provides a structured object for the result of the subscription registration.">
|
||||
public function createDtoFromResponse(Response $response): \Apoloz\AlfaBank\Sbp\Data\Subscription\RegQrSubResponseData
|
||||
public function createDtoFromResponse(Response $response): RegQrSubResponseData
|
||||
{
|
||||
return \Apoloz\AlfaBank\Sbp\Data\Subscription\RegQrSubResponseData::from($response->json());
|
||||
return RegQrSubResponseData::from($response->json());
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="body_builder" intent="Construct the JSON body for the request.">
|
||||
// <BELIEF_STATE "The `command` field specifies the operation to the SBP API. Using the DTO's `toArray` method ensures the payload is correctly structured.">
|
||||
protected function defaultBody(): array
|
||||
protected function defaultBody(): string
|
||||
{
|
||||
return array_merge(
|
||||
$bodyArray = array_merge(
|
||||
['command' => 'RegQRcSub'],
|
||||
$this->data->toArray()
|
||||
);
|
||||
|
||||
return CmsSigner::canonicalize($bodyArray);
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
|
||||
@@ -1,47 +1,33 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/*
|
||||
// MODULE_CONTRACT: Implements `SignerInterface` using OpenSSL for PKCS#7 (CMS) data signing.
|
||||
// RESPONSIBILITY: To provide a concrete implementation of digital signing that takes a raw data string (e.g., canonicalized JSON), signs it using the configured mTLS certificate and private key, and returns a Base64 encoded PKCS#7 detached signature, adhering to Alfa Bank's security requirements.
|
||||
// INPUTS: Data string to be signed. Certificate path and private key path are provided during instantiation.
|
||||
// OUTPUTS: Base64 encoded PKCS#7 detached signature string.
|
||||
// LINKS: Contracts/SecurityContracts.php, Utils/CmsSigner.php, README.md#security
|
||||
*/
|
||||
|
||||
namespace Apoloz\AlfaBank\Services;
|
||||
|
||||
// <SECTION name="module_imports" intent="Import necessary classes for the signer contract.">
|
||||
// <BELIEF_STATE "The `SignerInterface` is imported to ensure that `OpenSslCmsSigner` adheres to a predefined contract for digital signing, promoting interoperability and testability within the SDK.">
|
||||
use Apoloz\AlfaBank\Contracts\SignerInterface;
|
||||
use Apoloz\AlfaBank\Exceptions\SignerException;
|
||||
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="class_definition" intent="Define the OpenSSL-based CMS signer service.">
|
||||
// <BELIEF_STATE "The `OpenSslCmsSigner` class provides a robust and compliant solution for PKCS#7 CMS signing. By implementing `SignerInterface` and utilizing OpenSSL functions, it ensures that data integrity and authenticity can be cryptographically verified, which is critical for secure communication with financial institutions like Alfa Bank. The class takes certificate and private key paths during construction, allowing for flexible configuration.">
|
||||
class OpenSslCmsSigner implements SignerInterface
|
||||
{
|
||||
// <SECTION name="constructor_definition" intent="Initialize the signer with certificate and private key paths.">
|
||||
// <BELIEF_STATE "The constructor receives the file paths to the mTLS certificate and private key. These paths are stored as protected properties, ensuring that the signer instance is configured with the necessary credentials to perform digital signing operations, aligning with the principle of dependency injection for external resources.">
|
||||
public function __construct(
|
||||
protected string $certificatePath,
|
||||
protected string $privateKeyPath
|
||||
) {}
|
||||
// </SECTION>
|
||||
|
||||
// <SECTION name="sign_method" intent="Sign a given data string using PKCS#7 CMS.">
|
||||
// <BELIEF_STATE "The `sign` method performs the digital signature process as required by Alfa Bank. It reads the certificate and private key from the configured paths, then uses `openssl_pkcs7_sign` with `PKCS7_BINARY | PKCS7_DETACHED` flags to create a detached CMS signature. Error handling is included for robust operation, and the final signature is Base64 encoded after stripping unnecessary headers, ensuring compatibility with API expectations.">
|
||||
public function sign(string $data): string
|
||||
{
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents($this->privateKeyPath)); // assuming no passphrase for simplicity here
|
||||
if (! $privateKey) {
|
||||
throw new SignerException("Could not read private key for signing from {$this->privateKeyPath}.");
|
||||
if (!file_exists($this->privateKeyPath)) {
|
||||
throw new SignerException("Private key file not found: {$this->privateKeyPath}");
|
||||
}
|
||||
if (!file_exists($this->certificatePath)) {
|
||||
throw new SignerException("Certificate file not found: {$this->certificatePath}");
|
||||
}
|
||||
|
||||
$privateKey = openssl_pkey_get_private(file_get_contents($this->privateKeyPath));
|
||||
$cert = openssl_x509_read(file_get_contents($this->certificatePath));
|
||||
if (! $cert) {
|
||||
throw new SignerException("Could not read certificate for signing from {$this->certificatePath}.");
|
||||
|
||||
if (!$privateKey || !$cert) {
|
||||
throw new SignerException("Could not read private key or certificate for signing.");
|
||||
}
|
||||
|
||||
$inFile = tempnam(sys_get_temp_dir(), 'alfa_in');
|
||||
@@ -49,6 +35,7 @@ class OpenSslCmsSigner implements SignerInterface
|
||||
|
||||
file_put_contents($inFile, $data);
|
||||
|
||||
// Используем PKCS7_DETACHED согласно документации Альфа-Банка для digestSignatures
|
||||
$status = openssl_pkcs7_sign(
|
||||
$inFile,
|
||||
$outFile,
|
||||
@@ -58,25 +45,27 @@ class OpenSslCmsSigner implements SignerInterface
|
||||
PKCS7_BINARY | PKCS7_DETACHED
|
||||
);
|
||||
|
||||
if (! $status) {
|
||||
if (file_exists($inFile)) {
|
||||
unlink($inFile);
|
||||
}
|
||||
if (file_exists($outFile)) {
|
||||
unlink($outFile);
|
||||
}
|
||||
throw new SignerException('Signing failed: ' . openssl_error_string());
|
||||
if (!$status) {
|
||||
@unlink($inFile);
|
||||
@unlink($outFile);
|
||||
throw new SignerException("OpenSSL sign failed: " . openssl_error_string());
|
||||
}
|
||||
|
||||
$signedData = file_get_contents($outFile);
|
||||
unlink($inFile);
|
||||
unlink($outFile);
|
||||
@unlink($inFile);
|
||||
@unlink($outFile);
|
||||
|
||||
// Надежно извлекаем только Base64 блок подписи из S/MIME или PEM структуры
|
||||
$parts = explode("\n\n", $signedData);
|
||||
$signature = end($parts);
|
||||
foreach ($parts as $part) {
|
||||
// Очищаем часть от пробелов и переносов
|
||||
$cleaned = str_replace(["\n", "\r", ' '], '', $part);
|
||||
// Ищем блок, который выглядит как длинный Base64 (больше 128 символов) и не содержит S/MIME заголовков
|
||||
if (preg_match('/^[a-zA-Z0-9\/+]+=*$/', $cleaned) && strlen($cleaned) > 128) {
|
||||
return $cleaned;
|
||||
}
|
||||
}
|
||||
|
||||
return str_replace(["\n", "\r"], '', $signature);
|
||||
throw new SignerException("Failed to extract signature body from CMS container. Output: " . substr($signedData, 0, 100));
|
||||
}
|
||||
// </SECTION>
|
||||
}
|
||||
// </SECTION>
|
||||
|
||||
@@ -43,7 +43,8 @@ trait HasAlfaErrorHandling
|
||||
if (str_contains($contentType, 'application/json')) {
|
||||
$data = $response->json();
|
||||
$errorCode = $data['error'] ?? $data['ErrorCode'] ?? 'HTTP_' . $response->status();
|
||||
$errorDescription = $data['error_description'] ?? $data['message'] ?? 'Request failed';
|
||||
$rawDescription = $data['error_description'] ?? $data['message'] ?? 'Request failed';
|
||||
$errorDescription = $this->decodeBankMessage($rawDescription);
|
||||
} else {
|
||||
$errorCode = 'HTTP_' . $response->status();
|
||||
$errorDescription = 'Request failed with status ' . $response->status();
|
||||
@@ -55,4 +56,15 @@ trait HasAlfaErrorHandling
|
||||
"({$requestId}) {$errorDescription}"
|
||||
);
|
||||
}
|
||||
|
||||
private function decodeBankMessage(string $message): string
|
||||
{
|
||||
$decoded = preg_replace_callback(
|
||||
'/%u([0-9A-Fa-f]{4})/',
|
||||
fn ($m) => mb_convert_encoding(pack('H*', $m[1]), 'UTF-8', 'UCS-2BE'),
|
||||
$message
|
||||
);
|
||||
|
||||
return urldecode($decoded);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,37 +12,47 @@ trait SignableData
|
||||
{
|
||||
public function sign(SignerInterface $signer): self
|
||||
{
|
||||
// 1. Create a clone to represent the data-to-be-signed (without existing signatures)
|
||||
$clone = clone $this;
|
||||
// 1. Get raw data as array
|
||||
$data = $this->toArray();
|
||||
|
||||
// We explicitly set digestSignatures to null or empty for the signature calculation
|
||||
// assuming the bank expects the "business payload" only.
|
||||
// If the bank expects the field "digestSignatures": [] to be present in signed string,
|
||||
// we should initialize it as empty collection.
|
||||
// Based on common practices, we exclude it or keep it null.
|
||||
// Let's assume we exclude it (set to null if the property is nullable).
|
||||
$clone->digestSignatures = null;
|
||||
// 2. Remove existing signatures if any
|
||||
unset($data['digestSignatures']);
|
||||
|
||||
// 2. Serialize to JSON
|
||||
// We use JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES to match typical API expectations
|
||||
$jsonToSign = $clone->toJson(JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
// 3. Canonicalize (RFC 8785 - simple version: sort keys, remove nulls, no spaces)
|
||||
$canonicalData = $this->canonicalizeArray($data);
|
||||
|
||||
// 3. Sign
|
||||
$jsonToSign = json_encode($canonicalData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
|
||||
// 4. Sign
|
||||
$signature = $signer->sign($jsonToSign);
|
||||
|
||||
// 4. Attach signature to the original object
|
||||
// 5. Attach signature to the original object
|
||||
if ($this->digestSignatures === null) {
|
||||
$this->digestSignatures = new DataCollection(DigestSignatureData::class, []);
|
||||
}
|
||||
|
||||
// We can't push to DataCollection directly if it's not array-access compatible in all versions,
|
||||
// but Spatie DataCollection is usually iterable.
|
||||
// Safest way is to reconstruct it.
|
||||
$current = $this->digestSignatures->toCollection()->all();
|
||||
$current[] = new DigestSignatureData($signature, 'cms');
|
||||
$current = array_values($this->digestSignatures->toCollection()->all());
|
||||
$current[] = new DigestSignatureData($signature, 'RSA');
|
||||
|
||||
$this->digestSignatures = new DataCollection(DigestSignatureData::class, $current);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function canonicalizeArray(array $array): array
|
||||
{
|
||||
// Remove nulls and empty strings
|
||||
$array = array_filter($array, fn ($v) => $v !== null);
|
||||
|
||||
// Sort keys lexically
|
||||
ksort($array);
|
||||
|
||||
foreach ($array as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$array[$key] = $this->canonicalizeArray($value);
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user