如何在Ruby on Rails中实现Stripe支付成功后向用户发送邮件
看起来你已经搞定了Stripe Webhook的基础处理逻辑,现在要给完成结账的用户自动发邮件对吧?我来一步步帮你实现这个功能:
在Stripe结账完成后发送用户邮件的实现方案
1. 从Stripe Session提取用户与订单信息
首先在你已有的checkout.session.completed分支里,我们可以从Stripe返回的Session对象中拿到用户邮箱,同时整理好订单商品信息,作为邮件内容的基础:
when 'checkout.session.completed' session = event.data.object # 获取用户邮箱(优先取Session里的直接邮箱,关联了Customer的话也可以从Customer对象取) customer_email = session.customer_email || session.customer&.email # 拉取并整理订单商品详情 session_with_expand = Stripe::Checkout::Session.retrieve({id: session.id, expand: ["line_items"] }) order_items = session_with_expand.line_items.data.map do |line_item| product = Product.find_by(stripe_product_id: line_item.price.product) product.increment!(:sales_count) # 格式化商品信息,方便在邮件里展示 "#{product.name} x #{line_item.quantity} - $#{line_item.price.unit_amount.to_f / 100}" end.join("\n") # 提取订单总额(Stripe返回的单位是分,转成美元) total_amount = session.amount_total.to_f / 100
2. 创建Action Mailer邮件模板
Rails里用Action Mailer来处理邮件发送最方便,先生成一个邮件控制器:
rails generate mailer OrderMailer thank_you
然后在app/mailers/order_mailer.rb里编写发送逻辑:
class OrderMailer < ApplicationMailer # 设置默认发件人 default from: '你的商城名称 <your-support-email@example.com>' def thank_you(customer_email, order_items, total_amount) # 把变量传递给视图模板 @order_items = order_items @total_amount = total_amount # 发送邮件 mail(to: customer_email, subject: '感谢你的订单!') end end
接下来编辑邮件的视图文件,分别准备HTML和纯文本格式(确保不同邮箱客户端都能正常显示):
- HTML格式(
app/views/order_mailer/thank_you.html.erb):
<h1>嗨~感谢你的订单!</h1> <p>你的订单详情如下:</p> <ul> <% @order_items.split("\n").each do |item| %> <li><%= item %></li> <% end %> </ul> <p>订单总额:$<%= @total_amount %></p> <p>如果有任何问题,随时联系我们哦!</p>
- 纯文本格式(
app/views/order_mailer/thank_you.text.erb):
嗨~感谢你的订单! 你的订单详情如下: <%= @order_items %> 订单总额:$<%= @total_amount %> 如果有任何问题,随时联系我们哦!
3. 在Webhook中触发邮件发送
回到你的WebhooksController,在整理好所有信息后调用邮件发送方法。重点:一定要用deliver_later异步发送,避免因为邮件服务延迟导致Stripe Webhook超时重试:
when 'checkout.session.completed' session = event.data.object customer_email = session.customer_email || session.customer&.email session_with_expand = Stripe::Checkout::Session.retrieve({id: session.id, expand: ["line_items"] }) order_items = session_with_expand.line_items.data.map do |line_item| product = Product.find_by(stripe_product_id: line_item.price.product) product.increment!(:sales_count) "#{product.name} x #{line_item.quantity} - $#{line_item.price.unit_amount.to_f / 100}" end.join("\n") total_amount = session.amount_total.to_f / 100 # 确保有邮箱才发送,同时捕获异常避免影响Webhook响应 if customer_email.present? begin OrderMailer.thank_you(customer_email, order_items, total_amount).deliver_later rescue => e Rails.logger.error "订单邮件发送失败: #{e.message}" end end
4. 额外注意事项
- 测试验证:开发环境可以用
letter_openergem直接在浏览器查看发送的邮件;也可以用Stripe测试模式模拟结账完成事件,验证Webhook和邮件流程是否正常。 - 个性化优化:如果你的系统有本地用户模型,可以通过邮箱关联到用户,在邮件里添加更多个性化内容(比如用户名、历史订单入口等)。
- 重试机制:如果邮件发送失败,Rails的异步任务队列(比如Sidekiq)会自动重试,确保用户能收到邮件。
内容的提问来源于stack exchange,提问作者StrikerGs
相关产品推荐
相关产品推荐

