在Rails 7中不使用webpacker如何集成Stripe Elements?
Rails 7 + Importmap + Stimulus 集成 Stripe Elements 操作指南
1. 配置Stripe JS依赖
无需安装webpacker,直接通过importmap引入Stripe JS SDK:
运行以下命令完成自动配置:bin/importmap pin @stripe/stripe-js
也可以手动在config/importmap.rb中添加对应配置:
pin "@stripe/stripe-js", to: "https://ga.jspm.io/npm:@stripe/stripe-js@3.24.0/dist/stripe.esm.js"
注意:可以根据需求替换为对应版本的Stripe JS地址
2. 创建Stripe专用Stimulus控制器
在app/javascript/controllers目录下新建stripe_controller.js,内容如下:
import { Controller } from "@hotwired/stimulus" import { loadStripe } from "@stripe/stripe-js" export default class extends Controller { // 声明入参和target节点 static values = { publishableKey: String } static targets = ["cardElement", "errorMessage"] // 控制器挂载时初始化Stripe Elements async connect() { this.stripe = await loadStripe(this.publishableKeyValue) const elements = this.stripe.elements() // 创建卡输入组件,可自定义样式参数 this.card = elements.create("card", { style: { base: { fontSize: '16px' } } }) this.card.mount(this.cardElementTarget) // 实时监听输入错误提示 this.card.on("change", (event) => { this.errorMessageTarget.textContent = event.error?.message || "" this.errorMessageTarget.classList.toggle("hidden", !event.error) }) } // 提交支付逻辑 async submitPayment(e) { e.preventDefault() const { error, paymentMethod } = await this.stripe.createPaymentMethod({ type: "card", card: this.card }) if (error) { this.errorMessageTarget.textContent = error.message this.errorMessageTarget.classList.remove("hidden") return } // 提交支付凭证到后端完成支付 const response = await fetch("/payments", { method: "POST", headers: { "Content-Type": "application/json", "X-CSRF-Token": document.querySelector("meta[name='csrf-token']").content }, body: JSON.stringify({ payment_method_id: paymentMethod.id }) }) if (response.ok) { // 支付成功后自定义跳转逻辑 window.location.href = "/orders/success" } else { const res = await response.json() this.errorMessageTarget.textContent = res.error this.errorMessageTarget.classList.remove("hidden") } } }
3. 视图层接入
在需要展示支付表单的ERB视图中添加如下代码,关联Stimulus控制器:
<!-- 注入Stripe公钥,建议通过Rails Credentials管理,不要硬编码 --> <div data-controller="stripe" data-stripe-publishable-key-value="<%= Rails.application.credentials.stripe[:publishable_key] %>"> <!-- Stripe Elements挂载节点 --> <div data-stripe-target="cardElement" class="border p-3 rounded mb-3"></div> <!-- 错误提示节点 --> <p data-stripe-target="errorMessage" class="text-red-500 mb-3 hidden"></p> <!-- 支付提交按钮 --> <button data-action="stripe#submitPayment" class="bg-blue-500 text-white px-4 py-2 rounded">确认支付</button> </div>
注意:务必配置路由post "/payments", to: "payments#create"匹配后端接口
4. 后端配置
4.1 安装Stripe Ruby SDK
在Gemfile中添加:gem 'stripe'
运行bundle install完成安装。
4.2 配置Stripe密钥
新建config/initializers/stripe.rb:
Stripe.api_key = Rails.application.credentials.stripe[:secret_key]
注意:测试环境使用Stripe测试密钥,生产环境切换为生产密钥
4.3 支付接口实现
新建app/controllers/payments_controller.rb:
class PaymentsController < ApplicationController before_action :authenticate_user! # 根据自身业务调整权限校验 def create # 从当前用户的待支付订单获取金额,禁止使用前端传递的金额避免被篡改 order = current_user.orders.where(status: :pending).last return render json: { error: "无待支付订单" }, status: :bad_request unless order payment_intent = Stripe::PaymentIntent.create( amount: order.amount_cents, # 金额单位为分 currency: 'cny', # 按需切换对应货币单位 payment_method: params[:payment_method_id], confirm: true, automatic_payment_methods: { enabled: true, allow_redirects: 'never' } ) if payment_intent.status == 'succeeded' order.update!(status: :paid, payment_intent_id: payment_intent.id) render json: { success: true }, status: :ok else render json: { error: "支付失败,请重试" }, status: :unprocessable_entity end rescue Stripe::CardError => e render json: { error: e.message }, status: :payment_required end end
常见排查点
- 确认Stimulus控制器已正常注册,Rails 7默认自动加载controllers目录下的所有控制器,无需手动配置
- 检查Stripe公钥、密钥是否和当前使用环境匹配,测试环境无法使用生产密钥
- 确认跨域配置、CSRF Token是否正常传递,避免后端接口请求失败
- 若支付需要跳转3DS验证,可调整
automatic_payment_methods的allow_redirects参数,自行补充跳转逻辑
内容的提问来源于stack exchange,提问作者Samuel Da Costa
相关产品推荐
相关产品推荐

