Tích hợp thanh toán chuyển khoản vào website sử dụng Laravel
Hướng dẫn chi tiết cách tích hợp tính năng thanh toán chuyển khoản ngân hàng vào hệ thống website xây dựng bởi Laravel framework thông qua webhook.
Thanh toán trực tuyến là một trong những tính năng không thể thiếu trên các website thương mại điện tử. Trong đó chuyển khoản ngân hàng là hình thức thanh toán được ưa chuộng vì nó mang lại nhiều tiện lợi cũng như tính an toàn cho cả người bán và khách hàng. Bài viết này sẽ hướng dẫn cho bạn cách tích hợp thanh toán trực tuyến bằng hình thức chuyển khoản ngân hàng thông qua webhook và tiến hành cập nhật trạng thái cho đơn hàng. Cùng tham khảo nhé!
Giả sử rằng bạn đã có những kiến thức cơ bản về php cũng như Laravel framework, do đó chúng ta sẽ không đi quá sâu vào chi tiết về cách cài đặt cũng như quản lý dự án của mình nữa.
Laravel là một PHP Framework mã nguồn mở miễn phí, được phát triển bởi Taylor Otwell với phiên bản đầu tiên được ra mắt vào tháng 6 năm 2011. Laravel ra đời nhằm mục đích hỗ trợ phát triển các ứng dụng web, dựa trên mô hình MVC (Model – View – Controller).
Chúng ta sẽ tiến hành xây dựng một website bán hàng dựa trên Laravel 8 và một vài gói packages hỗ trợ sau đây:
Cài đặt
Trước hết hãy khởi tạo project mới:
laravel new laravel-bank-payment
Tiếp đến di chuyển vào thư mục đã được khởi tạo:
cd laravel-bank-payment
Và chạy nó:
php artisan serve
Chuẩn bị cơ sở dữ liệu
Như đã trình bày ở trên, bài viết này sẽ không đi chi tiết vào việc xây dựng hệ thống website thương mại điện tử do nhu cầu phụ thuộc tùy theo từng dự án. Do đó chúng ta sẽ chỉ tạo một bảng dữ liệu về đơn hàng để làm ví dụ.
Tạo file migrate để thiết lập cơ sở dữ liệu cho đơn hàng:
php artisan make:migration create_orders_table
Nội dung của file create_orders_table như sau:
Schema::create('orders', function (Blueprint $table) {
$table->id();
$table->string('status');
$table->timestamps();
});
Tiếp đến bạn cần chạy lệnh migrate để tạo bảng vào cơ sở dữ liệu như sau:
php artisan migrate
Thiết lập webhook endpoint URL
Package laravel-webhook-client sẽ giúp bạn xây dựng địa chỉ nhận truy vấn webhook một cách hoàn toàn đơn giản. Bên cạnh đó gói cũng cung cấp tính năng kiểm tra mã bảo mật phù hợp với chữ ký số mà Transmoni gửi kèm theo trong mỗi truy vấn.
Tiến hành cài đặt package laravel-webhook-client:
composer require spatie/laravel-webhook-client
Publish file config cho laravel-webhook-client:
php artisan vendor:publish --provider="Spatie\WebhookClient\WebhookClientServiceProvider" --tag="config"
Publish file migrate cho laravel-webhook-client:
php artisan vendor:publish --provider="Spatie\WebhookClient\WebhookClientServiceProvider" --tag="migrations"
Tiếp tục chạy lệnh migrate để thêm các bảng dữ liệu phục vụ cho laravel-webhook-client:
php artisan migrate
Thêm webhook endpoint vào routes/web.php:
Route::webhooks('webhook-receiving-url');
Lưu ý, vì đoạn code trên sẽ đăng ký một đường dẫn chấp nhận truy vấn POST, tuy nhiên vì hệ thống gửi truy vấn không thể có được csrf-token trên website của bạn do đó bạn cần thêm ngoại lệ vào phần kiểm duyệt csrf-token middleware tại App\Http\Middleware\VerifyCsrfToken như sau:
protected $except = [
'webhook-receiving-url',
];
Cấu hình webhook
Để có thể nhận được truy vấn từ Transmoni tới dự án của bạn dưới máy tính local, bạn cần sử dụng ngrok để đăng ký cho website của mình một địa chỉ tạm thời.
Nếu bạn sử dụng valet, hãy chạy lệnh
valet share
là sẽ có ngay một địa chỉ website phục vụ cho nhu cầu kiểm thử.
Địa chỉ webhook URL của bạn sẽ có dạng như sau:
https://158f1e515b28.ap.ngrok.io/webhook-receiving-url
Tiếp đến bạn truy cập vào trang quản lý tài khoản của Transmoni để thêm địa chỉ tiếp nhận truy vấn webhook này.
Sau khi hoàn thành, Transmoni sẽ cung cấp cho bạn một mã bảo mật ngẫu nhiên nhằm giúp bạn kiểm tra và xác định truy vấn đó được gửi đi từ Transmoni chứ không phải một ai khác.
Package laravel-webhook-client có thể tự động xác thực mã bảo mật này, hãy sao chép nó lại và điền vào file .env
của dự án.
WEBHOOK_CLIENT_SECRET=OV7JDlSDBhdhyJCuqt45UAgT2a6gc5ZLYH7noUsa
Sau đó bạn di chuyển đến trang quản lý chi tiết cho địa chỉ webhook vừa thêm. Tại đây bạn có thể xem danh sách lịch sử các truy vấn đã được thực hiện cũng như trạng thái phản hồi của từng truy vấn.
Bên cạnh đó Transmoni cũng cung cấp cho bạn tính năng gửi truy vấn kiểm thử. Tính năng này sẽ gửi một truy vấn giống với truy vấn thông thường tới địa chỉ webhook của bạn, tuy nhiên dữ liệu gửi đi được tạo ra một cách ngẫu nhiên nhằm giúp bạn có thể kiểm tra đường dẫn webhook của mình có thực sự hoạt động trơn tru hay không. Ngoài ra thì bạn cũng có thể tự nhập nội dung truy vấn để việc kiểm thử được dễ dàng hơn.
Nhận và xử lý truy vấn webhook
Sau khi thiết lập hoàn tất, giờ là lúc chúng ta tiến hành nhận truy vấn và thực hiện quy trình xử lý dữ liệu của truy vấn. laravel-webhook-client
cung cấp cho bạn đầy đủ từ route cho đến job để tiếp nhận truy vấn webhook. Bên cạnh đó việc xác thực mã bảo mật cũng được xử lý hoàn toàn tự động và trùng khớp với phương thức mã hóa của Transmoni. Việc của bạn là tạo một job class của mình để xử lý nó mà thôi.
Trước hết, chúng ta cần tạo job class và extends SpatieProcessWebhookJob
để xử lý truy vấn:
php artisan make:job ProcessWebhookJob
Nội dung của job class này như sau:
namespace App\Jobs;
use \Spatie\WebhookClient\ProcessWebhookJob as SpatieProcessWebhookJob;
class ProcessWebhookJob extends SpatieProcessWebhookJob
{
public function handle()
{
// $this->webhookCall // contains an instance of `WebhookCall`
// perform the work here
}
}
Giả sử khách hàng cần thanh toán đơn hàng mã số 12345
với số tiền là 500,000VND . Hãy hướng dẫn họ chuyển số tiền như trên với nội dung ghi chú là TTDH 12345
.
Nội dung ghi chú là hoàn toàn do bạn thiết lập, không bắt buộc phải sử dụng như mẫu của chúng tôi.
Chúng ta sẽ sử dụng tính năng thử nghiệm để gửi một truy vấn với số tiền và nội dung như trên.
Tiếp đến, phía website của bạn chúng ta sẽ cần xử lý dữ liệu truy vấn bằng cách bóc tách nội dung ghi chú chuyển khoản như sau:
<?php
namespace App\Jobs;
use \Spatie\WebhookClient\ProcessWebhookJob as SpatieProcessWebhookJob;
use Illuminate\Support\Str;
use App\Models\Order;
class ProcessWebhookJob extends SpatieProcessWebhookJob
{
public function handle()
{
// Get the transaction data
$transaction = $this->webhookCall->payload['transaction'];
// Check if the transaction description contains the key of payment
if (Str::contains($transaction['description'], 'TTDH')) {
// Grab the order number from transaction description
$order_number = preg_replace('/[^0-9]/', '', $transaction['description']);
// Find the order
$order = Order::find($order_number)->firstOrFail();
// Set new status for order
$order->status = 'payment_received';
// Finish job
$order->save();
}
}
}
Vậy là xong
Tất nhiên chúng ta không thể chỉ sử dụng ví dụ trên để áp dụng vào môi trường thật, bạn cần thực hiện các quy trình phức tạp hơn như: kiểm tra số tiền thanh toán có trùng khớp với giá trị của đơn hàng hay không, hoặc lưu lại lịch sử thanh toán... Tuy nhiên hy vọng bài viết này sẽ giúp bạn hiểu được phần nào quy trình áp dụng webhook để tích hợp tính năng thanh toán thông qua giao dịch chuyển khoản ngân hàng. Chúc các bạn thành công!