订阅支付解决方案:Laravel Cashier | 官方扩展包 | Laravel 5.5 中文文档


本站和网页 https://xueyuanjun.com/post/8505.html 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。

订阅支付解决方案:Laravel Cashier | 官方扩展包 | Laravel 5.5 中文文档
Laravel 学院
文档
Laravel 8.x 中文文档
Laravel 7.x 中文文档
Laravel 6.x 中文文档
Laravel 5.8 中文文档
Laravel 5.7 中文文档
Laravel 5.6 中文文档
Laravel 5.5 中文文档
Laravel 5.4 中文文档
Laravel 5.3 中文文档
Laravel 5.2 中文文档
Laravel 5.1 中文文档
Lumen 中文文档
全栈教程
PHP 全栈工程师指南
PHP 入门到实战
Laravel 入门到精通
Vue.js 入门到实战
玩转 PhpStorm 教程
Laravel 博客入门项目
Laravel 微信小程序项目
Laravel 前后端分离项目
Swoole 入门到实战
Eloquent 性能优化实战
Redis 高性能实战系列
Laravel 新版本特性
PHP 新特性与最佳实践
Golang
Go 入门教程
Go Web 编程
Gin 使用教程
微服务开发
内功修炼
数据结构与算法
网络协议
微服务从入门到实践
高性能 MySQL 实战
高性能 Redis 实战
Laravel 消息队列实战
Laravel 从学徒到工匠
PHP 设计模式系列
名企面试指南
资源库
Laravel 资源大全
Laravel 开源项目
Laravel 扩展包
Laravel 资源下载
更多
博客 & 新闻
问答 & 讨论
Leetcode 题解
学院君读书笔记系列
关于 Laravel 学院
Laravel 互助学习群
Golang 互助学习群
更多
Laravel 中文文档
Laravel 全栈教程
Laravel 学习路径
Go 入门教程
程序员内功修炼
博客
问答
搜索
注册
登录
Info
Content
章节导航
Laravel 5.5 中文文档
目录索引
序言
2篇文章
新版特性
升级指南
快速入门
6篇文章
安装配置篇
目录结构篇
重量级开发环境:Homestead 安装使用详细教程
轻量级开发环境:Valet 安装使用详细教程
使用 Laradock 搭建基于 Docker 的 PHP 开发环境
使用 Laragon 在 Windows 中搭建 Laravel 开发环境
核心架构
5篇文章
一次 Laravel 请求的生命周期
服务容器
服务提供者
门面(Facades)
契约(Contracts)
基础组件
14篇文章
Laravel 应用的入口:路由系列之基础入门篇
Laravel 应用的入口:路由系列之参数、命名和分组篇
Laravel 应用的入口:路由系列之路由模型绑定篇
HTTP 请求的过滤器:中间件
使用中间件 VerifyCsrfToken 避免 CSRF 攻击
HTTP 请求的处理层:控制器
HTTP 请求参数获取、Cookie设置及文件上传
HTTP 响应、重定向及文件下载
Laravel 视图渲染:Blade 模板引擎
Laravel 视图的创建和数据传递
辅助函数篇:请求 URL 生成
Session 实现、配置与使用详解
请求表单验证及错误处理大全
异常处理 & 错误日志
前端开发
3篇文章
视图渲染本地化:让你的应用轻松实现多语言支持
快速入门:JavaScript & CSS 脚手架
使用进阶:通过 Laravel Mix 编译前端资源
安全系列
6篇文章
在 Laravel 中实现用户注册登录认证
使用 Laravel Passport 实现 API 认证
在 Laravel 中实现对资源操作的权限控制
在 Laravel 中对敏感数据进行加密解密
使用哈希算法在 Laravel 中实现密码加密
如何在 Laravel 中实现密码重置功能
数据库操作
5篇文章
快速入门:基本配置和使用、读写分离 & 数据库事务
使用进阶:通过查询构建器实现高级功能
在 Laravel 中轻松实现分页功能
数据库迁移:以版本控制的方式维护数据表
数据库填充器:初始化测试数据的好帮手
Eloquent模型
6篇文章
入门篇:使用 Eloquent 模型进行数据库操作
进阶篇:使用 Eloquent 模型管理关联关系
Eloquent 查询返回的数据格式:集合
使用访问器和修改器格式化模型数据
API 资源类:架起模型与 JSON API 之间的桥梁
将模型数据序列化为数组或 JSON
进阶系列
13篇文章
使用 Artisan 构建强大的控制台应用
通过事件和事件监听器实现服务解耦
Laravel 队列系统实现及使用教程
Laravel 中服务端与客户端事件广播实现
通过缓存构建高性能 Laravel 应用
键值对存储系统 Redis 在 Laravel 中的使用
集合:给 PHP 数组插上翅膀
辅助函数:简化 Laravel 代码编写的利器
集成 Flysystem 实现对文件系统的高级操作
在 Laravel 中实现邮件配置、预览和发送
在 Laravel 中使用多种通道实现通知发送
Laravel 自定义扩展包的开发和使用
定时任务调度在 Laravel 中的实现
测试
5篇文章
快速入门:集成 PHPUnit 编写测试用例
HTTP 测试:如何测试 HTTP 请求和响应
浏览器测试:使用 Laravel Dusk 进行浏览器测试
数据库测试:模型工厂生成及使用
模拟:通过伪造事件、邮件、通知、队列、文件存储等服务简化测试
官方扩展包
5篇文章
订阅支付解决方案:Laravel Cashier
远程操作解决方案:Envoy Task Runner
队列系统解决方案:Laravel Horizon
全文搜索解决方案:Laravel Scout
第三方登录解决方案:Laravel Socialite
图书
Laravel 5.5 中文文档
官方扩展包
订阅支付解决方案:Laravel Cashier
订阅支付解决方案:Laravel Cashier
由 学院君 创建于4年前, 最后更新于 2年前
版本号 #2
14636 views
0 likes
0 collects
简介
Laravel Cashier 为通过 Stripe 和 Braintree 实现订阅支付服务提供了一个优雅的流式接口。它封装了几乎所有你恐惧编写的样板化的订阅支付代码。除了基本的订阅管理外,Cashier 还支持处理优惠券、订阅升级/替换、订阅“数量”、取消宽限期,甚至生成 PDF 发票。
注:如果你只需要一次性支付,并不提供订阅,就不应该使用 Cashier,而是直接使用 Stripe 和 Braintree SDK。
配置
Stripe
Composer
首先,通过 Composer 安装 Cashier 扩展包依赖:
composer require "laravel/cashier":"~7.0"
数据库迁移
使用 Cashier 之前,我们需要准备好数据库。我们需要添加一个字段到 users 表,还要创建新的 subscriptions 表来处理所有用户订阅:
Schema::table('users', function ($table) {
$table->string('stripe_id')->nullable();
$table->string('card_brand')->nullable();
$table->string('card_last_four')->nullable();
$table->timestamp('trial_ends_at')->nullable();
});
Schema::create('subscriptions', function ($table) {
$table->increments('id');
$table->integer('user_id');
$table->string('name');
$table->string('stripe_id');
$table->string('stripe_plan');
$table->integer('quantity');
$table->timestamp('trial_ends_at')->nullable();
$table->timestamp('ends_at')->nullable();
$table->timestamps();
});
创建好迁移后,只需简单运行 migrate 命令,相应修改就会更新到数据库。
Billable模型
接下来,添加 Billable trait 到模型定义,这个 trait 提供了多个方法以便执行常用支付任务,例如创建订阅、使用优惠券以及更新信用卡信息:
use Laravel\Cashier\Billable;
class User extends Authenticatable
use Billable;
API Key
最后,在配置文件 services.php 中配置 Stripe 的 key,你可以在Stripe 官网个人中心的控制面板中获取这些 Stripe API key 信息:
'stripe' => [
'model' => App\User::class,
'key' => env('STRIPE_KEY'),
'secret' => env('STRIPE_API_SECRET'),
],
Braintree
Braintree 注意事项
对于很多操作,Stripe 和 Braintree 实现的 Cashier 功能都是一样的,两者都提供了通过信用卡进行订阅支付的功能,但是 Braintree 还支持通过 PayPal 支付。不过,Braintree 也缺失一些 Stripe 支持的功能,在决定使用 Stripe 还是 Braintree 之前,需要考虑以下几点:
Braintree 支持 PayPal 而 Stripe 不支持;
Braintree 不支持 increment 和 decrement 方法,这个是 Braintree 级别的限制,不是 Cashier 级别的;
Braintree 不支持基于百分比的折扣,这个也是 Braintree 级别的限制,不是 Cashier 级别的
Composer
首先,通过 Composer 安装 Cashier 扩展包依赖:
composer require "laravel/cashier-braintree":"~2.0"
服务提供者
接下来,在配置文件 config/app.php 中注册服务提供者 Laravel\Cashier\CashierServiceProvider。
计划信用优惠券
在使用基于 Braintree 的 Cashier 之前,需要在 Braintree 的控制面板中定义一个 plan-credit 折扣,这个折扣将会用于从年到月或者从月到年支付的优惠额度比例分配。
配置在 Braintree 控制面板中的这个折扣值可以是你希望的任何值,Cashier 将会在每次使用优惠券的时候通过自定义的值来重写这个默认定义的值。该优惠券之所以是必须的是因为 Braintree 不支持本地根据订阅时长进行优惠额度的按比例分配。
数据库迁移
使用 Cashier 之前,需要准备好数据库。我们需要添加额外的字段到 users 表并创建一个新的 subscriptions 表用于存放所有用户订阅:
Schema::table('users', function ($table) {
$table->string('braintree_id')->nullable();
$table->string('paypal_email')->nullable();
$table->string('card_brand')->nullable();
$table->string('card_last_four')->nullable();
$table->timestamp('trial_ends_at')->nullable();
});
Schema::create('subscriptions', function ($table) {
$table->increments('id');
$table->integer('user_id');
$table->string('name');
$table->string('braintree_id');
$table->string('braintree_plan');
$table->integer('quantity');
$table->timestamp('trial_ends_at')->nullable();
$table->timestamp('ends_at')->nullable();
$table->timestamps();
});
迁移被创建之后,只需要执行 Artisan 命令 migrate 即可。
Billable模型
接下来,添加 Billable trait 到模型定义:
use Laravel\Cashier\Billable;
class User extends Authenticatable
use Billable;
API Key
接下来,需要在配置文件 services.php 中配置如下选项:
'braintree' => [
'model' => App\User::class,
'environment' => env('BRAINTREE_ENV'),
'merchant_id' => env('BRAINTREE_MERCHANT_ID'),
'public_key' => env('BRAINTREE_PUBLIC_KEY'),
'private_key' => env('BRAINTREE_PRIVATE_KEY'),
],
然后你需要在服务提供者 AppServiceProvider 的 boot 方法中添加对 Braintree SDK 的调用:
\Braintree_Configuration::environment(config('services.braintree.environment'));
\Braintree_Configuration::merchantId(config('services.braintree.merchant_id'));
\Braintree_Configuration::publicKey(config('services.braintree.public_key'));
\Braintree_Configuration::privateKey(config('services.braintree.private_key'));
货币配置
Cashier 默认货币是美元(USD),你可以在某个服务提供者的 boot 方法中通过调用 Cashier::useCurrency 方法来更改默认的货币, useCurrency 方法接收两个字符串参数:货币及货币符号:
use Laravel\Cashier\Cashier;
Cashier::useCurrency('rmb', '¥');
订阅
创建订阅
要创建一个订阅,首先要获取一个账单模型的实例,通常是 App\User 的实例。获取到该模型实例之后,你可以使用 newSubscription 方法来创建该模型的订阅:
$user = User::find(1);
$user->newSubscription('main', 'premium')->create($stripeToken);
第一个传递给 newSubscription 方法的参数是该订阅的名字,如果应用只有一个订阅,可以将其称作 main 或 primary,第二个参数用于指定用户订阅的 Stripe/Braintree 计划,该值对应 Stripe 或 Braintree 中相应计划的 id。
create 方法会自动创建这个 Stripe 订阅,同时更新数据库中 Stripe 的客户 ID(即 users 表中的 stripe_id)和其它相关的账单信息。
额外的用户信息
如果你想要指定额外的客户信息,你可以将其作为第二个参数传递给 create 方法:
$user->newSubscription('main', 'monthly')->create($stripeToken, [
'email' => $email,
]);
要了解更多 Stripe 支持的字段,可以查看 Stripe 关于创建消费者的文档或者相应的Braintree文档。
优惠券
如果你想要在创建订阅的时候使用优惠券,可以使用 withCoupon 方法:
$user->newSubscription('main', 'monthly')
->withCoupon('code')
->create($stripeToken);
检查订阅状态
用户订阅你的应用后,你可以使用各种便利的方法来简单检查订阅状态。首先,如果用户有一个有效的订阅,则 subscribed 方法返回 true,即使订阅现在处于试用期:
if ($user->subscribed('main')) {
//
subscribed 方法还可以用于路由中间件,基于用户订阅状态允许你对路由和控制器的访问进行过滤:
public function handle($request, Closure $next){
if ($request->user() && ! $request->user()->subscribed('main')) {
// This user is not a paying customer...
return redirect('billing');
return $next($request);
如果你想要判断一个用户是否还在试用期,可以使用 onTrial 方法,该方法对于还处于试用期的用户显示警告信息很有用:
if ($user->->subscription('main')->onTrial()) {
//
subscribedToPlan 方法可用于判断用户是否基于 Stripe/Braintree ID 订阅了给定的计划,在本例中,我们会判断用户的 main 订阅是否订阅了 monthly 计划:
if ($user->subscribedToPlan('monthly', 'main')) {
//
已取消的订阅状态
要判断用户是否曾经是有效的订阅者,但现在取消了订阅,可以使用 cancelled 方法:
if ($user->subscription('main')->cancelled()) {
//
你还可以判断用户是否曾经取消过订阅,但现在仍然在“宽限期”直到完全失效。例如,如果一个用户在3月5号取消了一个实际有效期到3月10号的订阅,该用户处于“宽限期”直到3月10号。注意 subscribed 方法在此期间仍然返回 true。
if ($user->subscription('main')->onGracePeriod()) {
//
修改计划
用户订阅应用后,偶尔想要改变到新的订阅计划,要将用户切换到新的订阅, 传递计划标识到 swap 方法:
$user = App\User::find(1);
$user->subscription('main')->swap('provider-plan-id');
如果用户在试用,试用期将会被维护。还有,如果订阅存在多个,数量也可以被维护。
如果你想要切换计划并取消用户所在的所有试用期,你可以使用 skipTrial 方法:
$user->subscription('main')
->skipTrial()
->swap('provider-plan-id');
订阅数量
注:只有 Stripe 版本的 Cashier 支持订阅数量,Braintree 没有提供类似 Stripe “数量”这样的特性。
有时候订阅也会被数量影响,例如,应用中每个账户每月需要付费$10,要简单增加或减少订阅数量,使用 incrementQuantity 和 decrementQuantity 方法:
$user = User::find(1);
$user->subscription('main')->incrementQuantity();
// Add five to the subscription's current quantity...
$user->subscription('main')->incrementQuantity(5);
$user->subscription('main')->decrementQuantity();
// Subtract five to the subscription's current quantity...
$user->subscription('main')->decrementQuantity(5);
你也可以使用 updateQuantity 方法指定数量:
$user->subscription('main')->updateQuantity(10);
想要了解更多订阅数量信息,查阅相关Stripe文档。
订阅税金
要指定用户支付订阅的税率,实现账单模型的 taxPercentage 方法,并返回一个在0到100之间的数值,不要超过两位小数:
public function taxPercentage() {
return 20;
这将使你可以在模型基础上使用税率,对跨越不同国家不同税率的用户很有用。
注: taxPercentage 方法只能用于订阅支付,如果你使用 Cashier 生成一次性账单,需要手动指定税率。
取消订阅
要取消订阅,可以调用用户订阅上的 cancel 方法:
$user->subscription('main')->cancel();
当订阅被取消时,Cashier 将会自动设置数据库中的 ends_at 字段。该字段用于了解 subscribed 方法什么时候开始返回 false。例如,如果客户3月1号份取消订阅,但订阅直到3月5号才会结束,那么 subscribed 方法继续返回 true 直到3月5号。
你可以使用 onGracePeriod 方法判断用户是否已经取消订阅但仍然在“宽限期”:
if ($user->subscription('main')->onGracePeriod()) {
//
如果你想要立即取消订阅,调用用户订阅上的方法 cancelNow 即可:
$user->subscription('main')->cancelNow();
恢复订阅
如果用户已经取消订阅但想要恢复该订阅,可以使用 resume 方法,前提是该用户必须在宽限期内:
$user->subscription('main')->resume();
如果该用户取消了一个订阅然后在订阅失效之前恢复了这个订阅,则不会立即支付该账单,取而代之的,他们的订阅只是被重新激活,并回到正常的支付周期。
更新信用卡
updateCard 方法可用于更新用户的信用卡信息,该方法接收一个 Stripe 令牌并设置新的信用卡作为支付源:
$user->updateCard($stripeToken);
订阅试用期
带信用卡信息
如果你想要在提供给用户试用期的同时预先收集支付方式信息,可以在创建订阅的时候使用 trialDays 方法:
$user = User::find(1);
$user->newSubscription('main', 'monthly')
->trialDays(10)
->create($stripeToken);
该方法会在数据库订阅记录上设置试用期结束日期,以便告知 Stripe/Braintree 在此之前不要计算用户的账单信息。
注:如果用户的订阅没有在试用期结束之前取消,则会在试用期结束时立即支付,所以要确保通知用户试用期结束时间。
可以使用用户实例或订阅实例上的 onTrial 方法判断用户是否处于试用期,下面两个例子作用是等价的:
if ($user->onTrial('main')) {
//
if ($user->subscription('main')->onTrial()) {
//
不带信用卡信息
如果你不想在提供试用期的时候收集用户支付方式信息,只需设置用户记录的 trial_ends_at 字段为期望的试用期结束日期即可,这通常在用户注册期间完成:
$user = User::create([
// Populate other user properties...
'trial_ends_at' => Carbon::now()->addDays(10),
]);
注:确保已添加 trial_ends_at 日期修改器到模型定义。
Cashier 将这种类型的试用期看作“一般体验”,因为这种使用并没有附加到任何已经在的订阅,如果当前日期没有超过 trial_ends_at 的值, User 实例上的 onTrial 方法将返回 true:
if ($user->onTrial()) {
// User is within their trial period...
如果你想要知道用户是否在“一般”试用期并且还没有创建实际的订阅还可以使用 onGenericTrial 方法:
if ($user->onGenericTrial()) {
// User is within their "generic" trial period...
一旦你准备好为用户创建实际的订阅,可以使用 newSubscription 方法:
$user = User::find(1);
$user->newSubscription('main', 'monthly')->create($stripeToken);
处理 Stripe Webhooks
Stripe 和 Braintree 都可以通过 webhooks 通知应用各种事件,要处理 Stripe webhooks,需要定义一个指向 Cashier webhook 控制器的路由,这个控制器将会处理所有输入 webhook 请求并将它们分发到合适的控制器方法:
Route::post(
'stripe/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
注:注册好控制器后,还要在 Stripe 控制面板中配置 webhook URL。
默认情况下,这个控制器将会自动对支付失败次数(这个次数可以在 Stripe 设置中定义)过多的订阅进行取消;此外,我们很快会发现,你可以扩展这个控制器来处理任何你想要处理的 webhook 事件。
Webhooks & CSRF 防护
由于 Stripe webhook 需要绕开 Laravel 的 CSRF 保护,所以需要将其罗列到 VerifyCsrfToken 中间件的排除列表或者将其置于 web 中间件组之外:
protected $except = [
'stripe/*',
];
定义 Webhook 事件处理器
Cashier 会基于支付失败次数自动取消订阅,但是如果你想要处理额外的 Stripe webhook 事件,扩展 Webhook 控制器即可。定义的方法名需要与 Cashier 约定的格式保持一致,特别是方法名需要以 handle 开头并且是想要处理的 Stripe webhook 的驼峰格式。例如,如果你想要处理 invoice.payment_succeeded webhook,则需要添加一个 handleInvoicePaymentSucceeded 方法到控制器:
<?php
namespace App\Http\Controllers;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
/**
* Handle a Stripe webhook.
* @param array $payload
* @return Response
*/
public function handleInvoicePaymentSucceeded($payload)
// Handle The Event
失败的订阅
如果用户的信用卡过期怎么办?不用担心 —— Cashier webhook 控制器可以轻松为你取消该用户的订阅,正如上面所提到的,你所需要做的只是将路由指向该控制器:
Route::post(
'stripe/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
就是这样,失败的支付将会被控制器捕获和处理,该控制器将会在 Stripe 判断订阅支付失败次数(通常是3次)达到上限时取消该用户的订阅。
处理 Braintree Webhooks
Stripe 和 Braintree 都可以通过 webhooks 通知应用各种事件,要处理 Braintree webhooks,需要定义一个指向 Cashier webhook 控制器的路由,这个控制器将会处理所有输入 webhook 请求并将它们分发到合适的控制器方法:
Route::post(
'braintree/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
注:注册好控制器后,还要在 Braintree 控制面板中配置 webhook URL。
默认情况下,这个控制器将会自动对支付失败次数(这个次数可以在 Braintree 设置中定义)过多的订阅进行取消;此外,我们很快会发现,你可以扩展这个控制器来处理任何你想要处理的 webhook 事件。
Webhooks & CSRF 防护
由于 Braintree webhook 需要绕开 Laravel 的 CSRF 保护,所以需要将其罗列到 VerifyCsrfToken 中间件的排除列表或者将其置于 web 中间件组之外:
protected $except = [
'braintree/*',
];
定义 Webhook 事件处理器
Cashier 会基于支付失败次数自动取消订阅,但是如果你想要处理额外的 Braintree webhook 事件,扩展 Webhook 控制器即可。定义的方法名需要与 Cashier 约定的格式保持一致,特别是方法名需要以 handle 开头并且是想要处理的 Braintree webhook 的驼峰格式。例如,如果你想要处理 dispute_opened webhook,则需要添加一个 handleDisputeOpened 方法到控制器:
<?php
namespace App\Http\Controllers;
use Braintree\WebhookNotification;
use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;
class WebhookController extends CashierController
/**
* Handle a Braintree webhook.
* @param WebhookNotification $webhook
* @return Response
*/
public function handleDisputeOpened(WebhookNotification $notification)
// Handle The Event
失败的订阅
如果用户的信用卡过期怎么办?不用担心 —— Cashier webhook 控制器可以轻松为你取消该用户的订阅,正如上面所提到的,你所需要做的只是将路由指向该控制器:
Route::post(
'braintree/webhook',
'\Laravel\Cashier\Http\Controllers\WebhookController@handleWebhook'
);
就是这样,失败的支付将会被控制器捕获和处理,该控制器将会在 Braintree 判断订阅支付失败次数(通常是3次)达到上限时取消该用户的订阅。不要忘记在 Braintree 控制面板中配置 webhook URI。
一次性支付
简单支付
注:使用 Stripe 时, charge 方法可以接收应用所使用货币对应的最小单位金额,但是使用 Braintree 时,必须传递完整的美元金额到 charge 方法。
如果你想要使用订阅客户的信用卡一次性结清账单,可以使用账单模型实例上的 charge 方法:
// Stripe Accepts Charges In Cents...
$user->charge(100);
// Braintree Accepts Charges In Dollars...
$user->charge(1);
charge 方法接收一个数组作为第二个参数,允许你传递任何你想要传递的底层 Stripe/Braintree 账单创建参数,创建账单时我们可以参考 Stripe 或者 Braintree 文档提供的可用选项:
$user->charge(100, [
'custom_option' => $value,
]);
如果支付失败 charge 方法将抛出异常,如果支付成功,该方法会返回完整的 Stripe / Braintree 响应:
try {
$response = $user->charge(100);
} catch (Exception $e) {
//
带发票的支付
有时候你需要创建一个一次性支付并且同时生成对应发票以便为用户提供一个PDF单据, invoiceFor 方法可以帮助我们实现这个需求。例如,让我们为用户的“一次性费用”生成一张$5.00的发票:
// Stripe Accepts Charges In Cents...
$user->invoiceFor('One Time Fee', 500);
// Braintree Accepts Charges In Dollars...
$user->invoiceFor('One Time Fee', 5);
该单据会通过用户信用卡立即支付, invoiceFor 方法还可以接收一个数组作为第三个参数,从而允许你传递任意你希望的选项到底层 Stripe/Braintree 支付创建:
$user->invoiceFor('One Time Fee', 500, [
'custom-option' => $value,
]);
注: invoiceFor 方法会创建一个对失败支付进行重试的 Stripe 单据,如果你不想要单据重试失败的支付,需要在首次支付失败后使用 Stripe API 关闭它们。
发票
你可以使用 invoices 方法轻松获取账单模型的发票数组:
$invoices = $user->invoices();
// Include pending invoices in the results...
$invoices = $user->invoicesIncludingPending();
当列出客户发票时,你可以使用发票的辅助函数来显示相关的发票信息。例如,你可能想要在表格中列出每张发票,从而方便用户下载它们:
@foreach ($invoices as $invoice)
{{ $invoice->date()->toFormattedDateString() }}
{{ $invoice->total() }}
Download
@endforeach
生成 PDF 发票
在生成 PDF 发票之前,需要安装 PHP 库 dompdf:
composer require dompdf/dompdf
然后,在路由或控制器中,使用 downloadInvoice 方法生成发票的 PDF 下载,该方法将会自动生成相应的 HTTP 响应发送下载到浏览器:
use Illuminate\Http\Request;
Route::get('user/invoice/{invoice}', function (Request $request, $invoiceId) {
return $request->user()->downloadInvoice($invoiceId, [
'vendor' => 'Your Company',
'product' => 'Your Product',
]);
});
Laravel
文档
CSRF
Stripe
发票
信用卡
优惠券
PDF
订阅
支付
Cashier
Webhook
试用期
Braintree
5.5
点赞
取消点赞
收藏
取消收藏
赞赏
分享到以下平台:
<< 上一篇:
模拟:通过伪造事件、邮件、通知、队列、文件存储等服务简化测试
>> 下一篇:
远程操作解决方案:Envoy Task Runner
无评论
登录后即可添加评论
升级为学院君订阅用户(新年优惠🎁)
内容导航
简介
配置
Stripe
Braintree
货币配置
订阅
创建订阅
检查订阅状态
修改计划
订阅数量
订阅税金
取消订阅
恢复订阅
更新信用卡
订阅试用期
带信用卡信息
不带信用卡信息
处理 Stripe Webhooks
定义 Webhook 事件处理器
失败的订阅
处理 Braintree Webhooks
定义 Webhook 事件处理器
失败的订阅
一次性支付
简单支付
带发票的支付
发票
生成 PDF 发票
相关推荐
Laravel Cashier
Laravel 5.1 中文文档
服务
订阅支付实现:Laravel Cashier
Laravel 5.2 中文文档
服务
Laravel Cashier
Laravel 5.4 中文文档
官方扩展包
订阅支付解决方案:Laravel Cashier
Laravel 5.6 中文文档
官方扩展包
订阅支付解决方案:Laravel Cashier
Laravel 5.7 中文文档
官方扩展包
回到顶部
2022 基于 Laravel 6 构建
关于学院
订阅服务
友情链接
站点地图
本站 CDN 加速服务由又拍云赞助