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

Laravel 8中如何通过Stripe API将账户资金划转至客户银行账户?

在Laravel 8中通过Stripe API向客户银行账户划转资金的实现方案

以下是针对你的积分兑换现金场景的具体实现步骤,涵盖从依赖安装到Webhook状态同步的完整流程:

1. 前期准备

  • 安装Stripe SDK:通过Composer引入官方包
    composer require stripe/stripe-php
    
  • 配置密钥:在.env文件中添加Stripe的密钥信息
    STRIPE_SECRET_KEY=sk_your_secret_key
    STRIPE_PUBLISHABLE_KEY=pk_your_publishable_key
    STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
    
    然后在config/services.php中补充Stripe配置:
    'stripe' => [
        'secret' => env('STRIPE_SECRET_KEY'),
        'publishable' => env('STRIPE_PUBLISHABLE_KEY'),
        'webhook_secret' => env('STRIPE_WEBHOOK_SECRET'),
    ],
    

2. 绑定客户银行账户

首先需要将客户的银行账户信息关联到Stripe客户对象上(建议通过Stripe Elements收集前端信息,避免直接处理敏感数据),后端接收Stripe返回的支付方式ID并完成绑定:

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use Stripe\Stripe;
use Stripe\Customer;
use Stripe\PaymentMethod;
use App\Models\User;

class StripePaymentMethodController extends Controller
{
    public function attach(Request $request)
    {
        Stripe::setApiKey(config('services.stripe.secret'));
        $user = auth()->user();

        // 为用户创建或获取Stripe客户ID
        if (!$user->stripe_customer_id) {
            $customer = Customer::create(['email' => $user->email]);
            $user->update(['stripe_customer_id' => $customer->id]);
        }

        // 将支付方式绑定到Stripe客户
        PaymentMethod::attach(
            $request->payment_method_id,
            ['customer' => $user->stripe_customer_id]
        );

        // 可选:设置该支付方式为默认提现渠道
        Customer::update(
            $user->stripe_customer_id,
            ['invoice_settings' => ['default_payment_method' => $request->payment_method_id]]
        );

        return response()->json(['message' => '银行账户绑定成功']);
    }
}

3. 创建提现请求

当用户发起积分兑换时,计算对应金额(注意Stripe使用最小货币单位,如1美元=100分),调用Payout API完成资金划转:

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use Stripe\Stripe;
use Stripe\Payout;
use App\Models\User;
use App\Models\PayoutRecord;

class PayoutController extends Controller
{
    public function create(Request $request)
    {
        Stripe::setApiKey(config('services.stripe.secret'));
        $user = auth()->user();
        $amountInCents = $request->amount * 100; // 转换为最小货币单位

        try {
            $payout = Payout::create([
                'amount' => $amountInCents,
                'currency' => 'cn', // 根据业务设置对应货币,如usd、eur
                'destination' => $user->default_payment_method_id, // 绑定的银行账户支付方式ID
                'description' => "{$user->name}积分兑换提现",
            ]);

            // 记录本地提现日志
            PayoutRecord::create([
                'user_id' => $user->id,
                'stripe_payout_id' => $payout->id,
                'amount' => $request->amount,
                'status' => $payout->status,
            ]);

            return response()->json([
                'message' => '提现申请已提交',
                'payout_id' => $payout->id,
                'current_status' => $payout->status
            ]);
        } catch (\Stripe\Exception\ApiErrorException $e) {
            return response()->json(['error' => $e->getMessage()], 400);
        }
    }
}

4. 处理Webhook同步提现状态

Stripe会通过Webhook推送提现状态变更(成功/失败),需要验证签名并更新本地记录:

4.1 配置Webhook路由

在routes/api.php中添加:

Route::post('/stripe/webhook', [StripeWebhookController::class, 'handle']);

4.2 实现Webhook控制器

namespace App\Http\Controllers\Api;

use Illuminate\Http\Request;
use Stripe\Webhook;
use Stripe\Stripe;
use App\Models\PayoutRecord;

class StripeWebhookController extends Controller
{
    public function handle(Request $request)
    {
        Stripe::setApiKey(config('services.stripe.secret'));
        $payload = $request->getContent();
        $sigHeader = $request->header('Stripe-Signature');
        $webhookSecret = config('services.stripe.webhook_secret');

        try {
            $event = Webhook::constructEvent($payload, $sigHeader, $webhookSecret);
        } catch (\Exception $e) {
            return response('', 400);
        }

        // 处理提现成功事件
        if ($event->type === 'payout.succeeded') {
            $stripePayout = $event->data->object;
            $localRecord = PayoutRecord::where('stripe_payout_id', $stripePayout->id)->first();
            if ($localRecord) {
                $localRecord->update(['status' => 'succeeded']);
                // 这里可以添加通知用户的逻辑,如推送短信/APP通知
            }
        }

        // 处理提现失败事件
        if ($event->type === 'payout.failed') {
            $stripePayout = $event->data->object;
            $localRecord = PayoutRecord::where('stripe_payout_id', $stripePayout->id)->first();
            if ($localRecord) {
                $localRecord->update([
                    'status' => 'failed',
                    'failure_reason' => $stripePayout->failure_message
                ]);
                // 通知用户提现失败并说明原因
            }
        }

        return response('', 200);
    }
}

关键注意事项

  • 金额单位转换:务必将业务金额转换为Stripe要求的最小货币单位,否则会出现金额错误。
  • 账户验证要求:不同地区的银行账户需要不同的验证信息(如美国需要路由号+账户号,欧洲需要IBAN),需确保前端收集的信息符合Stripe规范。
  • 提现限制:Stripe对提现有最低金额限制,且不同货币的到账时间不同,需提前告知用户。
  • 错误处理:捕获Stripe的API异常,如资金不足、支付方式无效等,返回清晰的错误提示给用户。
  • Webhook安全:必须验证Stripe的Webhook签名,防止恶意伪造请求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 05:15:46