15 分钟内用 Laravel 和 PHP 接入 PAYWISE
使用 PAYWISE PHP SDK 逐步完成 Laravel 集成:安装、配置、创建付款、处理带签名的 Webhook,并在沙盒中测试。
发布于 11 十月 2026 阅读约 4 分钟
本指南使用官方 PHP SDK 将 Laravel 网店接入 PAYWISE:创建 QRIS 付款,将顾客引导至支付页面,并在收到带签名的 Webhook 时将订单标记为已付款。纯 PHP 的做法相同,差异在文末说明。
您需要:PHP 7.4 或更高版本(含 curl 和 json 扩展)、一个 PAYWISE 账户、一个沙盒 API 密钥(pw_test_…,在 API 密钥页面创建),以及一个已开启托管支付页面的网站(在网站与 Webhook 页面设置)。

1. 安装 SDK(2 分钟)
从 开发者页面 下载 PHP SDK,并解压到项目中,例如 packages/paywise-php。然后在 composer.json 中告诉 Composer 它的位置:
"repositories": [
{ "type": "path", "url": "packages/paywise-php" }
]
再进行安装:
composer require "paywise/paywise-php:*@dev"
该 SDK 本身没有任何依赖。
2. 配置密钥(2 分钟)
在 .env 中:
PAYWISE_KEY=pw_test_xxxxxxxxxxxxxxxx
PAYWISE_WEBHOOK_SECRET=your-webhook-secret
Webhook 密钥在网站与 Webhook页面。在 config/services.php 中:
'paywise' => [
'key' => env('PAYWISE_KEY'),
'webhook_secret' => env('PAYWISE_WEBHOOK_SECRET'),
],
添加一个字段,用于保存每笔订单的 PAYWISE 参考号:
$table->string('paywise_reference')->nullable()->index();
3. 创建付款(4 分钟)
use Paywise\Client;
use Paywise\PaywiseException;
class PaymentController extends Controller
{
public function pay(Order $order)
{
$paywise = new Client(config('services.paywise.key'));
try {
$payment = $paywise->createTransaction([
'merchant_reference' => 'ORDER-' . $order->id, // 同时作为幂等键
'amount' => $order->total, // QRIS:整数印尼盾
'payment_method' => 'QRIS',
'customer_id' => (string) $order->user_id,
]);
} catch (PaywiseException $e) {
report($e);
return back()->with('error', '无法发起付款,请重试。');
}
$order->update(['paywise_reference' => $payment['reference']]);
return redirect()->away($payment['checkout_url']);
}
}
如果请求超时,可以使用相同的 merchant_reference 放心重试:PAYWISE 会返回原来的付款,而不会再创建一笔。$e->isRetryable() 会告诉您何时适合重试。
4. 处理 Webhook(5 分钟)
use Illuminate\Http\Request;
use Paywise\Webhook;
public function webhook(Request $request)
{
try {
$event = Webhook::parse(
$request->getContent(), // 原始请求体
(string) $request->header('X-PAYWISE-Signature'),
config('services.paywise.webhook_secret')
);
} catch (PaywiseException $e) {
return response('Invalid signature', 400);
}
$reference = $event['data']['reference'];
if ($event['event'] === 'payment.paid') {
// 只有未付款的订单会改变,因此重复送达不会产生影响。
Order::where('paywise_reference', $reference)->where('status', 'unpaid')
->update(['status' => 'paid', 'paid_at' => now()]);
} elseif (in_array($event['event'], ['payment.expired', 'payment.failed'], true)) {
Order::where('paywise_reference', $reference)->where('status', 'unpaid')
->update(['status' => 'payment_failed']);
}
return response('OK');
}
路由,在 routes/web.php 中:
Route::post('/orders/{order}/pay', [PaymentController::class, 'pay'])->name('orders.pay');
Route::post('/webhooks/paywise', [PaymentController::class, 'webhook']);
Webhook 来自 PAYWISE 而非浏览器,因此不带 CSRF 令牌。请在 bootstrap/app.php 中将其排除(Laravel 11 及以上):
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: ['webhooks/paywise']);
})
在 Laravel 10 中,将 'webhooks/paywise' 添加到 app/Http/Middleware/VerifyCsrfToken.php 的 $except 中。
最后,在网站与 Webhook页面将 https://your-shop.com/webhooks/paywise 填为 Webhook URL,选择事件,然后点击发送测试。
5. 在沙盒中测试(2 分钟)
在您的店铺下一个订单。在支付页面的模拟结果中选择已支付:您的 Webhook 会收到 payment.paid,订单随即变为已付款。也请试试失败和已过期。每次送达及您服务器的响应都会列在网站与 Webhook页面。
一切正常后,将沙盒密钥替换为正式密钥(pw_live_…),并完成一笔小额真实付款。
纯 PHP
不使用 Composer 时,直接引入 SDK:
require __DIR__ . '/paywise-php/autoload.php';
调用方式相同。在 Webhook 脚本中,用 file_get_contents('php://input') 读取原始请求体,用 $_SERVER['HTTP_X_PAYWISE_SIGNATURE'] 读取签名。
下一步
- 如需 USDT,请发送
'payment_method' => 'USDT'和'network' => 'BEP20'。 - 阅读 为什么以 Webhook 而非重定向为准 和 10 个常见集成错误。
- 完整参考请见 API 文档。

