Laravel Cashier (Paddle)
Table of Contents
Introduction
WARNING
このドキュメンテーションは、 Cashier Paddle 2.x が Paddle Billing と統合するためのものです。まだ Paddle Classic を使用している場合は、Cashier Paddle 1.x を使用する必要があります。
Laravel Cashier Paddle は、Paddle's subscription 課金 services に対して、表現豊かで流暢なインターフェースを提供します。ほとんどの既製の subscription 課金 code を処理します。基本的な subscription 管理に加えて、 Cashier は handle : subscriptions の切り替え、 subscription の"quantities"、 subscription の一時停止、キャンセル猶予期間、などを行うことができます。
まず、 Cashier Paddle を掘り下げる前に、Paddle の概念ガイド とAPI ドキュメンテーション もレビューすることをお勧めします。
Upgrading Cashier
Cashier の新しいバージョンにアップグレードする際には、アップグレードガイド を慎重に確認することが重要です。
Installation
まず、 Composer パッケージマネージャーを使用して、Paddle 用の Cashier パッケージをインストールします:
composer require laravel/cashier-paddle
次に、vendor:publish
の Artisan command を使用して、 Cashier の移行ファイルを publish する必要があります。
php artisan vendor:publish --tag="cashier-migrations"
次に、アプリケーションの database migrations を実行する必要があります。 Cashier migrations により、新しいcustomers
テーブルが作成されます。さらに、お客様の subscriptions をすべて保存するための新しいsubscriptions
およびsubscription_items
テーブルが作成されます。最後に、お客様と関連付けられた Paddle の transactions をすべて保存するための新しいtransactions
テーブルが作成されます。
php artisan migrate
WARNING
Cashier が全ての Paddle events を適切に処理するためには、Cashier の webhook ハンドリングを設定することを忘れないでください。
パドル・サンドボックス
ローカルおよびステージングの開発中は、Paddle の Sandbox アカウントをregister する必要があります。このアカウントは、実際の支払いを行うことなくアプリケーションをテストおよび開発するためのサンドボックス化された environment を提供します。さまざまな支払いシナリオをシミュレートするために、Paddle のtest card numbers を使用できます。
Paddle Sandbox の environment を使用する際には、アプリケーションの.env
ファイル内でPADDLE_SANDBOX
environment 変数をtrue
に設定する必要があります:
PADDLE_SANDBOX=true
あなたが application の開発を終えたら、Paddle vendor アカウントを申請 することができます。あなたの application が production に配置される前に、Paddle はあなたのアプリケーションの domain を承認する必要があります。
Configuration
Billable Model
Cashier を使用する前に、Billable
トレイトを user model の定義に追加する必要があります。このトレイトは、 subscriptions の作成や決済 method 情報の更新など、一般的な課金タスクを実行するための様々なメソッドを提供します。
use Laravel\Paddle\Billable;
class User extends Authenticatable
{
use Billable;
}
もし、 users でない billable というエンティティがある場合、それらのクラスにもトレイトを追加することができます:
use Illuminate\Database\Eloquent\Model;
use Laravel\Paddle\Billable;
class Team extends Model
{
use Billable;
}
API Keys
次に、アプリケーションの.env
ファイルで Paddle の keys を設定する必要があります。 Paddle の API keys は Paddle コントロールパネルから取得できます:
PADDLE_CLIENT_SIDE_TOKEN=your-paddle-client-side-token
PADDLE_API_KEY=your-paddle-api-key
PADDLE_RETAIN_KEY=your-paddle-retain-key
PADDLE_WEBHOOK_SECRET="your-paddle-webhook-secret"
PADDLE_SANDBOX=true
PADDLE_SANDBOX
環境 variable は、Paddle のサンドボックス環境を使用している場合にはtrue
に設定する必要があります。PADDLE_SANDBOX
variable は、あなたの application を production にデプロイし、Paddle のライブベンダー環境を使用している場合にはfalse
に設定する必要があります。
PADDLE_RETAIN_KEY
は任意であり、Paddle をRetain と一緒に使用している場合のみ設定する必要があります。
Paddle JS
Paddle は、Paddle の checkout ウィジェットを開始するために独自の JavaScript library に依存しています。 JavaScript library は、あなたの application レイアウトの閉じタグ </head>
の直前に @paddleJS
Blade ディレクティブを配置することでロードできます。
<head>
...
@paddleJS
</head>
Currency Configuration
請求書の表示用に金額の values をフォーマットする際に、使用する locale を指定することができます。内部的には、 Cashier は通貨の locale を設定するためにPHP の NumberFormatter
class を使用しています。
CASHIER_CURRENCY_LOCALE=nl_BE
WARNING
en
以外のロケールを使用するためには、サーバー上にext-intl
PHP 拡張がインストールされ、設定されていることを確認してください。
Default Models のオーバーライド
あなたは自分の model を定義し、対応する Cashier model を拡張することで、 Cashier が内部的に使用する models を自由に拡張することができます。
use Laravel\Paddle\Subscription as CashierSubscription;
class Subscription extends CashierSubscription
{
// ...
}
あなたの model を定義した後、あなたは Cashier にあなたの custom model を使うように指示することができます。これは、Laravel\Paddle\Cashier
class を通じて行います。通常、アプリケーションのApp\Providers\AppServiceProvider
class のboot
method で、あなたの custom models について Cashier に知らせるべきです。
use App\Models\Cashier\Subscription;
use App\Models\Cashier\Transaction;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Cashier::useSubscriptionModel(Subscription::class);
Cashier::useTransactionModel(Transaction::class);
}
Quickstart
Selling Products
NOTE
Paddle の Checkout を利用する前に、Paddle ダッシュボードで固定価格の製品を定義する必要があります。また、Paddle の webhook 処理を設定するべきです。
あなたの application を通じて商品と subscription の請求を提供することはたくさんの気後れを伴います。しかし、Cashier と、Paddle の CheckoutOverlay のおかげで、現代的で頑丈な支払い統合を簡単に作成することができます。
非反復的な、一度だけの請求商品に対して顧客から料金を請求するために、私たちは Cashier を利用して、Paddle の Checkout オーバーレイで顧客に請求します。そこで彼らは支払い詳細を提供し、購入を確認します。支払いが Checkout オーバーレイを介して行われた後、顧客は、お客様が選択した成功の URL にあなたの application 内でリダイレクトされます:
use Illuminate\Http\Request;
Route::get('/buy', function (Request $request) {
$checkout = $request->user()->checkout('pri_deluxe_album')
->returnTo(route('dashboard'));
return view('buy', ['checkout' => $checkout]);
})->name('checkout');
上記の例で見ることができるように、私たちは Cashier が提供する checkout
method を利用して、指定された"price identifier"に対する Paddle checkout object Overlay を顧客に提示するための Checkout オブジェクト を作成します。Paddle を使用する場合、"prices"は特定の商品のために定義された価格 を指します。
必要に応じて、checkout
method は自動的に Paddle で顧客を作成し、その Paddle 顧客記録をアプリケーションの database 内の対応する user に関連付けます。 checkout session を完了すると、顧客は専用の成功ページにリダイレクトされ、そこで顧客に対する情報メッセージを表示することができます。
buy
view には、 Checkout オーバーレイを表示する button を含めます。 paddle-button
Blade component は Cashier Paddle に含まれていますが、手動で render オーバーレイ checkout:も可能です。
<x-paddle-button :checkout="$checkout" class="px-8 py-4">
Buy Product
</x-paddle-button>
Paddle Checkout に Meta Data を提供する
商品を販売する際、自身が定義した application 内のCart
およびOrder
の models を利用して、完了した注文や購入された商品を追跡するのが一般的です。購入を完了するために顧客を Paddle の Checkout オーバーレイに redirect する際には、完了した購入を対応する注文と関連付けるために、既存の注文識別子を提供する必要があるかもしれません。その後、顧客があなたのアプリケーションに redirect されます。
これを達成するために、checkout
の method に custom data の array を提供することができます。 私たちの application 内で、 user が checkout process を開始するときに保留中のOrder
が作られると想像してみましょう。 この例のCart
とOrder
の models は、単なる説明用であり、 Cashier によって提供されていないことを覚えておいてください。 これらの概念をあなた自身の application のニーズに基づいて実装することは自由です。
use App\Models\Cart;
use App\Models\Order;
use Illuminate\Http\Request;
Route::get('/cart/{cart}/checkout', function (Request $request, Cart $cart) {
$order = Order::create([
'cart_id' => $cart->id,
'price_ids' => $cart->price_ids,
'status' => 'incomplete',
]);
$checkout = $request->user()->checkout($order->price_ids)
->customData(['order_id' => $order->id]);
return view('billing', ['checkout' => $checkout]);
})->name('checkout');
上記の例で見ることができるように、 user が checkout process を開始すると、私たちはカート/注文に関連するすべての Paddle price 識別子をcheckout
method に提供します。もちろん、これらのアイテムを shopping cart または顧客が追加する注文に関連付けるのは、あなたの application の責任です。また、注文の ID を Paddle Checkout オーバーレイにcustomData
method 経由で提供します。
もちろん、顧客が checkout process を完了したら、注文を"完了"とマークしたくなるでしょう。これを達成するために、Paddle によって発行され、 Cashier によって events として引き上げられる webhooks を聞くかもしれません。これにより、注文情報を database に保存することができます。
始めるには、TransactionCompleted
event を Cashier が発行するのをリッスンします。通常、application のAppServiceProvider
のboot
method で event listener を register するべきです:
use App\Listeners\CompleteOrder;
use Illuminate\Support\Facades\Event;
use Laravel\Paddle\Events\TransactionCompleted;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Event::listen(TransactionCompleted::class, CompleteOrder::class);
}
この例では、CompleteOrder
リスナーは次のようになるかもしれません:
namespace App\Listeners;
use App\Models\Order;
use Laravel\Cashier\Cashier;
use Laravel\Cashier\Events\TransactionCompleted;
class CompleteOrder
{
/**
* Handle the incoming Cashier webhook event.
*/
public function handle(TransactionCompleted $event): void
{
$orderId = $event->payload['data']['custom_data']['order_id'] ?? null;
$order = Order::findOrFail($orderId);
$order->update(['status' => 'completed']);
}
}
詳細な情報については、Paddle のドキュメンテーションを参照してください。transaction.completed
event に含まれる data についてです。
Selling Subscriptions
NOTE
Paddle の Checkout を利用する前に、Paddle のダッシュボードで固定価格の製品を定義する必要があります。さらに、Paddle の webhook ハンドリングを設定するべきです。
あなたの application を通じて商品や subscription 課金を提供することは、ちょっと怖いかもしれません。しかし、 Cashier とPaddle の Checkout オーバーレイ のおかげで、簡単に現代的で強固な支払い統合を build することができます。
Cashier と Paddle の Checkout オーバーレイを使用して subscriptions を販売する方法を学ぶために、基本的な月間(price_basic_monthly
)プランと年間(price_basic_yearly
)プランを提供する subscription service のシンプルなシナリオを考えてみましょう。これら 2 つの価格は、Paddle ダッシュボードの"Basic"商品(pro_basic
)の下にグループ化することができます。さらに、私たちの subscription service は、Expert プランもpro_expert
として提供するかもしれません。
まず、お客様が我々の services に subscribe する方法を見つけてみましょう。もちろん、お客様が application の料金ページで Basic プランの subscribe button をクリックする可能性があることを想像することができます。この button は、選択したプランのための Paddle Checkout オーバーレイを呼び出します。始めるためには、 checkout
method により checkout session を開始しましょう:
use Illuminate\Http\Request;
Route::get('/subscribe', function (Request $request) {
$checkout = $request->user()->checkout('price_basic_monthly')
->returnTo(route('dashboard'));
return view('subscribe', ['checkout' => $checkout]);
})->name('subscribe');
subscribe
view には、checkout オーバーレイを表示するための button を含めます。paddle-button
Bladecomponent は Cashier Paddle に含まれていますが、手動で rendering のオーバーレイ checkoutも可能です。
<x-paddle-button :checkout="$checkout" class="px-8 py-4">
Subscribe
</x-paddle-button>
これで、 Subscribe button がクリックされたとき、顧客は自分の支払い詳細を入力し、 subscription を開始できます。彼らの subscription が実際にいつ開始されたか(一部の支払い方法では process に数秒かかることがあるため)を知るためには、Cashier の webhook 処理を設定するべきです。
お客様が subscriptions を開始できるようになったため、 subscribed users だけがアクセスできるように、 application の一部を制限する必要があります。もちろん、Cashier の Billable
trait が提供する method subscribed
を使って、ユーザーの現在の subscription status を常に確認することができます:
@if ($user->subscribed())
<p>You are subscribed.</p>
@endif
特定の製品や価格に user が加入しているかどうかも簡単に判断することができます:
@if ($user->subscribedToProduct('pro_basic'))
<p>You are subscribed to our Basic product.</p>
@endif
@if ($user->subscribedToPrice('price_basic_monthly'))
<p>You are subscribed to our monthly Basic plan.</p>
@endif
Building a Subscribed Middleware
便宜上、入ってくる request が subscribed user からのものかどうかを判断する middlewareを作成することをお勧めします。この middleware が定義されたら、 subscribed でない users が route にアクセスするのを防ぐために簡単にそれを route に割り当てることができます:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class Subscribed
{
/**
* Handle an incoming request.
*/
public function handle(Request $request, Closure $next): Response
{
if (! $request->user()?->subscribed()) {
// Redirect user to billing page and ask them to subscribe...
return redirect('/subscribe');
}
return $next($request);
}
}
middleware が定義されたら、それを route に割り当てることができます:
use App\Http\Middleware\Subscribed;
Route::get('/dashboard', function () {
// ...
})->middleware([Subscribed::class]);
Allowing Customers to Manage Their Billing Plan
もちろん、お客様は subscription プランを他の商品や"tier"に変更したいと思うかもしれません。上記の例では、お客様が月間の subscription を年間の subscription に変更することを可能にしたいと考えています。そのためには、以下の route につながるような button を実装する必要があります:
use Illuminate\Http\Request;
Route::put('/subscription/{price}/swap', function (Request $request, $price) {
$user->subscription()->swap($price); // With "$price" being "price_basic_yearly" for this example.
return redirect()->route('dashboard');
})->name('subscription.swap');
プランの交換だけでなく、顧客が cancel (キャンセル)して subscription (サブスクリプション)を終了することを許可する必要があります。プランを交換するように、次の route (ルート)につながる button (ボタン)を提供してください:
use Illuminate\Http\Request;
Route::put('/subscription/cancel', function (Request $request, $price) {
$user->subscription()->cancel();
return redirect()->route('dashboard');
})->name('subscription.cancel');
そして今、あなたの subscription は、請求期間の終わりにキャンセルされます。
NOTE
あなたが Cashier の webhook の処理を設定していれば、Cashier は自動的に Paddle から来る webhooks を検査することで、application の Cashier 関連の database テーブルを sync に保ちます。例えば、Paddle のダッシュボードから顧客の subscription を cancel すると、Cashier は対応する webhook を受け取り、application の database で subscription を"cancel"とマークします。
Checkout Sessions
ほとんどの顧客請求業務は、Paddle のCheckout Overlay widget を使用するか、またはinline checkout を利用することで実行されます。
Paddle を使用して processing checkout の支払いを処理する前に、アプリケーションのdefault payment link を Paddle の checkout 設定ダッシュボードで定義するべきです。
オーバーレイ Checkout
Checkout オーバーレイウィジェットを表示する前に、 Cashier を使用して checkout session を生成する必要があります。 checkout session は、実行すべき課金操作を checkout ウィジェットに通知します。
use Illuminate\Http\Request;
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
return view('billing', ['checkout' => $checkout]);
});
Cashier はpaddle-button
Blade コンポーネントを含みます。 チェックアウト session をこの component に"prop"として渡すこともできます。その後、この button がクリックされると、Paddle の checkout ウィジェットが表示されます。
<x-paddle-button :checkout="$checkout" class="px-8 py-4">
Subscribe
</x-paddle-button>
default として、これは Paddle の defaultstyle を使用してウィジェットを表示します。ウィジェットは、data-theme='light'
属性などのPaddle がサポートする属性 を component に追加することでカスタマイズできます。
<x-paddle-button :url="$payLink" class="px-8 py-4" data-theme="light">
Subscribe
</x-paddle-button>
Paddle の checkout ウィジェットは非同期です。一度 user がウィジェット内で subscription を作成すると、Paddle はあなたの application に webhook を送り、あなたがアプリケーションの database の subscription state を適切に update できるようにします。そのため、Paddle からの state の変更を適切に受け入れるために、適切にwebhooks の設定をすることが重要です。
WARNING
subscription state の変更後、 webhook を受信するまでの delay は通常最小限ですが、ユーザーの subscription が checkout 完了後すぐに利用できない可能性を考慮し、 application でこれを考慮する必要があります。
オーバーレイ Checkout を手動でレンダリング
また、Laravel の組み込みの Blade コンポーネントを使用せずに、 checkout のオーバーレイを手動で render することも可能です。始めるためには、前の例で示したように checkout session を生成してください。
use Illuminate\Http\Request;
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
return view('billing', ['checkout' => $checkout]);
});
次に、Paddle.js を使用して checkout を初期化することができます。この例では、paddle_button
class を割り当てられたリンクを作成します。Paddle.js はこの class を検出し、リンクがクリックされたときにオーバーレイの checkout を表示します:
<?php
$items = $checkout->getItems();
$customer = $checkout->getCustomer();
$custom = $checkout->getCustomData();
?>
<a
href='#!'
class='paddle_button'
data-items='{!! json_encode($items) !!}'
@if ($customer) data-customer-id='{{ $customer->paddle_id }}' @endif
@if ($custom) data-custom-data='{{ json_encode($custom) }}' @endif
@if ($returnUrl = $checkout->getReturnUrl()) data-success-url='{{ $returnUrl }}' @endif
>
Buy Product
</a>
インライン Checkout
Paddle の"overlay"スタイルの checkout ウィジェットを使用したくない場合、Paddle はウィジェットをインラインで表示するオプションも提供しています。このアプローチでは、チェックアウトの HTML フィールドを調整することはできませんが、ウィジェットをあなたの application 内に埋め込むことができます。
あなたがインライン checkout をすぐに始められるように、 Cashier は paddle-checkout
Blade component が含まれています。始めるためには、まずcheckout session を生成する必要があります:
use Illuminate\Http\Request;
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
return view('billing', ['checkout' => $checkout]);
});
次に、 checkout session をコンポーネントのcheckout
attribute に渡すことができます:
<x-paddle-checkout :checkout="$checkout" class="w-full" />
inline checkout component の高さを調整するには、 height
attribute を Blade component に渡すことができます:
<x-paddle-checkout :checkout="$checkout" class="w-full" height="500" />
Paddle のインライン Checkout に関するガイド と利用可能な checkout 設定 をご参照ください。これらは、インラインチェックアウトのカスタマイズ options に関する詳細情報を提供しています。
手動でインラインの Checkout をレンダリングする
また、Laravel の組み込みの Blade コンポーネントを使用せずに、手動で render したインラインの checkout を表示することもできます。始めるには、前の例で示したように、 checkout session を生成してください。
use Illuminate\Http\Request;
Route::get('/buy', function (Request $request) {
$checkout = $user->checkout('pri_34567')
->returnTo(route('dashboard'));
return view('billing', ['checkout' => $checkout]);
});
次に、Paddle.js を使用して checkout を初期化することができます。この例では、Alpine.js を使用してこれをデモンストレーションしますが、自身のフロントエンド stack にこの例を自由に変更しても構いません:
<?php
$options = $checkout->options();
$options['settings']['frameTarget'] = 'paddle-checkout';
$options['settings']['frameInitialHeight'] = 366;
?>
<div class="paddle-checkout" x-data="{}" x-init="
Paddle.Checkout.open(@json($options));
">
</div>
Guest Checkouts
時折、あなたの application にアカウントが不要な users のために、 checkout session を作成する必要があるかもしれません。その際、guest
method を使用することができます:
use Illuminate\Http\Request;
use Laravel\Paddle\Checkout;
Route::get('/buy', function (Request $request) {
$checkout = Checkout::guest('pri_34567')
->returnTo(route('home'));
return view('billing', ['checkout' => $checkout]);
});
次に、Paddle buttonまたはinline checkoutの Blade コンポーネントに checkout session を提供することができます。
Price Previews
Paddle では、通貨ごとに価格をカスタマイズできます。つまり、各国ごとに異なる価格を設定することができます。 Cashier Paddle では、これらすべての価格をpreviewPrices
method を使用して取得できます。この method では、価格を取得したい price ID を受け付けます:
use Laravel\Paddle\Cashier;
$prices = Cashier::previewPrices(['pri_123', 'pri_456']);
通貨はリクエストの IP アドレスに基づいて決定されますが、特定の国の価格を取得するために、オプションで国を指定することも可能です。
use Laravel\Paddle\Cashier;
$prices = Cashier::previewPrices(['pri_123', 'pri_456'], ['address' => [
'country_code' => 'BE',
'postal_code' => '1234',
]]);
価格を取得した後、あなたの希望する方法でそれらを表示することができます:
<ul>
@foreach ($prices as $price)
<li>{{ $price->product['name'] }} - {{ $price->total() }}</li>
@endforeach
</ul>
あなたはまた、小計の price と税金額を別々に表示することもできます:
<ul>
@foreach ($prices as $price)
<li>{{ $price->product['name'] }} - {{ $price->subtotal() }} (+ {{ $price->tax() }} tax)</li>
@endforeach
</ul>
詳細については、Paddle の API ドキュメンテーションで price プレビューを checkout してください。
顧客 Price プレビュー
もし user がすでに顧客であり、その顧客に適用される価格を表示したい場合は、顧客インスタンスから直接価格を取得することで表示することができます:
use App\Models\User;
$prices = User::find(1)->previewPrices(['pri_123', 'pri_456']);
内部的に、Cashier は user の顧客 ID を使用して、彼らの通貨で価格を取得します。例えば、アメリカに住む user は米ドルで価格を見ることになり、ベルギーに住む user はユーロで価格を見ることになります。一致する通貨が見つからない場合、商品の default の通貨が使用されます。Paddle コントロールパネルで製品や subscription プランのすべての価格をカスタマイズすることができます。
Discounts
また、割引後の価格を表示することも選択できます。previewPrices
の method を呼び出すときには、discount_id
オプションを通じて割引 ID を提供します:
use Laravel\Paddle\Cashier;
$prices = Cashier::previewPrices(['pri_123', 'pri_456'], [
'discount_id' => 'dsc_123'
]);
次に、計算された価格を表示します:
<ul>
@foreach ($prices as $price)
<li>{{ $price->product['name'] }} - {{ $price->total() }}</li>
@endforeach
</ul>
Customers
お客様の Defaults
Cashier は、 checkout セッションを作成する際に、お客様にとって役立つ defaults を定義することを可能にします。これらの defaults を設定することで、お客様の email アドレスや名前を事前に入力することで、お客様はすぐに checkout ウィジェットの支払い部分に進むことができます。 billable model 上の次のメソッドをオーバーライドすることで、これらの defaults を設定することができます:
/**
* Get the customer's name to associate with Paddle.
*/
public function paddleName(): string|null
{
return $this->name;
}
/**
* Get the customer's email address to associate with Paddle.
*/
public function paddleEmail(): string|null
{
return $this->email;
}
これらの defaults は、 Cashier 内で checkout session を生成するすべての action に使用されます。
Retrieving Customers
顧客は、Cashier::findBillable
の method を使用して、Paddle Customer ID によって取り出すことができます。この method は、請求可能 model のインスタンスを返します:
use Laravel\Cashier\Cashier;
$user = Cashier::findBillable($customerId);
Creating Customers
たまに、 subscription を開始せずに Paddle の顧客を作成したいと思うかもしれません。これは、createAsCustomer
method を使用して実現できます。
$customer = $user->createAsCustomer();
Laravel\Paddle\Customer
のインスタンスが返されます。Paddle で顧客が作成されたら、後日 subscription を始めることができます。任意の$options
アレイを提供して、追加の顧客作成パラメーターを PaddleAPI に渡すことができます。
$customer = $user->createAsCustomer($options);
Subscriptions
Creating Subscriptions
subscription を作成するには、まず database から billable model のインスタンスを取得します。これは通常、App\Models\User
のインスタンスになります。 model インスタンスを retrieved したら、そのモデルの checkout session を作成するためにsubscribe
method を使用できます。
use Illuminate\Http\Request;
Route::get('/user/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe($premium = 12345, 'default')
->returnTo(route('home'));
return view('billing', ['checkout' => $checkout]);
});
subscribe
method に渡される最初の引数は、 user が購読する特定の price です。この value は、 Paddle の価格の識別子に対応しているべきです。returnTo
method は、 user が checkout を正常に完了した後に redirect される URL を受け入れます。subscribe
method に渡される二つ目の引数は、 subscription の内部"type"であるべきです。あなたの application が single subscription のみを提供している場合、これを default
または primary
と呼ぶことができます。この subscription type は、内部の application 使用のためだけで、 users に表示することを意図していません。また、スペースを含んではならず、 subscription を作成した後にこれを変更することは決してありません。
また、customData
の method を使用して、subscription に関する custommetadata の array を提供することもできます。
$checkout = $request->user()->subscribe($premium = 12345, 'default')
->customData(['key' => 'value'])
->returnTo(route('home'));
一度 subscription checkout session が作成されると、その checkout session は、 Cashier Paddle に含まれるpaddle-button
Blade componentに提供できます。
<x-paddle-button :checkout="$checkout" class="px-8 py-4">
Subscribe
</x-paddle-button>
user が checkout を終えた後、Paddle からsubscription_created
webhooks が発行されます。 Cashier はこの webhook を受け取り、お客様のための subscription を設定します。すべての webhook があなたの application に適切に受け取られ、取り扱われることを確認するために、正しく webhook の処理を設定 していることを確認してください。
Checking Subscription Status
一度 user があなたの application に subscribed すると、その subscription status を確認するためのさまざまな便利な方法を使用することができます。まず、 subscribed
method は、 user が有効な subscription を持っている場合、たとえその subscription が現在試用期間内であっても true
を返します。
if ($user->subscribed()) {
// ...
}
あなたの application が複数の subscriptions を提供している場合、subscribed
method を呼び出すときに subscription を指定することができます:
if ($user->subscribed('default')) {
// ...
}
subscribed
の method は、ユーザーの subscription status に基づいて routes とコントローラへのアクセスをフィルタリングするためのroute middlewareとしても大いに有用です:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureUserIsSubscribed
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
if ($request->user() && ! $request->user()->subscribed()) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
}
もし user がまだ試用期間内にいるかどうかを判断したい場合、onTrial
method を使用することができます。この method は、試用期間中であることを user に警告を表示すべきかどうかを判断するのに役立つことがあります:
if ($user->subscription()->onTrial()) {
// ...
}
subscribedToPrice
method は、与えられた Paddle price ID に基づいて、 user が特定のプランに subscribed しているかどうかを判断するために使用することができます。この例では、ユーザーのdefault
subscription が月額 price に積極的に subscribed しているかどうかを判断します。
if ($user->subscribedToPrice($monthly = 'pri_123', 'default')) {
// ...
}
recurring
method は、 user が現在アクティブな subscription に存在し、試用期間や猶予期間が終了しているかどうかを判断するために使用することができます:
if ($user->subscription()->recurring()) {
// ...
}
Canceled Subscription Status
user がかつて活動的な加入者であり、それが subscription をキャンセルしたかどうかを判断するには、canceled
method を使用することができます:
if ($user->subscription()->canceled()) {
// ...
}
また、 user が subscription を解約したが、まだ grace period にあるかどうかを決定することもできます。 subscription が完全に満了するまでの間です。例えば、 user が 3 月 5 日に subscription をキャンセルし、それが元々 3 月 10 日に満了する予定だった場合、 user は 3 月 10 日まで grace period になります。さらに、この期間中でもsubscribed
method はtrue
を返し続けます。
if ($user->subscription()->onGracePeriod()) {
// ...
}
期限切れの Status
subscription の支払いが失敗した場合、それはpast_due
とマークされます。あなたの subscription がこの state にあるときは、顧客が支払い情報を更新するまでアクティブになりません。 subscription が過去に到着したかどうかを判断するには、 subscription のインスタンス上のpastDue
method を使用できます
if ($user->subscription()->pastDue()) {
// ...
}
subscription が未払いになった場合、 user にupdate するよう指示するべきです。
past_due
の状態であっても subscriptions を有効とみなしたい場合は、keepPastDueSubscriptionsActive
という Cashier が提供する method を使用することができます。通常、この method はAppServiceProvider
のregister
method で呼び出されるべきです。
use Laravel\Paddle\Cashier;
/**
* Register any application services.
*/
public function register(): void
{
Cashier::keepPastDueSubscriptionsActive();
}
WARNING
subscription が
past_due
の state にある場合、支払い情報が更新されるまで変更することはできません。そのため、swap
およびupdateQuantity
のメソッドは、 subscription がpast_due
の state にある場合に例外を throw します。
Subscription Scopes
ほとんどの subscription 状態は、指定した state にある subscriptions をあなたの database から簡単に query できるように、 query スコープとしても利用できます:
// Get all valid subscriptions...
$subscriptions = Subscription::query()->valid()->get();
// Get all of the canceled subscriptions for a user...
$subscriptions = $user->subscriptions()->canceled()->get();
利用可能なスコープの完全なリストは以下にあります:
Subscription::query()->valid();
Subscription::query()->onTrial();
Subscription::query()->expiredTrial();
Subscription::query()->notOnTrial();
Subscription::query()->active();
Subscription::query()->recurring();
Subscription::query()->pastDue();
Subscription::query()->paused();
Subscription::query()->notPaused();
Subscription::query()->onPausedGracePeriod();
Subscription::query()->notOnPausedGracePeriod();
Subscription::query()->canceled();
Subscription::query()->notCanceled();
Subscription::query()->onGracePeriod();
Subscription::query()->notOnGracePeriod();
Subscription Single の料金
Subscription single 料金は、購読者に対してその subscriptions の上に一回限りの料金を請求することを可能にします。あなたはcharge
method を呼び出すときに一つまたは複数の price ID を提供する必要があります:
// Charge a single price...
$response = $user->subscription()->charge('pri_123');
// Charge multiple prices at once...
$response = $user->subscription()->charge(['pri_123', 'pri_456']);
charge
method は、顧客の subscription の次の請求期間まで実際には請求しません。もしすぐに顧客に請求したい場合は、代わりにchargeAndInvoice
method を使用することができます。
$response = $user->subscription()->chargeAndInvoice('pri_123');
支払情報の更新
Paddle は常に subscription ごとに支払いの method を保存します。 subscription の default の支払い method を update したい場合は、redirectToUpdatePaymentMethod
method を使用して、お客様を Paddle のホストされた支払い method update ページに redirect する必要があります。
use Illuminate\Http\Request;
Route::get('/update-payment-method', function (Request $request) {
$user = $request->user();
return $user->subscription()->redirectToUpdatePaymentMethod();
});
user が情報の更新を終えたとき、Paddle によりsubscription_updated
の webhook が発行され、ご利用の application の database に subscription の詳細が更新されます。
プランの変更
user があなたの application に登録した後、彼らは時折新しい subscription プランに変更したいと思うかもしれません。 user の subscription プランを更新するには、Paddle 価格の識別子を subscription のswap
method に渡すべきです。
use App\Models\User;
$user = User::find(1);
$user->subscription()->swap($premium = 'pri_456');
もし、次の請求サイクルを待つ代わりに、 user にすぐに請求書を送り、 swap プランを切り替えたい場合は、swapAndInvoice
method を使用することができます。
$user = User::find(1);
$user->subscription()->swapAndInvoice($premium = 'pri_456');
Prorations
default では、Paddle はプラン間で変更する際に料金を按分します。 noProrate
method は、料金を按分せずに subscriptions を更新するために使用することができます:
$user->subscription('default')->noProrate()->swap($premium = 'pri_456');
精算を無効にし、顧客にすぐに請求したい場合は、swapAndInvoice
method をnoProrate
と組み合わせて使用することができます:
$user->subscription('default')->noProrate()->swapAndInvoice($premium = 'pri_456');
または、顧客に subscription の変更を請求しないために、doNotBill
method を利用することもできます:
$user->subscription('default')->doNotBill()->swap($premium = 'pri_456');
Paddle の精算 policies に関する詳細については、Paddle の精算ドキュメント をご覧ください。
Subscription Quantity
時には subscriptions は quantity に影響を受けます。例えば、project 管理 application は、project ごとに月額$10 を請求するかもしれません。あなたの subscriptions の quantity を簡単に increment またはデクリメントするには、 incrementQuantity
とdecrementQuantity
の method を使用します。
$user = User::find(1);
$user->subscription()->incrementQuantity();
// Add five to the subscription's current quantity...
$user->subscription()->incrementQuantity(5);
$user->subscription()->decrementQuantity();
// Subtract five from the subscription's current quantity...
$user->subscription()->decrementQuantity(5);
別の方法として、updateQuantity
method を使用して特定の quantity を設定することもできます:
$user->subscription()->updateQuantity(10);
noProrate
method は、料金の按分をせずに subscription の数量を更新するために使用できます:
$user->subscription()->noProrate()->updateQuantity(10);
Quantities for Subscriptions With Multiple Products
あなたの subscription が複数の製品の subscriptionである場合、increment または decrement したい price の ID を increment/ decrement methods の第二引数として渡すべきです:
$user->subscription()->incrementQuantity(1, 'price_chat');
Subscriptions With Multiple Products
Subscription with multiple products は、複数の課金製品を単一の Subscription に割り当てることができます。たとえば、月額 10 ドルの基本 Subscription 価格を設定し、さらに毎月 15 ドルのライブチャットの追加製品を提供する顧客 service ヘルプデスク application を構築することを想像してみてください。
subscribe
method の第一引数として array の価格を渡すことにより、特定の subscription に対して複数の製品を指定することができます:
use Illuminate\Http\Request;
Route::post('/user/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe([
'price_monthly',
'price_chat',
]);
return view('billing', ['checkout' => $checkout]);
});
上記の例では、顧客はdefault
subscription に 2 つの価格が付けられます。両方の価格はそれぞれの課金間隔で請求されます。必要に応じて、特定の quantity を示すためのキー/ value ペアの連想 array を渡すことができます。各 price について:
$user = User::find(1);
$checkout = $user->subscribe('default', ['price_monthly', 'price_chat' => 5]);
既存の subscription に別の price を追加したい場合は、その subscription のswap
method を使用する必要があります。swap
method を呼び出すときには、subscription の現在の価格と数量も含めるべきです:
$user = User::find(1);
$user->subscription()->swap(['price_chat', 'price_original' => 2]);
上記の例では、新しい price を追加しますが、顧客がそれに対して請求されるのは次の請求サイクルになります。顧客にすぐに請求したい場合は、swapAndInvoice
method を使用することができます。
$user->subscription()->swapAndInvoice(['price_chat', 'price_original' => 2]);
あなたは、swap
の method を使用して、削除したい price を省略することで、 subscriptions から価格を削除することができます:
$user->subscription()->swap(['price_original' => 2]);
WARNING
subscription の最後の price を削除することはできません。代わりに、単に subscription を cancel すべきです。
Multiple Subscriptions
Paddle は、お客様が複数の subscriptions を同時に持つことを可能にします。例えば、あなたがスイミングの subscription とウェイトリフティングの subscription を提供するジムを運営している場合、各 subscription には異なる価格設定があるかもしれません。もちろん、お客様はいずれかまたは両方のプランに subscribe することができるべきです。
あなたの application が subscriptions を作成するとき、 subscription の type を二つ目の引数としてsubscribe
method に提供することができます。 type は、 user が開始している subscription の type を表す任意の string にすることができます。
use Illuminate\Http\Request;
Route::post('/swimming/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe($swimmingMonthly = 'pri_123', 'swimming');
return view('billing', ['checkout' => $checkout]);
});
この例では、顧客に対して月額の subscription を開始しました。しかし、彼らは後で年間の subscription に swap することを希望するかもしれません。顧客の subscription を調整する際には、単にswimming
の subscription の price を swap するだけで済みます。
$user->subscription('swimming')->swap($swimmingYearly = 'pri_456');
Of course, you may also cancel the subscription entirely:
$user->subscription('swimming')->cancel();
Subscriptions の一時停止
ユーザーの subscription を一時停止するには、ユーザーの subscription に対してpause
method を呼び出します。
$user->subscription()->pause();
subscription が一時停止されると、 Cashier は自動的にあなたの database 内のpaused_at
の column を設定します。この column は、paused
の method がいつからtrue
を返し始めるべきかを判断するために使用されます。例えば、顧客が 3 月 1 日に subscription を一時停止し、しかし、その subscription が 3 月 5 日まで再発する予定がなかった場合、paused
の method は 3 月 5 日までfalse
を返し続けます。これは、 user が通常、課金サイクルの終了まで application を使い続けることが許されているためです。
default では、顧客が支払った期間の残りを使用できるように、次の請求間隔で一時停止が発生します。すぐに subscription を一時停止したい場合は、pauseNow
method を使用することができます:
$user->subscription()->pauseNow();
pauseUntil
method を使用すると、特定の時間まで subscription を一時停止することができます:
$user->subscription()->pauseUntil(now()->addMonth());
または、pauseNowUntil
method を使用して、指定された時点まで直ちに subscription を一時停止することもできます:
$user->subscription()->pauseNowUntil(now()->addMonth());
onPausedGracePeriod
method を使用して、 user が subscription を一時停止し、しかしまだ猶予期間中であるかどうかを判断することができます。
if ($user->subscription()->onPausedGracePeriod()) {
// ...
}
停止中の subscription を再開するには、 subscription 上でresume
method を呼び出すことができます:
$user->subscription()->resume();
WARNING
subscription は一時停止中に変更することはできません。別のプランに swap したり、数量を update したい場合は、まず subscription を再開する必要があります。
Subscriptions のキャンセル
ユーザーの subscription に対してcancel
method を呼び出して、 subscription を cancel します。
$user->subscription()->cancel();
subscription がキャンセルされると、 Cashier は自動的にあなたの database の ends_at
column を設定します。この column は、subscribed
method がfalse
を返すべきタイミングを決定するために使用されます。例えば、3 月 1 日に顧客が subscription をキャンセルしたが、その subscription が 3 月 5 日まで終了しない予定だった場合、subscribed
method は 3 月 5 日まで続けてtrue
を返します。これは、 user が通常、課金サイクルの終わりまで application を続けて使用できるからです。
onGracePeriod
method を使用して、 user が subscription を cancel したが、まだ "grace period" にいるかどうかを判断することができます。
if ($user->subscription()->onGracePeriod()) {
// ...
}
すぐに subscription を cancel したい場合は、 subscription の上でcancelNow
method を呼び出すことができます。
$user->subscription()->cancelNow();
その猶予期間中の subscription をキャンセルから停止するには、stopCancelation
method を呼び出すことができます。
$user->subscription()->stopCancelation();
WARNING
Paddle の subscriptions は、キャンセル後に再開することはできません。お客様が subscription を再開したい場合は、新たに subscription を作成する必要があります。
Subscription Trials
With Payment Method Up Front
お客様にトライアル期間を提供しながら、前もって method 情報を集めることを希望する場合は、お客様が登録している price の Paddle ダッシュボードでトライアル時間を設定する必要があります。その後、通常通り checkout session を開始してください:
use Illuminate\Http\Request;
Route::get('/user/subscribe', function (Request $request) {
$checkout = $request->user()->subscribe('pri_monthly')
->returnTo(route('home'));
return view('billing', ['checkout' => $checkout]);
});
あなたの application が subscription_created
event を受信したときに、 Cashier はお使いのアプリケーションの database の subscription レコード上の試用期間終了日を設定します。また、この日付まで顧客に請求を始めないように Paddle に指示します。
WARNING
お客様が subscription を試用期間終了日前にキャンセルしない場合、試用期間が終了するとすぐに課金されます。そのため、 users に試用期間終了日を通知するようにしましょう。
user がトライアル期間内かどうかを判断するには、user インスタンスのonTrial
method または subscription インスタンスのonTrial
method のいずれかを使用できます。以下の二つの例は同等です:
if ($user->onTrial()) {
// ...
}
if ($user->subscription()->onTrial()) {
// ...
}
既存の試用期間が終了したかどうかを判断するためには、hasExpiredTrial
メソッドを使用することができます:
if ($user->hasExpiredTrial()) {
// ...
}
if ($user->subscription()->hasExpiredTrial()) {
// ...
}
特定の subscription type に対して user が試用中かどうかを判断するためには、 type を onTrial
または hasExpiredTrial
メソッドに指定することができます。
if ($user->onTrial('default')) {
// ...
}
if ($user->hasExpiredTrial('default')) {
// ...
}
Without Payment Method Up Front
ユーザーの支払い method 情報を前もって収集せずに試用期間を提供したい場合は、お客様の記録に付随するあなたの user のtrial_ends_at
column を希望の試用終了日に設定することができます。これは通常、 user の登録時に行われます:
use App\Models\User;
$user = User::create([
// ...
]);
$user->createAsCustomer([
'trial_ends_at' => now()->addDays(10)
]);
Cashier は、既存の subscription に関連付けられていないため、一般的な試用期間と呼んでいます。User
インスタンス上のonTrial
method は、現在の日付がtrial_ends_at
の value を過ぎていない場合、true
を返します。
if ($user->onTrial()) {
// User is within their trial period...
}
あなたが実際に user のための subscription を作成する準備ができたら、通常通りsubscribe
method を使用することができます:
use Illuminate\Http\Request;
Route::get('/user/subscribe', function (Request $request) {
$checkout = $user->subscribe('pri_monthly')
->returnTo(route('home'));
return view('billing', ['checkout' => $checkout]);
});
ユーザーの試用期間終了日を取得するには、trialEndsAt
method を使用できます。この method は、 user が試用期間中である場合は Carbon 日付インスタンスを返し、そうでない場合はnull
を返します。また、特定の subscription の試用期間終了日を取得したい場合は、オプションで subscription type パラメータを指定することもできます。これは default のもの以外である場合に便利です:
if ($user->onTrial('default')) {
$trialEndsAt = $user->trialEndsAt();
}
onGenericTrial
の method が使用可能です。これは、特に user が"generic"のトライアル期間内であり、まだ実際の subscription を作成していないかどうかを知りたい場合に利用できます:
if ($user->onGenericTrial()) {
// User is within their "generic" trial period...
}
トライアルを延長または有効化する
既存の試用期間を延長するには、extendTrial
method を呼び出し、試用期間が終了すべき時間を指定して subscription を延長できます:
$user->subscription()->extendTrial(now()->addDays(5));
または、activate
method を subscription に呼び出すことにより、その試用期間を終了させてすぐに subscription をアクティブにすることもできます。
$user->subscription()->activate();
Handling Paddle Webhooks
Paddle は、webhooks を介して、さまざまな events をあなたの application に通知できます。default では、Cashier の webhook controller に指す route が Cashier.service provider によって登録されます。この controller は、すべての入ってくる webhookrequest を handle します。
default では、この controller は自動的に失敗した請求が多すぎる subscriptions のキャンセル、 subscription の更新、および支払い method の変更を handle します。しかし、すぐにわかるように、好きな Paddle webhook event を handle するために、この controller を拡張することができます。
あなたの application が Paddle の webhooks を handle できるようにするためには、Paddle の制御パネルで webhook URL を設定する ことを必ず確認してください。 default では、Cashier の webhook controller は /paddle/webhook
URL path に対応しています。Paddle の制御パネルで有効にするべき全ての webhooks のリストは次の通りです:
- お客様情報更新済み
- Transaction 完了しました
- Transaction 更新済み
- Subscription が作成されました
- Subscription 更新されました
- Subscription 一時停止中
- Subscription キャンセルされました
WARNING
Cashier に含まれるwebhook signature の確認 middleware を使用して、着信リクエストを保護することを確認してください。
Webhooks and CSRF Protection
Paddle の webhooks は webhooks のCSRF protectionを回避する必要があるため、 Laravel が CSRF の token を確認しようと attempt しないようにするべきです。これを達成するためには、アプリケーションのbootstrap/app.php
ファイルでpaddle/*
を CSRF protection から除外すべきです:
->withMiddleware(function (Middleware $middleware) {
$middleware->validateCsrfTokens(except: [
'paddle/*',
]);
})
Webhooks とローカル開発
Paddle がローカル開発中にあなたの application webhooks を送信できるようにするためには、Ngrok や Expose などのサイト共有の service を介してあなたの application を公開する必要があります。もし、Laravel Sailを使ってローカルで application を開発しているのであれば、Sail のサイト共有 commandを使うことができます。
Defining Webhook Event Handlers
Cashier は、課金失敗やその他の一般的な Paddle の webhooks に対する subscription のキャンセルを自動的に処理します。しかし、追加の webhook events を handle したい場合は、 Cashier から発行される次の events を購読することで行うことができます。
Laravel\Paddle\Events\WebhookReceived
Laravel\Paddle\Events\WebhookHandled
両方の events は Paddle の webhook のフルペイロードを含んでいます。例えば、もしあなたがtransaction.billed
の webhook を handle したい場合、 event を handle するlistenerを register することができます。
<?php
namespace App\Listeners;
use Laravel\Paddle\Events\WebhookReceived;
class PaddleEventListener
{
/**
* Handle received Paddle webhooks.
*/
public function handle(WebhookReceived $event): void
{
if ($event->payload['event_type'] === 'transaction.billed') {
// Handle the incoming event...
}
}
}
Cashier は、受け取った webhook の type に専用の events も発行します。Paddle からの完全なペイロードに加えて、 billable model 、 subscription 、またはレシートなど、 webhook を process するのに使用された関連 models も含まれています。
Laravel\Paddle\Events\CustomerUpdated
Laravel\Paddle\Events\TransactionCompleted
Laravel\Paddle\Events\TransactionUpdated
Laravel\Paddle\Events\SubscriptionCreated
Laravel\Paddle\Events\SubscriptionUpdated
Laravel\Paddle\Events\SubscriptionPaused
Laravel\Paddle\Events\SubscriptionCanceled
あなたはまた、application の.env
ファイルでCASHIER_WEBHOOK
を定義することで、default で組み込まれている webhook route を上書きすることもできます。この value は webhook route への完全な URL であるべきで、Paddle のコントロールパネルで設定された URL と match する必要があります:
CASHIER_WEBHOOK=https://example.com/my-paddle-webhook-url
Verifying Webhook Signatures
あなたの webhooks を保護するために、Paddle の webhook 署名 を使用することができます。便利なことに、 Cashier は自動的に、受信した Paddle の webhook request が有効であることを検証する middleware を含めます。
webhook の検証を有効にするには、PADDLE_WEBHOOK_SECRET
environment variables が application の.env
ファイルに定義されていることを確認してください。 webhook secret は、あなたの Paddle アカウントダッシュボードから取得することができます。
Single Charges
製品の課金
お客様のために製品の購入を開始したい場合、 checkout
の method を billable model のインスタンスで使用して、購入のための checkout session を生成できます。 checkout
の method は 1 つまたは複数の価格 ID を受け付けます。必要に応じて、関連する array が使用され、購入される製品の数量を提供することができます:
use Illuminate\Http\Request;
Route::get('/buy', function (Request $request) {
$checkout = $request->user()->checkout(['pri_tshirt', 'pri_socks' => 5]);
return view('buy', ['checkout' => $checkout]);
});
checkout session を生成した後、Cashier が提供するpaddle-button
Blade componentを使用して、 user が Paddle checkout ウィジェットを view し、購入を完了することを許可できます:
<x-paddle-button :checkout="$checkout" class="px-8 py-4">
Buy
</x-paddle-button>
checkout session には、customData
method があり、希望する custom data を基礎となる transaction の作成に渡すことができます。 custom data を渡す際の利用可能な options については、Paddle のドキュメンテーション をご覧ください。
$checkout = $user->checkout('pri_tshirt')
->customData([
'custom_option' => $value,
]);
Transactions の返金
transactions を返金すると、購入時に使用されたお客様の支払い method に返金額が戻ります。 Paddle の購入を返金する必要がある場合は、Cashier\Paddle\Transaction
model 上のrefund
method を使用することができます。 この method は、最初の引数として理由を受け付け、一つまたは複数の price ID を、任意の金額とともに関連 array として返金することができます。 特定の billable model の transactions をtransactions
method を使用して取得することができます。
例えば、特定の transaction で、pri_123
とpri_456
の価格を払い戻したいと想像してみてください。pri_123
は全額払い戻しをしたいのですが、pri_456
については 2 ドルだけ払い戻したいと考えています。
use App\Models\User;
$user = User::find(1);
$transaction = $user->transactions()->first();
$response = $transaction->refund('Accidental charge', [
'pri_123', // Fully refund this price...
'pri_456' => 200, // Only partially refund this price...
]);
上記の例では、 transaction 内の特定の明細を払い戻します。もし全体の transaction を払い戻したい場合は、理由を簡単に提供してください:
$response = $transaction->refund('Accidental charge');
返金に関する詳しい情報は、Paddle の返金ドキュメンテーション をご覧ください。
WARNING
返金は常に完全に processing する前に Paddle によって承認される必要があります。
Transactions のクレジット
返金と同様に、transactions もクレジットできます。transactions をクレジットすると、資金は顧客の balance に追加され、将来の購入に使用できます。ただし、手動で集めた transactions のみをクレジットでき、自動的に収集された transactions(subscriptions など)はクレジットできません。これは Paddle が subscription のクレジットを自動的に処理するためです。
$transaction = $user->transactions()->first();
// Credit a specific line item fully...
$response = $transaction->credit('Compensation', 'pri_123');
詳細な info については、Paddle のクレジットに関するドキュメンテーションを参照してください 。
WARNING
クレジットは、手動で収集された transactions にのみ適用できます。自動的に収集された transactions は、Paddle 自体がクレジットを付与します。
Transactions
transactions
プロパティを通じて、 billable モデルの transactions という array を容易に取得できます:
use App\Models\User;
$user = User::find(1);
$transactions = $user->transactions;
Transactions は商品や購入品に対する支払いを示し、請求書が添付されます。完了した transactions のみがあなたのアプリケーションの database に保存されます。
顧客の transactions をリスト表示する際には、 transaction インスタンスのメソッドを使用して関連する支払い情報を表示することができます。例えば、すべての transaction をテーブルにリスト表示し、 user が請求書を簡単に download できるようにするかもしれません:
<table>
@foreach ($transactions as $transaction)
<tr>
<td>{{ $transaction->billed_at->toFormattedDateString() }}</td>
<td>{{ $transaction->total() }}</td>
<td>{{ $transaction->tax() }}</td>
<td>
<a
href="{{ route('download-invoice', $transaction->id) }}"
target="_blank"
>Download</a
>
</td>
</tr>
@endforeach
</table>
download-invoice
route は次のようになるかもしれません:
use Illuminate\Http\Request;
use Laravel\Cashier\Transaction;
Route::get('/download-invoice/{transaction}', function (Request $request, Transaction $transaction) {
return $transaction->redirectToInvoicePdf();
})->name('download-invoice');
過去と今後の支払い
顧客の過去のまたは即時の定期的な subscriptions の支払いを取得して表示するために、lastPayment
およびnextPayment
のメソッドを使用することができます。
use App\Models\User;
$user = User::find(1);
$subscription = $user->subscription();
$lastPayment = $subscription->lastPayment();
$nextPayment = $subscription->nextPayment();
これらの両方の方法は、Laravel\Paddle\Payment
のインスタンスを返します。しかし、lastPayment
は transactions がまだ webhooks によって同期されていないときにnull
を返し、一方nextPayment
は課金サイクルが終了したとき( subscription がキャンセルされたときなど)にnull
を返します。
Next payment: {{ $nextPayment->amount() }} due on {{ $nextPayment->date()->format('d/m/Y') }}
Testing
testing の間に、手動で請求フローをテストし、あなたのインテグレーションが期待通りに動作していることを確認すべきです。
自動化テストには、CI environment 内で実行されるものを含めて、Laravel の HTTP Clientを使用して、Paddle への fake HTTP コールを行うことができます。これにより、Paddle からの実際のレスポンスをテストしないで済ます一方で、Paddle の API を実際に呼び出すことなく application をテストする方法が提供されます。