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で実装した話

petitviolet

July 13, 2022
Tweet

More Decks by petitviolet

Other Decks in Programming

Transcript

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

    w (PPHMF'PSNͰͦͷࢫΛૹ৴ͯ͠΋ΒͬͯɺεϓϨου γʔτͰ੥ٻॻ෷͍ͷϢʔβʔΛ؅ཧ w .˓OFZ'PSXBSEͰ੥ٻॻൃߦɾૹ෇ w ౰વɺ৭ʑͱਏ͍ w ೋॏ؅ཧɺ%#ͱͷঢ়ଶ੔߹ੑɺకΊ࡞ۀɺFUD
  2. 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
  3. 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
  4. 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
  5. 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'), });
  6. 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Λ࡞੒ ແྉτϥΠΞϧظؒ ΞΧ΢ϯτొ࿥ޙϲ݄ ʹ੥ٻॻ෷͍Ͱొ࿥͢Δͱ ੥ٻλΠϛϯάͷઃఆ͕ෳࡶԽ
  7. 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'), }); ੥ٻॻൃߦ͸ແྉτϥΠΞϧऴྃ࣌ ࢧ෷ظݶ͸ͦͷཌ݄຤
  8. 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࡞੒
  9. 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࡞੒ ੥ٻॻͷࢧ෷ظݶΛଗ͍͑ͨ
  10. 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, }); } }
  11. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ 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', }, }, });
  12. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ 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', }, }, }); ফࠐϞʔυΛखಈʹมߋ
  13. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ 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', }, }, }); ফࠐ͢Δ
  14. కΊ੾ΓΛ͗ͨ͢ࢧ෷͍ͷফࠐ खಈͰফࠐ͢Δ࣮૷͕ඞཁ 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', }, }, }); ফࠐϞʔυΛࣗಈʹ໭͢