收款方为个人时,商家分账如何完成实名认证?
结论
小程序通常无法直接读取用户在支付平台登记的真实姓名。个人收款方的实名认证也不需要商家自行查询实名信息,而是由支付平台核对商家提交的姓名与收款人平台账号是否一致。
通常可以按以下流程处理:
- 用户在小程序中主动填写真实姓名,并明确授权该信息用于分账认证。
- 小程序将姓名提交给商家服务端,不直接调用分账接口。
- 服务端按照分账接口的要求,加密姓名等敏感字段后再提交。
- 支付平台根据收款人的
openid、会员 ID 或其他平台账号,核对其支付账户的实名认证信息。 - 商家根据接口结果,分别处理校验成功、姓名不一致和收款人尚未实名等情况。
如果支付平台要求个人收款方先完成账户实名认证,应引导用户前往对应平台办理。商家不能通过小程序 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: '收款方验证失败,请稍后重试'
};
}
}
错误码名称应以实际接口返回为准。日志可以记录平台错误码和请求流水号,但不能明文保存姓名、身份证号或完整收款账号。
注意事项
- 姓名必须由用户主动填写,不能根据昵称、手机号或其他非实名字段推断。
- 实名信息是否一致,应由支付平台作出最终判断。商家本地只能检查空值、长度和字符等基本格式。
- 如果接口要求加密敏感字段,应由服务端使用平台指定的证书或公钥完成加密,不能在小程序端保存私钥。
- 对姓名进行加密并不意味着可以省略用户授权。商家仍需提供隐私政策,说明信息用途、保存期限和删除机制。
- 只收集分账接口要求的信息。如果接口只需要姓名,就不要额外收集身份证号、身份证照片或人脸信息。
- 用户修改姓名后,需要重新校验收款方信息,不能沿用此前的认证结果。
- 发起分账前,还应确认收款方已经成功添加、当前可以参与分账,并满足平台对账户、关系类型和额度的要求。
- 各支付平台及接口版本采用的字段、加密方式和认证规则可能不同,应以当前接入产品的官方接口文档和实际返回的错误码为准。
备注:内容仅供参考。
