'APPID123', 'merchant_code' => 'MERCH001', 'merchant_key' => 'test-merchant-key', 'base_url' => 'https://kbz.test/gateway', ]; /** * @return array */ $signedKbzNotification = function (array $overrides, string $merchantKey): array { $notification = array_merge([ 'appid' => 'APPID123', 'notify_time' => '1576842150', 'merch_code' => 'MERCH001', 'merch_order_id' => 'EVB-FIXTURE-001-1', 'mm_order_id' => '01001814070006560257', 'trans_currency' => 'MMK', 'total_amount' => '15000', 'trade_status' => 'PAY_SUCCESS', 'trans_end_time' => '1576834704', 'nonce_str' => '513ba55344ad44c8b69465aae66f7703', 'sign_type' => 'SHA256', ], $overrides); $notification['sign'] = KbzSignature::sign($notification, $merchantKey); return $notification; }; test('handleWebhook maps a validly signed PAY_SUCCESS notification to a completed PaymentResultData', function () use ($config, $signedKbzNotification) { $notification = $signedKbzNotification([], $config['merchant_key']); $result = (new KbzMiniAppGateway($config))->handleWebhook(['Request' => $notification]); expect($result->status)->toBe(PaymentStatus::Completed) ->and($result->gatewayTransactionId)->toBe('EVB-FIXTURE-001-1') ->and($result->gatewayPayload)->toBe($notification); }); test('handleWebhook maps a validly signed WAIT_PAY notification to a pending PaymentResultData', function () use ($config, $signedKbzNotification) { $notification = $signedKbzNotification(['trade_status' => 'WAIT_PAY'], $config['merchant_key']); $result = (new KbzMiniAppGateway($config))->handleWebhook(['Request' => $notification]); expect($result->status)->toBe(PaymentStatus::Pending); }); test('handleWebhook throws InvalidWebhookSignatureException when the sign does not match', function () use ($config, $signedKbzNotification) { $notification = $signedKbzNotification([], $config['merchant_key']); $notification['sign'] = 'not-the-real-signature'; expect(fn () => (new KbzMiniAppGateway($config))->handleWebhook(['Request' => $notification])) ->toThrow(InvalidWebhookSignatureException::class); }); test('handleWebhook throws InvalidWebhookSignatureException when signed with the wrong merchant key', function () use ($config, $signedKbzNotification) { $notification = $signedKbzNotification([], 'a-different-merchant-key'); expect(fn () => (new KbzMiniAppGateway($config))->handleWebhook(['Request' => $notification])) ->toThrow(InvalidWebhookSignatureException::class); }); test('handleWebhook throws InvalidWebhookSignatureException when the sign field is missing entirely', function () use ($config) { expect(fn () => (new KbzMiniAppGateway($config))->handleWebhook(['Request' => ['trade_status' => 'PAY_SUCCESS']])) ->toThrow(InvalidWebhookSignatureException::class); }); test('handleWebhook throws InvalidWebhookSignatureException when the Request key is missing entirely', function () use ($config) { expect(fn () => (new KbzMiniAppGateway($config))->handleWebhook([])) ->toThrow(InvalidWebhookSignatureException::class); });