I believe you're correct. Here's something similar to how I'm handling it now. I fetch the stripe customer, create a source from the token generated from stripe, set the source to the customer and then create a subscription on the customer with the plan and personally, I always pass in an idempotency key.
```
customer = current_user.stripe_customer
source = customer.sources.create({ source: token })
customer.default_source = source
customer.save
subscription = customer.subscriptions.create({ plan: plan }, { idempotency_key: unique_key })
```
It's kind of strange how it works. The client browser side of things only communicates to the Stripe servers. The Stripe servers respond back with a token. In our javascript, we then add the token to the form parameters and then submit our form to the application. So, we would have something like a plan name and then the generated stripeToken which gets sent to our servers (never the credit card information!). From there, we will do the actual charge. The stripeToken is really just a "preauthorization" rather than a purchase. We then create the idempotent key.
So, if you were to have it all in the create action of the subscriptions controller, it would look something like this.
However, I would move out the logic for creating the stripe customer and the subscription into a service object.
The unique_key can really be anything that will be unique. In this case, you could generate a timestamp for the user as an epoch time in milliseconds.
```
def create
begin
customer = current_user.stripe_customer
source = customer.sources.create({ source: params[:stripeToken] })
customer.default_source = source
customer.save
subscription = customer.subscriptions.create({ plan: 'plus' }, { idempotency_key: unique_key })
current_user.update(stripe_subscription_id: subscription.id)
redirect_to root_path, notice: 'Thanks for subscribing!'
rescue Stripe::CardError => e
flash.alert = e.message
render action: :new
end
end
private
def unique_key
@unique_key ||= Rails.cache.fetch(['stripe', current_user], expires_in: 5.minutes) { (Time.now.to_f * 1000000).to_i.to_s }
end
```