fix kbz payment success payload
PHP Tests / php-tests (push) Failing after 3m6s

This commit is contained in:
Nyan Lin Paing
2026-08-18 11:54:34 +07:00
parent c3a6f6cc6e
commit 532f2ddf99
2 changed files with 31 additions and 16 deletions
@@ -114,13 +114,19 @@ class KbzMiniAppGateway implements PaymentGatewayInterface
);
}
$orderInfo = $this->createOrderInfo($body['prepay_id'] ?? '');
return new PaymentResultData(
// KBZ's queryorder/refund calls both key off our own merch_order_id,
// not their prepay_id — so that's what gets stored/passed forward as
// the gateway transaction id (prepay_id still lives in the payload).
status: PaymentStatus::Pending,
gatewayTransactionId: $data->merchantOrderId,
gatewayPayload: $body,
gatewayPayload: [
'prepayId' => $body['prepay_id'] ?? null,
'orderInfo' => KbzSignature::joinKeyVal($orderInfo),
'signature' => KbzSignature::sign($orderInfo, $this->merchantKey),
],
);
}
@@ -239,7 +245,7 @@ class KbzMiniAppGateway implements PaymentGatewayInterface
'timestamp' => (string) now()->timestamp,
'method' => 'kbz.payment.precreate',
'notify_url' => $data->notifyUrl ?? $this->notifyUrl,
'nonce_str' => $this->nonceStr(),
'nonce_str' => uniqid(),
'version' => '1.0',
'biz_content' => [
'appid' => $this->appId,
@@ -266,7 +272,7 @@ class KbzMiniAppGateway implements PaymentGatewayInterface
$params = [
'timestamp' => (string) now()->timestamp,
'method' => 'kbz.payment.queryorder',
'nonce_str' => $this->nonceStr(),
'nonce_str' => uniqid(),
'version' => '1.0',
'biz_content' => [
'appid' => $this->appId,
@@ -303,7 +309,7 @@ class KbzMiniAppGateway implements PaymentGatewayInterface
$params = [
'timestamp' => (string) now()->timestamp,
'method' => 'kbz.payment.refund',
'nonce_str' => $this->nonceStr(),
'nonce_str' => uniqid(),
'version' => '1.0',
'biz_content' => [
'appid' => $this->appId,
@@ -329,18 +335,6 @@ class KbzMiniAppGateway implements PaymentGatewayInterface
return now()->format('YmdHi').strtoupper(Str::random(8));
}
/**
* KBZ requires `nonce_str` to be a plain alphanumeric string of at most
* 32 characters no hyphens or other special characters (confirmed
* against KBZ's "Query Order" field spec). `Str::uuid()` violates both
* constraints (36 chars, hyphenated), which silently broke `precreate`
* downstream even though the request's own signature still validated.
*/
private function nonceStr(): string
{
return strtoupper(Str::random(32));
}
/**
* mTLS options for the refund call KBZ requires a client cert/key +
* CA bundle on `kbz.payment.refund` specifically (domain.md §6).
@@ -369,4 +363,15 @@ class KbzMiniAppGateway implements PaymentGatewayInterface
return $options;
}
public function createOrderInfo($prepayId): array
{
return [
'appid' => $this->appId,
'merch_code' => $this->merchantCode,
'nonce_str' => uniqid(),
'prepay_id' => $prepayId,
'timestamp' => (string)time()
];
}
}
@@ -8,6 +8,7 @@ use Illuminate\Routing\Controller;
use Illuminate\Support\Facades\Gate;
use Modules\Booking\Models\Booking;
use Modules\Payment\Actions\InitiatePaymentAction;
use Modules\Payment\Enums\PaymentStatus;
use Modules\Payment\Http\Resources\PaymentResource;
class PaymentController extends Controller
@@ -26,6 +27,15 @@ class PaymentController extends Controller
$payment = $this->initiatePaymentAction->handle($booking);
if ($payment->status === PaymentStatus::Failed) {
return response()->json([
'message' => 'Payment initiation failed',
'errors' => [
'payment' => ['Payment initiation failed'],
],
], 422);
}
return (new PaymentResource($payment))
->response()
->setStatusCode(201);