PAYATHON 2026

安装 Mollie payments API 时出现 unpermitted_parameters

支付老李

结论

unpermitted parameters: _method, authenticity_token 是 Rails Strong Parameters 发出的提示,通常与 Mollie API 无关。它说明表单把 Rails 自动生成的字段传给了 permit,不能据此判断支付接口是否被调用。

问题更可能出在后续流程上:mollie.payments.create 只负责在服务端创建支付,不会自动打开 Mollie 的付款页面。创建成功后,还要把浏览器重定向到 Mollie 返回的 checkout URL。

正确的调用流程

完整的支付流程通常如下:

  1. 保存 reservation。
  2. 调用 Mollie 创建 payment。
  3. 保存 Mollie 返回的 payment ID。
  4. 通过 redirect_to 跳转到 Mollie 的付款页面。
  5. 支付完成后,Mollie 通过 redirectUrl 将用户带回站点。
  6. 服务端重新查询 payment 状态,不能只根据用户是否返回页面来判断支付成功。

以旧版 Mollie Ruby API 为例:

def create
  @reservation = Reservation.new(reservation_params)

  if @reservation.save
    mollie = Mollie::API::Client.new(ENV.fetch('MOLLIE_API_KEY'))

    payment = mollie.payments.create(
      amount: 10.00,
      description: "Reservation #{@reservation.id}",
      redirectUrl: reservation_url(@reservation)
    )

    @reservation.update(mollie_payment_id: payment.id)

    redirect_to payment.payment_url
  else
    render :new
  end
end

其中不能缺少最后的重定向:

redirect_to payment.payment_url

如果没有执行这行代码,即使 API 已成功创建 payment,用户也会继续停留在当前页面。

不同 gem 版本的字段可能不同

问题中的写法适用于较旧版本的 Mollie Ruby 客户端。新版客户端通常要求金额包含币种,参数名也改为 snake_case:

payment = mollie.payments.create(
  amount: {
    currency: 'EUR',
    value: '10.00'
  },
  description: "Reservation #{@reservation.id}",
  redirect_url: reservation_url(@reservation)
)

新版响应中的 checkout URL 也可能需要从链接对象中获取:

redirect_to payment._links.checkout.href

应当使用:

payment.payment_url

还是:

payment._links.checkout.href

要看项目实际安装的 gem 版本。不要混用不同版本文档里的参数格式。可以先通过日志确认返回对象,但不要输出完整对象,以免敏感信息被写入日志:

Rails.logger.info("Mollie payment created: #{payment.id}")

处理 unpermitted parameters

_method 和 authenticity_token 都是 Rails 的表单字段,不需要加入业务模型的允许参数。Strong Parameters 只应处理 reservation 下的嵌套字段:

private

def reservation_params
  params.require(:reservation).permit(
    :name,
    :email,
    :start_date,
    :end_date
  )
end

不要直接对整个 params 调用 permit:

# 不推荐
params.permit(:name, :email)

只要 reservation 的合法字段能够正常保存,这两项警告一般不会妨碍 Mollie API 调用。

检查保存条件

下面的判断不能说明 reservation 已成功保存:

if @reservation

对象只要已经创建,即使验证失败,通常也是真值。应该直接检查保存结果:

if @reservation.save
  # 创建 Mollie payment
else
  render :new
end

如果 reservation 已经在前面保存,也可以检查:

if @reservation.persisted?

其他注意事项

不要把 API 密钥直接写在 controller 中。问题里展示的测试密钥已经暴露,建议立即到 Mollie 后台撤销并重新生成,再通过环境变量读取:

mollie = Mollie::API::Client.new(ENV.fetch('MOLLIE_API_KEY'))

localhost 可以作为本机浏览器的返回地址,但 Mollie 的服务器无法访问你的本机。如果需要接收 webhook,就要使用 Mollie 能从公网访问的 HTTPS 地址。

Ruby 的 require 路径通常区分大小写。如果确实需要手动加载,应按照 gem 提供的路径编写,例如:

require 'mollie/api/client'

Rails 通过 Bundler 加载 gem 后,通常不需要在 controller 中再次 require。

创建支付失败时,SDK 一般会抛出异常。应记录清晰的错误信息,不要把异常当成普通的页面跳转处理:

begin
  payment = mollie.payments.create(payment_attributes)
  redirect_to payment.payment_url
rescue StandardError => e
  Rails.logger.error("Mollie payment creation failed: #{e.class}: #{e.message}")
  redirect_to @reservation, alert: '支付暂时无法创建,请稍后重试。'
end

生产环境中最好只捕获当前 Mollie gem 定义的具体异常类型,具体类名以项目所安装版本的文档为准。

备注:内容仅供参考。