Module: SpreeStripe::Gateway::PaymentIntents

Extended by:
ActiveSupport::Concern
Included in:
SpreeStripe::Gateway
Defined in:
app/models/spree_stripe/gateway/payment_intents.rb

Constant Summary collapse

DELAYED_NOTIFICATION_PAYMENT_METHOD_TYPES =
%w[sepa_debit us_bank_account].freeze
BANK_PAYMENT_METHOD_TYPES =
%w[customer_balance us_bank_account].freeze
MANUAL_CAPTURE_METHOD =
'manual'.freeze

Instance Method Summary collapse

Instance Method Details

#cancel_payment_intent(payment_intent_id) ⇒ Object

Cancels a Stripe payment intent

Parameters:

  • payment_intent_id (String)

    Stripe payment intent ID, eg. pi_123



106
107
108
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 106

def cancel_payment_intent(payment_intent_id)
  send_request { |opts| Stripe::PaymentIntent.cancel(payment_intent_id, {}, opts) }
end

#capture_payment_intent(payment_intent_id, amount_in_cents) ⇒ Object



99
100
101
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 99

def capture_payment_intent(payment_intent_id, amount_in_cents)
  send_request { |opts| Stripe::PaymentIntent.capture(payment_intent_id, { amount_to_capture: amount_in_cents }, opts) }
end

#confirm_payment_intent(payment_intent_id) ⇒ Object



95
96
97
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 95

def confirm_payment_intent(payment_intent_id)
  send_request { |opts| Stripe::PaymentIntent.confirm(payment_intent_id, {}, opts) }
end

#create_payment_intent(amount_in_cents, order, payment_method_id: nil, off_session: false, customer_profile_id: nil) ⇒ Spree::PaymentResponse

Creates a Stripe payment intent for the order

Parameters:

  • amount_in_cents (Integer)

    the amount in cents

  • order (Spree::Order)

    the order to create a payment intent for

  • payment_method_id (String) (defaults to: nil)

    Stripe payment method id to use, eg. a card token

  • off_session (Boolean) (defaults to: false)

    whether the payment intent is off session

  • customer_profile_id (String) (defaults to: nil)

    Stripe customer profile id to use, eg. cus_123

Returns:

  • (Spree::PaymentResponse)

    the response from the payment intent creation



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 52

def create_payment_intent(amount_in_cents, order, payment_method_id: nil, off_session: false, customer_profile_id: nil)
  payload = SpreeStripe::PaymentIntentPresenter.new(
    amount: amount_in_cents,
    order: order,
    customer: customer_profile_id || fetch_or_create_customer(order: order)&.profile_id,
    payment_method_id: payment_method_id,
    off_session: off_session,
    capture_method: stripe_capture_method
  ).call

  protect_from_error do
    response = send_request { |opts| Stripe::PaymentIntent.create(payload, opts) }

    success(response.id, response)
  end
end

#ensure_payment_intent_exists_for_payment(payment, amount_in_cents = nil, payment_source = nil) ⇒ Spree::Payment

Ensures a Stripe payment intent exists for Spree payment

Parameters:

  • payment (Spree::Payment)

    the payment to ensure a payment intent exists for

  • amount_in_cents (Integer) (defaults to: nil)

    the amount in cents

  • payment_source (Spree::CreditCard | Spree::PaymentSource) (defaults to: nil)

    the payment source to use

Returns:

  • (Spree::Payment)

    the payment with the payment intent



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 116

def ensure_payment_intent_exists_for_payment(payment, amount_in_cents = nil, payment_source = nil)
  return payment if payment.response_code.present?

  amount_in_cents ||= payment.display_amount.cents
  payment_source ||= payment.source

  response = create_payment_intent(
    amount_in_cents,
    payment.order,
    payment_method_id: payment_source.gateway_payment_profile_id,
    off_session: true,
    customer_profile_id: payment_source.gateway_customer_profile_id
  )

  payment.update_columns(
    response_code: response.authorization,
    updated_at: Time.current
  )

  payment
end

#payment_intent_accepted?(payment_intent) ⇒ Boolean

Returns:

  • (Boolean)


14
15
16
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 14

def payment_intent_accepted?(payment_intent)
  payment_intent.status.in?(payment_intent_accepted_statuses(payment_intent))
end

#payment_intent_bank_payment_method?(payment_intent) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
32
33
34
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 29

def payment_intent_bank_payment_method?(payment_intent)
  payment_method = payment_intent.payment_method
  return false unless payment_method.respond_to?(:type)

  payment_intent.payment_method.type.in?(BANK_PAYMENT_METHOD_TYPES)
end

#payment_intent_charge_not_required?(payment_intent) ⇒ Boolean

Returns:

  • (Boolean)


25
26
27
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 25

def payment_intent_charge_not_required?(payment_intent)
  payment_intent_bank_payment_method?(payment_intent)
end

#payment_intent_delayed_notification?(payment_intent) ⇒ Boolean

Returns:

  • (Boolean)


18
19
20
21
22
23
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 18

def payment_intent_delayed_notification?(payment_intent)
  payment_method = payment_intent.payment_method
  return false unless payment_method.respond_to?(:type)

  payment_intent.payment_method.type.in?(DELAYED_NOTIFICATION_PAYMENT_METHOD_TYPES)
end

#payment_intent_manual_capture?(payment_intent) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 40

def payment_intent_manual_capture?(payment_intent)
  payment_intent.respond_to?(:capture_method) && payment_intent.capture_method == MANUAL_CAPTURE_METHOD
end

#payment_intent_requires_capture?(payment_intent) ⇒ Boolean

Returns:

  • (Boolean)


36
37
38
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 36

def payment_intent_requires_capture?(payment_intent)
  payment_intent.status == 'requires_capture'
end

#retrieve_payment_intent(payment_intent_id) ⇒ Object



91
92
93
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 91

def retrieve_payment_intent(payment_intent_id)
  send_request { |opts| Stripe::PaymentIntent.retrieve({ id: payment_intent_id, expand: ['payment_method'] }, opts) }
end

#update_payment_intent(payment_intent_id, amount_in_cents, order, payment_method_id = nil) ⇒ Spree::PaymentResponse

Updates a Stripe payment intent for the order

Parameters:

  • payment_intent_id (String)

    Stripe payment intent id

  • amount_in_cents (Integer)

    the amount in cents

  • order (Spree::Order)

    the order to update the payment intent for

  • payment_method_id (String) (defaults to: nil)

    Stripe payment method id to use, eg. a card token

Returns:

  • (Spree::PaymentResponse)

    the response from the payment intent update



76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'app/models/spree_stripe/gateway/payment_intents.rb', line 76

def update_payment_intent(payment_intent_id, amount_in_cents, order, payment_method_id = nil)
  protect_from_error do
    payload = SpreeStripe::PaymentIntentPresenter.new(
      amount: amount_in_cents,
      order: order,
      customer: fetch_or_create_customer(order: order)&.profile_id,
      payment_method_id: payment_method_id
    ).call.slice(:amount, :currency, :payment_method, :shipping, :customer)

    response = send_request { |opts| Stripe::PaymentIntent.update(payment_intent_id, payload, opts) }

    success(response.id, response)
  end
end