alipay.fund.trans.uni.transfer如何获取收款方账号或UID?
结论
优先通过支付宝会员授权获取当前登录用户的支付宝用户标识。服务端拿到一次性 auth_code 后,调用 alipay.system.oauth.token 换取令牌,再使用返回的用户标识发起转账。
如果授权结果返回可用于资金接口的 user_id,可以这样填写收款方信息:
payee_info.identity_type = ALIPAY_USER_ID
payee_info.identity = 用户授权得到的 user_id
不建议让用户手工填写支付宝登录账号。alipay.user.info.share 用于读取授权范围内的用户公开信息。接口是否返回 user_id、open_id,以及这些字段能否用于转账,要看应用类型、授权范围和支付宝当前的数据开放规则。除非转账文档明确支持,否则不能把 open_id 当作 ALIPAY_USER_ID 使用。
“实名证件信息比对验证”用于核验姓名、证件等信息,并不能查询支付宝账号或 UID。即使实名核验通过,接口也未必会返回可直接用于转账的支付宝账号。
推荐的业务流程
收款人绑定可以按以下流程设计:
- 收款人点击”绑定支付宝”。
- 跳转到支付宝会员授权页面。
- 支付宝回调业务系统,并携带一次性
auth_code。 - 服务端调用
alipay.system.oauth.token换取access_token。 - 从令牌响应中读取
user_id。如果业务还需要昵称、头像、认证状态等信息,再调用alipay.user.info.share。 - 保存 UID 与当前业务用户的绑定关系。
- 转账时使用 UID,并将收款人姓名作为一致性校验字段。
- 首次绑定、换绑和高额转账时,增加短信验证、人工审核或二次确认。
这套流程建立的关系是:
业务系统用户
↓ 本人支付宝授权
支付宝 user_id
↓
alipay.fund.trans.uni.transfer
通过这种方式,可以确认 UID 来自当时登录并授权的支付宝用户,比手工填写手机号或邮箱形式的支付宝登录账号更可靠。
获取用户标识
网页应用通常需要先生成支付宝授权地址。以下代码只展示核心参数,实际地址和可用的 scope 应以应用后台及当前官方文档为准:
<?php
$appId = '你的应用 APPID';
$redirectUri = 'https://example.com/alipay/oauth/callback';
$query = http_build_query([
'app_id' => $appId,
'scope' => 'auth_user',
'redirect_uri' => $redirectUri,
]);
$authorizeUrl =
'https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?' . $query;
header('Location: ' . $authorizeUrl);
exit;
回调地址收到 auth_code 后,由服务端换取令牌:
<?php
$authCode = $_GET['auth_code'] ?? '';
if ($authCode === '') {
throw new RuntimeException('缺少 auth_code');
}
$request = new AlipaySystemOauthTokenRequest();
$request->setGrantType('authorization_code');
$request->setCode($authCode);
// $aop 为已经按证书模式初始化的官方 PHP SDK 客户端。
$response = $aop->execute($request);
if (!isset($response->access_token)) {
throw new RuntimeException(
'换取支付宝授权令牌失败:' .
json_encode($response, JSON_UNESCAPED_UNICODE)
);
}
$accessToken = $response->access_token;
$userId = $response->user_id ?? null;
$openId = $response->open_id ?? null;
不同版本 SDK 的响应对象结构可能不同。应根据官方 SDK 的实际返回结构判断错误码,再读取所需字段,不要假定所有应用都能同时取得 user_id 和 open_id。
如果令牌响应没有返回可用于转账的 user_id,不能强行把 open_id 填入 ALIPAY_USER_ID。此时需要检查:
- 应用是否已经开通相应的会员能力;
- 授权范围是否正确;
- 当前应用类型是否允许获取该字段;
- 转账产品是否支持当前返回的用户标识类型;
- 支付宝是否已对该应用启用新的用户标识规则。
调用 alipay.user.info.share
取得 access_token 后,可以读取用户已经授权的公开信息:
<?php
$request = new AlipayUserInfoShareRequest();
$response = $aop->execute($request, $accessToken);
if (isset($response->code) && $response->code !== '10000') {
throw new RuntimeException(
'获取支付宝会员信息失败:' .
json_encode($response, JSON_UNESCAPED_UNICODE)
);
}
$userInfo = [
'user_id' => $response->user_id ?? null,
'open_id' => $response->open_id ?? null,
'nick_name' => $response->nick_name ?? null,
'is_certified' => $response->is_certified ?? null,
];
使用这个接口时需要注意:
- 它只能返回用户明确授权且应用有权获取的字段。
is_certified一般只能说明账户是否完成支付宝实名认证,不能代替姓名与身份证号码的一致性核验。- 它不能通过姓名查询支付宝 UID,也不能反查任意用户。
会员授权可以获取当前授权用户的标识,但不能根据姓名查询对方的支付宝账号。
使用 UID 发起单笔转账
确认取得的 user_id 可以作为 ALIPAY_USER_ID 后,可以这样组织转账业务参数:
<?php
$bizContent = [
'out_biz_no' => 'TRANSFER_' . date('YmdHis') . '_001',
'trans_amount' => '100.00',
'product_code' => 'TRANS_ACCOUNT_NO_PWD',
'biz_scene' => 'DIRECT_TRANSFER',
'order_title' => '用户提现',
'payee_info' => [
'identity' => $userId,
'identity_type' => 'ALIPAY_USER_ID',
'name' => $realName,
],
];
$request = new AlipayFundTransUniTransferRequest();
$request->setBizContent(
json_encode($bizContent, JSON_UNESCAPED_UNICODE)
);
$response = $aop->execute($request);
不同 SDK 发行包在证书模式的执行方法、命名空间和响应解析方式上可能存在差异,应以当前使用的 PHP SDK 为准。业务参数中的收款方信息应按以下形式填写:
{
"payee_info": {
"identity": "支付宝用户ID",
"identity_type": "ALIPAY_USER_ID",
"name": "收款人真实姓名"
}
}
不要混用这些标识:
支付宝登录账号 → ALIPAY_LOGON_ID
支付宝用户 UID → ALIPAY_USER_ID
open_id → 只有转账文档明确支持时才能使用相应类型
open_id、应用内会员编号、业务系统用户 ID 和支付宝 user_id 是不同的概念。
实名信息验证能力的定位
alipay.user.certdoc.certverify.preconsult 和 alipay.user.certdoc.certverify.consult 用于比对实名证件信息,例如检查用户提交的姓名与证件号码是否一致。
业务确实需要法定身份核验时,可以使用这项能力,但它不是支付宝账号查询服务:
- 实名验证成功,不代表接口会返回支付宝登录账号。
- 实名验证成功,不代表接口会返回转账所需的
user_id。 - 不能通过姓名或身份证号反查任意支付宝账户。
- 获得授权令牌只是调用流程的一部分,不会自动取得所有会员字段。
如果后台的”可调用产品”中没有这项能力,通常说明当前应用尚未签约、没有接口权限,或者不符合对应产品的准入条件。这类能力涉及实名和隐私数据,不能只靠代码调用开通。需要在支付宝开放平台确认产品签约入口、应用类型、商户资质、业务场景及隐私合规要求。如果后台没有申请入口,应通过支付宝开放平台的服务渠道确认准入情况。
应用已经上线或转账接口已经开通,都不能说明实名验证接口也已开通,因为两者属于不同的产品权限。
“获取会员信息”是否可以使用
如果应用后台显示”会员-获取会员信息”并且已经开通,通常可以按照会员授权流程接入。不过,最终能否取得转账所需的 user_id,仍要以实际授权响应和当前接口字段说明为准。
可以依次完成以下验证:
- 确认应用已经开通会员授权或获取会员信息能力。
- 使用应用自己的
app_id完成一次真实授权。 - 检查
alipay.system.oauth.token的原始响应。 - 检查
alipay.user.info.share的原始响应。 - 区分
user_id和open_id。 - 对照
alipay.fund.trans.uni.transfer当前支持的identity_type。 - 在沙箱或小额真实业务中验证完整的绑定与转账流程。
如果只能取得 open_id,而转账接口只接受 ALIPAY_USER_ID 或 ALIPAY_LOGON_ID,就不能直接转换标识。需要向支付宝确认应用是否可以申请取得 user_id,或者转账产品是否支持与 open_id 对应的收款方标识类型。
PHP、v2 和证书模式的常见问题
授权回调必须防止伪造
生成授权地址时,应同时保存随机 state,并在回调时校验。auth_code 应由服务端处理,不能交给前端长期保存。
auth_code 不能重复使用
授权码通常只能使用一次,而且有效期较短。收到回调后应尽快换取令牌。换取失败时,不要无限重试同一个授权码。
不要把 access_token 写入普通日志
令牌、证件号码、支付宝账号、UID 和真实姓名都属于敏感信息。日志应做脱敏处理,同时限制数据库访问权限。
UID 必须和业务用户绑定
不要允许前端在每次提现时直接提交任意 user_id。服务端应读取此前通过授权绑定的 UID,例如:
$payeeUserId = $repository->getBoundAlipayUserId($currentUserId);
转账接口中的 identity 必须由服务端生成,不能信任前端传入的参数。
换绑需要重新授权
用户更换收款支付宝账户时,应重新完成支付宝授权和业务侧身份确认。换绑后可以设置冷静期,防止账号被盗后资金立即转出。
保留姓名校验
即使使用 UID,在业务允许且接口要求的情况下,仍建议填写收款人的真实姓名。UID 用于定位账户,姓名可以降低绑错账户和数据被篡改的风险。
做好幂等控制
out_biz_no 必须由服务端生成并保证唯一。遇到网络超时,应先查询原转账结果,不要立即更换业务单号重新转账,否则可能造成重复付款。
证书配置与会员授权是两回事
证书模式负责接口请求签名和支付宝响应验签,不会自动赋予会员信息或实名验证权限。即使应用公钥证书、支付宝公钥证书和支付宝根证书都配置正确,也不代表应用已经签约某个产品接口。
最终建议
如果只需要安全获取收款账户并完成转账,可以采用以下组合:
支付宝会员授权
+ alipay.system.oauth.token 获取用户标识
+ 必要时 alipay.user.info.share 获取授权信息
+ 服务端绑定 user_id
+ alipay.fund.trans.uni.transfer 使用 ALIPAY_USER_ID
如果业务还需要核验身份证和姓名,应在上述流程之外单独申请实名证件信息比对能力。实名验证用于判断身份信息是否匹配,会员授权用于确认当前登录的支付宝用户,转账接口则负责向该用户付款。这三项能力不能互相替代。
备注:内容仅供参考。
