PAYATHON 2026

支付宝普通链接二维码如何跳转同一收单小程序的不同商家页面

支付阿杰

结论

不需要为每个商家单独配置二维码关联规则。

可以把所有商家的普通链接二维码统一设计为“固定域名和路径 + 动态商家参数”,再在支付宝开放平台配置一条覆盖该路径的关联规则。扫码进入同一个收单小程序后,小程序从二维码原始链接或启动参数中解析 merchantId,并跳转到对应商家的收款页面。

例如:

https://pay.example.com/alipay/collect?merchantId=M10001
https://pay.example.com/alipay/collect?merchantId=M10002
https://pay.example.com/alipay/collect?merchantId=M10003

这些二维码的内容不同,但域名和路径相同,原则上可以由同一条路径规则覆盖。100 条的限制针对“关联规则数量”,与二维码数量和商家数量无关。

如果现有二维码使用了大量不同的域名和路径,又无法归一化,就很难用有限的关联规则全部覆盖。此时应增加统一的二维码入口地址,或者重新生成二维码,不宜为每个商家逐条配置。

推荐的整体设计

二维码入口、商家识别和支付参数生成可以分开处理:

支付宝扫码
    ↓
统一普通链接二维码
https://pay.example.com/alipay/collect?merchantId=M10001
    ↓
命中普通链接二维码关联规则
    ↓
启动同一个支付宝收单小程序
    ↓
解析 merchantId
    ↓
向服务端查询商家及门店信息
    ↓
进入对应商家的收款页面
    ↓
由服务端创建支付宝交易

二维码中只保存商家或门店的业务标识,不要直接写入金额、支付宝交易号、私钥相关数据,也不要把其中的收款参数当作可信数据。

配置步骤

1. 统一二维码 URL 结构

为所有商家使用同一个 HTTPS 域名,并尽量固定路径:

https://pay.example.com/alipay/collect?merchantId={merchantId}

如果还需要区分门店,可以增加门店标识:

https://pay.example.com/alipay/collect?merchantId=M10001&storeId=S20001

路径最好保持不变,把商家和门店的差异放在查询参数中。不要使用下面这种分散的结构:

https://merchant-a.example.com/pay
https://merchant-b.example.com/checkout
https://other.example.net/alipay

这种设计会很快消耗关联规则数量,也会增加后续维护成本。

2. 配置一条普通链接二维码关联规则

在支付宝小程序后台配置二维码关联时,让规则覆盖统一入口,例如:

https://pay.example.com/alipay/collect

究竟需要填写域名、完整路径还是路径前缀,以及匹配时是否包含查询参数,要以当前支付宝开放平台“关联普通链接二维码”页面提供的匹配方式为准。不同开放能力或后台版本的字段可能不同,不能直接假设规则支持通配符。

配置时需要确认:

  • merchantId 等查询参数是否不参与规则匹配;
  • 规则是否支持路径前缀;
  • 普通链接域名是否需要完成归属校验;
  • 扫码后,原始 URL 会通过哪个启动字段传给小程序;
  • 关联规则发布后是否还需审核,以及是否存在生效等待时间。

即使平台不支持任意通配符,只要能按固定 URL 路径匹配,并允许查询参数变化,一条规则通常就能覆盖大量商家。

3. 在小程序中解析扫码参数

不同接入方式传递参数的位置可能不同:

  • 普通链接二维码关联通常会将二维码原始 URL 放入启动参数;
  • 小程序 Scheme 可以直接携带页面路径和业务参数;
  • 实际字段名和编码方式必须以当前支付宝小程序文档及真机获取的启动参数为准。

下面假设启动参数中有 query.q,其内容是经过 URL 编码的原始二维码链接。这里只展示一种常见接入形式,正式接入前应先打印或调试实际启动参数。

App({
  onLaunch(options) {
    try {
      const query = options.query || {};
      const merchantId = query.merchantId || getMerchantIdFromQrUrl(query.q);

      if (!merchantId) {
        my.alert({
          title: '无法识别商家',
          content: '二维码缺少有效的商家信息,请重新扫码。'
        });
        return;
      }

      my.reLaunch({
        url: `/pages/collect/index?merchantId=${encodeURIComponent(merchantId)}`
      });
    } catch (error) {
      console.error('Parse QR code parameters failed:', error);

      my.alert({
        title: '二维码解析失败',
        content: '请确认二维码有效后重试。'
      });
    }
  }
});

function getMerchantIdFromQrUrl(rawQrUrl) {
  if (!rawQrUrl) {
    return '';
  }

  const decodedUrl = decodeURIComponent(rawQrUrl);
  const queryString = decodedUrl.split('?')[1] || '';
  const params = {};

  queryString.split('&').forEach((item) => {
    if (!item) {
      return;
    }

    const separatorIndex = item.indexOf('=');
    const key = separatorIndex >= 0 ? item.slice(0, separatorIndex) : item;
    const value = separatorIndex >= 0 ? item.slice(separatorIndex + 1) : '';

    params[decodeURIComponent(key)] = decodeURIComponent(value);
  });

  return params.merchantId || '';
}

如果运行环境支持标准 URL API,可以写得更简单:

function getMerchantIdFromQrUrl(rawQrUrl) {
  if (!rawQrUrl) {
    return '';
  }

  const qrUrl = new URL(decodeURIComponent(rawQrUrl));
  return qrUrl.searchParams.get('merchantId') || '';
}

使用前需要确认目标支付宝小程序运行环境及基础库是否兼容 URL API。

4. 服务端校验商家身份

小程序拿到 merchantId 后,应向自己的服务端查询商家信息:

Page({
  data: {
    merchant: null
  },

  onLoad(query) {
    const merchantId = query.merchantId;

    my.request({
      url: 'https://api.example.com/alipay/merchant/resolve',
      method: 'POST',
      headers: {
        'content-type': 'application/json'
      },
      data: {
        merchantId
      },
      success: (response) => {
        const result = response.data;

        if (!result || !result.success) {
          my.alert({
            title: '商家不可用',
            content: '该商家不存在、已停用或暂不支持收款。'
          });
          return;
        }

        this.setData({
          merchant: result.merchant
        });
      },
      fail: () => {
        my.alert({
          title: '加载失败',
          content: '网络异常,请稍后重试。'
        });
      }
    });
  }
});

服务端至少需要检查:

  • 商家是否存在,并且处于可收款状态;
  • 商家与门店是否匹配;
  • 商家是否已经完成支付宝收单签约;
  • 当前小程序是否有权为该商家发起交易;
  • 请求是否重复、过期或有被篡改的风险。

Scheme 链接是否适合这个场景

小程序 Scheme 可以直接启动指定的小程序页面,并携带商家参数。不同商家可以使用不同的 Scheme,再将 Scheme 制作成二维码。

不过,Scheme 与“普通 HTTPS 链接二维码关联”属于两种方案:

  • 已经部署普通 HTTPS 二维码,希望扫码后关联到小程序时,使用普通链接二维码关联能力;
  • 可以控制二维码内容,希望直接启动小程序时,可以考虑平台提供的小程序 Scheme 或其他小程序码能力;
  • 需要兼容支付宝外部浏览器、微信扫码或系统相机时,通常保留统一 HTTPS 链接更灵活,可以根据访问环境展示不同的落地页。

Scheme 的具体格式、有效期、生成接口和参数限制可能随支付宝开放能力调整,因此不建议手工拼接未经确认的 alipays:// 地址。应使用当前官方提供的 Scheme 生成能力,并按接口要求编码页面路径和查询参数。

无论选择普通链接还是 Scheme,都只应携带这类业务标识:

{
  "merchantId": "M10001",
  "storeId": "S20001"
}

真正的收款主体、金额和交易参数仍需由服务端校验并生成。

如果现有二维码无法统一

如果已有成千上万个二维码,且域名和路径各不相同,可以采用以下方式处理:

  1. 逐步将二维码替换为统一入口 URL。
  2. 对自己控制的旧域名设置跳转,将请求统一转到新的 HTTPS 入口,同时保留商家标识。
  3. 按品牌、渠道或业务线划分少量固定路径,每个路径配置一条规则。
  4. 对无法控制、无法修改,也无法被规则覆盖的旧链接,保留 H5 收款兜底流程。

需要注意,HTTP 重定向能否在“关联规则匹配之前”生效,取决于支付宝扫码链路的实际处理方式。不能默认未命中规则的旧 URL 会先完成重定向,再自动唤起小程序。这一流程必须使用支付宝客户端真机验证。

安全和运营注意事项

  • 不要把二维码中的 merchantId 当作可信身份,因为任何人都可以修改 URL 参数。
  • 可以使用不可枚举的短码,或者增加签名和有效期:
https://pay.example.com/alipay/collect?code=8fK2xP&ts=1788912000&sign=...
  • 签名必须由服务端校验,签名密钥不能放在小程序中。
  • 应防止攻击者替换商家参数,将付款引导到错误的收款主体。
  • 创建交易时,服务端需要再次确认商家、门店、订单和收款账号之间的绑定关系。
  • 对于长期张贴的二维码,商家停用或迁移后,应允许服务端修改短码映射,避免重新印刷二维码。
  • 上线前应分别测试支付宝首页扫码、聊天内识别二维码、相册识码、冷启动、热启动、未登录和商家失效等场景。

整体上,二维码数量不应与关联规则数量绑定。关联规则只负责把一类结构统一的链接导向小程序,具体的商家路由则由 URL 参数和服务端映射完成。

备注:内容仅供参考。