Class: Pay::Stripe::Billable
- Inherits:
-
Object
- Object
- Pay::Stripe::Billable
- Defined in:
- lib/pay/stripe/billable.rb
Instance Attribute Summary collapse
-
#billable ⇒ Object
readonly
Returns the value of attribute billable.
Class Method Summary collapse
Instance Method Summary collapse
- #billing_portal(**options) ⇒ Object
-
#charge(amount, options = {}) ⇒ Object
Handles Billable#charge.
- #checkout(**options) ⇒ Object
- #checkout_charge(amount:, name:, quantity: 1, **options) ⇒ Object
- #create_setup_intent ⇒ Object
-
#customer ⇒ Object
Handles Billable#customer.
-
#initialize(billable) ⇒ Billable
constructor
A new instance of Billable.
- #invoice!(options = {}) ⇒ Object
- #processor_subscription(subscription_id, options = {}) ⇒ Object
-
#subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options) ⇒ Object
Handles Billable#subscribe.
-
#sync_card_from_stripe ⇒ Object
Used by webhooks when the customer or source changes.
- #trial_end_date(stripe_sub) ⇒ Object
- #upcoming_invoice ⇒ Object
-
#update_card(payment_method_id) ⇒ Object
Handles Billable#update_card.
-
#update_card_on_file(card) ⇒ Object
Save the card to the database as the user’s current card.
- #update_email! ⇒ Object
Constructor Details
#initialize(billable) ⇒ Billable
Returns a new instance of Billable.
22 23 24 |
# File 'lib/pay/stripe/billable.rb', line 22 def initialize(billable) @billable = billable end |
Instance Attribute Details
#billable ⇒ Object (readonly)
Returns the value of attribute billable.
6 7 8 |
# File 'lib/pay/stripe/billable.rb', line 6 def billable @billable end |
Class Method Details
.default_url_options ⇒ Object
17 18 19 |
# File 'lib/pay/stripe/billable.rb', line 17 def Rails.application.config.action_mailer. || {} end |
Instance Method Details
#billing_portal(**options) ⇒ Object
228 229 230 231 232 233 234 |
# File 'lib/pay/stripe/billable.rb', line 228 def billing_portal(**) args = { customer: processor_id, return_url: .delete(:return_url) || root_url } ::Stripe::BillingPortal::Session.create(args.merge(), {stripe_account: stripe_account}) end |
#charge(amount, options = {}) ⇒ Object
Handles Billable#charge
Returns Pay::Charge
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/pay/stripe/billable.rb', line 53 def charge(amount, = {}) stripe_customer = customer args = { amount: amount, confirm: true, confirmation_method: :automatic, currency: "usd", customer: stripe_customer.id, payment_method: stripe_customer.invoice_settings.default_payment_method }.merge() payment_intent = ::Stripe::PaymentIntent.create(args, {stripe_account: stripe_account}) Pay::Payment.new(payment_intent).validate # Create a new charge object 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)
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/pay/stripe/billable.rb', line 185 def checkout(**) args = { customer: processor_id, payment_method_types: ["card"], mode: "payment", # These placeholder URLs will be replaced in a following step. success_url: .delete(:success_url) || root_url, cancel_url: .delete(:cancel_url) || root_url } # Line items are optional if (line_items = .delete(:line_items)) args[:line_items] = Array.wrap(line_items).map { |item| if item.is_a? Hash item else {price: item, quantity: .fetch(:quantity, 1)} end } end ::Stripe::Checkout::Session.create(args.merge(), {stripe_account: stripe_account}) 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)
213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/pay/stripe/billable.rb', line 213 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_setup_intent ⇒ Object
154 155 156 |
# File 'lib/pay/stripe/billable.rb', line 154 def create_setup_intent ::Stripe::SetupIntent.create({customer: processor_id, usage: :off_session}, {stripe_account: stripe_account}) end |
#customer ⇒ Object
Handles Billable#customer
Returns Stripe::Customer
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/pay/stripe/billable.rb', line 29 def customer stripe_customer = if processor_id? ::Stripe::Customer.retrieve(processor_id, {stripe_account: stripe_account}) else sc = ::Stripe::Customer.create({email: email, name: customer_name}, {stripe_account: stripe_account}) billable.update(processor: :stripe, processor_id: sc.id, stripe_account: stripe_account) sc end # Update the user's card on file if a token was passed in if card_token.present? payment_method = ::Stripe::PaymentMethod.attach(card_token, {customer: stripe_customer.id}, {stripe_account: stripe_account}) stripe_customer = ::Stripe::Customer.update(stripe_customer.id, {invoice_settings: {default_payment_method: payment_method.id}}, {stripe_account: stripe_account}) update_card_on_file(payment_method.card) end stripe_customer rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#invoice!(options = {}) ⇒ Object
136 137 138 139 |
# File 'lib/pay/stripe/billable.rb', line 136 def invoice!( = {}) return unless processor_id? ::Stripe::Invoice.create(.merge(customer: processor_id), {stripe_account: stripe_account}).pay end |
#processor_subscription(subscription_id, options = {}) ⇒ Object
132 133 134 |
# File 'lib/pay/stripe/billable.rb', line 132 def processor_subscription(subscription_id, = {}) ::Stripe::Subscription.retrieve(.merge(id: subscription_id), {stripe_account: stripe_account}) end |
#subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **options) ⇒ Object
Handles Billable#subscribe
Returns Pay::Subscription
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/pay/stripe/billable.rb', line 77 def subscribe(name: Pay.default_product_name, plan: Pay.default_plan_name, **) quantity = .delete(:quantity) || 1 opts = { expand: ["pending_setup_intent", "latest_invoice.payment_intent"], 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 card if needed opts[:customer] = customer.id # Create subscription on Stripe stripe_sub = ::Stripe::Subscription.create(opts, {stripe_account: stripe_account}) # Save Pay::Subscription subscription = Pay::Stripe::Subscription.sync(stripe_sub.id, object: stripe_sub, name: name) # No trial, card requires SCA if subscription.incomplete? Pay::Payment.new(stripe_sub.latest_invoice.payment_intent).validate # Trial, card requires SCA elsif subscription.on_trial? && stripe_sub.pending_setup_intent Pay::Payment.new(stripe_sub.pending_setup_intent).validate end subscription rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#sync_card_from_stripe ⇒ Object
Used by webhooks when the customer or source changes
146 147 148 149 150 151 152 |
# File 'lib/pay/stripe/billable.rb', line 146 def sync_card_from_stripe if (payment_method_id = customer.invoice_settings.default_payment_method) update_card_on_file ::Stripe::PaymentMethod.retrieve(payment_method_id, {stripe_account: stripe_account}).card else billable.update(card_type: nil, card_last4: nil) end end |
#trial_end_date(stripe_sub) ⇒ Object
158 159 160 161 |
# File 'lib/pay/stripe/billable.rb', line 158 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
141 142 143 |
# File 'lib/pay/stripe/billable.rb', line 141 def upcoming_invoice ::Stripe::Invoice.upcoming({customer: processor_id}, {stripe_account: stripe_account}) end |
#update_card(payment_method_id) ⇒ Object
Handles Billable#update_card
Returns true if successful
114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/pay/stripe/billable.rb', line 114 def update_card(payment_method_id) stripe_customer = customer return true if payment_method_id == stripe_customer.invoice_settings.default_payment_method payment_method = ::Stripe::PaymentMethod.attach(payment_method_id, {customer: stripe_customer.id}, {stripe_account: stripe_account}) ::Stripe::Customer.update(stripe_customer.id, {invoice_settings: {default_payment_method: payment_method.id}}, {stripe_account: stripe_account}) update_card_on_file(payment_method.card) true rescue ::Stripe::StripeError => e raise Pay::Stripe::Error, e end |
#update_card_on_file(card) ⇒ Object
Save the card to the database as the user’s current card
164 165 166 167 168 169 170 171 172 173 |
# File 'lib/pay/stripe/billable.rb', line 164 def update_card_on_file(card) billable.update!( card_type: card.brand.capitalize, card_last4: card.last4, card_exp_month: card.exp_month, card_exp_year: card.exp_year ) billable.card_token = nil end |
#update_email! ⇒ Object
128 129 130 |
# File 'lib/pay/stripe/billable.rb', line 128 def update_email! ::Stripe::Customer.update(processor_id, {email: email, name: customer_name}, {stripe_account: stripe_account}) end |