QRPH 二维码技术规范怎么看?尺寸、纠错等级与打印要求的实操标准(2026)
我在马尼拉负责一家连锁餐饮的 IT,去年给三十多家门店换 QRPH 台卡,第一批印出来就出了问题:有的码在柜台灯光下扫不出来,有的要凑到很近才能识别,还有一家店的码被人贴了贴纸之后直接失效。后来我们才意识到,QRPH 不只是"一个二维码",它背后有一套明确的技术规范:payload 怎么编、版本和尺寸怎么对应、纠错等级选哪一档、打印时对比度和静区怎么留。这篇文章把这些规范按实操顺序讲一遍,重点是让你印出来的码在真实门店环境里扫得快、扫得准、经得起磨损。QRPH 本身是什么、为什么是央行统一标准,QRPH 二维码支付是什么已经科普过,这里直接进入技术细节。
一张 QRPH 码里装的是什么
QRPH 采用 EMVCo 的商户出示模式(Merchant-Presented Mode)规范,整个 payload 是一串由"标签 + 长度 + 值"(TLV)拼接起来的文本。几个关键字段:
- 标签 00:payload 格式指示,固定值。
- 标签 01:发起方式,"11" 表示静态码(可重复使用),"12" 表示动态码(一次一用)。
- 标签 26 到 51:商户账户信息。QRPH 的核心就在这里,它指向收单机构和商户在该机构下的标识,扫码方据此知道钱该路由到哪个参与机构。
- 标签 52、53、58、59、60:商户类别码、货币代码(ISO 4217 数字码)、国家代码、商户名称、城市。
- 标签 54:金额,只有动态码携带;静态码不带金额,由付款人输入。
- 标签 62:附加数据,账单号、门店号、终端号等对账用的信息放这里。
- 标签 63:CRC 校验值,覆盖前面全部内容,保证 payload 没被篡改或打印残缺。
理解这个结构有两个实际用处:一是你能判断一张码"属于谁",标签 26 到 51 里的收单方标识决定了资金落到哪家持牌机构;二是你能理解为什么动态码比静态码更长、需要更大的版本号,因为它多带了金额和账单号。
版本、模块与尺寸:为什么有的码密有的码疏
QR 码按"版本"分级,版本号越高,每边的模块(黑白小方格)越多,能装的内容也越多。静态 QRPH 码的 payload 一般是一百多字节,落在中等版本;动态码带上金额、账单号和附加数据后会更长,版本随之上升。版本决定了模块总数,模块总数和你能接受的物理尺寸一起决定了每个模块的实际大小,而模块越小,对打印精度和扫码距离的要求越高。
我们现在用的尺寸规则是一条经验公式:扫码距离大约是码边长的十倍。柜台台卡用户在手臂距离内扫,码边长做到三厘米以上就稳;挂在门口或墙上让人隔着一两米扫,就要等比放大到十几厘米。另一条硬规则是静区:码的四周必须留出至少四个模块宽的空白,任何边框、文字、图案都不能侵入,否则扫码器找不到定位图案。第一批台卡扫不出来的那几家,问题就出在设计师把品牌边框压到了静区上。
纠错等级怎么选:L、M、Q、H 不是越高越好
QR 码内置纠错,分 L、M、Q、H 四档,能恢复的损坏面积依次递增,H 级大约能承受三成面积的遮挡或污损。代价是同样的 payload 在更高纠错等级下需要更高的版本号,码会变密,同样物理尺寸下每个模块变小。所以选择要看场景:
| 纠错等级 | 可恢复损坏 | 同一 payload 的码密度 | 适用场景 |
|---|---|---|---|
| L | 最低,约七分之一面积 | 最疏,模块最大 | 屏幕上短时展示、环境干净、不贴 logo |
| M | 中等 | 较疏 | 收银屏动态码、热敏小票、临时打印 |
| Q | 较高 | 较密 | 中央贴 logo 的台卡、半户外展示 |
| H | 最高,约三成面积 | 最密,模块最小 | 长期使用的门店台卡与贴纸、中央放 QR Ph 标志、易磨损环境 |
我们的取舍是:门店里长期使用、中央带 QR Ph 标志的静态码一律用 H,配合足够大的物理尺寸把模块撑开;收银屏上一次一用的动态码用 M,因为屏幕不会磨损,而动态码本来就长,用 H 会让码过密影响识别速度;热敏小票上的码用 M 并尽量缩短附加数据,因为热敏打印机分辨率有限。
打印要求:对比度、材质和那些容易忽略的细节
印刷环节决定了规范能不能落地,以下是我们和印刷厂反复确认后固定下来的要求:
- 深色模块、浅色底,不要反色(浅色模块配深色底),很多钱包 App 的扫码器对反色码支持不稳定。
- 颜色可以有,但对比度要够。深蓝、深绿配白底没问题,浅灰、金色、荧光色不行。
- 用矢量文件印刷(SVG 或 PDF),不要把一张小 PNG 放大,放大后的模块边缘发虚会降低识别率。
- 保持正方形。设计稿里任何非等比缩放都会让模块变形,这是最常见也最隐蔽的错误。
- 避免高反光覆膜。亮面覆膜在柜台射灯下会产生眩光,改用哑膜或亚克力台卡。
- 中央 logo 要按规范留位。QR Ph 标志放在码中央是官方视觉要求,但 logo 占用的面积要在纠错能力之内,并且 logo 周围留一圈白边,不要直接压在模块上。
- 每一版印刷前先打样实测,至少用三款不同的钱包或银行 App 在真实灯光下扫。
用代码生成一张合规的 QRPH 码
多数商户的 QRPH 码由收单机构或持牌网关直接生成,你拿到的是现成的 payload 或图片。但理解生成逻辑有助于排错,也方便你在收银系统里按需生成动态码。下面是 Node 版的 payload 构造与 CRC 计算,CRC 采用 EMVCo 规定的 CRC-16/CCITT-FALSE 算法:
// 构造 EMVCo 商户出示模式 payload,并追加 CRC
function tlv(tag, value) {
const len = String(value.length).padStart(2, '0');
return tag + len + value;
}
function crc16(payload) {
let crc = 0xFFFF;
for (const b of Buffer.from(payload, 'utf8')) {
crc ^= b << 8;
for (let i = 0; i < 8; i++) {
crc = (crc & 0x8000) ? ((crc << 1) ^ 0x1021) : (crc << 1);
crc &= 0xFFFF;
}
}
return crc.toString(16).toUpperCase().padStart(4, '0');
}
// 商户账户信息:具体标签号与子字段以收单机构分配为准
const merchantInfo = tlv('00', 'com.example.acquirer') + tlv('01', 'MERCHANT-ID-FROM-ACQUIRER');
let payload =
tlv('00', '01') + // payload 格式指示
tlv('01', '12') + // 12 = 动态码;11 = 静态码
tlv('27', merchantInfo) + // 商户账户信息
tlv('52', '5812') + // 商户类别码(示例:餐饮)
tlv('53', '608') + // 货币代码(ISO 4217 数字码)
tlv('54', '350.00') + // 金额,仅动态码携带
tlv('58', 'PH') +
tlv('59', 'SAMPLE CAFE') +
tlv('60', 'MANILA') +
tlv('62', tlv('01', 'ORD-000123')) + // 附加数据:账单号
'6304'; // CRC 标签与长度,值在下一行补上
payload += crc16(payload);
console.log(payload);
有了 payload,再按前面讲的纠错等级和静区把它渲染成图片。生成矢量文件交给印刷厂,生成位图放到收银屏:
const QRCode = require('qrcode');
// 门店台卡:矢量 + H 级纠错 + 四模块静区
await QRCode.toFile('qrph-table-card.svg', payload, {
type: 'svg',
errorCorrectionLevel: 'H',
margin: 4
});
// 收银屏动态码:位图 + M 级纠错,scale 控制每个模块的像素数
await QRCode.toFile('qrph-dynamic.png', payload, {
errorCorrectionLevel: 'M',
margin: 4,
scale: 10
});
生成后一定要做两件事:用至少三款 App 实扫,确认解析出来的商户名、金额和账单号与预期一致;把 payload 原文和图片一起归档,日后门店反馈"扫出来是别人家"时能立刻比对。QRPH 覆盖的钱包与银行列表见QRPH 支持哪些钱包。
静态码与动态码在规范层面的差别
很多人把"静态 vs 动态"理解成"贴纸 vs 屏幕",规范层面的差别其实在 payload:静态码的发起方式标签为"11",不带金额,长期有效,同一张码被无数人扫;动态码标签为"12",带金额和账单号,通常设有效期,一单一码。对规范的影响是:静态码短、版本低、可以印得很大很耐用;动态码长、版本高、更适合屏幕展示,并且因为账单号唯一,对账时能直接关联订单。两者的业务选型在QRPH 静态码 vs 动态码怎么选里讲过,这里只补一句:门店同时用两种码很正常,静态码兜底,动态码负责精确对账。
常见错误清单
| 现象 | 最常见原因 | 处理 |
|---|---|---|
| 扫不出来或要很近才能扫 | 码太小、静区被侵占、反色、覆膜眩光 | 放大尺寸、恢复四模块静区、改哑膜 |
| 能扫但偶尔失败 | 非等比缩放、位图放大边缘发虚、纠错等级偏低 | 改用矢量、提高到 Q 或 H |
| 贴了贴纸或磨损后失效 | 纠错等级低、logo 占面积过大 | 用 H 级、缩小 logo、更换材质 |
| 扫出来金额或商户名不对 | payload 字段填错、CRC 未重新计算 | 校对 TLV、每次改动后重算 CRC |
| 某款 App 能扫其他不能 | 使用了非标准字段或编码 | 按 EMVCo 规范回退到标准字段 |
| 钱到了别的账户 | 码被调包 | 定期巡检门店码与归档 payload 比对,见QRPH 收款没到账排查清单 |
码是谁生成的,钱就归谁管
最后说一个比技术更重要的事:标签 26 到 51 里的收单方标识决定了这张码的资金路径。商户自己按规范生成的码,仍然必须指向一个合法的参与机构;而大多数商户的做法是由持牌的收单机构或支付网关生成并分发码,商户只负责印刷和部署。拿到码之后,核对收单方身份是第一步,方法在QRPH 商户开通要什么条件有说明。
SMARTPAY 持有菲律宾央行(BSP)颁发的 OPS 与 EMI 资质,为商户生成的 QRPH 静态码与动态码,其商户账户信息字段指向持牌收单主体,资金经持牌机构归集并结算到商户账户。商户可随时向我们索取码对应的 payload 原文,用于巡检和比对。
常见问题
QRPH 码最小可以印多大?
没有统一的最小值,取决于版本号和扫码距离。按"扫码距离约为边长十倍"倒推:手持距离扫的台卡做到三厘米以上,墙面海报按距离等比放大。版本越高的码(比如带长附加数据的动态码)要印得更大。
可以把 QRPH 码做成品牌色吗?
可以,前提是深色模块配浅色底且对比度足够。避免反色和浅色模块,打样后用多款 App 实测。
中央一定要放 QR Ph 标志吗?
QR Ph 标志是国家标准的视觉识别,官方物料通常带有它。如果你放,纠错等级要用 Q 或 H,并给 logo 留白边。
同一张静态码能在多家门店复用吗?
技术上能,但对账会分不清门店。建议每家门店一张独立的码,并在附加数据里带门店号。
热敏小票上的 QRPH 码总是扫不出来怎么办?
缩短附加数据以降低版本号、用 M 级纠错、提高打印浓度,并确认小票宽度允许的码尺寸。如果仍不稳定,改为收银屏展示动态码。
动态码的有效期应该设多久?
按业务场景定:柜台付款几分钟足够,线上账单可以更长。过期后生成新码,不要复用旧账单号。
怎么判断门店的码有没有被调包?
把每张码的 payload 原文归档,巡检时扫码解析出商户信息与归档比对;更稳的做法是定期让门店自己扫一笔小额测试,并核对入账的是本店账户。
写在最后
QRPH 码的规范并不复杂,但每一条都对应着门店里的真实问题:payload 决定钱去哪,版本和尺寸决定扫得远不远,纠错等级决定耐不耐用,静区和对比度决定扫不扫得出。把这几条做成印刷前的检查表,配合生成后的多 App 实测和 payload 归档,绝大多数"扫不出来"和"扫错了"都能提前避免。如果你正在给门店部署 QRPH,或者想拿到一套按规范生成的静态码与动态码,欢迎通过 Telegram 联系@LouisSMARTPAY,或邮件联系[email protected]。