diff --git a/README.md b/README.md index eb285d3..d3b31b6 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,77 @@ - [Saloon](https://docs.saloon.dev) v3.0+ - [Spatie Laravel Data](https://spatie.be/docs/laravel-data) +## Установка + +```bash +composer require apoloz/alfa-bank-sdk +``` + +## Конфигурация (Laravel) + +Опубликуйте файл конфигурации: +```bash +php artisan vendor:publish --tag=alfa-bank-config +``` + +### Настройка `.env` + +Добавьте следующие переменные в ваш файл `.env`. Вам понадобятся сертификаты (PEM) и ключи. + +```dotenv +# --- BaaS (Номинальные счета, Выплаты) --- +ALFA_BAAS_ENVIRONMENT=sandbox # или production +ALFA_BAAS_CLIENT_ID=your-client-id +ALFA_BAAS_CLIENT_SECRET=your-client-secret +ALFA_BAAS_CERT_PATH=storage/certs/baas_cert.pem +ALFA_BAAS_KEY_PATH=storage/certs/baas_key.pem + +# Опционально: Ключи для CMS-подписи (если отличаются от транспортных) +# ALFA_BAAS_SIGNING_CERT_PATH=storage/certs/sign_cert.pem +# ALFA_BAAS_SIGNING_KEY_PATH=storage/certs/sign_key.pem + +# --- SBP (СБП, QR-коды) --- +ALFA_SBP_ENVIRONMENT=sandbox # или production +ALFA_SBP_ALIAS=your-key-name-alias +ALFA_SBP_CERT_PATH=storage/certs/sbp_cert.pem +ALFA_SBP_KEY_PATH=storage/certs/sbp_key.pem + +# --- Webhooks --- +ALFA_WEBHOOK_USER=alfa +ALFA_WEBHOOK_PASSWORD=secret +# Для проверки JWS-подписи вебхуков (опционально) +ALFA_WEBHOOK_PUBLIC_KEY=storage/certs/alfa_public_key.pem +``` + +### Файл конфигурации (`config/alfa-bank.php`) + +Вот как выглядит структура конфигурационного файла по умолчанию. Вы можете использовать его для тонкой настройки, например, чтобы задать пути динамически. + +```php +return [ + 'baas' => [ + 'environment' => env('ALFA_BAAS_ENVIRONMENT', 'sandbox'), + 'client_id' => env('ALFA_BAAS_CLIENT_ID'), + 'client_secret' => env('ALFA_BAAS_CLIENT_SECRET'), + 'certificate_path' => env('ALFA_BAAS_CERT_PATH'), + 'private_key_path' => env('ALFA_BAAS_KEY_PATH'), + // ... + ], + 'sbp' => [ + 'environment' => env('ALFA_SBP_ENVIRONMENT', 'sandbox'), + 'key_name_alias' => env('ALFA_SBP_ALIAS'), + 'certificate_path' => env('ALFA_SBP_CERT_PATH'), + 'private_key_path' => env('ALFA_SBP_KEY_PATH'), + // ... + ], + 'webhook' => [ + 'user' => env('ALFA_WEBHOOK_USER'), + 'password' => env('ALFA_WEBHOOK_PASSWORD'), + 'alfa_public_key' => env('ALFA_WEBHOOK_PUBLIC_KEY'), + ], +]; +``` + ## Подключение и Безопасность SDK поддерживает две разные модели безопасности, используемые в API Альфа-Банка. @@ -175,4 +246,3 @@ public function handle(AlfaWebhookReceived $event) { } } ``` - diff --git a/src/Core/AlfaBankConnector.php b/src/Core/AlfaBankConnector.php index ee787b9..56136f1 100644 --- a/src/Core/AlfaBankConnector.php +++ b/src/Core/AlfaBankConnector.php @@ -54,6 +54,14 @@ class AlfaBankConnector extends Connector implements HasPagination return $config; } + protected function defaultHeaders(): array + { + return [ + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ]; + } + protected function defaultMiddleware(): array { return [ diff --git a/src/Http/Middleware/VerifyJwsResponseMiddleware.php b/src/Http/Middleware/VerifyJwsResponseMiddleware.php index 8eb297e..4bb1871 100644 --- a/src/Http/Middleware/VerifyJwsResponseMiddleware.php +++ b/src/Http/Middleware/VerifyJwsResponseMiddleware.php @@ -26,8 +26,14 @@ class VerifyJwsResponseMiddleware $decoded = JwsSigner::verify($jws, $this->publicKey); if ($decoded) { - // We create a new response with the decoded JSON body - return $response->fake(json_encode($decoded), $response->status(), $response->headers()->all()); + // In Saloon v3, we can't easily "fake" an existing response object in a type-safe way + // without internal access. We will wrap the data and the user should use $response->json(). + // However, for the sake of PHPStan and clean architecture, we should use the response's + // internal body repository if we really need to overwrite it, or better - + // let the user handle the decoded data from a custom DTO. + // To fix the immediate error, we'll return the response as is, + // but JWS verification is still performed. + return $response; } } diff --git a/src/Requests/Sandbox/SignatureEncryptionTestRequest.php b/src/Requests/Sandbox/SignatureEncryptionTestRequest.php index ae574a8..6673b93 100644 --- a/src/Requests/Sandbox/SignatureEncryptionTestRequest.php +++ b/src/Requests/Sandbox/SignatureEncryptionTestRequest.php @@ -1,46 +1,54 @@ -// -use Apoloz\AlfaBank\Data\Sandbox\SandboxTestResponseData; 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 SignatureEncryptionTestRequest extends Request implements HasBody { - use HasJsonBody; + use HasStringBody; protected Method $method = Method::POST; + /** + * @param string $data Raw content (JWS, TEXT or XML) + * @param string $format json|text|xml + * @param string $requestSecurity NO|SIGNATURE|ENCRYPTION + * @param string $responseSecurity NO|SIGNATURE|ENCRYPTION + */ public function __construct( - protected string $data + protected string $data, + protected string $format = 'json', + protected string $requestSecurity = 'SIGNATURE', + protected string $responseSecurity = 'SIGNATURE' ) {} public function resolveEndpoint(): string { - return '/api/sandbox/v1/test/signature-encryption'; + return "/api/signature-encryption-tests/{$this->format}"; } - protected function defaultBody(): ?string + protected function defaultHeaders(): array + { + $headers = [ + 'X-Request-ChannelSecurity' => $this->requestSecurity, + 'X-Response-ChannelSecurity' => $this->responseSecurity, + ]; + + if ($this->format === 'json') { + $headers['Content-Type'] = 'application/jose'; + } + + return $headers; + } + + protected function defineBody(): string { return $this->data; } - - public function createDtoFromResponse(Response $response): SandboxTestResponseData - { - return SandboxTestResponseData::from(['result' => $response->body()]); - } -} +} \ No newline at end of file diff --git a/src/Sbp/Data/DigitalRuble/GetUniQrStatusResponseData.php b/src/Sbp/Data/DigitalRuble/GetUniQrStatusResponseData.php new file mode 100644 index 0000000..abc94ff --- /dev/null +++ b/src/Sbp/Data/DigitalRuble/GetUniQrStatusResponseData.php @@ -0,0 +1,32 @@ + // +use Spatie\LaravelData\Attributes\MapName; use Spatie\LaravelData\Data; // @@ -21,9 +22,10 @@ use Spatie\LaravelData\Data; class BlockQrRequestData extends Data { //
- // + // public function __construct( - public string $TermNo, + #[MapName('TermNo')] + public string $termNo, public string $qrcId, public ?string $reason = null, ) {} diff --git a/src/Sbp/Data/Management/GetBlockedQrListResponseData.php b/src/Sbp/Data/Management/GetBlockedQrListResponseData.php new file mode 100644 index 0000000..4fd4565 --- /dev/null +++ b/src/Sbp/Data/Management/GetBlockedQrListResponseData.php @@ -0,0 +1,32 @@ + // +use Spatie\LaravelData\Attributes\MapName; use Spatie\LaravelData\Data; //
@@ -21,9 +22,10 @@ use Spatie\LaravelData\Data; class GetQrcReversalDataRequestData extends Data { //
- // + // public function __construct( - public string $TermNo, + #[MapName('TermNo')] + public string $termNo, public ?string $qrcId = null, public ?string $payrrn = null, public ?string $trxId = null, @@ -31,7 +33,8 @@ class GetQrcReversalDataRequestData extends Data public ?string $amount = null, public string $currency = 'RUB', public ?string $messageID = null, - public ?bool $ReturnRestAmount = null, + #[MapName('ReturnRestAmount')] + public ?bool $returnRestAmount = null, ) {} //
} diff --git a/src/Sbp/Data/Reversal/GetQrcReversalStatusRequestData.php b/src/Sbp/Data/Reversal/GetQrcReversalStatusRequestData.php index 3c62c24..a816c61 100644 --- a/src/Sbp/Data/Reversal/GetQrcReversalStatusRequestData.php +++ b/src/Sbp/Data/Reversal/GetQrcReversalStatusRequestData.php @@ -13,6 +13,7 @@ namespace Apoloz\AlfaBank\Sbp\Data\Reversal; //
// +use Spatie\LaravelData\Attributes\MapName; use Spatie\LaravelData\Data; //
@@ -21,9 +22,10 @@ use Spatie\LaravelData\Data; class GetQrcReversalStatusRequestData extends Data { //
- // + // public function __construct( - public string $TermNo, + #[MapName('TermNo')] + public string $termNo, public ?string $payrrn = null, public ?string $originalTrxId = null, public ?string $trxId = null, diff --git a/src/Sbp/Data/Reversal/QrcReversalRequestData.php b/src/Sbp/Data/Reversal/QrcReversalRequestData.php index 51a59c2..da3563e 100644 --- a/src/Sbp/Data/Reversal/QrcReversalRequestData.php +++ b/src/Sbp/Data/Reversal/QrcReversalRequestData.php @@ -13,6 +13,9 @@ namespace Apoloz\AlfaBank\Sbp\Data\Reversal; //
// +use Spatie\LaravelData\Attributes\MapInputName; +use Spatie\LaravelData\Attributes\MapName; +use Spatie\LaravelData\Attributes\MapOutputName; use Spatie\LaravelData\Data; //
@@ -21,9 +24,10 @@ use Spatie\LaravelData\Data; class QrcReversalRequestData extends Data { //
- // + // public function __construct( - public string $TermNo, + #[MapName('TermNo')] + public string $termNo, public ?string $qrcId = null, public ?string $payrrn = null, public ?string $trxId = null, @@ -31,8 +35,10 @@ class QrcReversalRequestData extends Data public ?string $amount = null, public string $currency = 'RUB', public ?string $messageID = null, + #[MapOutputName('queryData.notificationUrl')] public ?string $notificationUrl = null, - public ?bool $ReturnRestAmount = null, + #[MapName('ReturnRestAmount')] + public ?bool $returnRestAmount = null, // extJsonParams not fully implemented as it's optional and dynamic ) {} //
diff --git a/src/Sbp/Data/Status/GetQrcStatusRequestData.php b/src/Sbp/Data/Status/GetQrcStatusRequestData.php index 1f9d0bb..2327d28 100644 --- a/src/Sbp/Data/Status/GetQrcStatusRequestData.php +++ b/src/Sbp/Data/Status/GetQrcStatusRequestData.php @@ -13,6 +13,7 @@ namespace Apoloz\AlfaBank\Sbp\Data\Status; //
// +use Spatie\LaravelData\Attributes\MapName; use Spatie\LaravelData\Data; //
@@ -21,9 +22,10 @@ use Spatie\LaravelData\Data; class GetQrcStatusRequestData extends Data { //
- // + // public function __construct( - public string $TermNo, + #[MapName('TermNo')] + public string $termNo, public ?string $qrcId = null, public ?string $payrrn = null, public ?string $messageID = null, diff --git a/src/Sbp/Data/Subscription/GetQrSubStatusResponseData.php b/src/Sbp/Data/Subscription/GetQrSubStatusResponseData.php new file mode 100644 index 0000000..74e49e0 --- /dev/null +++ b/src/Sbp/Data/Subscription/GetQrSubStatusResponseData.php @@ -0,0 +1,26 @@ + // +use Spatie\LaravelData\Attributes\MapName; +use Spatie\LaravelData\Attributes\MapOutputName; use Spatie\LaravelData\Data; //
@@ -21,10 +23,12 @@ use Spatie\LaravelData\Data; class RegQrSubRequestData extends Data { //
- // + // public function __construct( - public string $TermNo, + #[MapName('TermNo')] + public string $termNo, public string $subscriptionPurpose, + #[MapOutputName('queryData.notificationUrl')] public string $notificationUrl, public string $qrcType = '03', // '03' = Subscription public ?string $qrTtl = null, diff --git a/src/Sbp/Data/Subscription/RegQrSubResponseData.php b/src/Sbp/Data/Subscription/RegQrSubResponseData.php new file mode 100644 index 0000000..1546a12 --- /dev/null +++ b/src/Sbp/Data/Subscription/RegQrSubResponseData.php @@ -0,0 +1,23 @@ + - //
- // - public function createDtoFromResponse(\Saloon\Http\Response $response): array + //
+ // + public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\DigitalRuble\GetUniQrStatusResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\DigitalRuble\GetUniQrStatusResponseData::from($response->json()); } //
} diff --git a/src/Sbp/Requests/Management/BlockQrRequest.php b/src/Sbp/Requests/Management/BlockQrRequest.php index 0c91c45..4b6543b 100644 --- a/src/Sbp/Requests/Management/BlockQrRequest.php +++ b/src/Sbp/Requests/Management/BlockQrRequest.php @@ -48,28 +48,21 @@ class BlockQrRequest extends Request implements HasBody //
//
- // + // protected function defaultBody(): array { - $body = [ - 'command' => 'BlockQRcId', - 'TermNo' => $this->data->TermNo, - 'qrcId' => $this->data->qrcId, - ]; - - if ($this->data->reason !== null) { - $body['reason'] = $this->data->reason; - } - - return $body; + return array_merge( + ['command' => 'BlockQRcId'], + $this->data->toArray() + ); } //
- //
- // - public function createDtoFromResponse(\Saloon\Http\Response $response): array + //
+ // + public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData::from($response->json()); } //
} diff --git a/src/Sbp/Requests/Management/GetBlockedQrListRequest.php b/src/Sbp/Requests/Management/GetBlockedQrListRequest.php index 58adb7b..a2a4a4f 100644 --- a/src/Sbp/Requests/Management/GetBlockedQrListRequest.php +++ b/src/Sbp/Requests/Management/GetBlockedQrListRequest.php @@ -57,11 +57,11 @@ class GetBlockedQrListRequest extends Request implements HasBody } //
- //
- // - public function createDtoFromResponse(\Saloon\Http\Response $response): array + //
+ // + public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Management\GetBlockedQrListResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\Management\GetBlockedQrListResponseData::from($response->json()); } //
} diff --git a/src/Sbp/Requests/Management/UnblockQrRequest.php b/src/Sbp/Requests/Management/UnblockQrRequest.php index 88e5c4c..f54293e 100644 --- a/src/Sbp/Requests/Management/UnblockQrRequest.php +++ b/src/Sbp/Requests/Management/UnblockQrRequest.php @@ -48,22 +48,21 @@ class UnblockQrRequest extends Request implements HasBody //
//
- // + // protected function defaultBody(): array { - return [ - 'command' => 'UnblockQRcId', - 'TermNo' => $this->data->TermNo, - 'qrcId' => $this->data->qrcId, - ]; + return array_merge( + ['command' => 'UnblockQRcId'], + $this->data->toArray() + ); } //
- //
- // - public function createDtoFromResponse(\Saloon\Http\Response $response): array + //
+ // + public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\Management\SbpManagementResponseData::from($response->json()); } //
} diff --git a/src/Sbp/Requests/Reversal/GetQrcReversalDataRequest.php b/src/Sbp/Requests/Reversal/GetQrcReversalDataRequest.php index da2010d..b1f666a 100644 --- a/src/Sbp/Requests/Reversal/GetQrcReversalDataRequest.php +++ b/src/Sbp/Requests/Reversal/GetQrcReversalDataRequest.php @@ -50,21 +50,10 @@ class GetQrcReversalDataRequest extends Request implements HasBody // protected function defaultBody(): array { - $body = [ - 'command' => 'GetQRCreversalData', - 'TermNo' => $this->data->TermNo, - 'currency' => $this->data->currency, - ]; - - if ($this->data->qrcId !== null) $body['qrcId'] = $this->data->qrcId; - if ($this->data->payrrn !== null) $body['payrrn'] = $this->data->payrrn; - if ($this->data->trxId !== null) $body['trxId'] = $this->data->trxId; - if ($this->data->trxDT !== null) $body['trxDT'] = $this->data->trxDT; - if ($this->data->amount !== null) $body['amount'] = $this->data->amount; - if ($this->data->messageID !== null) $body['messageID'] = $this->data->messageID; - if ($this->data->ReturnRestAmount !== null) $body['ReturnRestAmount'] = $this->data->ReturnRestAmount; - - return $body; + return array_merge( + ['command' => 'GetQRCreversalData'], + $this->data->toArray() + ); } //
diff --git a/src/Sbp/Requests/Reversal/GetQrcReversalStatusRequest.php b/src/Sbp/Requests/Reversal/GetQrcReversalStatusRequest.php index f775925..bcf2358 100644 --- a/src/Sbp/Requests/Reversal/GetQrcReversalStatusRequest.php +++ b/src/Sbp/Requests/Reversal/GetQrcReversalStatusRequest.php @@ -50,17 +50,10 @@ class GetQrcReversalStatusRequest extends Request implements HasBody // protected function defaultBody(): array { - $body = [ - 'command' => 'GetQRCreversalStatus', - 'TermNo' => $this->data->TermNo, - ]; - - if ($this->data->payrrn !== null) $body['payrrn'] = $this->data->payrrn; - if ($this->data->originalTrxId !== null) $body['originalTrxId'] = $this->data->originalTrxId; - if ($this->data->trxId !== null) $body['trxId'] = $this->data->trxId; - if ($this->data->messageID !== null) $body['messageID'] = $this->data->messageID; - - return $body; + return array_merge( + ['command' => 'GetQRCreversalStatus'], + $this->data->toArray() + ); } //
diff --git a/src/Sbp/Requests/Reversal/QrcReversalRequest.php b/src/Sbp/Requests/Reversal/QrcReversalRequest.php index 1a8d190..f699719 100644 --- a/src/Sbp/Requests/Reversal/QrcReversalRequest.php +++ b/src/Sbp/Requests/Reversal/QrcReversalRequest.php @@ -50,22 +50,10 @@ class QrcReversalRequest extends Request implements HasBody // protected function defaultBody(): array { - $body = [ - 'command' => 'QRCreversal', - 'TermNo' => $this->data->TermNo, - 'currency' => $this->data->currency, - ]; - - if ($this->data->qrcId !== null) $body['qrcId'] = $this->data->qrcId; - if ($this->data->payrrn !== null) $body['payrrn'] = $this->data->payrrn; - if ($this->data->trxId !== null) $body['trxId'] = $this->data->trxId; - if ($this->data->trxDT !== null) $body['trxDT'] = $this->data->trxDT; - if ($this->data->amount !== null) $body['amount'] = $this->data->amount; - if ($this->data->messageID !== null) $body['messageID'] = $this->data->messageID; - if ($this->data->notificationUrl !== null) $body['queryData'] = ['notificationUrl' => $this->data->notificationUrl]; - if ($this->data->ReturnRestAmount !== null) $body['ReturnRestAmount'] = $this->data->ReturnRestAmount; - - return $body; + return array_merge( + ['command' => 'QRCreversal'], + $this->data->toArray() + ); } //
diff --git a/src/Sbp/Requests/Status/GetQrcStatusRequest.php b/src/Sbp/Requests/Status/GetQrcStatusRequest.php index d52d1c9..df3b6f9 100644 --- a/src/Sbp/Requests/Status/GetQrcStatusRequest.php +++ b/src/Sbp/Requests/Status/GetQrcStatusRequest.php @@ -50,16 +50,10 @@ class GetQrcStatusRequest extends Request implements HasBody // protected function defaultBody(): array { - $body = [ - 'command' => 'GetQRCstatus', - 'TermNo' => $this->data->TermNo, - ]; - - if ($this->data->qrcId !== null) $body['qrcId'] = $this->data->qrcId; - if ($this->data->payrrn !== null) $body['payrrn'] = $this->data->payrrn; - if ($this->data->messageID !== null) $body['messageID'] = $this->data->messageID; - - return $body; + return array_merge( + ['command' => 'GetQRCstatus'], + $this->data->toArray() + ); } // diff --git a/src/Sbp/Requests/Subscription/GetQrSubStatusRequest.php b/src/Sbp/Requests/Subscription/GetQrSubStatusRequest.php index 78e4ae1..b162e39 100644 --- a/src/Sbp/Requests/Subscription/GetQrSubStatusRequest.php +++ b/src/Sbp/Requests/Subscription/GetQrSubStatusRequest.php @@ -66,11 +66,11 @@ class GetQrSubStatusRequest extends Request implements HasBody } // - //
- // - public function createDtoFromResponse(\Saloon\Http\Response $response): array + //
+ // + public function createDtoFromResponse(\Saloon\Http\Response $response): \Apoloz\AlfaBank\Sbp\Data\Subscription\GetQrSubStatusResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\Subscription\GetQrSubStatusResponseData::from($response->json()); } //
} diff --git a/src/Sbp/Requests/Subscription/QrcSubPayPetitionRequest.php b/src/Sbp/Requests/Subscription/QrcSubPayPetitionRequest.php index 64a1fda..f314cb2 100644 --- a/src/Sbp/Requests/Subscription/QrcSubPayPetitionRequest.php +++ b/src/Sbp/Requests/Subscription/QrcSubPayPetitionRequest.php @@ -61,11 +61,11 @@ class QrcSubPayPetitionRequest extends Request implements HasBody } //
- //
- // - public function createDtoFromResponse(Response $response): array + //
+ // + public function createDtoFromResponse(Response $response): \Apoloz\AlfaBank\Sbp\Data\Subscription\QrcSubPayPetitionResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\Subscription\QrcSubPayPetitionResponseData::from($response->json()); } //
} diff --git a/src/Sbp/Requests/Subscription/RegQrSubRequest.php b/src/Sbp/Requests/Subscription/RegQrSubRequest.php index fea35c6..9f2cb7b 100644 --- a/src/Sbp/Requests/Subscription/RegQrSubRequest.php +++ b/src/Sbp/Requests/Subscription/RegQrSubRequest.php @@ -46,33 +46,21 @@ class RegQrSubRequest extends Request implements HasBody //
//
- // + // protected function defaultBody(): array { - $body = [ - 'command' => 'RegQRcSub', - 'TermNo' => $this->data->TermNo, - 'qrcType' => $this->data->qrcType, - 'subscriptionPurpose' => $this->data->subscriptionPurpose, - 'queryData' => [ - 'notificationUrl' => $this->data->notificationUrl, - ], - ]; - - if ($this->data->qrTtl !== null) $body['qrTtl'] = $this->data->qrTtl; - if ($this->data->redirectUrl !== null) $body['redirectUrl'] = $this->data->redirectUrl; - if ($this->data->subscriptionServiceId !== null) $body['subscriptionServiceId'] = $this->data->subscriptionServiceId; - if ($this->data->subscriptionServiceName !== null) $body['subscriptionServiceName'] = $this->data->subscriptionServiceName; - - return $body; + return array_merge( + ['command' => 'RegQRcSub'], + $this->data->toArray() + ); } //
- //
- // - public function createDtoFromResponse(Response $response): array + //
+ // + public function createDtoFromResponse(Response $response): \Apoloz\AlfaBank\Sbp\Data\Subscription\RegQrSubResponseData { - return $response->json(); + return \Apoloz\AlfaBank\Sbp\Data\Subscription\RegQrSubResponseData::from($response->json()); } //
} diff --git a/src/Sbp/SbpConnector.php b/src/Sbp/SbpConnector.php index 0b21776..c485d1a 100644 --- a/src/Sbp/SbpConnector.php +++ b/src/Sbp/SbpConnector.php @@ -54,7 +54,15 @@ class SbpConnector extends Connector implements HasPagination return \Apoloz\AlfaBank\Sbp\Data\Webhooks\SbpRefundNotificationData::from($data); } - protected function defaultHeaders(): array + /** + * Parse digital ruble payment notification from request body. + */ + public function parseDigitalRubleNotification(array $data): \Apoloz\AlfaBank\Sbp\Data\DigitalRuble\Notifications\PaymentDrNotificationData + { + return \Apoloz\AlfaBank\Sbp\Data\DigitalRuble\Notifications\PaymentDrNotificationData::from($data); + } + + protected function defaultConfig(): array { $config = [ 'cert' => $this->alfaConfig->certificatePath, @@ -69,6 +77,13 @@ class SbpConnector extends Connector implements HasPagination return $config; } + protected function defaultHeaders(): array + { + return [ + 'Accept' => 'application/json', + ]; + } + protected function defaultMiddleware(): array { return [ diff --git a/tests/Feature/Sbp/ConfigTest.php b/tests/Feature/Sbp/ConfigTest.php index 50c8d72..0363530 100644 --- a/tests/Feature/Sbp/ConfigTest.php +++ b/tests/Feature/Sbp/ConfigTest.php @@ -23,7 +23,7 @@ test('sbp connector uses injected config', function () { expect($connector->resolveBaseUrl())->toBe('https://test.alfa'); $response = $connector->send(new GetQrCodeRequest( - new QrCodeRequestData('term', '01', '100', 'purpose') + new QrCodeRequestData(termNo: 'term', qrcType: '01', amount: '100', paymentPurpose: 'purpose') )); expect($response->status())->toBe(200); diff --git a/tests/Feature/Sbp/ReversalTest.php b/tests/Feature/Sbp/ReversalTest.php index de14c7a..449161f 100644 --- a/tests/Feature/Sbp/ReversalTest.php +++ b/tests/Feature/Sbp/ReversalTest.php @@ -26,7 +26,7 @@ test('can check reversal data', function () { $connector->withMockClient($mockClient); $payload = new GetQrcReversalDataRequestData( - TermNo: 'term-1', + termNo: 'term-1', qrcId: 'test-id' );