edo1z blog

プログラミングなどに関するブログです

Stripeのサブスクリプション

課金の有効性チェック

Stripeでサブスクリプション使うときに、支払いが有効で、現在サービス利用可能かというのを判断するときのやり方が書いてあった。

stripe.com

  • 最初の支払いが成功したら、current_period_endに、有効期日を保存。月額課金だったら、課金日+1ヶ月(+α)を保存しておく。
  • ログイン時は、毎回current_period_endをチェックして、有効期日が過ぎていなければ、サービス利用可能とする。
  • 定期的な支払いは、Webhookで、invoice.payment_succeededイベントを受け取る。これを受け取ったら、current_period_endを更新する。

無料お試し期間

商品の料金プランに「トライアル期間」というのが設定できるようになっているので、これを設定するだけなんだけど、サブスクリプション作成時に trial_from_plan: true を入れないと、無料お試し期間が設定されていても、サブスクリプション作成時に即決済されてしまうみたい。

return await stripe.subscriptions.create({
  customer: customer.id,
  tax_percent: 0,
  trial_from_plan: true,
  items: [{plan: stripeConfig.normalPlan}]
})

サブスクリプションのテスト

stripe.com

テスト用カード等

stripe.com

Webhook

Webhookのローカルテスト

ローカルでWebhookの動作テストを行う場合は、下記等を使ってねと書いてある

ngrok.com

Webhookの署名検証

stripe.com

下記のように公式ライブラリを使ってできる。(PHPの場合)

<?php
\Stripe\Stripe::setApiKey("sk_test_******");
$endpoint_secret = 'whsec_...';

$payload = @file_get_contents('php://input');
$sig_header = $_SERVER['HTTP_STRIPE_SIGNATURE'];
$event = null;

try {
    $event = \Stripe\Webhook::constructEvent(
        $payload, $sig_header, $endpoint_secret
    );
} catch(\UnexpectedValueException $e) {
    // Invalid payload
    http_response_code(400);
    exit();
} catch(\Stripe\Error\SignatureVerification $e) {
    // Invalid signature
    http_response_code(400);
    exit();
}

// Handle the event
switch ($event->type) {
    case 'payment_intent.succeeded':
        break;
    default:
        http_response_code(400);
        exit();
}
http_response_code(200);

Event

サブスクリプションに関する主なイベント

  • invoice.payment_succeeded (支払い成功時に発動)
  • invoice.payment_failed (支払い失敗時に発動)
  • customer.subscription.updated (サブスク更新時に発動)
  • customer.subscription.deleted (サブスクキャンセル時に発動)

サブスクリプションの状態

stripe.com

  • trialing(トライアル期間中)
  • active (有効)
  • incomplete (最初の支払いに失敗した状態)
  • incomplete_expired(incompleteから23時間経過すると有効期限切れとなり、このステータスになる)
  • past_due(自動支払いが失敗した状態。今回の請求が失敗に終わっても、次回の請求は普通に試行する。)
  • canceled (キャンセル済みの状態で、customer.subscription.deletedイベントがトリガされる。再度アクティブにすることはできない。)
  • unpaid(自動請求がOFFになる)