stripe connectにて子アカウントの本人確認が完了したタイミングでユーザーにメールで伝える実装をしたのでまとめます。
やったこと
実装内容は下記になります。
- webhookをtype connectで新しく作成
- account.updateのみをリッスン
- account.updateのpayouts_enabledがtrueになったら対象ユーザーにメール通知
- testでメール送信されるかをテスト
前提
前提として下記になります
- rails
- stripe
- connect使用
- expressアカウント
webhookの設計
今回、webhookは新しく作成しています。今までinvoice.createdなど支払いに関するwebhookも受けていましたがそちらはtype directで親アカウントのeventを受け取るものだったんですが、今回のaccount.updateは子アカウントのeventになるのでtype connectにする必要があります。
一つのwebhookで二つのtypeは受け取れないので別にwebhookを作成しました。詳細な設定は下記
- type connect
- リッスンするのはaccount.update
- urlはwebhook/connectなど別のもの
controllerの設計
signatureが別になるので受け取るcontrollerも別にします。webhook_connect_controllerを作成します。
class WebhookConnectController < ActionController::API
def webhook_event
webhook認証のコード
case event.type
when 'account.updated'
event_account_update(data)
else
puts "Unhandled event type: \#{event.type}"
puts event.type
end
render status: 200, json: { status: 200, message: "Success" }
end
private
def event_account_update(data)
if data[:object][:payouts_enabled]
stripe_account_id = data[:object][:id]
account_user = User.find_by(stripe_account_id: stripe_account_id)
NotificationMailer.send_account_update_payout_enabled_to_account_user(account_user).deliver_later
end
end
end
controllerを作成し、ActionController::APIからの継承に変更。やっていることとしては
- secretの確認
- eventがaccount.updateならevent_account_updateを呼び出す
- event_account_updateでメール送信
テスト
テストは下記で
RSpec.describe "webhook_connect_controller", type: :request do
describe "webhook/connect" do
let!(:user_01) { FactoryBot.create(:user) }
include StripeEventHelpers
let!(:account_update_params) { {
"object": "event",
"data": {
"object": {
"id": user_01.stripe_account_id,
"object": "account",
"payouts_enabled": true,
}
},
"type": "account.updated"
}
}
example "本人確認メールが送られるか" do
expect{ post_with_stripe_signature_connect '/webhook/connect', params: account_update_params.to_json }.to have_enqueued_job.on_queue("mailers")
end
end
end
post_with_stripe_signature_connectはsupport配下に置いたhelperになります。
module StripeEventHelpers
def post_with_stripe_signature(path, **options)
post(
path,
headers: {
'Stripe-Signature': generate_stripe_event_signature(options[:params])
},
**options
)
end
def post_with_stripe_signature_connect(path, **options)
post(
path,
headers: {
'Stripe-Signature': generate_stripe_event_signature_connect(options[:params])
},
**options
)
end
private
def generate_stripe_event_signature(payload)
time = Time.now
secret = ENV['WEBHOOK_SECRET']
signature = Stripe::Webhook::Signature.compute_signature(time, payload, secret)
Stripe::Webhook::Signature.generate_header(
time,
signature
)
end
def generate_stripe_event_signature_connect(payload)
time = Time.now
secret = ENV['WEBHOOK_SECRET_CONNECT']
signature = Stripe::Webhook::Signature.compute_signature(time, payload, secret)
Stripe::Webhook::Signature.generate_header(
time,
signature
)
end
end