PAYATHON 2026

能否实现会员码与支付付款码二合一?

支付小周

结论

普通商户不能直接把自有会员码改成支付宝、微信支付等平台的付款码。付款码由支付平台生成,其编码规则、安全机制和有效期都由平台控制,商户无法自行拼接或替换。

不过,可以实现这样的结账体验:顾客只出示会员码,收银台识别会员后自动扣款。要做到这一点,商户必须接入支付平台提供的签约代扣、免密支付或类似产品,用户也需要提前绑定账户并授权扣款。盒马一类的场景通常依赖深度业务合作,并非简单地把两个条码合成一个。

推荐的实现方式

可以按以下流程实现:

  1. 用户在 App 或小程序中绑定会员账户。
  2. 引导用户与指定支付渠道签订免密扣款协议。
  3. 商户保存会员与支付协议的关联关系,例如 member_id、协议号和协议状态。
  4. 用户结账时出示商户生成的动态会员码。
  5. 收银系统扫描会员码,并向商户服务端查询会员身份。
  6. 服务端核对协议状态、订单金额和风控条件。
  7. 服务端调用已开通的代扣接口发起支付。
  8. 根据支付平台返回的同步结果和异步通知更新订单状态。
动态会员码
    ↓
解析会员身份
    ↓
查询有效扣款协议
    ↓
创建商户订单
    ↓
调用支付平台代扣接口
    ↓
接收异步支付通知
    ↓
更新订单与会员权益

会员码在这个流程中只是身份凭证,不应直接包含支付账号、协议号或其他敏感信息。

为什么不能直接调用付款码支付接口

以常见的当面付流程为例,收银台扫描支付平台生成的付款码,再将该值作为 auth_code 提交给支付接口:

{
  "out_trade_no": "ORDER_202609140001",
  "scene": "bar_code",
  "auth_code": "用户支付客户端生成的付款码",
  "subject": "门店消费",
  "total_amount": "88.00"
}

支付宝当面付的常见接口是 alipay.trade.pay。其中的 auth_code 必须是支付宝客户端生成的有效付款码,不能使用商户自己的会员码。即使两者的字段格式相似,支付平台也无法通过自定义会员码找到对应的付款账户并完成支付。

所以下面的调用方式不可行:

{
  "scene": "bar_code",
  "auth_code": "商户自定义会员码"
}

也不能通过字符串拼接、二维码嵌套等方式强行合并会员码和付款码。这些做法无法绕过支付平台的校验,还可能造成信息泄露和盗刷。

会员码支付的服务端示例

不同支付平台和签约产品使用的接口名称、请求参数会有差异。下面只展示商户系统的处理结构,不代表任何支付平台的正式代扣 API。

public PaymentResult payByMemberCode(
        String dynamicMemberCode,
        String outTradeNo,
        BigDecimal amount) {

    // 会员码必须是短时有效、一次性或可防重放的动态凭证
    MemberIdentity member = memberCodeService.verify(dynamicMemberCode);
    if (member == null) {
        throw new IllegalArgumentException("会员码无效或已过期");
    }

    PaymentAgreement agreement =
            agreementService.findActiveAgreement(member.getMemberId());

    if (agreement == null) {
        throw new IllegalStateException("会员尚未开通免密支付");
    }

    Order order = orderService.createOrLoad(outTradeNo, member, amount);

    // merchantDeductClient 需要对接已经签约并获准使用的正式支付产品
    DeductRequest request = new DeductRequest();
    request.setOutTradeNo(order.getOutTradeNo());
    request.setAmount(order.getAmount());
    request.setAgreementNo(agreement.getAgreementNo());
    request.setNotifyUrl("https://merchant.example.com/payment/notify");

    return merchantDeductClient.deduct(request);
}

前端生成动态会员码时,可以只在码中放置随机令牌:

const response = await fetch("/api/member/payment-code", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${accessToken}`
  }
});

const { token, expiresAt } = await response.json();

// 将 token 渲染为条形码或二维码
renderBarcode(token);

服务端负责维护令牌与会员之间的映射关系,并为令牌设置较短的有效期:

{
  "token": "mcode_7f2c1d9a...",
  "member_id": "M100086",
  "expires_at": "2026-09-14T18:30:30+08:00",
  "status": "ACTIVE"
}

没有代扣权限时的替代方案

如果暂时无法接入免密支付,可以采用两步扫码:

  1. 先扫描会员码,识别会员并计算积分和优惠。
  2. 再扫描支付宝或微信付款码,通过标准当面付接口收款。

收银系统可以连续执行这两个步骤,减少收银员来回切换页面的操作。顾客虽然仍要出示两个码,但对普通商户来说,这种方案更容易落地,合规边界也更清楚。

还可以在识别会员后创建订单,再让用户扫码确认付款。这种方式无法实现完全无感支付,但商户不需要获得代扣能力。

接入前需要确认的事项

接入前,应先向支付服务商确认是否提供适用于当前行业的签约代扣、免密支付或会员支付产品,以及商户是否符合准入条件。这类能力通常需要单独签约和审核,也不一定向所有商户开放。

实施过程中还需要注意:

  • 用户必须明确授权扣款,并且能够查询和解除协议。
  • 会员码应动态生成、短时有效,并具备防重放能力。
  • 扣款接口必须保证订单幂等,不能只依赖前端或收银台返回的结果。
  • 最终支付状态应以服务端查询结果或验签后的异步通知为准。
  • 金额、门店、设备、会员状态和协议状态都应由服务端校验。
  • 不要在条码中放入支付账号、手机号、协议号等敏感数据。
  • 需要提供扣款提示、付款失败后的普通付款入口和退款流程。
  • 未经支付平台许可,不得自行模拟付款码或保存用户付款码。

如果只是想改善收银体验,可以先采用“识别会员后再扫付款码”的方式。如果必须实现“一码完成会员识别和支付”,则需要申请相应的签约扣款能力,并由商户服务端安全关联会员身份与支付协议。

备注:内容仅供参考。