PAYATHON 2026

收款方为个人时,商家分账如何完成实名认证?

支付阿杰

结论

小程序通常无法直接读取用户在支付平台登记的真实姓名。个人收款方的实名认证也不需要商家自行查询实名信息,而是由支付平台核对商家提交的姓名与收款人平台账号是否一致。

通常可以按以下流程处理:

  1. 用户在小程序中主动填写真实姓名,并明确授权该信息用于分账认证。
  2. 小程序将姓名提交给商家服务端,不直接调用分账接口。
  3. 服务端按照分账接口的要求,加密姓名等敏感字段后再提交。
  4. 支付平台根据收款人的 openid、会员 ID 或其他平台账号,核对其支付账户的实名认证信息。
  5. 商家根据接口结果,分别处理校验成功、姓名不一致和收款人尚未实名等情况。

如果支付平台要求个人收款方先完成账户实名认证,应引导用户前往对应平台办理。商家不能通过小程序 API 代替用户实名,也不应收集接口不需要的身份证照片、身份证号等信息。

为什么不能直接获取真实姓名

openid、用户昵称和手机号都无法证明用户的法定姓名:

  • openid 只是用户在特定应用下的唯一标识。
  • 昵称可以随意设置,不能作为实名校验依据。
  • 手机号的实名登记人不一定是实际使用人。
  • 小程序登录授权通常不会返回支付账户登记的真实姓名。
  • 支付平台保存的实名信息属于敏感个人信息,一般不会通过普通用户信息 API 提供给商家。

因此,商家应收集用户主动填写的姓名,再交给支付平台完成最终核验,不能从小程序侧反查用户的实名信息。

推荐实现流程

1. 确认收款方账号类型

先查看所用分账产品的接口要求,确认个人收款方需要提交哪一种账号标识,例如:

  • 当前小程序对应的 openid
  • 支付平台会员 ID
  • 商户体系下的用户标识

不同应用、商户主体或支付场景生成的用户标识不能混用。账号标识不匹配时,即使姓名正确,也可能无法通过校验。

2. 获取用户明确授权

收集姓名时,应在页面上说明具体用途,例如:

真实姓名仅用于验证个人分账收款资格,并提交至支付平台完成身份一致性校验。

输入框应明确提示用户填写支付账户实名认证时使用的姓名。不要用昵称作为默认值,也不要让用户误以为系统已经读取了其实名信息。

3. 将信息提交到商家服务端

小程序端只负责采集并提交信息。商户私钥不能存放在小程序端,需要商户签名的分账接口也不应由小程序直接调用。

// 小程序端示例
async function submitReceiver() {
  const realName = receiverName.trim();

  if (!realName) {
    throw new Error('请输入支付账户实名认证姓名');
  }

  const result = await request({
    url: '/api/profit-sharing/receivers',
    method: 'POST',
    data: {
      realName
    }
  });

  return result;
}

服务端应根据当前登录态取得该用户对应的 openid 或平台会员 ID,不要允许客户端随意传入其他用户的收款账号。

4. 服务端加密并调用分账接口

下面的代码仅展示与具体支付平台无关的处理结构。实际字段名、加密算法、证书格式和签名方式,应以所接入分账接口的官方文档为准。

app.post('/api/profit-sharing/receivers', async (req, res) => {
  const userId = req.auth.userId;
  const realName = String(req.body.realName || '').trim();

  if (!realName) {
    return res.status(400).json({
      code: 'INVALID_REAL_NAME',
      message: '真实姓名不能为空'
    });
  }

  // 根据可信登录态查询,避免客户端伪造收款账号
  const paymentAccount = await getPaymentAccountByUserId(userId);

  // 具体加密方式由支付平台接口规范决定
  const encryptedName = encryptSensitiveField(realName);

  const receiver = {
    type: 'PERSONAL_ACCOUNT',
    account: paymentAccount,
    name: encryptedName
  };

  try {
    const result = await paymentClient.addProfitSharingReceiver(receiver);

    return res.json({
      success: true,
      receiverId: result.receiverId
    });
  } catch (error) {
    return res.status(400).json(
      mapProfitSharingError(error)
    );
  }
});

其中,PERSONAL_ACCOUNT、name、receiverId 和 addProfitSharingReceiver 只用于表达业务含义,并非某个支付平台的固定字段或 API 名称。正式接入时,需要替换为实际接口定义。

5. 正确处理校验失败

可以将支付平台返回的错误码转换成用户容易理解的提示:

function mapProfitSharingError(error) {
  switch (error.code) {
    case 'NAME_MISMATCH':
      return {
        code: 'REAL_NAME_MISMATCH',
        message: '姓名与该支付账户的实名认证信息不一致,请核对后重试'
      };

    case 'ACCOUNT_NOT_VERIFIED':
      return {
        code: 'ACCOUNT_NOT_VERIFIED',
        message: '该支付账户尚未完成实名认证,请先在支付平台完成认证'
      };

    case 'INVALID_ACCOUNT':
      return {
        code: 'INVALID_RECEIVER_ACCOUNT',
        message: '无法识别收款账户,请重新进入小程序后再试'
      };

    default:
      return {
        code: 'RECEIVER_VERIFY_FAILED',
        message: '收款方验证失败,请稍后重试'
      };
  }
}

错误码名称应以实际接口返回为准。日志可以记录平台错误码和请求流水号,但不能明文保存姓名、身份证号或完整收款账号。

注意事项

  • 姓名必须由用户主动填写,不能根据昵称、手机号或其他非实名字段推断。
  • 实名信息是否一致,应由支付平台作出最终判断。商家本地只能检查空值、长度和字符等基本格式。
  • 如果接口要求加密敏感字段,应由服务端使用平台指定的证书或公钥完成加密,不能在小程序端保存私钥。
  • 对姓名进行加密并不意味着可以省略用户授权。商家仍需提供隐私政策,说明信息用途、保存期限和删除机制。
  • 只收集分账接口要求的信息。如果接口只需要姓名,就不要额外收集身份证号、身份证照片或人脸信息。
  • 用户修改姓名后,需要重新校验收款方信息,不能沿用此前的认证结果。
  • 发起分账前,还应确认收款方已经成功添加、当前可以参与分账,并满足平台对账户、关系类型和额度的要求。
  • 各支付平台及接口版本采用的字段、加密方式和认证规则可能不同,应以当前接入产品的官方接口文档和实际返回的错误码为准。

备注:内容仅供参考。