diff --git a/app/controllers/api/payments_controller.rb b/app/controllers/api/payments_controller.rb index 1c692a679..058226470 100644 --- a/app/controllers/api/payments_controller.rb +++ b/app/controllers/api/payments_controller.rb @@ -105,7 +105,7 @@ class API::PaymentsController < API::ApiController is_reserve = Reservations::Reserve.new(user_id, current_user.invoicing_profile.id) .pay_and_save(@reservation, payment_details: details, - payment_intent_id: intent.id, + intent_id: intent.id, schedule: params[:cart_items][:reservation][:payment_schedule], payment_method: params[:cart_items][:reservation][:payment_method]) if intent.class == Stripe::PaymentIntent @@ -135,7 +135,7 @@ class API::PaymentsController < API::ApiController is_subscribe = Subscriptions::Subscribe.new(current_user.invoicing_profile.id, user_id) .pay_and_save(@subscription, payment_details: details, - payment_intent_id: intent.id, + intent_id: intent.id, schedule: params[:cart_items][:subscription][:payment_schedule], payment_method: 'stripe') if intent.class == Stripe::PaymentIntent diff --git a/app/services/payment_schedule_service.rb b/app/services/payment_schedule_service.rb index abba2445e..96d8ae7a4 100644 --- a/app/services/payment_schedule_service.rb +++ b/app/services/payment_schedule_service.rb @@ -46,7 +46,7 @@ class PaymentScheduleService { payment_schedule: ps, items: items } end - def create(subscription, total, coupon: nil, operator: nil, payment_method: nil, reservation: nil, user: nil) + def create(subscription, total, coupon: nil, operator: nil, payment_method: nil, reservation: nil, user: nil, setup_intent_id: nil) subscription = reservation.generate_subscription if !subscription && reservation.plan_id schedule = compute(subscription.plan, total, coupon) @@ -55,6 +55,7 @@ class PaymentScheduleService ps.scheduled = reservation || subscription ps.payment_method = payment_method + ps.stp_setup_intent_id = setup_intent_id ps.operator_profile = operator.invoicing_profile ps.invoicing_profile = user.invoicing_profile ps.save! @@ -63,7 +64,7 @@ class PaymentScheduleService item.save! end - StripeService.create_stripe_subscription(ps.id, reservation&.reservable&.stp_product_id) if payment_method == 'stripe' + StripeService.create_stripe_subscription(ps.id, reservation&.reservable&.stp_product_id, setup_intent_id) if payment_method == 'stripe' ps end end diff --git a/app/services/reservations/reserve.rb b/app/services/reservations/reserve.rb index 6d7afd5c7..e74ac0ef5 100644 --- a/app/services/reservations/reserve.rb +++ b/app/services/reservations/reserve.rb @@ -13,7 +13,7 @@ class Reservations::Reserve # Confirm the payment of the given reservation, generate the associated documents and save teh record into # the database. ## - def pay_and_save(reservation, payment_details: nil, payment_intent_id: nil, schedule: false, payment_method: nil) + def pay_and_save(reservation, payment_details: nil, intent_id: nil, schedule: false, payment_method: nil) user = User.find(user_id) reservation.statistic_profile_id = StatisticProfile.find_by(user_id: user_id).id @@ -25,9 +25,10 @@ class Reservations::Reserve operator_profile_id: operator_profile_id, user: user, payment_method: payment_method, - coupon_code: payment_details[:coupon]) + coupon_code: payment_details[:coupon], + setup_intent_id: intent_id) else - generate_invoice(reservation, operator_profile_id, payment_details, payment_intent_id) + generate_invoice(reservation, operator_profile_id, payment_details, intent_id) end payment.save WalletService.debit_user_wallet(payment, user, reservation) @@ -41,7 +42,8 @@ class Reservations::Reserve ## # Generate the invoice for the given reservation+subscription ## - def generate_schedule(reservation: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil) + def generate_schedule(reservation: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil, + setup_intent_id: nil) operator = InvoicingProfile.find(operator_profile_id)&.user coupon = Coupon.find_by(code: coupon_code) unless coupon_code.nil? @@ -52,7 +54,8 @@ class Reservations::Reserve operator: operator, payment_method: payment_method, user: user, - reservation: reservation + reservation: reservation, + setup_intent_id: setup_intent_id ) end diff --git a/app/services/stripe_service.rb b/app/services/stripe_service.rb index 51271f658..a1f4ae556 100644 --- a/app/services/stripe_service.rb +++ b/app/services/stripe_service.rb @@ -5,10 +5,13 @@ class StripeService class << self # Create the provided PaymentSchedule on Stripe, using the Subscription API - def create_stripe_subscription(payment_schedule_id, reservable_stp_id) + def create_stripe_subscription(payment_schedule_id, reservable_stp_id, setup_intent_id) + stripe_key = Setting.get('stripe_secret_key') payment_schedule = PaymentSchedule.find(payment_schedule_id) first_item = payment_schedule.ordered_items.first + # setup intent (associates the customer and the payment method) + intent = Stripe::SetupIntent.retrieve(setup_intent_id, api_key: stripe_key) # subscription (recurring price) price = create_price(first_item.details['recurring'], payment_schedule.scheduled.plan.stp_product_id, @@ -23,8 +26,9 @@ class StripeService add_invoice_items: items, items: [ { price: price[:id] } - ] - }, { api_key: Setting.get('stripe_secret_key') }) + ], + default_payment_method: intent[:payment_method] + }, { api_key: stripe_key }) payment_schedule.update_attributes(stp_subscription_id: stp_subscription.id) end @@ -65,7 +69,7 @@ class StripeService } params[:recurring] = { interval: 'month', interval_count: 1 } if monthly - Stripe::Price.create(params, { api_key: Setting.get('stripe_secret_key') }) + Stripe::Price.create(params, api_key: Setting.get('stripe_secret_key')) end end end diff --git a/app/services/subscriptions/subscribe.rb b/app/services/subscriptions/subscribe.rb index a3774cd17..685308d7c 100644 --- a/app/services/subscriptions/subscribe.rb +++ b/app/services/subscriptions/subscribe.rb @@ -12,11 +12,11 @@ class Subscriptions::Subscribe ## # @param subscription {Subscription} # @param payment_details {Hash} as generated by Price.compute - # @param payment_intent_id {String} from stripe + # @param intent_id {String} from stripe # @param schedule {Boolean} # @param payment_method {String} only for schedules ## - def pay_and_save(subscription, payment_details: nil, payment_intent_id: nil, schedule: false, payment_method: nil) + def pay_and_save(subscription, payment_details: nil, intent_id: nil, schedule: false, payment_method: nil) return false if user_id.nil? user = User.find(user_id) @@ -30,9 +30,10 @@ class Subscriptions::Subscribe operator_profile_id: operator_profile_id, user: user, payment_method: payment_method, - coupon_code: payment_details[:coupon]) + coupon_code: payment_details[:coupon], + setup_intent_id: intent_id) else - generate_invoice(subscription, operator_profile_id, payment_details, payment_intent_id) + generate_invoice(subscription, operator_profile_id, payment_details, intent_id) end payment.save WalletService.debit_user_wallet(payment, user, subscription) @@ -56,7 +57,8 @@ class Subscriptions::Subscribe total: details[:before_coupon], operator_profile_id: operator_profile_id, user: new_sub.user, - payment_method: schedule.payment_method) + payment_method: schedule.payment_method, + setup_intent_id: schedule.stp_setup_intent_id) else generate_invoice(subscription, operator_profile_id, details) end @@ -72,7 +74,8 @@ class Subscriptions::Subscribe ## # Generate the invoice for the given subscription ## - def generate_schedule(subscription: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil) + def generate_schedule(subscription: nil, total: nil, operator_profile_id: nil, user: nil, payment_method: nil, coupon_code: nil, + setup_intent_id: nil) operator = InvoicingProfile.find(operator_profile_id)&.user coupon = Coupon.find_by(code: coupon_code) unless coupon_code.nil? @@ -82,7 +85,8 @@ class Subscriptions::Subscribe coupon: coupon, operator: operator, payment_method: payment_method, - user: user + user: user, + setup_intent_id: setup_intent_id ) end diff --git a/db/migrate/20201027100746_create_payment_schedules.rb b/db/migrate/20201027100746_create_payment_schedules.rb index 8b3692afc..75ca38352 100644 --- a/db/migrate/20201027100746_create_payment_schedules.rb +++ b/db/migrate/20201027100746_create_payment_schedules.rb @@ -8,6 +8,7 @@ class CreatePaymentSchedules < ActiveRecord::Migration[5.2] t.references :scheduled, polymorphic: true t.integer :total t.string :stp_subscription_id + t.string :stp_setup_intent_id t.string :reference t.string :payment_method t.integer :wallet_amount diff --git a/db/structure.sql b/db/structure.sql index 7abfbbd95..84cc9f3ea 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1509,6 +1509,7 @@ CREATE TABLE public.payment_schedules ( scheduled_id bigint, total integer, stp_subscription_id character varying, + stp_setup_intent_id character varying, reference character varying, payment_method character varying, wallet_amount integer,