Class: Pay::Stripe::Customer
- Inherits:
-
Customer
- Object
- Customer
- Pay::Stripe::Customer
- Includes:
- Routing
- Defined in:
- app/models/pay/stripe/customer.rb
Instance Method Summary collapse
- #add_payment_method(payment_method_id, default: false) ⇒ Object
- #api_record(expand: ["tax", "invoice_credit_balance"]) ⇒ Object
-
#api_record_attributes ⇒ Object
Returns a hash of attributes for the Stripe::Customer object.
- #authorize(amount, options = {}) ⇒ Object
- #billing_portal(**options) ⇒ Object
-
#charge(amount, options = {}) ⇒ Object
Charges an amount to the customer's default payment method.
- #checkout(**options) ⇒ Object
- #checkout_charge(amount:, name:, quantity: 1, **options) ⇒ Object
-
#create_meter_event(event_name, payload: {}, **options) ⇒ Object
Creates a meter event to bill for usage.
-
#create_payment_intent(amount, options = {}) ⇒ Object
Creates and returns a Stripe::PaymentIntent.
- #create_setup_intent(options = {}) ⇒ Object
- #customer_session(**options) ⇒ Object
- #invoice!(options = {}) ⇒ Object
- #preview_invoice(**options) ⇒ Object
-
#retry_past_due_subscriptions!(status: [:past_due]) ⇒ Object
Attempts to pay all past_due subscription invoices to bring them back to active state Pass in
status: []to include other subscription statuses. -
#save_payment_method(payment_method, default:) ⇒ Object
Save the Stripe::PaymentMethod to the database.
- #subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options) ⇒ Object
-
#sync_subscriptions(**options) ⇒ Object
Syncs a customer's subscriptions from Stripe to the database.
-
#terminal_charge(amount, options = {}) ⇒ Object
Used for creating Stripe Terminal charges.
- #update_api_record(**attributes) ⇒ Object
Methods included from Routing
Instance Method Details
#add_payment_method(payment_method_id, default: false) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'app/models/pay/stripe/customer.rb', line 85 def add_payment_method(payment_method_id, default: false) payment_method = ::Stripe::PaymentMethod.attach(payment_method_id, {customer: stripe_customer_id}, ) if default ::Stripe::Customer.update(stripe_customer_id, { invoice_settings: { default_payment_method: payment_method.id } }, ) end save_payment_method(payment_method, default: default) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#api_record(expand: ["tax", "invoice_credit_balance"]) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'app/models/pay/stripe/customer.rb', line 26 def api_record(expand: ["tax", "invoice_credit_balance"]) with_lock do if processor_id? ::Stripe::Customer.retrieve({id: processor_id, expand: }, ) else ::Stripe::Customer.create(api_record_attributes.merge(expand: ), ).tap do |customer| update!(processor_id: customer.id, stripe_account: stripe_account) end end end rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#api_record_attributes ⇒ Object
Returns a hash of attributes for the Stripe::Customer object
12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'app/models/pay/stripe/customer.rb', line 12 def api_record_attributes attributes = case owner.class.pay_stripe_customer_attributes when Symbol owner.send(owner.class.pay_stripe_customer_attributes, self) when Proc owner.class.pay_stripe_customer_attributes.call(self) end # Guard against attributes being returned nil attributes ||= {} {email: email, name: customer_name}.merge(attributes) end |
#authorize(amount, options = {}) ⇒ Object
251 252 253 |
# File 'app/models/pay/stripe/customer.rb', line 251 def (amount, = {}) charge(amount, .merge(capture_method: :manual)) end |
#billing_portal(**options) ⇒ Object
234 235 236 237 238 239 240 241 242 |
# File 'app/models/pay/stripe/customer.rb', line 234 def billing_portal(**) args = { customer: stripe_customer_id, return_url: .delete(:return_url) || root_url } ::Stripe::BillingPortal::Session.create(args.merge(), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#charge(amount, options = {}) ⇒ Object
Charges an amount to the customer's default payment method
47 48 49 50 51 52 53 54 55 56 57 |
# File 'app/models/pay/stripe/customer.rb', line 47 def charge(amount, = {}) args = {confirm: true, payment_method: default_payment_method&.processor_id}.merge() payment_intent = create_payment_intent(amount, args) Pay::Payment.new(payment_intent).validate charge = payment_intent.latest_charge Pay::Stripe::Charge.sync(charge.id, object: charge, stripe_account: stripe_account) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#checkout(**options) ⇒ Object
https://stripe.com/docs/api/checkout/sessions/create
checkout(mode: "payment") checkout(mode: "setup") checkout(mode: "subscription")
checkout(line_items: "price_12345", quantity: 2) checkout(line_items: [{ price: "price_123" }, { price: "price_456" }]) checkout(line_items: "price_12345", allow_promotion_codes: true)
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'app/models/pay/stripe/customer.rb', line 178 def checkout(**) args = { customer: stripe_customer_id, mode: "payment" } # Hosted (the default) checkout sessions require a success_url and cancel_url if ["", "hosted_page"].include?([:ui_mode].to_s) args[:success_url] = merge_session_id_param(.delete(:success_url) || root_url) args[:cancel_url] = merge_session_id_param(.delete(:cancel_url) || root_url) end if [:return_url] args[:return_url] = merge_session_id_param(.delete(:return_url)) end # Line items are optional if (line_items = .delete(:line_items)) quantity = .delete(:quantity) || 1 args[:line_items] = Array.wrap(line_items).map { |item| if item.is_a? Hash item else { price: item, quantity: quantity } end } end ::Stripe::Checkout::Session.create(args.merge(), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#checkout_charge(amount:, name:, quantity: 1, **options) ⇒ Object
https://stripe.com/docs/api/checkout/sessions/create
checkout_charge(amount: 15_00, name: "T-shirt", quantity: 2)
219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'app/models/pay/stripe/customer.rb', line 219 def checkout_charge(amount:, name:, quantity: 1, **) currency = .delete(:currency) || "usd" checkout( line_items: { price_data: { currency: currency, product_data: {name: name}, unit_amount: amount }, quantity: quantity }, ** ) end |
#create_meter_event(event_name, payload: {}, **options) ⇒ Object
Creates a meter event to bill for usage
create_meter_event(:api_request, value: 1) create_meter_event(:api_request, token: 7)
265 266 267 268 269 270 271 272 |
# File 'app/models/pay/stripe/customer.rb', line 265 def create_meter_event(event_name, payload: {}, **) ::Stripe::Billing::MeterEvent.create({ event_name: event_name, payload: {stripe_customer_id: stripe_customer_id}.merge(payload) }.merge(), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#create_payment_intent(amount, options = {}) ⇒ Object
Creates and returns a Stripe::PaymentIntent
120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'app/models/pay/stripe/customer.rb', line 120 def create_payment_intent(amount, = {}) args = { amount: amount, currency: "usd", customer: stripe_customer_id, expand: Pay::Stripe::Charge::EXPAND.map { |option| "latest_charge.#{option}" }, return_url: root_url }.merge() ::Stripe::PaymentIntent.create(args, ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#create_setup_intent(options = {}) ⇒ Object
139 140 141 142 143 |
# File 'app/models/pay/stripe/customer.rb', line 139 def create_setup_intent( = {}) ::Stripe::SetupIntent.create({customer: stripe_customer_id, usage: :off_session}.merge(), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#customer_session(**options) ⇒ Object
244 245 246 247 248 249 |
# File 'app/models/pay/stripe/customer.rb', line 244 def customer_session(**) args = {customer: stripe_customer_id} ::Stripe::CustomerSession.create(args.merge(), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#invoice!(options = {}) ⇒ Object
145 146 147 148 149 |
# File 'app/models/pay/stripe/customer.rb', line 145 def invoice!( = {}) ::Stripe::Invoice.create(.merge(customer: stripe_customer_id), ).pay rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#preview_invoice(**options) ⇒ Object
151 152 153 154 155 |
# File 'app/models/pay/stripe/customer.rb', line 151 def preview_invoice(**) ::Stripe::Invoice.create_preview(.merge(customer: stripe_customer_id), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#retry_past_due_subscriptions!(status: [:past_due]) ⇒ Object
Attempts to pay all past_due subscription invoices to bring them back to active state
Pass in status: [] to include other subscription statuses
257 258 259 |
# File 'app/models/pay/stripe/customer.rb', line 257 def retry_past_due_subscriptions!(status: [:past_due]) subscriptions.where(status: Array.wrap(status)).each(&:pay_open_invoices) end |
#save_payment_method(payment_method, default:) ⇒ Object
Save the Stripe::PaymentMethod to the database
102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'app/models/pay/stripe/customer.rb', line 102 def save_payment_method(payment_method, default:) pay_payment_method = payment_methods.where(processor_id: payment_method.id).first_or_initialize attributes = Pay::Stripe::PaymentMethod.extract_attributes(payment_method).merge(default: default) # Ignore the payment method if it's already in the database payment_methods.where.not(id: pay_payment_method.id).update_all(default: false) if default pay_payment_method.update!(attributes) # Reload the Rails association reload_default_payment_method pay_payment_method end |
#subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'app/models/pay/stripe/customer.rb', line 59 def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **) quantity = .delete(:quantity) opts = { items: [price: plan, quantity: quantity] }.merge() # Load the Stripe customer to verify it exists and update payment method if needed opts[:customer] = stripe_customer_id # Create subscription on Stripe stripe_sub = ::Stripe::Subscription.create(opts.merge(Pay::Stripe::Subscription.), ) # Save Pay::Subscription subscription = Pay::Stripe::Subscription.sync(stripe_sub.id, object: stripe_sub, name: name) # No trial, payment method requires SCA if [:payment_behavior].to_s != "default_incomplete" && subscription.incomplete? payment_intent_id = stripe_sub.latest_invoice.payments.first.payment.payment_intent Pay::Payment.from_id(payment_intent_id, stripe_account: stripe_account).validate end subscription rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#sync_subscriptions(**options) ⇒ Object
Syncs a customer's subscriptions from Stripe to the database.
Note that by default canceled subscriptions are NOT returned by Stripe. In order to include them, use sync_subscriptions(status: "all").
159 160 161 162 163 164 165 166 |
# File 'app/models/pay/stripe/customer.rb', line 159 def sync_subscriptions(**) subscriptions = ::Stripe::Subscription.list(.with_defaults(customer: processor_id), ) subscriptions.map do |subscription| Pay::Stripe::Subscription.sync(subscription.id, stripe_account: stripe_account) end rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#terminal_charge(amount, options = {}) ⇒ Object
Used for creating Stripe Terminal charges
135 136 137 |
# File 'app/models/pay/stripe/customer.rb', line 135 def terminal_charge(amount, = {}) create_payment_intent(amount, .merge(payment_method_types: ["card_present"], capture_method: "manual")) end |
#update_api_record(**attributes) ⇒ Object
40 41 42 43 44 |
# File 'app/models/pay/stripe/customer.rb', line 40 def update_api_record(**attributes) ::Stripe::Customer.update(stripe_customer_id, api_record_attributes.merge(attributes), ) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |