Rails纯API项目集成Stripe报错:禁止直接发送信用卡号
Rails纯API集成Stripe信用卡支付报错问题
测试信用卡支付时触发错误:
"Sending credit card numbers directly to the Stripe API is generally unsafe. We suggest you use test tokens that map to the test card you are using, see https://stripe.com/docs/testing."
我清楚不能直接将信用卡信息传给Stripe API,已经尝试先调用Stripe::Token生成令牌,再传入Stripe::Charge方法,但仍报上述错误。
相关代码
用户模型(User)
class User < ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :trackable, :validatable include DeviseTokenAuth::Concerns::User validates :stripe_id, presence: true has_many :orders before_validation :create_on_stripe, on: :create def create_on_stripe params = { email: self.email, name: self.first_name } response = Stripe::Customer.create(params) pry self.stripe_id = response.id end end
订单模型(Order)
class Order < ApplicationRecord attr_accessor :credit_card_number, :credit_card_exp_month, :credit_card_exp_year, :credit_card_cvv belongs_to :user has_one :payment after_create :create_payment enum payment_method: %i[credit_card] def create_payment params = { order_id: id, credit_card_number: credit_card_number, credit_card_exp_month: credit_card_exp_month, credit_card_exp_year: credit_card_exp_year, credit_card_cvv: credit_card_cvv } Payment.create!(params) end end
支付模型(Payment)
class Payment < ApplicationRecord attr_accessor :credit_card_number, :credit_card_exp_month, :credit_card_exp_year, :credit_card_cvv belongs_to :order before_validation :create_on_stripe def create_on_stripe token = get_token params = { amount: order.amount_cents, currency: 'usd', source: token} response = Stripe::Charge.create(params) self.stripe_id = response.id end def get_token Stripe::Token.create({ card: { number: credit_card_number, exp_month: credit_card_exp_month, exp_year: credit_card_exp_year, cvc: credit_card_cvv, } }) end end
订单控制器(OrdersController)
module Api module V1 class OrdersController < Api::V1::ApiController include Pundit after_action :verify_authorized, except: [:create] def create @order = Order.new(order_params.merge(amount_cents: 500, payment_method: 'credit_card')) if @order.save render json: { order: @order, payment: @order.payment }, status: :created else render json: @response.errors, status: :unprocessable_entity end end private def order_params params.require(:data).permit(:user_id, :credit_card_number, :credit_card_exp_month, :credit_card_exp_year, :credit_card_cvv) end end end end
Postman请求示例
POST http://localhost:3000/api/v1/orders { "data": { "user_id": 1, "credit_card_number": "4000056655665556", "credit_card_exp_month": "12", "credit_card_exp_year": "2030", "credit_card_cvv": "123" } }
所有参数能正常传递到get_token方法,但在此处触发上述错误。
解决方案
错误核心原因:Stripe禁止在服务器端直接创建Token(除非持有PCI合规资质),服务器端仅能使用客户端生成的Token或Stripe官方提供的测试Token。
具体修正步骤:
- 移除服务器端
Stripe::Token.create的逻辑,改为接收客户端生成的Token,或直接使用Stripe测试Token(如tok_visa对应测试卡4242424242424242)。 - 修改订单控制器参数,接收
stripe_token而非信用卡四要素:def order_params params.require(:data).permit(:user_id, :stripe_token) end - 调整订单模型的
create_payment方法,传递stripe_token:class Order < ApplicationRecord attr_accessor :stripe_token # ... 其他原有代码 def create_payment Payment.create!(order_id: id, stripe_token: stripe_token) end end - 更新支付模型,直接用传入的Token创建Charge,并关联到已有Stripe客户:
class Payment < ApplicationRecord belongs_to :order before_validation :create_on_stripe attr_accessor :stripe_token def create_on_stripe params = { amount: order.amount_cents, currency: 'usd', source: stripe_token, customer: order.user.stripe_id } response = Stripe::Charge.create(params) self.stripe_id = response.id end end - 测试阶段可直接使用Stripe测试Token发起请求:
{ "data": { "user_id": 1, "stripe_token": "tok_visa" } }
- 移除服务器端
额外建议:
- 始终将支付方式关联到Stripe客户,便于后续实现订阅、重复支付等功能,符合Stripe设计规范。
- 确保服务器端使用Stripe测试密钥,避免误操作生产环境。
内容的提问来源于stack exchange,提问作者Rodrigo Ladrón de Guevara
相关产品推荐
相关产品推荐

