# 如何为 Laravel SaaS 添加支付功能

> Laravel 应用支付处理集成完整指南，涵盖结账集成、webhook 处理、订阅管理以及借助 Dodo Payments 实现全球税务合规。
- **Author**: Ayush Agarwal
- **Published**: 2026-03-24
- **Category**: Payments, Developer Tools, How-To
- **URL**: https://dodopayments.com/blogs/zh/add-payments-laravel-saas

---

为 Laravel SaaS 添加支付功能需要四个部分：一个通过支付 API 创建结账会话的控制器；一个打开结账页面的 Blade 或 Livewire 视图；一个验证签名并更新用户表的 webhook 路由；以及一个根据订阅状态限制付费路由访问的中间件。由 MoR（名义商户）处理结账后，你可以完全跳过税务登记工作。

Laravel 是成千上万 SaaS 产品的技术骨干，既适用于独立开发者的小型项目，也适用于大型企业平台。优雅的语法和强大的生态系统，让它成为希望快速构建和扩展产品的开发者的首选。然而，在整个流程的"资金"环节，许多开发者会陷入复杂的计费逻辑、税务合规和订阅管理之中。

大多数 Laravel 开发者的默认选择是 Stripe 和 Laravel Cashier。Cashier 确实是一个出色的工具，但你仍然需要承担全球销售税、增值税以及作为名义商户所涉及的法律复杂性。如果你向 50 个不同国家的客户销售产品，就需要在 50 个不同的司法管辖区负责税务登记、税款代收和申报缴纳。

这正是 Dodo Payments 改变游戏规则的地方。作为 [SaaS 的 MoR（名义商户）](https://dodopayments.com/blogs/merchant-of-record-for-saas)，Dodo Payments 会为你处理全部税务和合规负担。你获得的不只是一个支付网关，而是一个全球税务部门。在本指南中，我们将介绍如何把 Dodo Payments 集成到 Laravel 应用中，打造顺畅且符合税务要求的结账体验。

## 为什么选择 Laravel 和 Dodo Payments？

Laravel 的理念是让开发者更愉快、更高效。Dodo Payments 也秉持这一理念，通过简化运营 SaaS 最棘手的环节----全球支付----来帮助你提升效率。一个下午之内，你就可以从全新的 Laravel 安装开始，构建出能够产生收入的产品。

其中一个最大优势是 [SaaS 的嵌入式支付](https://dodopayments.com/blogs/embedded-payments-saas)方案。你无需将用户重定向到外部托管页面，而是可以使用 Dodo 的叠加式或内嵌式结账。这能让用户留在你的网站上，因为结账流程中的每一个阻碍点，都可能导致客户流失。

Dodo 面向 SaaS 的[支付架构](https://dodopayments.com/blogs/payments-architecture-saas)同样专为现代订阅模式设计。无论你采用统一费率、分层定价还是按用量计费，集成都能在 Laravel 代码库中保持易于管理。当定价策略不断演进时，这种灵活性非常重要，你不必每增加一个新层级就重写代码。

> 大多数 SaaS 创始人都低估了税务合规的成本。它不只是提交申报表，还包括在每个有客户的司法管辖区完成登记、在结账时计算税款、申报缴纳以及做好审计准备。
>
> \- Ayush Agarwal，Dodo Payments 联合创始人兼 CPTO

## Laravel 支付流程

在开始编写代码之前，我们先来看看 Laravel 应用与 Dodo Payments 之间的数据流。这个高层次概览可以帮助你了解集成中的每个部分分别发挥什么作用。

```mermaid
flowchart TD
    A[User clicks 'Subscribe'] --> B[Laravel Controller]
    B -->|"Create Checkout Session"| C[Dodo Payments API]
    C -->|"Return Checkout URL"| B
    B --> D[Blade View / Livewire]
    D -->|"Open Overlay"| E[Dodo Checkout]
    E -->|"Payment Success"| F[Dodo Webhook]
    F --> G[Laravel Webhook Route]
    G -->|"Process Event"| H[Laravel Queue]
    H --> I[Update Database]
    I --> J[Middleware Grants Access]
```

这一流程确保你的应用仍然是用户访问权限的唯一事实来源，而 Dodo 负责安全交易和税费计算。

## 第 1 步：设置 Dodo 账户

首先，你需要在 Dodo Payments 创建账户。进入控制面板后，你可以创建产品和价格。对于 SaaS，你通常会创建一个按月或按年定价的"订阅"产品。

请从开发者设置中获取 API 密钥，并立即将其添加到 Laravel 的 `.env` 文件中：

```env
DODO_PAYMENTS_API_KEY=your_api_key_here
DODO_PAYMENTS_WEBHOOK_SECRET=your_webhook_secret_here
DODO_PAYMENTS_MODE=test
```

使用环境变量是 Laravel 的标准实践，可以保护你的凭证安全，并让你轻松切换测试模式和正式模式。

## 第 2 步：安装 HTTP 客户端

虽然 Dodo 为多种语言提供了 [SDK](https://docs.dodopayments.com/developer-resources/dodo-payments-sdks)，但 Laravel 内置的 `Http` facade 在发起 API 请求方面非常强大。我们将使用它与 Dodo API 交互。

如果你更喜欢结构化程度更高的方式，或者正在使用混合技术栈，也可以使用 Dodo Payments Node SDK。但对于纯 Laravel 应用来说，`Http` facade 通常是最简洁的方案。

## 第 3 步：创建结账会话

当用户想要订阅时，你需要创建一个结账会话。该会话会告诉 Dodo 用户购买的内容，以及支付完成后应将用户发送到哪里。

创建一个名为 `SubscriptionController` 的控制器：

```php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class SubscriptionController extends Controller
{
    public function createSession(Request $request)
    {
        $user = $request->user();

        $response = Http::withToken(config('services.dodo.key'))
            ->post('https://test.dodopayments.com/checkouts', [
                'product_cart' => [
                    [
                        'product_id' => 'pdt_your_product_id',
                        'quantity' => 1,
                    ]
                ],
                'customer' => [
                    'email' => $user->email,
                    'name' => $user->name,
                ],
                'billing' => [
                    'country' => 'US', // You can collect this or default it
                ],
                'payment_link' => true,
                'return_url' => route('subscription.success'),
            ]);
        if ($response->failed()) {
            return back()->withErrors('Could not create checkout session.');
        }

        return response()->json([
            'checkout_url' => $response->json('checkout_url')
        ]);
    }
}
```

这个控制器会获取已认证用户的信息并将其发送给 Dodo。Dodo 会返回一个 `checkout_url`，我们将在前端使用它。

## 第 4 步：集成叠加式结账

现在我们已经有了结账 URL，接下来需要向用户展示结账界面。Dodo 的[叠加式结账](https://docs.dodopayments.com/developer-resources/overlay-checkout)非常适合这一场景。它提供模态窗口体验，无需用户离开你的网站。

在 Blade 模板中（例如 `resources/views/billing.blade.php`），添加 Dodo Checkout 的 script 标签。请从 [Dodo Payments SDK 文档](https://docs.dodopayments.com/developer-resources/dodo-payments-sdks)复制当前 CDN 路径，不要手动固定版本，然后在其下方添加初始化代码：

```html
<script>
  DodoPaymentsCheckout.DodoPayments.Initialize({
    mode: "{{ config('services.dodo.mode') }}",
    displayType: "overlay",
  });

  async function handleSubscribe() {
    const response = await fetch("{{ route('subscription.session') }}", {
      method: "POST",
      headers: {
        "X-CSRF-TOKEN": "{{ csrf_token() }}",
        "Content-Type": "application/json",
      },
    });

    const data = await response.json();

    if (data.checkout_url) {
      DodoPaymentsCheckout.DodoPayments.Checkout.open({
        checkoutUrl: data.checkout_url,
      });
    }
  }
</script>

<button onclick="handleSubscribe()" class="btn btn-primary">
  Upgrade to Pro
</button>
```

这一设置可以让应用界面顺畅地过渡到支付表单。用户输入信息、完成支付后，叠加窗口会关闭，并将用户带回你的应用。

## 第 5 步：处理 Webhook

Webhook 对任何[最佳订阅计费软件](https://dodopayments.com/blogs/best-subscription-billing-software)集成都至关重要。当支付成功、订阅续期或支付失败时，Dodo 可以通过 webhook 通知你的 Laravel 应用。

首先，在 `routes/api.php` 中为 webhook 创建路由：

```php
Route::post('/webhooks/dodo', [WebhookController::class, 'handle']);
```

接下来，创建 `WebhookController`。建议参考 Laravel 的[集成指南](https://docs.dodopayments.com/developer-resources/integration-guide)原则，确保 webhook 处理程序安全可靠。

```php
namespace App\Http\Controllers;

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

class WebhookController extends Controller
{
    public function handle(Request $request)
    {
        $payload = $request->all();
        $header = $request->header('X-Dodo-Signature');

        // Verify signature here using your secret
        if (!$this->verifySignature($request->getContent(), $header)) {
            return response()->json(['error' => 'Invalid signature'], 400);
        }

        $eventType = $payload['event_type'];

        switch ($eventType) {
            case 'subscription.active':
                $this->handleSubscriptionActive($payload['data']);
                break;
            case 'payment.succeeded':
                $this->handlePaymentSucceeded($payload['data']);
                break;
            case 'subscription.cancelled':
                $this->handleSubscriptionCancelled($payload['data']);
                break;
        }

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

    protected function handleSubscriptionActive($data)
    {
        $user = User::where('email', $data['customer']['email'])->first();
        if ($user) {
            $user->update([
                'subscription_id' => $data['subscription_id'],
                'plan' => 'pro',
                'subscription_status' => 'active',
            ]);
        }
    }

    protected function verifySignature($payload, $signature)
    {
        $secret = config('services.dodo.webhook_secret');
        $computed = hash_hmac('sha256', $payload, $secret);
        return hash_equals($computed, $signature);
    }
}
```

别忘了在 `app/Http/Middleware/VerifyCsrfToken.php` 中将此路由排除在 CSRF 保护之外（或者在较新 Laravel 版本的对应位置完成相同配置）。

## 第 6 步：使用中间件保护路由

Webhook 更新数据库后，你需要确保只有活跃订阅用户才能访问 SaaS 的特定部分。Laravel 的中间件非常适合完成这一任务。

创建一个名为 `Subscribed` 的中间件：

```php
namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class Subscribed
{
    public function handle(Request $request, Closure $next)
    {
        if (!$request->user() || $request->user()->subscription_status !== 'active') {
            return redirect()->route('billing')->with('error', 'You need an active subscription.');
        }

        return $next($request);
    }
}
```

在内核中注册此中间件，并将其应用到受保护的路由：

```php
Route::middleware(['auth', 'subscribed'])->group(function () {
    Route::get('/dashboard', [DashboardController::class, 'index']);
    Route::get('/settings/pro', [SettingsController::class, 'proFeatures']);
});
```

这一简单检查可以确保你的[订阅定价模式](https://dodopayments.com/blogs/subscription-pricing-models)在整个应用中得到执行。

## 进阶：使用 Laravel 队列处理 Webhook

在生产环境中，绝不要直接在 webhook 控制器中处理耗时逻辑。如果数据库更新耗时过长，或者你需要发送一封"欢迎"邮件，webhook 请求可能会超时，导致 Dodo 重试该事件。

相反，请分派一个任务：

```php
public function handle(Request $request)
{
    // ... verification logic ...

    ProcessDodoWebhook::dispatch($request->all());

    return response()->json(['status' => 'accepted'], 202);
}
```

这样一来，你的应用可以立即响应 Dodo，而实际工作则在后台执行。这是可扩展的[如何接受在线支付](https://dodopayments.com/blogs/how-to-accept-online-payments)策略的核心部分。

## 测试集成

Laravel 提供了出色的测试工具。你可以模拟 Dodo API 的响应，在不发起真实网络请求的情况下测试控制器逻辑。

```php
public function test_user_can_create_checkout_session()
{
    Http::fake([
        'test.dodopayments.com/*' => Http::response(['checkout_url' => 'https://checkout.dodopayments.com/session/cks_123'], 200),
    ]);

    $user = User::factory()->create();

    $response = $this->actingAs($user)->postJson('/api/subscription/session');

    $response->assertStatus(200)
             ->assertJson(['checkout_url' => 'https://checkout.dodopayments.com/session/cks_123']);
}
```

对于 webhook，你可以使用 `php artisan make:test WebhookTest`，并向 webhook 端点发送带有示例负载的 POST 请求。这样可以确保你的[如何在线销售软件](https://dodopayments.com/blogs/how-to-sell-software-online)流程在正式上线前足够可靠。

## 管理订阅生命周期

成功的 SaaS 集成不只是完成初始结账。你还需要处理订阅的完整生命周期，包括续期、取消和套餐变更。Dodo Payments 提供完整的 webhook 和 API 端点，让这一切变得简单。

订阅续期时，Dodo 会发送 `subscription.renewed` 事件。你的 Laravel 应用应监听此事件，以延长用户的访问权限。同样，当用户取消订阅时，你会收到 `subscription.cancelled` 事件。与其立即撤销访问权限，通常更好的做法是在数据库中设置 `trial_ends_at` 或 `subscription_ends_at` 日期，让用户可以继续使用服务，直到当前计费周期结束。

对于套餐变更，你可以使用 Dodo API 更新订阅。这对于从"Pro"升级到"Enterprise"等场景非常有用。Dodo 会自动处理按比例计费，因此你不必计算当月剩余天数应向用户收取多少费用。这种自动化程度正是专业计费方案与脆弱的自研方案之间的区别。

## 提供客户门户

现代 SaaS 用户希望能够自行管理订阅。他们希望更新信用卡信息、查看账单记录并下载发票，而不必联系支持团队。Dodo Payments 提供内置客户门户，你可以直接从 Laravel 应用链接到该门户。

你可以通过 API 生成门户链接，并将用户重定向到该链接。这样就不必在应用中构建复杂的"账单设置"页面。门户完全由 Dodo 托管，并负责管理敏感支付信息所需的全部安全和合规要求。

在 Laravel 应用中，你可以添加一个"管理账单"按钮：

```php
public function redirectToPortal(Request $request)
{
    $response = Http::withToken(config('services.dodo.key'))
        ->get("https://test.dodopayments.com/customers/{$request->user()->dodo_customer_id}/portal");

    return redirect($response->json('portal_url'));
}
```

这种方式能让你的应用保持精简，专注于核心价值主张，同时为客户提供一流体验。

## 轻松实现全球税务合规

在 Laravel 中使用 Dodo 的真正优势，是你不再需要为税务问题操心。当德国客户购买你的 SaaS 时，Dodo 会计算正确的增值税、代收税款并处理申报。你的 Laravel 应用只需接收"支付成功"事件。

这一变化之所以可行，是因为名义商户发生了变化。我们关于[什么是 MoR（名义商户）](https://dodopayments.com/blogs/what-is-a-merchant-of-record)的说明详细介绍了哪些责任会转移、哪些责任仍由你承担；如果你之前评估过支付服务商模式，也值得阅读 [MoR（名义商户）与 PayFac 的比较](https://dodopayments.com/blogs/merchant-of-record-vs-payfac)。

这也是 Dodo 常被认为是[销售数字产品的最佳平台](https://dodopayments.com/blogs/best-platform-sell-digital-products)的原因。你既能获得定制 Laravel 应用的强大能力，也能享受托管式市场平台带来的合规安心。

## 常见问题

### Dodo Payments 支持 Laravel Cashier 吗？

Dodo Payments 目前不使用 Laravel Cashier，因为 Cashier 专为 Stripe 构建。不过，Dodo 提供了更简单的集成路径，无需 Cashier 那种复杂的本地数据库同步。你可以通过 Dodo 的 API 和 webhook 直接管理订阅，同时大幅减少代码量。

### 如何处理订阅升级和降级？

你可以调用 Dodo Payments API 更新订阅的产品 ID，从而处理升级和降级。变更完成后，Dodo 会向你的 Laravel 应用发送 webhook，让你能够更新数据库中的用户套餐。Dodo 会自动处理按比例计费的计算。

### 可以将 Dodo Payments 与 Laravel Livewire 一起使用吗？

可以，Dodo Payments 与 Livewire 完美兼容。你可以通过触发浏览器事件，或使用 `wire:click` 指令调用打开 Dodo Checkout 的 JavaScript 函数，从 Livewire 组件触发结账叠加层。这样可以构建高度动态且响应迅速的计费界面。

### 可以使用 Dodo 和 Laravel 提供免费试用吗？

当然可以。你可以在 Dodo 控制面板中配置产品，加入试用期。用户注册时，Dodo 会收集其支付信息，但在试用期结束前不会扣款。当试用开始以及首次支付成功时，你的 Laravel 应用都会分别收到 webhook。

### Dodo 如何在 Laravel 中处理支付失败？

支付失败时，Dodo 会发送 `payment.failed` webhook。你应在 Laravel 应用中设置监听器来捕获此事件，并将用户的 `subscription_status` 更新为 `past_due` 或 `inactive`。随后，你可以使用中间件将用户重定向到"更新支付方式"页面。

## 总结

为 Laravel SaaS 添加支付功能，不必成为一个需要税务律师和复杂计费引擎、耗时数月的项目。借助 Dodo Payments 作为你的 MoR（名义商户），你可以在几小时内实现世界级、符合全球合规要求的计费系统。

从最初的[结账会话](https://docs.dodopayments.com/api-reference/introduction)到最终的 [webhook 处理](https://docs.dodopayments.com/developer-resources/webhooks)，整个集成过程简洁、安全且开发者友好。无论你是在构建下一个热门 AI 工具，还是面向细分市场的 B2B 平台，Dodo 与 Laravel 都能为你的增长提供理想基础。

准备开始销售了吗？查看 [Dodo Payments 定价](https://dodopayments.com/pricing)，立即注册开发者账户。
---
- [More Payments articles](https://dodopayments.com/blogs/category/payments)
- [All articles](https://dodopayments.com/blogs)