Hướng Dẫn Tích Hợp Thanh Toán Từ A-Z: Khi Bên Thứ 3 Chưa Sẵn Sàng, Ta Tự Build Cổng "Fake"!
Chào các anh em Developer!
Có bao giờ bạn rơi vào tình huống oái ăm: Sếp giục "Tuần sau phải xong luồng thanh toán", khách hàng gật đầu lia lịa, nhưng khi liên hệ với bên Provider (VNPAY, Momo, Stripe...) thì họ bảo: "Dạ, bên em đang bảo trì hệ thống Sandbox" hoặc "Anh chờ 3-5 ngày để bên em cấp tài khoản test"?
Chờ đợi là hạnh phúc, nhưng chờ đợi trong lúc Deadline dí sát nút thì là thảm họa. Hôm nay, mình sẽ chia sẻ cách mình "vượt rào" bằng cách tự xây dựng một Fake Payment Gateway ngay trong lòng Laravel để phát triển vèo vèo mà không cần đợi bất kỳ ai.
1. Tư duy "Trừu tượng hóa" (Abstraction)
Đừng bao giờ code trực tiếp API của bên thứ ba vào Controller. Sai lầm lớn nhất là viết VNPAY::pay()ngay trong hàm checkout.
Thay vào đó, hãy tạo một Interface. Đây là chiếc "mặt nạ" giúp bạn tráo đổi giữa hàng thật và hàng fake một cách trơn tru.
interface PaymentProviderInterface {
public function makePayment(float $amount, string $orderId): array;
public function verifyReturn(array $data): bool;
}
2. Xây dựng "Hàng Fake" (The Mock Logic)
Bây giờ, chúng ta sẽ tạo một Class FakePaymentProvider. Class này sẽ mô phỏng lại đúng những gì một cổng thanh toán thật hay làm: Trả về một URL để người dùng chuyển hướng.
namespace App\Services\Payment;
class FakePaymentProvider implements PaymentProviderInterface {
public function makePayment(float $amount, string $orderId): array {
// Thay vì gọi API thật, ta tạo một URL trỏ về Route "giả" của mình
$fakeUrl = route('fake.payment.view', ['order_id' => $orderId, 'amount' => $amount]);
return [
'status' => 'success',
'payment_url' => $fakeUrl
];
}
public function verifyReturn(array $data): bool {
// Giả lập logic kiểm tra chữ ký (signature)
return $data['status'] === 'completed';
}
}
3. Tạo Giao diện "Cổng thanh toán" ảo
Để trải nghiệm thật nhất, bạn hãy tạo một Route và một View đơn giản. View này sẽ có 2 nút: "Thanh toán thành công" và "Thanh toán thất bại".
// routes/web.php
Route::get('/fake-payment', function (Request $request) {
return view('payment.fake_gateway', [
'orderId' => $request->order_id,
'amount' => $request->amount
]);
})->name('fake.payment.view');
Trong View fake_gateway.blade.php, khi nhấn "Thành công", bạn gửi Request về URL callback của hệ thống mình kèm theo một mã hash giả.
4. Bind vào Service Container
Đây là nơi phép màu của Laravel xảy ra. Trong AppServiceProvider, bạn chỉ cần check môi trường. Nếu là local hoặc testing, hãy dùng hàng Fake. Khi lên production, hãy dùng hàng Thật.
public function register() {
$this->app->singleton(PaymentProviderInterface::class, function ($app) {
if (app()->environment('production')) {
return new RealVNPayProvider();
}
return new FakePaymentProvider();
});
}
5. Lợi ích của việc "Tự biên tự diễn"
Tốc độ: Bạn không tốn 2-3 giây đợi API bên thứ ba phản hồi mỗi khi test.
Chủ động: Bạn có thể giả lập trường hợp "Số dư không đủ", "Lỗi hệ thống ngân hàng" chỉ bằng một cái click chuột.
Unit Test cực nhàn: Bạn có thể dùng Http::fake() hoặc Mock Class dễ dàng mà không sợ tốn tiền thật hay tạo rác trên server đối tác.
Hy vọng bài viết này giúp anh em "chiến binh" Laravel sống sót qua mùa tích hợp thanh toán!
Kinh nghiệm xương máu: Dù Fake có giống thật đến đâu, trước khi Go-live vẫn phải dành ít nhất 1 ngày để test trên Sandbox thật của đối tác nhé!
Nếu bạn thấy bài viết hữu ích, đừng quên Upvote và Clip để dành đọc lại khi cần nhé! Chúc các bạn coding vui vẻ.
All rights reserved