Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Stripeで請求書払い&銀行振込を実装する

 Stripeで請求書払い&銀行振込を実装する

#JP_Stripes https://jpstripes.connpass.com/event/252130/
PlayTechnologies, Inc.が提供するLINE予約サービス『ポチコ』に請求書払い(カードor銀行振込)をStripeで実装した話

93bc8fb48f57c11e417dad9d26a2fb8a?s=128

petitviolet

July 13, 2022
Tweet

More Decks by petitviolet

Other Decks in Programming

Transcript

  1. 4USJQFͰ੥ٻॻ෷͍ۜߦৼࠐΈ +1@4USJQF0OMJOF7PM 1MBZ5FDIOPMPHJFT *OD )JSPLJ,PNVSBTBLJ!QFUJUWJPMFU

  2. ࣗݾ঺հ w খࢵ߂و )JSPLJ,PNVSBTBLJ  w !QFUJUWJPMFU w 1MBZ5FDIOPMPHJFTͰΤϯδχΞΛ΍͍ͬͯ·͢ w

    IUUQTQMBZUFDIKQ w ʰϙνίʱΛఏڙ͍ͯ͠·͢
  3. ࠓ೔࿩͢͜ͱ w 4USJQFͰ࣮૷͢Δ੥ٻॻ෷͍ ۜߦৼࠐ  w ʰཌ݄຤కΊ੾Γʱͷ࣮૷ w ະ෷͍ϢʔβΛࣗಈͰղ໿ͤ͞Δ w

    కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ
  4. ϙνίʁ -*/&༧໿αʔϏε ˇ ݄ͳαϒεΫϦϓγϣϯܕϏδωε

  5. ϙνίͱ4USJQF w ༗ྉϢʔβʔͷ؅ཧ w 'JSFCBTF"VUIFOUJDBUJPO w αϒεΫϦϓγϣϯͷ؅ཧ w ແྉτϥΠΞϧ w

    ੥ٻ w Χʔυ෷͍ w ੥ٻॻ෷͍ ΧʔυPSۜߦৼࠐ ˡ/&8ʂ
  6. 4USJQFͰ࣮૷͢Δ੥ٻॻ෷͍ ۜߦৼࠐ

  7. ϙνίͷར༻ྉࢧ෷͍ํ๏ w Χʔυ෷͍͍ͨ͠Ϣʔβʔ w ՝ۚ։࢝࣌ʹΧʔυ৘ใΛೖྗˠ4USJQFͰ؅ཧ w ੥ٻॻ෷͍͍ͨ͠Ϣʔβʔ w ౰ॳ͸αϙʔτ͍ͯ͠ͳ͔͕ͬͨɺཁ๬ͷଟ͞ʹ·͚ͯ ӡ༻ͰΧόʔ͠͸͡Ίͨ

    w (PPHMF'PSNͰͦͷࢫΛૹ৴ͯ͠΋ΒͬͯɺεϓϨου γʔτͰ੥ٻॻ෷͍ͷϢʔβʔΛ؅ཧ w .˓OFZ'PSXBSEͰ੥ٻॻൃߦɾૹ෇ w ౰વɺ৭ʑͱਏ͍ w ೋॏ؅ཧɺ%#ͱͷঢ়ଶ੔߹ੑɺకΊ࡞ۀɺFUD
  8. ͕࣌ܦͪ Χʔυ෷͍ɾۜߦৼࠐͷͲͪΒʹ΋ରԠͨ͠੥ٻॻ ෷͍͕4USJQFͰՄೳʹͳͬͨʂ ੥ٻॻͷϢʔβʔΛ εϓϨουγʔτ .˓OFZ'PSXBSE ˣ

  9. 4USJQF΁ͷҠߦεςοϓ  4USJQFͷ$VTUPNFSΛ࡞੒  4USJQFͷ4VCTDSJQUJPOΛ࡞੒ w DPMMFDUJPO@NFUIPEʹzTFOE@JOWPJDFzΛ༩͑Δ

  10. 4USJQF΁ͷҠߦεςοϓ  4USJQFͷ$VTUPNFSΛ࡞੒  4USJQFͷ4VCTDSJQUJPOΛ࡞੒ w DPMMFDUJPO@NFUIPEʹzTFOE@JOWPJDFzΛ༩͑Δ

  11. 4USJQFͷ$VTUPNFSΛ࡞੒ ୯ʹ$VTUPNFSΛ࡞੒͢Δ͚ͩ ಛච͢΂͖͜ͱ͸ͳ͍ stripe.customers.create({ email, name, description, metadata: { paymentType:

    'invoice', // metadataに請求書払いユーザであることをマークしている }, });
  12. 4USJQF΁ͷҠߦεςοϓ  4USJQFͷ$VTUPNFSΛ࡞੒  4USJQFͷ4VCTDSJQUJPOΛ࡞੒ w DPMMFDUJPO@NFUIPEʹzTFOE@JOWPJDFzΛ༩͑Δ

  13. 4USJQFͷ4VCTDSJQUJPOΛ࡞੒ 4VCTDSJQUJPOΛ࡞੒͢Δ͚ͩ stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }],

    default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, backdate_start_date: today.startOf('M').unix(), // 今月頭 billing_cycle_anchor: today.startOf('M').add(1, 'M').unix(), // 月初請求 days_until_due: 60, // 雑な"翌月末" trial_end: 'now', }); IUUQTTUSJQFDPNEPDTBQJTVCTDSJQUJPOTDSFBUF
  14. 4USJQFͷ4VCTDSJQUJPOΛ࡞੒ 4VCTDSJQUJPOΛ࡞੒͢Δ͚ͩ stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }],

    default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, backdate_start_date: today.startOf('M').unix(), // 今月頭 billing_cycle_anchor: today.startOf('M').add(1, 'M').unix(), // 月初請求 days_until_due: 60, // 雑な"翌月末" trial_end: 'now', }); ੥ٻॻૹ෇ɾΧʔυPSۜߦৼࠐͰͷࢧ෷͍Մ IUUQTTUSJQFDPNEPDTBQJTVCTDSJQUJPOTDSFBUF
  15. 4USJQFͷ4VCTDSJQUJPOΛ࡞੒ 4VCTDSJQUJPOΛ࡞੒͢Δ͚ͩ stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }],

    default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, backdate_start_date: today.startOf('M').unix(), // 今月頭 billing_cycle_anchor: today.startOf('M').add(1, 'M').unix(), // 月初請求 days_until_due: 60, // 雑な"翌月末" trial_end: 'now', }); ੥ٻλΠϛϯάͷઃఆ IUUQTTUSJQFDPNEPDTBQJTVCTDSJQUJPOTDSFBUF
  16. 4USJQFͷ4VCTDSJQUJPOΛ࡞੒ ແྉτϥΠΞϧظؒ ΞΧ΢ϯτొ࿥ޙϲ݄ ʹ੥ٻॻ෷͍Ͱొ࿥͢Δͱ return stripe.subscriptions.create({ customer: customerId, items: [{

    price: priceId }], default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, // 無料トライアル終了後の翌月頭 billing_cycle_anchor: account.createdAt.add(1, 'M').startOf('M').add(1, ‘M').unix(), // アカウント作成後1ヶ月は無料トライアル trial_end: account.createdAt.add(1, 'M').startOf('d').subtract(1, ’s').unix(), // 支払いは翌月末 days_until_due: today.add(1, 'M').endOf('M').diff(today, 'd'), });
  17. return stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }], default_tax_rates:

    defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, // 無料トライアル終了後の翌月頭 billing_cycle_anchor: account.createdAt.add(1, 'M').startOf('M').add(1, ‘M').unix(), // アカウント作成後1ヶ月は無料トライアル trial_end: account.createdAt.add(1, 'M').startOf('d').subtract(1, ’s').unix(), // 支払いは翌月末 days_until_due: today.add(1, 'M').endOf('M').diff(today, 'd'), }); 4USJQFͷ4VCTDSJQUJPOΛ࡞੒ ແྉτϥΠΞϧظؒ ΞΧ΢ϯτొ࿥ޙϲ݄ ʹ੥ٻॻ෷͍Ͱొ࿥͢Δͱ ੥ٻλΠϛϯάͷઃఆ͕ෳࡶԽ
  18. 4USJQFͷ4VCTDSJQUJPOΛ࡞੒ ແྉτϥΠΞϧظؒ ΞΧ΢ϯτొ࿥ޙϲ݄ ʹ੥ٻॻ෷͍Ͱొ࿥͢Δͱ ͜ͷ··ʹ͓ͯ͘͠ͱɺ࣍ͷ੥ٻॻͷࢧ෷ظݶ͕ཌ݄຤Ͱͳ͘ͳͬͯ͠·͏ return stripe.subscriptions.create({ customer: customerId, items:

    [{ price: priceId }], default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, // 無料トライアル終了後の翌月頭 billing_cycle_anchor: account.createdAt.add(1, 'M').startOf('M').add(1, ‘M').unix(), // アカウント作成後1ヶ月は無料トライアル trial_end: account.createdAt.add(1, 'M').startOf('d').subtract(1, ’s').unix(), // 支払いは翌月末 days_until_due: today.add(1, 'M').endOf('M').diff(today, 'd'), }); ੥ٻॻൃߦ͸ແྉτϥΠΞϧऴྃ࣌ ࢧ෷ظݶ͸ͦͷཌ݄຤
  19. ʰཌ݄຤కΊ੾Γʱͷ࣮૷

  20. 4VCTDSJQUJPOͷEBZT@VOUJM@EVF return stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }],

    default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, // 無料トライアル終了後の翌月頭 billing_cycle_anchor: account.createdAt.add(1, 'M').startOf('M').add(1, ‘M').unix(), // アカウント作成後1ヶ月は無料トライアル trial_end: account.createdAt.add(1, 'M').startOf('d').subtract(1, ’s').unix(), // 支払いは翌月末 days_until_due: today.add(1, 'M').endOf('M').diff(today, 'd'), }); ແྉτϥΠΞϧதͷ4VCTDSJQUJPO࡞੒ stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }], collection_method: 'send_invoice', default_tax_rates: defaultTaxRates, payment_settings: { payment_method_types: ['card', 'customer_balance'] }, backdate_start_date: today.startOf('M').unix(), // 今月頭 billing_cycle_anchor: today.startOf('M').add(1, 'M').unix(), // 月初請求 days_until_due: 60, // 雑な"翌月末" trial_end: 'now', }); ௨ৗ࣌ͷ4VCTDSJQUJPO࡞੒
  21. 4VCTDSJQUJPOͷEBZT@VOUJM@EVF return stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }],

    default_tax_rates: defaultTaxRates, collection_method: 'send_invoice', payment_settings: { payment_method_types: ['card', 'customer_balance'] }, // 無料トライアル終了後の翌月頭 billing_cycle_anchor: account.createdAt.add(1, 'M').startOf('M').add(1, ‘M').unix(), // アカウント作成後1ヶ月は無料トライアル trial_end: account.createdAt.add(1, 'M').startOf('d').subtract(1, ’s').unix(), // 支払いは翌月末 days_until_due: today.add(1, 'M').endOf('M').diff(today, 'd'), }); ແྉτϥΠΞϧதͷ4VCTDSJQUJPO࡞੒ stripe.subscriptions.create({ customer: customerId, items: [{ price: priceId }], collection_method: 'send_invoice', default_tax_rates: defaultTaxRates, payment_settings: { payment_method_types: ['card', 'customer_balance'] }, backdate_start_date: today.startOf('M').unix(), // 今月頭 billing_cycle_anchor: today.startOf('M').add(1, 'M').unix(), // 月初請求 days_until_due: 60, // 雑な"翌月末" trial_end: 'now', }); ௨ৗ࣌ͷ4VCTDSJQUJPO࡞੒ ੥ٻॻͷࢧ෷ظݶΛଗ͍͑ͨ
  22. 8FCIPPLΛ࢖͏ 4USJQF͸Πϕϯτ͝ͱʹ8FCIPPLΛඈ͹ͯ͘͠ΕΔ IUUQTTUSJQFDPNEPDTXFCIPPLT

  23. 8FCIPPLΛ࢖͏ 4USJQF͸Πϕϯτ͝ͱʹ8FCIPPLΛඈ͹ͯ͘͠ΕΔ ࠓճ࢖ͬͨͷ͸zDVTUPNFSTVCTDSJQUJPOVQEBUFEz ແྉτϥΠΞϧऴྃ࣌ʹൃՐ͢Δ IUUQTTUSJQFDPNEPDTBQJFWFOUTUZQFTFWFOU@UZQFTDVTUPNFSTVCTDSJQUJPOVQEBUFE

  24. 8FCIPPLΛ࢖͏ 8FCIPPLͷઃఆͰDVTUPNFSTVCTDSJQUJPOVQEBUFEΛ ड͚औΔΑ͏ʹ໌͓ࣔͯ͘͜͠ͱ

  25. 8FCIPPLΛ࢖͏ lDVTUPNFSTVCTDSJQUJPOVQEBUFEzΛड͚औͬͯ TVCTDSJQUJPOEBZT@VOUJM@EVFΛઃఆ͠௚͢ if (event.type === 'customer.subscription.updated') { const previousAttributes

    = event.data.previous_attributes; const trialEnded = 'status' in previousAttributes && previousAttributes.status === 'trialing'; if (trialEnded) { // 請求書払いなsubscriptionのtrialが終わったら、 // daysUntilDueを更新して請求書を月末発行・翌月末期限に調整する await updateSubscription(event.data.object.id, { days_until_due: 60, }); } }
  26. ະ෷͍ϢʔβΛࣗಈͰղ໿ͤ͞Δ

  27. ࢧ෷Θͳ͍Ϣʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞ ੥ٻॻ෷͍ ۜߦৼࠐ ͩͱࢧ෷͍͕஗Ε͕ͪ ˣ ஗ΕͨϢʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞ Ͱ΋ଈղ໿͸ݫ͗͢͠ΔͷͰ༛༧Λ͍࣋ͨͤͨ

  28. ࢧ෷Θͳ͍Ϣʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞ ੥ٻॻ෷͍ ۜߦৼࠐ ͩͱࢧ෷͍͕஗Ε͕ͪ ˣ ஗ΕͨϢʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞ Ͱ΋ଈղ໿͸ݫ͗͢͠ΔͷͰ༛༧Λ͍࣋ͨͤͨ 4USJQFͳΒ؆୯ʹग़དྷΔΑʂ

  29. ࢧ෷Θͳ͍Ϣʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞

  30. ࢧ෷Θͳ͍Ϣʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞

  31. ࢧ෷Θͳ͍Ϣʔβʔ͸ࣗಈͰղ໿͍ͤͨ͞ ཌ݄຤͕ࢧ෷ظݶ ཌʑ݄຤ʹࣗಈղ໿

  32. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ

  33. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ కΊ੾ΓˠਅͷకΊ੾Γ ࣗಈղ໿ ·Ͱ༛༧͕͋Δ ͜ͷؒʹࢧ෷͍͕͋Δͱফࠐ͞Εͣʹʰ࢒ߴʱʹ ೖͬͯ͠·͏

  34. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ ݱۚ࢒ߴ͕͋Δͷʹ੥ٻॻ͕ະ෷͍Ͱͦͷ··ղ໿ ͞Εͯ͠·͏ͱ͍͏࠷ѱͷ݁Ռʹ ͦͯۜ͠ߦৼࠐ͸4USJQFʹ൓ө͞ΕΔ·Ͱϥά͕͋Δʜ

  35. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ IUUQTTUSJQFDPNEPDTQBZNFOUTDVTUPNFSCBMBODFSFDPODJMJBUJPODBTINBOVBMSFDPODJMJBUJPO await stripe.customers.update(customer.id, { cash_balance: { settings: {

    reconciliation_mode: 'manual', }, }, }); await stripe.paymentIntents.applyCustomerBalance( invoice.payment_intent as string ); await stripe.customers.update(customer.id, { cash_balance: { settings: { reconciliation_mode: 'automatic', }, }, });
  36. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ IUUQTTUSJQFDPNEPDTQBZNFOUTDVTUPNFSCBMBODFSFDPODJMJBUJPODBTINBOVBMSFDPODJMJBUJPO await stripe.customers.update(customer.id, { cash_balance: { settings: {

    reconciliation_mode: 'manual', }, }, }); await stripe.paymentIntents.applyCustomerBalance( invoice.payment_intent as string ); await stripe.customers.update(customer.id, { cash_balance: { settings: { reconciliation_mode: 'automatic', }, }, }); ফࠐϞʔυΛखಈʹมߋ
  37. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ IUUQTTUSJQFDPNEPDTQBZNFOUTDVTUPNFSCBMBODFSFDPODJMJBUJPODBTINBOVBMSFDPODJMJBUJPO await stripe.customers.update(customer.id, { cash_balance: { settings: {

    reconciliation_mode: 'manual', }, }, }); await stripe.paymentIntents.applyCustomerBalance( invoice.payment_intent as string ); await stripe.customers.update(customer.id, { cash_balance: { settings: { reconciliation_mode: 'automatic', }, }, }); ফࠐ͢Δ
  38. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ IUUQTTUSJQFDPNEPDTQBZNFOUTDVTUPNFSCBMBODFSFDPODJMJBUJPODBTINBOVBMSFDPODJMJBUJPO await stripe.customers.update(customer.id, { cash_balance: { settings: {

    reconciliation_mode: 'manual', }, }, }); await stripe.paymentIntents.applyCustomerBalance( invoice.payment_intent as string ); await stripe.customers.update(customer.id, { cash_balance: { settings: { reconciliation_mode: 'automatic', }, }, }); ফࠐϞʔυΛࣗಈʹ໭͢
  39. ࠓ೔࿩ͨ͜͠ͱ w 4USJQFͰ࣮૷͢Δ੥ٻॻ෷͍ ۜߦৼࠐ  w ʰཌ݄຤కΊ੾Γʱͷ࣮૷ w ະ෷͍ϢʔβΛࣗಈͰղ໿ͤ͞Δ w

    కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ ڵຯ͕͋Ε͹IUUQTQPDIJDPBQQ࢖ͬͯΈͯͶʂ