見出し画像

Djangoでサブスクリプションの支払い情報を受け取る(stripe)

前回の記事で、stripeを利用して、Djangoでサブスクリプション商品を売れるようになりました。でも、サブスクリプション商品は売っただけで終わりにはなりません。

クレジットカードで支払いがされていますが、支払いができなかった場合にどうするのか?
お客さんが解約したいと言った時にどうするのか?
いつ請求を送ったり、金額更新の連絡をするのか?

いろいろ考えることがあります。

まずは、stripeでサブスクリプションの支払いがうまくいっているか、Djangoで情報を受け取れるようにしていきましょう。

Djangoのプロジェクトは前回の続きから作成していきます。まだそちらをみていない方は、この記事の先頭にあるリンクから確認してください。

stripeからのwebhookイベントを取得する

webhookイベントは、stripeで何か動きを検知した時に、こちらに通知してくれる機能です。

例えば、前回の記事のサブスクリプション登録処理を行なった場合、checkout.session.completedイベントが発生します。イベントの一覧は下記から確認できます。

最低限、必要な対応として、checkout.session.completed、invoice.paid、invoice.payment_failedのイベントを確認できるようにしていきましょう。

invoice.paidは支払いが問題なく実施されたというイベント、invoice.payment_failedは支払いが失敗したというイベントです。

これらのイベントをDjangoで取得できるようにする必要がありますが、ローカル開発時には、残念ながら実施できません。

…というわけでここではreplit.comを利用します。replit.comにプロジェクトを追加すれば、urlが付与されるのでエンドポイントを試すことができます。replit.comの基本的な使い方は以下の記事を参考にしてください。

replit.comにプロジェクトをアップロードしたところ、以下のurlが設定されていました。後で、このurlにwebhookのイベントを取得したいアドレスを追加して、webhookを取得できるようにします。

https://django-tutorial-stripe-endpoint.sonnenkorona.repl.co/

スクリーンショット 2021-06-04 8.49.45

次に、stripe側の設定を行います。stripeのダッシュボードの左メニューにあるWebhookをクリックします。

スクリーンショット 2021-06-04 8.18.02

エンドポイントを作成します。エンドポイントというのは、webhookのイベントが発生した時に、どこに送るか設定しておくということです。

「+エンドポイントを追加」から作成を始めます。

エンドポイントurlに先ほどのurlに"webhook/"を追加したアドレスを設定し、3つのイベントを選択して「エンドポイントの追加」を押下します。

スクリーンショット 2021-06-04 9.11.28

これでWebhookエンドポイントが作成されました。Webhookを作成したら、「署名シークレット」を控えておきます。

スクリーンショット 2021-06-04 8.56.51

Django側の設定

まずはイベントを受け取るルーティングを作成しておきます。先ほどwebhookURLにwebhookを追加していたので、同じようにルーティングします。

# subscription/urls.py

...省略...
urlpatterns = [
 ...省略...

  path('webhook/', views.subscription_webhook, name='webhook'),
]

そしてviews.pyにwebhookを受け取る処理を追加します。

subscription/views.py

...省略...

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def subscription_webhook_received(request):
   stripe.api_key = 'sk_test_あなたのシークレットキーを入力してください'
   webhook_secret = 'whsec_あなたの署名シークレットを入力してください'

   post_data = json.loads(request.body.decode("utf-8"))

   if webhook_secret:
       # Retrieve the event by verifying the signature using the raw body and secret if webhook signing is configured.
       signature = request.headers.get('stripe-signature')
       try:
           event = stripe.Webhook.construct_event(
               payload=request.body, sig_header=signature, secret=webhook_secret)
           data = event['data']
       except Exception as e:
           return e
       # Get the type of webhook event sent - used to check the status of PaymentIntents.
       event_type = event['type']
   else:
       data = post_data['data']
       event_type = post_data['type']

   data_object = data['object']

   if event_type == 'checkout.session.completed':
   # Payment is successful and the subscription is created.
   # You should provision the subscription and save the customer ID to your database.
       print(data)
   elif event_type == 'invoice.paid':
   # Continue to provision the subscription as payments continue to be made.
   # Store the status in your database and check when a user accesses your service.
   # This approach helps you avoid hitting rate limits.
       print(data)
   elif event_type == 'invoice.payment_failed':
   # The payment failed or the customer does not have a valid payment method.
   # The subscription becomes past_due. Notify your customer and send them to the
   # customer portal to update their payment information.
        print(data)
   else:
       print('Unhandled event type {}'.format(event_type))
   return JsonResponse({'status': 'success'})

最初の2行はあなたのシークレットキーに設定してください。

stripeから取得する情報には、csrf tokenがないのでエラーが発生してしまいます。そのため、この関数には"@csrf_exempt"を設定しています。詳細は以下リンク先を確認してください。

この関数はstripeのサンプルをほぼそのまま使っています。やっていることはシンプルで、webhookを取得して、イベントの種類ごとに分岐しているだけです。

現在は各イベントでprint(data)の処理しかしていませんが、それぞれ適切な処理を実装していくことになります。アプリケーションによって処理は異なるので、今回は特に実装しません。

webhookのテスト

これで実装は完了したので、実際にwebhookの処理が行われるか、確認してみましょう。

replit.comのプロジェクト上で[Run]をクリックして実行します。

スクリーンショット 2021-06-04 9.04.42

右側に小さなウィンドウでも実行結果が表示されますが、CSRF関係のエラーが出たので、右上にあるアイコン(カーソルを当てるとopen in a new tabと表示されるもの)を押して違うタブで開きます(その場合はなぜかちゃんと動きます)。

スクリーンショット 2021-06-04 9.07.37

そして、テスト用のクレジットカードで、サブスクリプションに登録してみます。うまくいけばここでwebhookを受け取ることができるはずです。

スクリーンショット 2021-06-04 9.19.27

購入ページに遷移した後、replit.comのconsoleを見ると…

スクリーンショット 2021-06-04 9.20.03

ちゃんとstripeから情報を受け取っているようです!

まとめ

stripeの定期支払いを行う際に、webhookを利用してstripeからイベント情報を受け取る方法を紹介しました。

今回のサンプルコードはreplit.comに記載してあります。ただし、stripeのシークレットキーは削除しているので、[Run]しても動きません。ご自身の環境で試してみてください。

ここまで読んでいただけたなら、”スキ”ボタンを押していただけると励みになります!(*´ー`*)ワクワク


この記事が気に入ったらサポートをしてみませんか?