digikraaft / laravel-paystack-subscription
一个简单的Paystack订阅计费服务的接口。它从您手中取走实施订阅管理的痛苦。
Requires
- php: ^8.0|^8.1
- digikraaft/laravel-paystack-webhooks: ^2.1
- digikraaft/paystack-php: ^2.2
- laravel/framework: ^9.0|^10.0
Requires (Dev)
- orchestra/testbench: ^7.6
- phpunit/phpunit: ^9.5
- vimeo/psalm: ^4.24
README
Laravel Paystack Subscription 提供了访问Paystack订阅计费服务的简单、流畅的接口。不再需要担心编写订阅计费代码了!
安装
您可以通过Composer安装此包
composer require digikraaft/laravel-paystack-subscription
配置文件
Laravel Paystack Subscription 包附带一个配置文件,以下是文件内容
return [ /* |-------------------------------------------------------------------------- | Paystack Keys |-------------------------------------------------------------------------- | | The Paystack publishable key and secret key. You can get these from your Paystack dashboard. | */ 'public_key' => env('PAYSTACK_PUBLIC_KEY'), 'secret' => env('PAYSTACK_SECRET'), /* |-------------------------------------------------------------------------- | Subscription Model |-------------------------------------------------------------------------- | | This is the model in your application that implements the Billable trait | provided by PaystackSubscription. It will serve as the primary model you use while | interacting with PaystackSubscription related methods, subscriptions, etc. | */ 'model' => env('SUBSCRIPTION_MODEL', App\User::class), /* |-------------------------------------------------------------------------- | User Table |-------------------------------------------------------------------------- | | This is the table in your application where your users' information is stored. | */ 'user_table' => 'users', /* |-------------------------------------------------------------------------- | Webhooks Path |-------------------------------------------------------------------------- | | This is the base URI path where webhooks will be handled from. | | This should correspond to the webhooks URL set in your Paystack dashboard: | https://dashboard.paystack.com/#/settings/developer. | | If your webhook URL is https://domain.com/paystack/webhook/ then you should simply enter paystack here. | | Remember to also add this as an exception in your VerifyCsrfToken middleware. | | See the demo application linked on github to help you get started. | */ 'webhook_path' => env('PAYSTACK_WEBHOOK_PATH', 'paystack'), ];
您可以使用以下命令发布此配置文件
php artisan vendor:publish --provider="Digikraaft\PaystackSubscription\PaystackSubscriptionServiceProvider" --tag="config"
数据库迁移
您需要使用以下命令发布数据库迁移
php artisan vendor:publish --provider="Digikraaft\PaystackSubscription\PaystackSubscriptionServiceProvider" --tag="migrations" php artisan migrate
这些迁移将在您的用户表中添加几个列,并创建一个新的订阅表以保存所有客户的订阅。
配置
可计费模型
在使用此包之前,将Billable trait添加到您的模型定义中。此特性提供了各种方法,允许您执行常见的计费任务,例如创建订阅、续订订阅和取消订阅
use Digikraaft\PaystackSubscription\Billable; class User extends Authenticatable { use Billable; }
该包假设您的Billable模型将是Laravel附带的标准App\User类。如果您想更改这一点,可以在.env文件或包发布的配置文件中指定不同的模型
SUBSCRIPTION_MODEL = App\User
请注意,如果您使用的是除Laravel提供的App\User模型之外的其他模型,您需要发布并修改提供的迁移以匹配您替代模型的表名。
您还可以为您的可计费模型指定不同的表名。请参阅配置文件部分。
API密钥
接下来,您应该在.env文件中配置您的Paystack密钥。您可以从Paystack仪表板获取您的Paystack API密钥。
PAYSTACK_PUBLIC_KEY=your-paystack-public-key PAYSTACK_SECRET=your-paystack-secret
客户
检索客户
您可以使用PaystackSubscription::findBillable
方法通过Paystack ID检索客户。这将返回Billable模型的一个实例
use Digikraaft\PaystackSubscription\PaystackSubscription;
$user = PaystackSubscription::findBillable($paystackId);
创建客户
如果您需要创建一个不立即开始订阅的Paystack客户,可以使用createAsPaystackCustomer
方法
$paystackCustomer = $user->createAsPaystackCustomer();
该代码在Paystack中创建了一个客户。然后您可以在以后开始订阅。您还可以使用可选的$options
数组传递Paystack API支持的任何其他参数
$paystackCustomer = $user->createAsPaystackCustomer($options);
如果计费实体已经是Paystack中的客户,您可以使用asPaystackCustomer
方法检索客户对象
$paystackCustomer = $user->asPaystackCustomer();
如果您不确定计费实体是否已经是Paystack客户,可以使用createOrGetPaystackCustomer
方法获取客户对象。如果客户不存在,此方法将在Paystack中创建一个新的客户
$paystackCustomer = $user->createOrGetPaystackCustomer();
更新客户
如果您需要使用附加信息更新Paystack客户,可以使用updatePaystackCustomer
方法
$paystackCustomer = $user->updatePaystackCustomer($options);
订阅
创建订阅
要创建订阅,首先检索您的Billable模型的实例,这通常是一个App\User的实例。检索到模型实例后,您可以使用newSubscription方法创建模型订阅
$user = User::find(1);
$user->newSubscription('default', 'PLN_paystackplan_code')->create($transactionId);
将第一个参数传递给newSubscription
方法的应该是订阅的名称。如果你的应用程序只提供单个订阅,你可能将其称为default
或primary
。第二个参数是用户订阅的具体计划。此值应与Paystack中计划的代码相匹配。
接受Paystack交易ID的create
方法将开始订阅,并将客户ID和其他相关账单信息更新到您的数据库中。
您可以查看实现演示应用程序以了解如何轻松获取此计划代码并处理付款以从Paystack获取$transactionID
。
授权代码
当客户最初被收费时,Paystack会创建一个授权代码,该代码可以在客户取消订阅后用于向客户收费。如果您希望在以后日期向客户收费,可以将授权代码作为create
方法的第二个参数传递
$user->newSubscription('default', 'PLN_paystackplan_code')->create(null, $authorizationCode);
附加详情
如果您想指定额外的客户信息,可以通过将它们作为create
方法的第三个参数传递来实现
$user->newSubscription('default', 'PLN_paystackplan_code')->create($transactionId, null, [
'email' => $email,
]);
指定的附加字段必须由Paystack的API支持。
检查订阅状态
一旦用户订阅了您的应用程序,您就可以使用各种方便的方法轻松检查他们的订阅状态。首先,如果用户有一个有效的订阅(即使订阅已取消且在账单周期结束时不会续订),则subscribed
方法返回true
if ($user->subscribed('default')) {
//
}
您还可以在路由中间件中使用subscribed
方法,以便根据用户的订阅状态过滤对路由和控制器访问
public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('default')) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
此示例在包的演示实现中可见此处
可以使用subscribedToPlan
方法根据给定的Paystack计划代码确定用户是否订阅了特定的计划。在此示例中,我们将确定用户的default
订阅是否活跃订阅了PLN_paystackplan_code
计划
if ($user->subscribedToPlan('PLN_paystackplan_code', 'default')) {
//
}
通过向subscribedToPlan
方法传递一个数组,您可以确定用户的default
订阅是否活跃订阅了PLN_paystackplan_code
或PLN_paystackplan_code2
计划
if ($user->subscribedToPlan(['PLN_paystackplan_code', 'PLN_paystackplan_code2'], 'default')) {
//
}
可以使用active
方法确定用户当前是否有有效的订阅
if ($user->subscription('default')->active()) {
//
}
可以使用renews
方法确定用户的订阅在当前账单周期结束后是否会续订
if ($user->subscription('default')->renews()) {
//
}
可以使用daysLeft
方法获取当前账单周期剩余的天数
$daysLeft = $user->subscription('default')->daysLeft();
可以使用endsAt
方法获取当前账单周期结束的日期
$endDate = $user->subscription('default')->endsAt();
已取消订阅状态
要确定用户是否已取消订阅,请使用isCancelled
方法
if ($user->subscription('default')->isCancelled()) {
//
}
要确定用户的订阅是否过期,请使用pastDue
方法
if ($user->subscription('default')->pastDue()) {
//
}
订阅作用域
active
和cancelled
订阅状态也作为查询作用域提供,这样您可以轻松查询数据库中的订阅
// Get all active subscriptions...
$subscriptions = Subscription::query()->active()->get();
// Get all of the cancelled subscriptions for a user...
$subscriptions = $user->subscriptions()->cancelled()->get();
取消订阅
要取消订阅,请在用户的订阅上调用cancel
方法
$user->subscription('default')->cancel();
当订阅被取消时,数据库中的paystack_status
列被设置为complete
。这是基于Paytstack的实现,意味着订阅在账单周期结束时不会续订。订阅将继续活跃,直到当前账单周期结束。
恢复订阅
如果用户已取消订阅,您希望恢复它,请使用 enable
方法。
$user->subscription('default')->enable();
如果用户取消订阅然后在该订阅完全过期之前恢复,他们将不会立即被收费。相反,他们的订阅将被重新激活,并将按原始计费周期收费。
处理 Paystack Webhooks
Paystack 可以通过 Webhooks 通知您的应用程序关于各种事件。默认情况下,通过服务提供程序配置了一个指向此包的 webhook 控制器的路由。此控制器将处理所有传入的 webhook 请求。
默认情况下,此控制器将自动处理取消订阅、启用订阅和失败的发票。此控制器可以扩展以处理您喜欢的任何 webhook 事件。
为确保您的应用程序可以处理 Paystack Webhooks,请务必在 Paystack 控制台中配置 webhook URL。默认情况下,此包的 webhook 控制器监听 /paystack/webhook
Webhooks & CSRF 保护
由于 Paystack Webhooks 需要绕过 Laravel 的 CSRF 保护,请务必在您的 VerifyCsrfToken
中间件中将 URI 列为异常,或将路由列在 web
中间件组之外
protected $except = [
'paystack/*',
];
定义 Webhook 事件处理器
如果您要处理额外的 webhook 事件,请扩展 Webhook 控制器。您的方法名称应与该包的预期约定相匹配,具体来说,方法应以前缀 handle
和要处理的 webhook 的“驼峰命名法”名称开头。例如,如果您要处理 invoice.create
webhook,您应在控制器中添加一个 handleInvoiceCreate
方法
<?php namespace App\Http\Controllers; use Digikraaft\PaystackSubscription\Http\Controllers\WebhookController as PaystackWebhookController; class WebhookController extends PaystackWebhookController { /** * Handle invoice create. * * @param array $payload * @return \Symfony\Component\HttpFoundation\Response */ public function handleInvoiceCreate($payload) { // Handle The Event } }
接下来,在您的 routes/web.php
文件中定义到您控制器的路由。这将覆盖默认提供的路由
Route::post(
'paystack/webhook',
'\App\Http\Controllers\WebhookController@handleWebhook'
);
底层,使用 此包 来处理 webhook
有关 Paystack 事件的详细信息,请参阅 此处
Paystack API
如果您想直接与 Paystack 对象交互,您可以使用 asPaystack
方法方便地检索它们
$paystackSubscription = $subscription->asPaystackSubscription();
$paystackSubscription->quantity = 2;
$paystackSubscription->save();
有关如何与对象交互的详细信息,请参阅我们的 paystack-php
包 此处
测试
在测试使用此包的应用程序时,您可以自由模拟对 Paystack API 的实际 HTTP 请求;但是,这需要您部分重新实现此包的自身行为。因此,我们建议允许您的测试击中实际的 Paystack API。虽然这较慢,但它提供了更多的信心,即您的应用程序按预期工作,并且任何慢速测试都可以放置在其自己的 PHPUnit 测试组中。
在测试时,请记住,此包本身已经有一个很好的测试套件,因此您应仅关注测试您自己应用程序的订阅和支付流程,而不是此包的任何底层行为。
要开始,请将您的 Paystack 密钥和其他所需实体添加到您的 phpunit.xml
文件中的 测试 版本
<env name="PAYSTACK_SECRET" value="sk_test_your_secret_key"/>
<env name="PAYSTACK_CUSTOMER" value="CUS_<customercode1>" />
<env name="PAYSTACK_OTHER_CUSTOMER" value="CUS_<customercode2>" />
<env name="PAYSTACK_PLAN" value="PLN_<plan_code1>" />
<env name="PAYSTACK_OTHER_PLAN" value="PLN_<plan_code2>" />
<env name="PAYSTACK_TRANSACTION_ID" value="<valid_transaction_id_used_for_plan_code1>" />
<env name="PAYSTACK_TRANSACTION_ID_INVALID" value="<existing_paystack_transaction_id>" />
<env name="PAYSTACK_TRANSACTION_REF" value="valid_transaction_reference_used_for_plan_code1" />
<env name="PAYSTACK_TRANSACTION_REF_INVALID" value="<existing_paystack_transaction_id>" />
<env name="DB_CONNECTION" value="testing"/>
在测试时,请确保创建上述环境变量,并在 paystack 中与值的描述相匹配。
使用以下命令运行您的测试
composer test
更多好东西
请参阅 此处 了解更多免费的好东西!
替代方案
变更日志
请参阅 CHANGELOG 了解最近更改的更多信息。
贡献
请参阅 CONTRIBUTING 了解详细信息。
安全
如果您发现任何与安全相关的问题,请通过电子邮件 dev@digitalkraaft.com 联系我们,而不是使用问题跟踪器。
致谢
许可证
MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件。