You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Ruby on Rails中使用receipts gem为PDF收据添加支付信息二维码

在Receipts Gem生成的PDF中插入支付详情二维码

问题背景

使用Chris Oliver开发的receipts gem生成PDF收据,需要在页脚区域插入包含charge.partner.iban、charge.amount等支付详情的二维码。此前尝试用prawn-qrcode生成二维码后通过image_tag传入footer参数,但仅能显示文本,无法正常渲染二维码。

解决方案

Receipts gem底层基于Prawn实现PDF生成,因此可以利用Prawn的API直接操作PDF对象插入二维码,具体步骤如下:

1. 安装依赖

首先确保Gemfile中包含生成二维码所需的依赖:

gem 'rqrcode'       # 生成二维码数据
gem 'prawn-qrcode'  # 支持Prawn插入二维码

执行bundle install安装依赖。

2. 修改Charge模型的receipt方法

在receipt方法中生成包含支付详情的二维码,并通过Receipts提供的custom_content回调插入到PDF指定位置:

def receipt
  # 准备二维码包含的支付数据,用JSON格式便于扫码后解析
  qr_payload = {
    iban: partner.iban,
    amount: amount,
    receipt_number: "123", # 替换为实际收据编号字段
    paid_at: created_at.strftime("%Y-%m-%d")
  }.to_json

  # 生成二维码PNG
  qrcode = RQRCode::QRCode.new(qr_payload)
  qr_png = qrcode.as_png(
    size: 100,          # 二维码尺寸
    border_modules: 2,  # 边框宽度
    color: 'black',     # 码点颜色
    fill: 'white'       # 背景色
  )

  Receipts::Invoice.new(
    # 保留原有配置参数
    details: [
      ["Receipt Number", "123"],
      ["Date paid", Date.today],
      ["Payment method", "ACH super long super long super long super long super long"]
    ],
    company: {
      name: "Example, LLC",
      address: "123 Fake Street\nNew York City, NY 10012",
      email: "support@example.com",
      logo: File.expand_path("./app/assets/images/logo.png")
    },
    recipient: [
      partner.name,
      partner.address,
      "City, State Zipcode",
      nil,
      "customer@example.org"
    ],
    line_items: [
      ["<b>Item</b>", "<b>Unit Cost</b>", "<b>Quantity</b>", "<b>Amount</b>"],
      ["Subscription", "$19.00", "1", "$19.00"],
      [nil, nil, "Subtotal", "$19.00"],
      [nil, nil, "Tax", "$1.12"],
      [nil, nil, "Total", "$20.12"],
      [nil, nil, "<b>Amount paid</b>", "$20.12"],
      [nil, nil, "Refunded on #{Date.today}", "$5.00"]
    ],
    footer: "Thanks for your business. Please contact us if you have any questions.",
    # 自定义内容回调:插入二维码到页脚右侧
    custom_content: lambda { |pdf|
      # 坐标说明:x轴为PDF右边界减去二维码宽度-边距,y轴为PDF底边界加边距
      pdf.image StringIO.new(qr_png.to_s), 
                at: [pdf.bounds.right - 120, pdf.bounds.bottom + 20], 
                width: 100
    }
  )
end

3. 可选方案:在控制器中修改PDF

如果custom_content回调无法生效,也可以在send_pdf方法中直接操作Prawn对象:

private
def send_pdf
  invoice = @charge.receipt
  pdf = invoice.render_pdf # 获取Prawn实例而非直接渲染字符串

  # 生成二维码
  qr_payload = {
    iban: @charge.partner.iban,
    amount: @charge.amount,
    receipt_number: "123",
    paid_at: @charge.created_at.strftime("%Y-%m-%d")
  }.to_json
  qrcode = RQRCode::QRCode.new(qr_payload)
  qr_png = qrcode.as_png(size: 100, border_modules: 2)

  # 插入二维码到页脚位置
  pdf.image StringIO.new(qr_png.to_s), 
            at: [pdf.bounds.right - 120, pdf.bounds.bottom + 20], 
            width: 100

  # 发送最终PDF
  send_data pdf.render,
    filename: "#{@charge.created_at.strftime("%Y-%m-%d")}-gorails-receipt.pdf",
    type: "application/pdf",
    disposition: :inline
end

注意事项

  • 二维码数据格式可根据需求调整:除了JSON,也可以用纯文本格式(如IBAN: #{partner.iban} | Amount: #{amount})
  • 坐标调整:at: [x, y]参数需根据PDF实际尺寸微调,避免覆盖页脚文本或超出页面范围
  • Logo路径问题:如果File.expand_path找不到logo文件,可在模型中引入ActionView::Helpers::AssetUrlHelper后使用asset_path("logo.png")

内容的提问来源于stack exchange,提问作者Alexander V

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 18:27:52