如何在Laravel项目中集成孟加拉支付网关?

如何在Laravel项目中集成孟加拉支付网关:完整指南

前言

在当今全球化的电子商务环境中,为不同地区的用户提供本地化支付解决方案至关重要。对于面向孟加拉市场的Laravel项目而言,集成当地支付网关能显著提升用户体验和转化率。本文将详细介绍如何在Laravel框架中高效、安全地集成孟加拉主流支付网关。

一、了解孟加拉主流支付网关选项

在开始技术实现前,首先需要了解孟加拉市场常见的几种支付网关:

  1. bKash – 最受欢迎的移动金融服务提供商
  2. Nagad – 政府支持的电子金融服务平台
  3. Rocket – DBBL银行推出的数字钱包服务
  4. Upay – United Commercial Bank的支付解决方案
  5. SureCash – 另一家广泛使用的移动金融服务商

每种网关都有其特定的API文档和技术要求,开发者应根据目标用户群体选择最适合的方案。

二、前期准备工作

1. Laravel环境配置要求

确保您的开发环境满足以下条件:

  • PHP ≥7.3版本(推荐8.x)
  • Laravel ≥6.x(推荐最新稳定版)
  • Composer包管理器已安装
  • OpenSSL扩展启用

2. SSL证书配置

所有金融交易必须通过HTTPS进行:

sudo apt-get install certbot python3-certbot-nginx # Nginx服务器示例
sudo certbot --nginx -d yourdomain.com #获取Let's Encrypt免费证书

3. API密钥申请流程(以bKash为例)

  1. 注册商户账户
    2)提交企业资质文件验证身份
    3)获取Sandbox测试凭证(App Key/Secret)
    4)等待生产环境审核通过

注意:不同平台审核周期从24小时到7天不等

三、核心集成步骤详解

1.Laravel项目基础设置

安装必要的依赖包:

composer require guzzlehttp/guzzle phpseclib/phpseclib ^3.0 

创建配置文件:

php artisan make:config PaymentGateway.php  

内容示例:

return [
'bkash' => [
'sandbox' => env('BKASH_SANDBOX', true),
'app_key' => env('BKASH_APP_KEY'),
'app_secret' => env('BKASH_APP_SECRET'),
'username' => env('BKASH_USERNAME'), // Merchant account ID
'password' => env('BKASH_PASSWORD')
]
];

添加.env变量:

BKASH_SANDBOX=true  
BKASH_APP_KEY=your_sandbox_key
BKASH_APP_SECRET=your_sandbox_secret
//...其他参数类似设置...

2.OAuth认证模块实现

创建认证服务类App/Services/PaymentAuthService.php:

use GuzzleHttp\Client;

class PaymentAuthService {

protected $client;

public function __construct() {
$this->client = new Client([
'base_uri' => config('paymentgateway.bkash.base_url'),
'timeout' 20,
]);
}

public function getToken() {
try {
$response = $this->client->post('/tokenized/checkout/token/grant',[
json_encode([
"app_key" config("paymentgateway.bkash.app_key"),
"app_secret" config("paymentgateway.bkash.app_secret")
]),
headers Content-Type application/json'
]);
return json_decode($response->getBody());
} catch (\Exception e){
Log::error("Payment Auth Failed".e->getMessage());
throw new \Exception("Authentication failed");
}
}
}

关键点说明

  • Token通常有60分钟有效期需缓存处理
  • Sandbox和生产环境端点URL不同

四、支付流程完整实现

1. 创建支付请求(Create Payment)

在`app/Services/PaymentService.php`中实现:

“`php
public function createPayment($amount, $invoiceNo, $callbackURL) {
try {
$token = Cache::remember(‘bkash_token’, 50, function() {
return $this->authService->getToken();
});

$response = $this->client->post(‘/tokenized/checkout/create’, [
‘headers’ => [
‘Content-Type’ => ‘application/json’,
‘Authorization’ => $token,
‘X-APP-Key’ => config(‘paymentgateway.bkash.app_key’)
],
‘json’ => [
“mode” => “0011”, // Tokenized payment mode
“payerReference” => “customer_”.auth()->id(),
“callbackURL” => route($callbackURL),
“amount” => number_format($amount,2,’.’,”),
“currency” => “BDT”,
“intent” => “sale”,
merchantInvoiceNumber str_replace([‘ ‘,’-‘], ”,$invoiceNo)
]
]);

return json_decode($response->getBody());
} catch (\Exception e) {
Log::error(“Payment Creation Failed: “.e->getMessage());
throw new \Exception(“Could not initiate payment”);
}
}
“`

*关键参数说明*
– `mode`: bKash特定交易模式代码
– `payerReference`: 唯一用户标识符
– `merchantInvoiceNumber`: 仅允许字母数字字符,需过滤特殊符号

2.前端集成方案

方法A:标准重定向方式(推荐)

“`blade



“`

方法B:API直连方式(适合SPA应用)

“`javascript
// React/Vue示例:
async function handlePayment() {
const res await axios.post(‘/api/create-bkash-payment’,{
amount totalAmount,
order_id orderId
});

if(res.data.paymentUrl){
window.location.href res.data.paymentUrl; //跳转至网关页面
}
}
“`

五、回调处理与验证机制

1.Webhook控制器实现

创建路由:
“`php
Route::post(‘/webhook/bkazh’,’WebhookController@handle’);
“`

控制器逻辑:
“`php
public function handle(Request request){

verifySignature(request); //签名验证

switch(request input eventType)){

case PAYMENT_SUCCESS’:
DB transaction(function() use (request){
Order where invoice_no request input merchantInvoiceNumber’))
->update([ status PAID’]);
logTransaction(request all());
});
break;

case PAYMENT_FAILURE’: /*失败处理*/

default logger warning Unknown webhook event’);
}

return response()->json([“status OK”]);
}

private verifySignature request){/*…*/}
“`
*安全建议*
– IP白名单过滤(获取bKah官方IP段)
– HMAC签名验证每条通知

2.轮询校验备用方案

对于无法接收webhook的情况:

“`php php artisan make command VerifyPendingPayments –command=payments verify “`

命令内容:
“`php foreach(PendingPayment olderThanMinutes(10)) as p){
result gatewayApi checkStatus(p trxId);

if(result status SUCCESS’){
p markAsPaid();
} elseif(result expired’){
p cancel();
}} “`
设置定时任务:
“`bash * /5 * php artisan payments verify >> /var/log/payment cron.log “`

六、测试与上线指南

沙箱环境测试要点

1金额边界测试:
-最小金额10 BDT上限75万BDT
-小数位数处理(.00 vs .99)

2异常场景模拟:
-用户取消付款超时未付重复付款等

3性能基准测试建议指标:平均响应时间<800ms成功率>99%

生产环境检查清单:

✅ Nginx/Apache配置优化(TLSv1.3启用OCSP Stapling)
✅ Redis缓存层配置持久化策略
✅数据库索引优化(order表添加trx_id索引列)
✅监控系统集成NewRelic或Sentry错误跟踪

常见问题解决方案:

Q Webhooks未触发?
→检查服务器防火墙设置允许443入站流量

Q SSL证书错误? →更新CA根证书包sudo update ca certificates

Q阿拉伯数字显示问题? →确保前端设置正确的meta charset utf8标签

七、高级优化与安全实践

1. 支付流程性能优化

数据库设计建议:

Schema::create('payment_transactions', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('gateway')->index(); // bKash/Nagad等
$table->decimal('amount', 10,2);
$table->string('currency',3)->default('BDT');
$table->string('trx_id')->unique(); //网关交易ID
$table->string('invoice_no')->index();

状态机实现:
enum status pending success failed refunded')
->default pending');

索引优化:
index(['user_id','created_at']);
});

缓存策略示例:

// app/Services/PaymentCacheService.php
public cachePaymentRequest($requestId,$data){
Redis::connection( payment )
->setex("pay_req:$requestId",3600,json_encode($data));
}

public getCachedRequest requestId){
return json_decode(Redis get("pay_req:$requestId"));
}

2.多网关切换架构

创建抽象层:

interface PaymentGatewayContract {
public createPayment(array data): PaymentResponse;
public verifyPayment(string trxId): VerificationResponse;
}

class BkashGateway implements PaymentGatewayContract { /*...*/ }
class NagadGateway implements PaymentGatewayContract { /*...*/ }

//服务容器绑定 config/app.php providers:
$this app singleton(PaymentGateway class,function app){
switch(config payment default_gateway)){
case bkash return new BkashGateway;
case nagad return new NagadGateWay;
}});

使用示例:

app(Payment Gateway:class)->createPayment([
amount =>1000,
currency=>'BDT'
]);

八、合规性与本地化适配

1.孟加拉国金融法规要求

必须实现的特性:

  • 强制验证用户手机号格式8801[3-9]\d{8}正则表达式:
    regex ^8801[3-9][0-9]{8}$

  • 交易记录保留5年数据库归档方案:
    bash mysqldump payments transactions where created_at < DATE_SUB(NOW() INTERVAL5YEAR) gzip > archive.sql.gz

  • 增值税计算显示(当前税率15%)前端示例:
    javascript const addVAT = amount => (amount *115/100).toFixed(2);

2.语言本地化配置

resources/lang/bn/payments.php内容示例:

'title' => পেমেন্ট গেটওয়ে',
'instructions'=> '
১বিকাশ অ্যাপ খুলুন<br>
২পেমেন্ট অপশন নির্বাচন করুন<br>৩আমার মার্চেন্ট কোড লিখুন'.config merchant_code'),
];

Blade模板调用方式: @lang payments instructions’)

九、监控与日志分析

ELK Stack配置建议 filebeat.yml片段:

yaml filebeat.inputs paths var/www/storage/logs/laravel.log fields gateway_payments true processors decode_json_fields fields ["message"] target "json"

Kibana看板关键指标:成功率响应时间TOP错误类型

Prometheus监控指标示例:

metrics endpoint返回数据格式 HELP payment_request_total Total payment requests TYPE counter payment_requests_total{gateway="bkazh"}2387

Grafana报警规则设置当成功率<95%持续5分钟触发SMS通知

十、替代方案比较

特性 bKash Nagad Rocket
API稳定性99.95%99.98%99.%手续费率18BDT固定15BDT+05%17BDT最大金额75万50万25万结算周期TT+12天实时TT+24小时特殊要求营业执照必须政府认证银行账户

结语

通过本文的详细指南您应该已经掌握在Laravel项目中集成孟加拉支付网关的全套技术方案实际实施时请务必注意定期检查各网关的API更新公告推荐加入开发者社区获取最新动态遇到技术难题时可参考GitHub上的开源实现如laravel-bkazz包但生产环境建议自主开发以确保安全性