pay-rails / pay

Payments for Ruby on Rails apps
https://github.com/pay-rails/pay
MIT License
1.98k stars 316 forks source link

[BUG] Incorrect documentation for setting up Lemon Squeezy #1103

Closed harrison-broadbent closed 4 weeks ago

harrison-broadbent commented 4 weeks ago

Bug Report

In the documentation for setting up Lemon Squeezy, under "Creating Customers", the instructions state to run this code:

# Set the payment processor
@user.set_payment_processor :lemon_squeezy

# Create the customer on Lemon Squeezy
@user.payment_processor.customer

I believe this is incorrect.

Calling #customer returns a NoMethodError:

User.first.payment_processor.customer
Line 10:in `<main>': undefined method `customer' for an instance of Pay::LemonSqueezy::Customer (NoMethodError)
Did you mean?  customer_name

After hours of banging my head against the wall, I believe the correct method to call is @user.payment_processor.api_record (link) — this will find or create a customer in Lemon Squeezy, and create the matching LemonSqueezy::Customer locally.

The webhooks for a subscription or charge won't process correctly unless api_record has been called prior to a customer checking out and paying.

Fix

I propose the following to fix this:

  1. Fix the code block

As a very first step, lets fix the example code block to call the correct method:

# Set the payment processor
@user.set_payment_processor :lemon_squeezy

# Create the customer on Lemon Squeezy or retrieve an existing customer
@user.payment_processor.api_record
  1. Emphasize the need to call api_record before a user attempts a subscription or charge

Given that forgetting to call this method leads to catastrophic failure in that no payment or subscription can be correctly setup for a User, I think we should make it extremely clear that this method must be called before attempting any one-time or subscription charges. Something like

[!WARNING]
You must call user.payment_processor.api_record before attempting any one-time or subscription charges. This method sets up the correct customer record locally — if you don't call it first, the incoming webhooks from Lemon Squeezy can't be processed correctly and your subscriptions won't be created.

I've put it in an after-create callback which works well I think:

class User < ApplicationRecord
  ...
  after_create ->(user) { user.payment_processor.api_record if user.payment_processor.lemon_squeezy? }
end

We could suggest something similar in the docs, but it's not necessary.

excid3 commented 4 weeks ago

Any pay_customer.customer references in the docs do need updating to .api_record. This was renamed for clarity since pay_customer.customer was quite confusing.

If you call checkout with Lemon Squeezy, it will automatically create the Customer. LemonSqueezy requires you to go through their checkout, so charge and subscribe are no-ops.

See: https://github.com/pay-rails/pay/blob/main/app/models/pay/lemon_squeezy/customer.rb#L43-L63

harrison-broadbent commented 4 weeks ago

@excid3 Wow 🤦 I can't believe I missed that method!

Thanks