logo

配置

简介

在以下文档中,我们将讨论如何在使用 Stripe 付款提供商时配置 Laravel Spark 安装。所有 Spark 的配置选项都位于应用程序的 config/spark.php 配置文件中。

Stripe 配置

当然,要将 Stripe 用作 Laravel Spark 应用程序的付款提供商,您必须拥有一个活动的 Stripe 帐户.

环境变量

接下来,您应该配置 Spark 访问您的 Stripe 帐户所需的应用程序环境变量。这些变量应放在应用程序的 .env 环境文件中。

当然,您应该调整变量的值以对应您自己的 Stripe 帐户凭据。您的 Stripe API 凭据和公钥可在您的 Stripe 帐户仪表板中找到

bash
CASHIER_CURRENCY=USD
CASHIER_CURRENCY_LOCALE=en
STRIPE_KEY=pk_test_example
STRIPE_SECRET=sk_test_example
STRIPE_WEBHOOK_SECRET=sk_test_example

配置区域设置

为了使用除 en 之外的区域设置,请确保您的服务器上已安装并配置了 ext-intl PHP 扩展。

Stripe Webhooks

此外,您的 Spark 驱动的应用程序需要接收来自 Stripe 的 Webhook,以便将您的应用程序的计费和订阅数据与 Stripe 的数据同步。在您的 Stripe 仪表板的 Webhook 管理面板中,您应该将 Stripe 配置为将 Webhook 警报发送到您的应用程序的 /spark/webhook URI。您应该为以下事件启用 Webhook 警报

  • customer.deleted
  • customer.subscription.created
  • customer.subscription.deleted
  • customer.subscription.updated
  • customer.updated
  • invoice.payment_action_required
  • invoice.payment_succeeded
  • payment_method.automatically_updated

或者,当您准备好进行生产时,您可以通过在生产服务器上运行以下命令来创建包含所有必要事件的 Webhook

bash
php artisan cashier:webhook --url="https://your-production-url.com/spark/webhook"

创建后,Webhook 将立即生效。

Webhook 和本地开发

在本地开发期间,您需要一种方法让 Stripe 将 Webhook 发送到您在本地机器上运行的应用程序。一个简单的入门方法是通过 Stripe CLI,它提供了一个方便的 listen 命令。例如,如果您通过 artisan serve CLI 命令在本地进行开发,并将您的网站托管在 http://localhost:8000 上,您可以运行以下 Stripe CLI 命令以允许 Stripe 与您的应用程序通信

shell
stripe listen --forward-to http://localhost:8000/spark/webhook

或者,您可以通过其他网站共享服务(例如 NgrokExpose)公开您的应用程序。如果您使用 Laravel Sail 在本地开发应用程序,您可以使用 Sail 的 网站共享命令

配置计费项

Spark 允许您定义应用程序将管理的计费模型类型。最常见的是,应用程序会向单个用户收取每月和每年的订阅计划费用。但是,您的应用程序可以选择收取其他类型的模型费用,例如团队、组织、乐队等。Spark 的 Stripe 版本目前仅支持每个应用程序一个计费模型实体(团队、用户等)。

您可以在应用程序的 spark 配置文件中的 billables 数组中定义您的计费模型。默认情况下,此数组包含 App\Models\User 模型的条目。如果计费模型不是 App\Models\User,则应在 SparkServiceProvider 类中的 boot 方法中调用 Cashier 的 useCustomerModel 方法,以告知 Cashier 您自定义的模型

php
use App\Entities\User;
use Laravel\Cashier\Cashier;
 
/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Cashier::useCustomerModel(User::class);
}

在继续之前,您应该确保与您的计费模型相对应的模型类正在使用 Spark\Billable 特性,并且它将 trial_ends_at 属性转换为 datetime。此外,您的计费模型的主键应该是一个名为 idinteger

php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spark\Billable;

class User extends Authenticatable
{
    use Billable, HasFactory, Notifiable;

    protected $casts = [
        'trial_ends_at' => 'datetime',
    ];

}

计费项别名

您可能已经注意到,billables 配置数组中的每个条目都由一个“别名”键控,该别名是计费模型类的缩写形式。此别名可以在访问 Spark 客户计费门户时使用,例如 https://example.com/billing/userhttps://example.com/billing/team

计费项解析

当您安装 Laravel Spark 时,会为您创建一个 App\Providers\SparkServiceProvider 类。在此服务提供者中,您将找到一个回调,Spark 使用该回调在访问 Spark 计费门户时解析计费模型实例。默认情况下,此回调仅返回当前经过身份验证的用户,这是大多数使用 Laravel Spark 的应用程序所需的行为

php
use App\Models\User;
use Illuminate\Http\Request;
use Spark\Spark;

Spark::billable(User::class)->resolve(function (Request $request) {
    return $request->user();
});

但是,如果您的应用程序没有向单个用户收费,您可能需要调整此回调。例如,如果您的应用程序提供团队计费而不是用户计费,您可能会像这样自定义回调

php
use App\Models\Team;
use Illuminate\Http\Request;
use Spark\Spark;

Spark::billable(Team::class)->resolve(function (Request $request) {
    return $request->user()->currentTeam;
});

计费项授权

接下来,让我们检查 Spark 将用来确定您的应用程序的当前经过身份验证的用户是否有权查看特定计费模型的计费门户的授权回调。

当您安装 Laravel Spark 时,会为您创建一个 App\Providers\SparkServiceProvider 类。在此服务提供者中,您将找到用于确定给定用户是否有权查看 App\Models\User 计费类的计费门户的授权回调定义。当然,如果您的应用程序没有向用户收费,您应该更新计费类和授权回调逻辑以适应您的应用程序的需求。默认情况下,Spark 只会验证当前经过身份验证的用户只能管理其自己的计费设置

php
use App\Models\User;
use Illuminate\Http\Request;
use Spark\Spark;

Spark::billable(User::class)->authorize(function (User $billable, Request $request) {
    return $request->user() &&
           $request->user()->id == $billable->id;
});

如果授权回调返回 true,则当前经过身份验证的用户将被授权查看计费门户并管理给定 $billable 模型的计费设置。如果回调返回 false,则访问计费门户的请求将被拒绝。

您可以根据自己的应用程序需求自由定制authorize回调。例如,如果您的应用程序对团队而不是单个用户进行计费,您可以像这样更新回调

php
use App\Models\Team;
use Illuminate\Http\Request;
use Spark\Spark;

Spark::billable(Team::class)->authorize(function (Team $billable, Request $request) {
    return $request->user() &&
           $request->user()->ownsTeam($billable);
});

将客户数据与 Stripe 同步

当基础可计费 Eloquent 模型上的此数据更新时,Spark 会将用户数据(如姓名、电子邮件和账单地址信息)同步到 Stripe。为了确保这不会对您的应用程序性能产生负面影响,我们建议您配置一个队列工作器。如果已配置队列工作器,Spark 将使用您的应用程序的默认队列自动执行 Stripe 数据同步。

定义订阅计划

正如我们之前讨论的,Spark 允许您定义您的应用程序将管理的可计费模型类型。此可计费模型在应用程序的config/spark.php配置文件的billables数组中定义

billables数组中的可计费配置包含一个plans数组。在此数组中,您可以配置您的应用程序提供给该特定可计费类型的每个计费计划。monthly_idyearly_id标识符应与您在 Stripe 帐户仪表板中配置的价格/计划标识符相对应:

php
use App\Models\User;

'billables' => [
    'user' => [
        'model' => User::class,
        'trial_days' => 5,
        'plans' => [
            [
                'name' => 'Standard',
                'short_description' => 'This is a short, human friendly description of the plan.',
                'monthly_id' => 'price_id',
                'yearly_id' => 'price_id',
                'features' => [
                    'Feature 1',
                    'Feature 2',
                    'Feature 3',
                ],
            ],
        ],
    ],
]

如果您的订阅计划只提供每月计费周期,您可以从您的计划配置中省略yearly_id标识符。同样,如果您的计划只提供每年计费周期,您可以省略monthly_id标识符。

此外,您可以自由提供计划的简短描述以及与计划相关的功能列表。此信息将显示在 Spark 计费门户中。

如果您想指示某些功能不可用于给定计划,您可以使用--作为前缀。这些功能将使用删除线文本显示

php
'features' => [
    'Feature 1',
    'Feature 2',
    'Feature 3',
    '--No Batch Approve',
    '--No Additional Sources',
],

Disabled features example

自定义 Stripe 结账

当用户开始新的订阅时,他们将被重定向到 Stripe 的托管结账页面。使用checkoutSessionOptions方法,您可以通过提供一个接收可计费项目和所选计划作为参数的闭包来自定义 Stripe 结账体验。

通常,您应该在 SparkServiceProvider 类的 boot 方法中调用 Spark 的 checkoutSessionOptions 方法。提供的闭包可以返回 Stripe Checkout 接受的任何选项。

php
use App\Models\User;
use Spark\Plan;
use Spark\Spark;
 
/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Spark::checkoutSessionOptions('user', function ($billable, Plan $plan) {
        return [
            'locale' => $billable->language,
        ];
    });
}

自定义付款方式结账

除了在创建新订阅时自定义结账体验外,您还可以自定义在添加新付款方式时使用的结账会话。这可以通过使用 paymentMethodSessionOptions 方法来实现。通常,您应该在 SparkServiceProvider 类的 boot 方法中调用 Spark 的 paymentMethodSessionOptions 方法。

php
use App\Models\User;
use Spark\Plan;
use Spark\Spark;
 
/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Spark::paymentMethodSessionOptions('user', function ($billable) {
        return [
            'locale' => $billable->language,
        ];
    });
}

访问账单门户

配置好 Spark 安装后,您可以在 /billing URI 访问应用程序的账单门户。因此,如果您的应用程序在 localhost 上运行,您可以在 http://localhost/billing 访问应用程序的账单门户。

当然,您可以根据需要从应用程序的仪表板链接到账单门户。

html
<a href="/billing">
    Manage Subscription
</a>

许多应用程序在结账时会显示账单条款和条件。Spark 允许您在应用程序的账单门户中轻松地执行相同的操作。首先,在应用程序的 config/spark.php 配置文件中添加一个 terms_url 配置值。

php
'terms_url' => '/terms'

添加后,Spark 将在账单门户中显示指向 /terms 的链接。

发票电子邮件

Spark Stripe 还可以将订阅发票通过电子邮件发送给您的客户。要启用此功能,请在应用程序的 config/spark.php 配置文件中取消注释 'invoiceEmails' 功能条目。

php
'features' => [
    // ...
    Features::invoiceEmails(),
    // ...
]

如果您想让您的客户能够指定应将发票发送到的电子邮件地址,您可以在功能定义中提供 custom-addresses 选项。

php
'features' => [
    // ...
    Features::invoiceEmails(['custom-addresses' => true]),
    // ...
]

如果您在应用程序中启用了电子邮件发票,我们建议您禁用 Stripe 的发票邮件功能,这样客户就不会收到重复的发票电子邮件。禁用“将最终发票和贷项通知单发送给客户”选项即可实现此目的。

付款失败电子邮件

由于 SCA 规定要求客户即使在订阅处于活动状态时也偶尔验证其付款详细信息,因此 Spark 可以向客户发送通知,告知他们需要进行非会话付款确认。Spark 的付款确认通知可以通过在应用程序的 config/spark.php 配置文件中启用 paymentNotificationEmails 功能来启用。

php
'features' => [
    // ...
    Features::paymentNotificationEmails(),
    // ...
]