Class: Pay::Stripe::Billable
- Inherits:
-
Object
- Object
- Pay::Stripe::Billable
- Defined in:
- lib/pay/stripe/billable.rb
Instance Attribute Summary collapse
-
#pay_customer ⇒ Object
readonly
Returns the value of attribute pay_customer.
Class Method Summary collapse
Instance Method Summary collapse
- #add_payment_method(payment_method_id, default: false) ⇒ Object
- #authorize(amount, options = {}) ⇒ Object
- #billing_portal(**options) ⇒ Object
- #charge(amount, options = {}) ⇒ Object
- #checkout(**options) ⇒ Object
- #checkout_charge(amount:, name:, quantity: 1, **options) ⇒ Object
- #create_setup_intent(options = {}) ⇒ Object
-
#customer ⇒ Object
Retrieves a Stripe::Customer object.
-
#customer_attributes ⇒ Object
Returns a hash of attributes for the Stripe::Customer object.
-
#initialize(pay_customer) ⇒ Billable
constructor
A new instance of Billable.
- #invoice!(options = {}) ⇒ Object
- #processor_subscription(subscription_id, options = {}) ⇒ Object
-
#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 ⇒ Object
Syncs a customer's subscriptions from Stripe to the database.
- #trial_end_date(stripe_sub) ⇒ Object
- #upcoming_invoice ⇒ Object
-
#update_customer!(**attributes) ⇒ Object
Syncs name and email to Stripe::Customer You can also pass in other attributes that will be merged into the default attributes.
Constructor Details
#initialize(pay_customer) ⇒ Billable
Returns a new instance of Billable.
21 22 23 |
# File 'lib/pay/stripe/billable.rb', line 21 def initialize(pay_customer) @pay_customer = pay_customer end |
Instance Attribute Details
#pay_customer ⇒ Object (readonly)
Returns the value of attribute pay_customer.
6 7 8 |
# File 'lib/pay/stripe/billable.rb', line 6 def pay_customer @pay_customer end |
Class Method Details
.default_url_options ⇒ Object
17 18 19 |
# File 'lib/pay/stripe/billable.rb', line 17 def self. Rails.application.config.action_mailer. || {} end |
Instance Method Details
#add_payment_method(payment_method_id, default: false) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/pay/stripe/billable.rb', line 134 def add_payment_method(payment_method_id, default: false) customer unless processor_id? payment_method = ::Stripe::PaymentMethod.attach(payment_method_id, {customer: processor_id}, ) if default ::Stripe::Customer.update(processor_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 |
#authorize(amount, options = {}) ⇒ Object
270 271 272 |
# File 'lib/pay/stripe/billable.rb', line 270 def (amount, = {}) charge(amount, .merge(capture_method: :manual)) end |
#billing_portal(**options) ⇒ Object
261 262 263 264 265 266 267 268 |
# File 'lib/pay/stripe/billable.rb', line 261 def billing_portal(**) customer unless processor_id? args = { customer: processor_id, return_url: .delete(:return_url) || root_url } ::Stripe::BillingPortal::Session.create(args.merge(), ) end |
#charge(amount, options = {}) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/pay/stripe/billable.rb', line 83 def charge(amount, = {}) add_payment_method(payment_method_token, default: true) if payment_method_token? payment_method = pay_customer.default_payment_method args = { amount: amount, confirm: true, currency: "usd", customer: processor_id, payment_method: payment_method&.processor_id }.merge() payment_intent = ::Stripe::PaymentIntent.create(args, ) Pay::Payment.new(payment_intent).validate charge = payment_intent.charges.first Pay::Stripe::Charge.sync(charge.id, object: charge) rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#checkout(**options) ⇒ Object
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)
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
# File 'lib/pay/stripe/billable.rb', line 212 def checkout(**) customer unless processor_id? args = { customer: processor_id, mode: "payment", # These placeholder URLs will be replaced in a following step. success_url: merge_session_id_param(.delete(:success_url) || root_url), cancel_url: merge_session_id_param(.delete(:cancel_url) || root_url) } # 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(), ) end |
#checkout_charge(amount:, name:, quantity: 1, **options) ⇒ Object
stripe.com/docs/api/checkout/sessions/create
checkout_charge(amount: 15_00, name: “T-shirt”, quantity: 2)
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/pay/stripe/billable.rb', line 245 def checkout_charge(amount:, name:, quantity: 1, **) customer unless processor_id? currency = .delete(:currency) || "usd" checkout( line_items: { price_data: { currency: currency, product_data: {name: name}, unit_amount: amount }, quantity: quantity }, ** ) end |
#create_setup_intent(options = {}) ⇒ Object
180 181 182 183 184 185 |
# File 'lib/pay/stripe/billable.rb', line 180 def create_setup_intent( = {}) ::Stripe::SetupIntent.create({ customer: processor_id, usage: :off_session }.merge(), ) end |
#customer ⇒ Object
Retrieves a Stripe::Customer object
Finds an existing Stripe::Customer if processor_id exists Creates a new Stripe::Customer using `customer_attributes` if empty processor_id
Updates the default payment method automatically if a payment_method_token is set
Returns a Stripe::Customer object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/pay/stripe/billable.rb', line 50 def customer stripe_customer = if processor_id? ::Stripe::Customer.retrieve({id: processor_id, expand: ["tax"]}, ) else sc = ::Stripe::Customer.create(customer_attributes.merge(expand: ["tax"]), ) pay_customer.update!(processor_id: sc.id, stripe_account: stripe_account) sc end if payment_method_token? payment_method = ::Stripe::PaymentMethod.attach(payment_method_token, {customer: stripe_customer.id}, ) pay_payment_method = save_payment_method(payment_method, default: false) pay_payment_method.make_default! pay_customer.payment_method_token = nil end stripe_customer rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#customer_attributes ⇒ Object
Returns a hash of attributes for the Stripe::Customer object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/pay/stripe/billable.rb', line 26 def customer_attributes owner = pay_customer.owner attributes = case owner.class.pay_stripe_customer_attributes when Symbol owner.send(owner.class.pay_stripe_customer_attributes, pay_customer) when Proc owner.class.pay_stripe_customer_attributes.call(pay_customer) end # Guard against attributes being returned nil attributes ||= {} {email: email, name: customer_name}.merge(attributes) end |
#invoice!(options = {}) ⇒ Object
171 172 173 174 |
# File 'lib/pay/stripe/billable.rb', line 171 def invoice!( = {}) return unless processor_id? ::Stripe::Invoice.create(.merge(customer: processor_id), ).pay end |
#processor_subscription(subscription_id, options = {}) ⇒ Object
167 168 169 |
# File 'lib/pay/stripe/billable.rb', line 167 def processor_subscription(subscription_id, = {}) ::Stripe::Subscription.retrieve(.merge(id: subscription_id), ) end |
#save_payment_method(payment_method, default:) ⇒ Object
Save the Stripe::PaymentMethod to the database
152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/pay/stripe/billable.rb', line 152 def save_payment_method(payment_method, default:) pay_payment_method = pay_customer.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 pay_customer.payment_methods.where.not(id: pay_payment_method.id).update_all(default: false) if default pay_payment_method.update!(attributes) # Reload the Rails association pay_customer.reload_default_payment_method pay_payment_method end |
#subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/pay/stripe/billable.rb', line 104 def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **) quantity = .delete(:quantity) opts = { expand: ["pending_setup_intent", "latest_invoice.payment_intent", "latest_invoice.charge.invoice"], items: [plan: plan, quantity: quantity], off_session: true }.merge() # Inherit trial from plan unless trial override was specified opts[:trial_from_plan] = true unless opts[:trial_period_days] # Load the Stripe customer to verify it exists and update payment method if needed opts[:customer] = 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? Pay::Payment.new(stripe_sub.latest_invoice.payment_intent).validate end subscription rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#sync_subscriptions ⇒ Object
Syncs a customer's subscriptions from Stripe to the database
193 194 195 196 197 198 199 200 |
# File 'lib/pay/stripe/billable.rb', line 193 def sync_subscriptions subscriptions = ::Stripe::Subscription.list({customer: customer}, ) subscriptions.map do |subscription| Pay::Stripe::Subscription.sync(subscription.id) end rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#trial_end_date(stripe_sub) ⇒ Object
187 188 189 190 |
# File 'lib/pay/stripe/billable.rb', line 187 def trial_end_date(stripe_sub) # Times in Stripe are returned in UTC stripe_sub.trial_end.present? ? Time.at(stripe_sub.trial_end) : nil end |
#upcoming_invoice ⇒ Object
176 177 178 |
# File 'lib/pay/stripe/billable.rb', line 176 def upcoming_invoice ::Stripe::Invoice.upcoming({customer: processor_id}, ) end |
#update_customer!(**attributes) ⇒ Object
Syncs name and email to Stripe::Customer You can also pass in other attributes that will be merged into the default attributes
74 75 76 77 78 79 80 81 |
# File 'lib/pay/stripe/billable.rb', line 74 def update_customer!(**attributes) customer unless processor_id? ::Stripe::Customer.update( processor_id, customer_attributes.merge(attributes), ) end |