Rails Stripe webhook 更新钱包余额
Rails Stripe webhook to update wallet balance
最近怎么样?我需要一点帮助。
- 我正在开发一个允许用户购买 积分 的应用程序,该积分可用于预订
activities
- 积分存储在用户的
wallet
中,并通过多态wallet_entries
添加到其中(这些wallet_entries
连接到bookings
table 同样,当用户预订 activity 时,积分会被扣除)
- 我正在使用 Stripe 处理
payments
。当用户想要购买积分时,会创建一个 order
,它包含 credit_package
id 以及设置为 pending 的 "state" 属性。
- 我设法设置了 Stripe Checkout 并配置了一个 webhook,当支付成功
- 我的目标是在 Stripe 的 Webhook 更新
order's
状态时创建一个 wallet_entry
。所述 wallet_entry
包含 number_of_credits
和 wallet
参考等信息,以便使用正确的 number_of_credits
更新用户的 wallet
余额
- 我尝试在处理 Stripe 事件的控制器中执行此操作,我将其包装在一个原子事务中以确保仅当
order's
state 更新为 paid
- Webhook 正在成功更新
order's
state 但如果我添加更多行就会中断,这是我在 Stripe Webhooks 日志中遇到的错误:
NameError in StripeEvent::WebhookController#event undefined local variable or method current_user for <StripeCheckoutSessionService:0x000056103da42a38&>;
。我的猜测是这个逻辑应该在别处处理。
- 这是我的文件:
条纹初始化程序
Rails.configuration.stripe = {
publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
secret_key: ENV['STRIPE_SECRET_KEY'],
signing_secret: ENV['STRIPE_WEBHOOK_SECRET_KEY']
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
StripeEvent.signing_secret = Rails.configuration.stripe[:signing_secret]
StripeEvent.configure do |events|
events.subscribe 'checkout.session.completed', StripeCheckoutSessionService.new
end
条纹结帐会话服务
class StripeCheckoutSessionService
def call(event)
ActiveRecord::Base.transaction do
order = Order.find_by(checkout_session_id: event.data.object.id)
order.update(state: 'paid')
# Extra stuff that breaks code
wallet = current_user.wallet
wallet_entry = WalletEntry.create!(type: "Deposit", total_credits: order.credit_package.number_of_credits, wallet: wallet, entryable: order)
wallet.credit_total += wallet_entry.total_credits
end
end
end
支付控制器
class PaymentsController < ApplicationController
before_action :authenticate_user!
def new
@order = Order.where(state: 'pending').find(params[:order_id])
end
end
订单控制器
class OrdersController < ApplicationController
def create
credit_package = CreditPackage.find(params[:credit_package_id].to_i)
order = Order.create!(credit_package: credit_package, amount: credit_package.price, state: 'pending', amount_of_packages: 1 )
session = Stripe::Checkout::Session.create(
payment_method_types: ['card'],
line_items: [{
name: credit_package.name,
amount: credit_package.price_cents,
currency: 'eur',
quantity: order.amount_of_packages
}],
success_url: order_url(order),
cancel_url: order_url(order)
)
order.update(checkout_session_id: session.id)
redirect_to new_order_payment_path(order)
end
def show
@order = Order.find(params[:id])
end
end
路线
Rails.application.routes.draw do
get 'user_interests/destroy'
# Admin dashboard routes
namespace :admin do
resources :activities
resources :bookings
resources :coaches
resources :coach_profiles, except: :index
resources :coach_activities, except: :index
resources :activity_sessions
resources :taggings, except: :index
resources :tags
resources :users
resources :user_profiles, except: :index
resources :user_interests, except: :index
root to: 'coaches#index'
end
devise_for :coaches, controllers: {
sessions: 'coaches/sessions'
}
devise_for :users, controllers: {
sessions: 'users/sessions'
}
match '/users/:id', :to => 'users#destroy', :as => :destroy_user, :via => :delete
root 'pages#home'
# static pages
get 'pages/contact'
get 'pages/nousrejoindre'
get 'pages/notrehistoire'
get 'pages/mentionslegales'
get 'pages/politiques'
get 'pages/listeactivites'
resources :activities do
resources :sessions, only: [:index]
end
resources :activity_sessions do
resources :bookings, only: [:create]
end
resources :orders, only: [:show, :create] do
resources :payments, only: :new
end
resources :bookings, only: [:destroy]
resources :contacts
resources :users
resources :user_profiles
resources :coach_profiles
resources :user_interests, only: [:destroy]
resources :credit_packages, only: [:index]
# route for stripe endpoint
mount StripeEvent::Engine, at: '/stripe-webhooks'
end
- 关于如何进行的任何建议?我愿意完全改变方法,甚至是支付网关架构。谢谢
对于 Stripe webhook,请求是由 Stripe 向您自己的应用程序发出的。在此请求的上下文中,没有登录用户,因此 current_user
在执行 wallet = current_user.wallet
.
的行上不可用
可能您需要做的是使用不同的方法来获取链接到此订单的用户。我可以想象你的 Order
模型以某种方式链接到用户,在这种情况下你可以这样做:
order = Order.find_by(checkout_session_id: event.data.object.id)
order.update(state: 'paid')
wallet = order.user.wallet
最近怎么样?我需要一点帮助。
- 我正在开发一个允许用户购买 积分 的应用程序,该积分可用于预订
activities
- 积分存储在用户的
wallet
中,并通过多态wallet_entries
添加到其中(这些wallet_entries
连接到bookings
table 同样,当用户预订 activity 时,积分会被扣除) - 我正在使用 Stripe 处理
payments
。当用户想要购买积分时,会创建一个order
,它包含credit_package
id 以及设置为 pending 的 "state" 属性。 - 我设法设置了 Stripe Checkout 并配置了一个 webhook,当支付成功
- 我的目标是在 Stripe 的 Webhook 更新
order's
状态时创建一个wallet_entry
。所述wallet_entry
包含number_of_credits
和wallet
参考等信息,以便使用正确的number_of_credits
更新用户的 - 我尝试在处理 Stripe 事件的控制器中执行此操作,我将其包装在一个原子事务中以确保仅当
order's
state 更新为 paid - Webhook 正在成功更新
order's
state 但如果我添加更多行就会中断,这是我在 Stripe Webhooks 日志中遇到的错误:NameError in StripeEvent::WebhookController#event undefined local variable or method current_user for <StripeCheckoutSessionService:0x000056103da42a38&>;
。我的猜测是这个逻辑应该在别处处理。 - 这是我的文件:
wallet
余额
条纹初始化程序
Rails.configuration.stripe = {
publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'],
secret_key: ENV['STRIPE_SECRET_KEY'],
signing_secret: ENV['STRIPE_WEBHOOK_SECRET_KEY']
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
StripeEvent.signing_secret = Rails.configuration.stripe[:signing_secret]
StripeEvent.configure do |events|
events.subscribe 'checkout.session.completed', StripeCheckoutSessionService.new
end
条纹结帐会话服务
class StripeCheckoutSessionService
def call(event)
ActiveRecord::Base.transaction do
order = Order.find_by(checkout_session_id: event.data.object.id)
order.update(state: 'paid')
# Extra stuff that breaks code
wallet = current_user.wallet
wallet_entry = WalletEntry.create!(type: "Deposit", total_credits: order.credit_package.number_of_credits, wallet: wallet, entryable: order)
wallet.credit_total += wallet_entry.total_credits
end
end
end
支付控制器
class PaymentsController < ApplicationController
before_action :authenticate_user!
def new
@order = Order.where(state: 'pending').find(params[:order_id])
end
end
订单控制器
class OrdersController < ApplicationController
def create
credit_package = CreditPackage.find(params[:credit_package_id].to_i)
order = Order.create!(credit_package: credit_package, amount: credit_package.price, state: 'pending', amount_of_packages: 1 )
session = Stripe::Checkout::Session.create(
payment_method_types: ['card'],
line_items: [{
name: credit_package.name,
amount: credit_package.price_cents,
currency: 'eur',
quantity: order.amount_of_packages
}],
success_url: order_url(order),
cancel_url: order_url(order)
)
order.update(checkout_session_id: session.id)
redirect_to new_order_payment_path(order)
end
def show
@order = Order.find(params[:id])
end
end
路线
Rails.application.routes.draw do
get 'user_interests/destroy'
# Admin dashboard routes
namespace :admin do
resources :activities
resources :bookings
resources :coaches
resources :coach_profiles, except: :index
resources :coach_activities, except: :index
resources :activity_sessions
resources :taggings, except: :index
resources :tags
resources :users
resources :user_profiles, except: :index
resources :user_interests, except: :index
root to: 'coaches#index'
end
devise_for :coaches, controllers: {
sessions: 'coaches/sessions'
}
devise_for :users, controllers: {
sessions: 'users/sessions'
}
match '/users/:id', :to => 'users#destroy', :as => :destroy_user, :via => :delete
root 'pages#home'
# static pages
get 'pages/contact'
get 'pages/nousrejoindre'
get 'pages/notrehistoire'
get 'pages/mentionslegales'
get 'pages/politiques'
get 'pages/listeactivites'
resources :activities do
resources :sessions, only: [:index]
end
resources :activity_sessions do
resources :bookings, only: [:create]
end
resources :orders, only: [:show, :create] do
resources :payments, only: :new
end
resources :bookings, only: [:destroy]
resources :contacts
resources :users
resources :user_profiles
resources :coach_profiles
resources :user_interests, only: [:destroy]
resources :credit_packages, only: [:index]
# route for stripe endpoint
mount StripeEvent::Engine, at: '/stripe-webhooks'
end
- 关于如何进行的任何建议?我愿意完全改变方法,甚至是支付网关架构。谢谢
对于 Stripe webhook,请求是由 Stripe 向您自己的应用程序发出的。在此请求的上下文中,没有登录用户,因此 current_user
在执行 wallet = current_user.wallet
.
可能您需要做的是使用不同的方法来获取链接到此订单的用户。我可以想象你的 Order
模型以某种方式链接到用户,在这种情况下你可以这样做:
order = Order.find_by(checkout_session_id: event.data.object.id)
order.update(state: 'paid')
wallet = order.user.wallet