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

基于Laravel实现SQL转JSON并Base64编码调用支付API方案咨询

Laravel+Flutter对接支付API实现电子发票支付流程实操建议

一、Laravel后端核心实现(针对你Laravel不熟的情况,给出最简可运行的代码示例)

1. 搭建订单模型与数据库表

先生成订单模型和迁移文件,包含支付流程必需的核心字段:

php artisan make:model Order -m

打开生成的迁移文件(路径:database/migrations/xxxx_xx_xx_create_orders_table.php),补充字段定义:

public function up()
{
    Schema::create('orders', function (Blueprint $table) {
        $table->id();
        $table->foreignId('user_id')->constrained(); // 关联用户表,可根据实际业务调整
        $table->decimal('amount', 10, 2); // 订单金额
        $table->string('status')->default('draft'); // 订单状态:draft/processing/paid/failed
        $table->text('rtp_request')->nullable(); // 暂存Base64编码的支付请求内容
        $table->string('payment_token')->nullable(); // 存储支付API返回的令牌
        $table->timestamps();
    });
}

执行迁移生成数据库表:

php artisan migrate

2. 创建待支付草稿订单

在OrderController中实现创建订单的接口,接收Flutter前端传来的订单数据:

use App\Models\Order;
use Illuminate\Http\Request;

public function store(Request $request)
{
    // 验证前端参数合法性
    $validated = $request->validate([
        'user_id' => 'required|exists:users,id',
        'amount' => 'required|decimal:0,2|min:0.01',
        // 按需添加其他订单字段,如商品ID、发票抬头等
    ]);

    // 创建草稿状态的订单
    $order = Order::create(array_merge($validated, ['status' => 'draft']));

    return response()->json(['order_id' => $order->id], 201);
}

3. 生成指定结构JSON并Base64编码

新建支付服务类解耦业务逻辑,方便后续维护:

php artisan make:service PaymentService

在app/Services/PaymentService.php中实现数据组装与编码逻辑:

namespace App\Services;

use App\Models\Order;

class PaymentService
{
    public function generateEncodedRequest(Order $order)
    {
        // 严格按照支付API要求的结构组装数据
        $paymentData = [
            'order_id' => $order->id,
            'amount' => $order->amount,
            'currency' => 'CNY', // 根据实际币种调整
            'invoice_info' => [
                'title' => 'xxx公司', // 从订单或用户数据中提取
                'tax_number' => 'xxx'
            ],
            'return_url' => env('APP_URL') . '/api/payment/callback' // 回调地址
        ];

        // 转JSON并执行Base64编码
        $jsonData = json_encode($paymentData);
        return base64_encode($jsonData);
    }
}

4. 调用支付API获取并存储支付Token

在OrderController中添加发起支付的接口,调用服务类并发送POST请求:

use App\Services\PaymentService;
use Illuminate\Support\Facades\Http;

public function initiatePayment(Request $request)
{
    $order = Order::findOrFail($request->order_id);
    if ($order->status !== 'draft') {
        return response()->json(['error' => '订单状态异常'], 400);
    }

    $paymentService = new PaymentService();
    $encodedRequest = $paymentService->generateEncodedRequest($order);

    // 暂存编码后的请求内容
    $order->update(['rtp_request' => $encodedRequest]);

    try {
        // 调用支付API
        $response = Http::withHeaders([
            'Authorization' => 'Bearer ' . env('PAYMENT_API_KEY'),
            'Content-Type' => 'application/json',
        ])->post(env('PAYMENT_API_ENDPOINT'), [
            'rtp_request' => $encodedRequest
        ]);

        $responseData = $response->json();
        if ($response->successful() && isset($responseData['payment_token'])) {
            // 存储Token并更新订单为处理中状态
            $order->update([
                'payment_token' => $responseData['payment_token'],
                'status' => 'processing'
            ]);
            return response()->json(['payment_token' => $responseData['payment_token']]);
        }

        // API返回错误,标记订单为失败
        $order->update(['status' => 'failed']);
        return response()->json(['error' => $responseData['message'] ?? '支付请求失败'], 400);
    } catch (\Exception $e) {
        // 捕获网络或未知异常
        $order->update(['status' => 'failed']);
        return response()->json(['error' => '支付请求异常:' . $e->getMessage()], 500);
    }
}

在.env文件中配置支付API的密钥和地址:

PAYMENT_API_KEY=your_payment_api_secret_key
PAYMENT_API_ENDPOINT=https://your-payment-processor.com/api/initiate-payment

5. 处理支付回调更新订单状态

新建Webhook控制器处理支付API的回调请求:

php artisan make:controller PaymentWebhookController

在app/Http/Controllers/PaymentWebhookController.php中实现回调逻辑(重点做签名验证,防止伪造请求):

use App\Models\Order;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

public function handle(Request $request)
{
    // 1. 验证支付API的签名(按服务商文档实现,示例用HMAC-SHA256)
    $signature = $request->header('X-Payment-Signature');
    $expectedSignature = hash_hmac('sha256', $request->getContent(), env('PAYMENT_API_KEY'));
    if (!hash_equals($signature, $expectedSignature)) {
        Log::warning('支付回调签名验证失败', ['request' => $request->all()]);
        return response()->json(['status' => 'invalid'], 403);
    }

    // 2. 解析回调数据并找到对应订单
    $callbackData = $request->json();
    $order = Order::where('payment_token', $callbackData['payment_token'])->firstOrFail();

    // 3. 根据支付状态更新订单
    switch ($callbackData['status']) {
        case 'success':
            $order->update(['status' => 'paid']);
            // 可在此触发电子发票生成、Firebase推送通知等逻辑
            break;
        case 'processing':
            $order->update(['status' => 'processing']);
            break;
        case 'failed':
            $order->update(['status' => 'failed']);
            break;
    }

    return response()->json(['status' => 'ok']);
}

在routes/api.php中注册回调路由,并关闭CSRF验证(第三方API无需CSRF):

use App\Http\Controllers\PaymentWebhookController;

Route::post('/payment/callback', [PaymentWebhookController::class, 'handle'])->withoutMiddleware(['csrf']);

二、Flutter前端配合逻辑(你熟悉的部分,给出关键流程)

  1. 用户下单:调用Laravel的POST /api/orders接口,传入订单数据,获取order_id
  2. 发起支付:调用Laravel的POST /api/orders/initiate-payment接口,传入order_id,获取payment_token
  3. 结果同步:
    • 若支付API需前端调起支付组件,用payment_token调用对应SDK完成支付
    • 后端回调完成后,通过Firebase Cloud Messaging推送支付状态通知;或前端定时轮询GET /api/orders/{order_id}接口获取最新状态

三、关键注意事项

  • 日志记录:在创建订单、发起支付、回调处理等关键节点添加日志,方便排查问题:
    use Illuminate\Support\Facades\Log;
    Log::info('发起支付请求', ['order_id' => $order->id]);
    
  • 数据库事务:创建订单与生成支付请求的步骤可包裹在事务中,保证数据一致性:
    DB::transaction(function () use ($validated, $paymentService) {
        $order = Order::create(array_merge($validated, ['status' => 'draft']));
        $encodedRequest = $paymentService->generateEncodedRequest($order);
        $order->update(['rtp_request' => $encodedRequest]);
    });
    
  • 异常兜底:所有外部API调用必须添加try-catch,避免流程崩溃
  • 环境隔离:开发、测试、生产环境使用不同的支付API密钥,避免误操作

内容的提问来源于stack exchange,提问作者David Desilets

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 06:01:00