-
-
Notifications
You must be signed in to change notification settings - Fork 338
Description
I'm experiencing an undefined method 'payment_intent'
error in Pay 11.1.1 when syncing older Stripe subscriptions.
The Error
gems/stripe-15.3.0/lib/stripe/stripe_object.rb:417:in `Stripe::StripeObject#method_missing': undefined method 'payment_intent' for #<Stripe::StripeObject:0x00007a3334feabf0> (NoMethodError)
from gems/pay-11.1.1/app/models/pay/stripe/subscription.rb:106:in `block in Pay::Stripe::Subscription.sync'
from gems/pay-11.1.1/app/models/pay/stripe/subscription.rb:104:in `Array#each'
from gems/pay-11.1.1/app/models/pay/stripe/subscription.rb:104:in `Pay::Stripe::Subscription.sync'
from gems/pay-11.1.1/app/models/pay/stripe/customer.rb:154:in `block in Pay::Stripe::Customer#sync_subscriptions'
The Problem
Location: pay-11.1.1/app/models/pay/stripe/subscription.rb:104-107
The code assumes a nested structure that doesn't exist in Stripe's API:
Array(invoice.try(:payments)).each do |invoice_payment|
next unless invoice_payment.status == "paid"
Pay::Stripe::Charge.sync_payment_intent(invoice_payment.payment.payment_intent, stripe_account: pay_subscription.stripe_account)
end
The code tries to access invoice_payment.payment.payment_intent
, but:
- For some invoices (especially older ones from 2018-2019),
invoice.payments
returnsnil
- When payments do exist, they don't have a nested
.payment
property - The code expects
invoice_payment.payment.payment_intent
but this structure doesn't match Stripe's API
Environment
- Pay gem version: 11.1.1
- Stripe gem version: 15.3.0
- Ruby version: 3.4.2
- Rails version: 8.0.2
How to reproduce
- Have a user with an older Stripe subscription (especially from 2018-2019)
- Call
user.payment_processor.sync_subscriptions(status: "all")
- The error occurs when processing invoice payments
Example subscription that triggers this:
- Subscription ID:
sub_DqVLKzsG0JzYO9
(canceled, from 2018) - Invoice ID:
in_1E2xmHJCY2L6VQsLEEaoHvbA
invoice.payments
returnsnil
Note: This issue appears to primarily affect older subscriptions. The Stripe API response structure for invoices has evolved over time, and older invoices might not have the payments
array or payment intent data that the Pay gem expects. Payment Intents were introduced by Stripe in 2018-2019, so invoices before that time won't have this data.
Temporary Workaround
Create config/initializers/pay_stripe_subscription_patch.rb
:
module PayStripeSubscriptionPatch
def sync(object = nil, **options)
super
rescue NoMethodError => e
if e.message.include?("payment_intent")
Rails.logger.warn "Pay gem bug: #{e.message}. Skipping payment intent sync."
# Continue without the payment intent processing
# The subscription will still be synced, just without the payment intent data
pay_subscription
else
raise
end
end
end
Rails.application.config.after_initialize do
if defined?(Pay::Stripe::Subscription)
Pay::Stripe::Subscription.singleton_class.prepend(PayStripeSubscriptionPatch)
end
end
Suggested Fix
The code should handle cases where:
invoice.payments
is nil- Payment objects don't have the expected nested structure
- Older invoices that predate Payment Intents
Possible solutions:
- Add nil checks before accessing nested properties
- Check the invoice date or API version to determine if payment intents are available
- Gracefully skip payment intent sync for invoices that don't support it
Related Issues
This appears to be similar to #1123 where there was a method_missing
error with Stripe objects not having expected methods.