here is how you can configure stripe in rails
Step 1:
create packages table
class CreatePackages < ActiveRecord::Migration[7.0]
def change
create_table :packages do |t|
t.string :name, default: ""
t.integer :price, default: 0
t.string :stripe_product_id
t.string :stripe_price_id
t.boolean :status, default: true
t.timestamps
end
end
end
Step 2:
we will create stripe product on after_create callback in package controller
class Package < ApplicationRecord
has_one_attached :avatar
validates :name, :price, presence: true
validates :avatar, content_type: { in: %w[image/png image/jpg image/jpeg image/webp], message: 'has not a valid image type' }
after_create :create_stripe_product
before_update :update_stripe_product
def update_stripe_product
if self.stripe_product_id.present?
if self.price != price_was
response = Stripe::Price.create(product: self.stripe_product_id, unit_amount: self.price*100, currency: 'usd')
Stripe::Product.update(self.stripe_product_id, {default_price: response["id"]})
Stripe::Price.update(self.stripe_price_id, {active: false}) #archive previous price
self.stripe_price_id = response["id"]
end
if self.name != name_was
images_array = self.avatar.present? ? [Rails.application.routes.url_helpers.rails_blob_url(self.avatar)] : [""]
Stripe::Product.update(self.stripe_product_id, { name: name, images: images_array })
end
Stripe::Product.update(self.stripe_product_id, { active: self.status }) if self.status != status_was
end
end
def create_stripe_product
image_link = self.avatar.present? ? [Rails.application.routes.url_helpers.rails_blob_url(self.avatar)] : [""]
response = Stripe::Product.create({
name: self.name,
images: image_link,
description: self.id,
default_price_data: {
unit_amount: (self.price)*100,
currency: 'usd'
}
})
self.update(stripe_product_id: response["id"], stripe_price_id: response["default_price"])
end
end
create_stripe_product callback will create product and a default price for that product (due to default_price_data attribute in product.create ) on stripe.
Edit product price
here is a little problem we can not edit stripe product, stripe not allow to edit price. So instead of edit price we will create new price and assign it to the specific product. like we did in update_stripe_product in after_update call back in this block
if self.price != price_was
response = Stripe::Price.create(product: self.stripe_product_id, unit_amount: self.price*100, currency: 'usd')
Stripe::Product.update(self.stripe_product_id, {default_price: response["id"]})
Stripe::Price.update(self.stripe_price_id, {active: false}) #archive previous price
self.stripe_price_id = response["id"]
end
here what we are doing is we are creating new price and add it in the specific product after that we archive the default price of the product that was already assign to the product by making active: false and then replace the stripe_price_id with the new price id in our local database to access it in future