You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel 8中Razorpay Webhook集成指南及空数据问题排查

Laravel 8 集成 Razorpay Webhook 完整指南及问题排查

一、分步集成指南

1. 安装 Razorpay SDK

通过Composer安装官方SDK:

composer require razorpay/razorpay

2. 配置环境变量

在.env文件中添加Razorpay密钥及Webhook密钥:

RAZORPAY_KEY=your_key_here
RAZORPAY_SECRET=your_secret_here
RAZORPAY_WEBHOOK_SECRET=your_webhook_secret_here

3. 配置路由

在routes/api.php中添加Webhook接收路由:

Route::post('/razorpay/webhook', [App\Http\Controllers\RazorpayWebhookController::class, 'handle']);

关键:排除CSRF验证
Webhook请求来自外部,需跳过Laravel的CSRF检查。修改app/Http/Middleware/VerifyCsrfToken.php:

protected $except = [
    '/api/razorpay/webhook',
];

4. 创建Webhook控制器

生成控制器并编写核心处理逻辑:

php artisan make:controller RazorpayWebhookController

控制器代码示例:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Razorpay\Api\Api;
use Razorpay\Api\Errors\SignatureVerificationError;

class RazorpayWebhookController extends Controller
{
    public function handle(Request $request)
    {
        $api = new Api(env('RAZORPAY_KEY'), env('RAZORPAY_SECRET'));
        $webhookSecret = env('RAZORPAY_WEBHOOK_SECRET');

        try {
            // 验证Webhook签名,防止伪造请求
            $api->utility->verifyWebhookSignature(
                $request->getContent(),
                $request->header('X-Razorpay-Signature'),
                $webhookSecret
            );
        } catch (SignatureVerificationError $e) {
            \Log::error('Razorpay Webhook签名验证失败: ' . $e->getMessage());
            return response()->json(['status' => 'error'], 400);
        }

        // 获取Webhook payload
        $payload = $request->json()->all();
        $event = $payload['event'];

        // 根据不同事件处理业务逻辑
        switch ($event) {
            case 'payment.captured':
                $payment = $payload['payload']['payment']['entity'];
                // 示例:更新订单状态、发送支付成功通知
                \Log::info('支付成功,Payment ID: ' . $payment['id']);
                break;
            case 'payment.failed':
                $payment = $payload['payload']['payment']['entity'];
                // 示例:标记订单失败、通知用户
                \Log::info('支付失败,Payment ID: ' . $payment['id']);
                break;
            // 可按需添加其他事件(如refund.processed)的处理逻辑
            default:
                \Log::info('未处理的Webhook事件: ' . $event);
        }

        // 返回成功响应,告知Razorpay无需重试
        return response()->json(['status' => 'success'], 200);
    }
}

二、最佳实践

  • 强制签名验证:绝不能跳过签名验证,这是拦截伪造请求的核心防线,直接使用SDK提供的验证方法即可。
  • 异步处理业务逻辑:Webhook要求10秒内响应,将订单更新、通知发送等耗时操作放入队列:
    // 替换同步逻辑为队列任务
    dispatch(new ProcessRazorpayPayment($payment));
    
  • 完善日志记录:记录所有Webhook请求的原始payload、签名、处理结果,方便事后排查问题。
  • 保证幂等性:同一事件可能被Razorpay多次推送,需通过event_id或payment_id标记已处理事件,避免重复执行:
    if (WebhookLog::where('event_id', $payload['event_id'])->exists()) {
        return response()->json(['status' => 'already processed'], 200);
    }
    // 先记录日志再处理业务
    WebhookLog::create(['event_id' => $payload['event_id'], 'payload' => $payload]);
    
  • 正确返回响应码:处理成功返回200 OK,验证失败返回400 Bad Request,服务器错误返回500 Internal Server Error,Razorpay会对非200响应进行重试。

三、接收数据为空的排查步骤

  1. 检查CSRF拦截:确认Webhook路由已添加到VerifyCsrfToken的$except数组中,否则Laravel会直接拒绝请求,导致无法获取数据。
  2. 确认请求解析方式:Razorpay发送的是application/json格式请求,若使用web路由而非api路由,需手动解析原始内容:
    $payload = json_decode($request->getContent(), true);
    
  3. 排查服务器配置:检查Nginx/Apache是否拦截请求,比如ModSecurity模块可能误判Webhook请求为恶意请求,需添加放行规则。
  4. 本地测试验证:使用ngrok将本地服务暴露到公网,在Razorpay后台配置测试URL,触发测试事件后查看Laravel日志中的请求详情。
  5. 检查数据获取代码:优先使用$request->json()->all()或json_decode($request->getContent(), true)获取原始JSON数据,避免直接用$request->all()。
  6. 验证Webhook URL正确性:确认Razorpay后台配置的URL与本地路由完全一致,包括协议(http/https)、路径等。

内容的提问来源于stack exchange,提问作者Vaibhav Yadav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 06:22:55