alipay-easysdk PHP 统一下单如何获取 $buyerId?
明确结论
$buyerId 是付款用户的支付宝用户 ID,通常是以 2088 开头的 user_id,不是商户订单号、手机号或应用的 app_id。
调用以下代码时:
Factory::payment()->common()->create(
$subject,
$outTradeNo,
$totalAmount,
$buyerId
);
底层使用的是 alipay.trade.create。创建交易时,订单会绑定到 $buyerId 对应的支付宝账户。如果换用其他支付宝账户扫码付款,可能会出现:
该交易是由另外一个支付宝账户创建的,请更换支付宝账户付款或重新下单 [AE150003018]
在实际付款人尚未确定的扫码支付场景中,不要随意填写或固定 $buyerId。这类场景一般应使用 alipay.trade.precreate,也就是 EasySDK 的当面付预创建接口。
为什么扫码时无法获取 $buyerId
alipay.trade.create 要求在创建订单时提供 buyer_id,但用户扫码发生在订单创建之后。
如果任何支付宝用户都可以扫码付款,商户生成二维码时还不知道最终付款人是谁,自然无法提前取得准确的 $buyerId。这种流程不适合使用 alipay.trade.create,因为该接口会将交易绑定到指定账户。
示例代码里的 $buyerId 通常只是演示参数,不能直接用于生产环境。如果填入开发者、商户人员或其他测试账户的支付宝用户 ID,订单就会绑定到该账户。
方案一:扫码付款使用预创建接口
线下扫码、PC 页面展示二维码等先生成二维码、再由任意用户扫码的场景,应使用当面付预创建接口:
<?php
use Alipay\EasySDK\Kernel\Factory;
$result = Factory::payment()
->faceToFace()
->preCreate(
'订单标题',
'ORDER_202609080001',
'0.01'
);
if (!empty($result->qrCode)) {
$qrCode = $result->qrCode;
// 使用二维码组件将 $qrCode 生成为二维码图片
echo $qrCode;
}
这个接口不需要传入 $buyerId。用户扫码并登录支付宝后,支付宝会按照实际付款账户完成交易。
$result->qrCode 通常只是二维码内容,不一定是能直接显示的图片地址。商户还需要通过二维码生成组件,将它转换成二维码图片。
不同版本的 alipay-easysdk 在具体类名和返回字段写法上可能略有差异,请以项目实际安装版本的 EasySDK 接口定义为准。
方案二:需要绑定用户时,通过支付宝授权获取
如果业务要求当前登录的支付宝用户为自己创建订单并付款,可以先让用户完成支付宝 OAuth 授权,再用授权码换取用户 ID。
基本流程如下:
- 引导用户访问支付宝授权地址。
- 用户确认授权后,支付宝跳转到商户配置的回调地址,并携带
auth_code。 - 使用
auth_code调用alipay.system.oauth.token。 - 从响应中取得
user_id。 - 将这个
user_id作为$buyerId创建订单。
EasySDK 的调用方式通常如下:
<?php
use Alipay\EasySDK\Kernel\Factory;
$authCode = $_GET['auth_code'] ?? '';
if ($authCode === '') {
throw new RuntimeException('缺少支付宝授权码 auth_code');
}
$tokenResult = Factory::base()
->oauth()
->getToken($authCode);
$buyerId = $tokenResult->userId ?? '';
if ($buyerId === '') {
throw new RuntimeException('未能从授权结果中取得支付宝 user_id');
}
$orderResult = Factory::payment()
->common()
->create(
'订单标题',
'ORDER_202609080002',
'0.01',
$buyerId
);
echo $orderResult->tradeNo;
获取授权码时,需要按照支付宝网页授权流程构造授权地址,并正确配置回调地址和授权范围。授权码通常有时效限制,而且只能使用一次,不应缓存后重复换取。
方案三:网页或移动端支付使用对应产品接口
如果只是希望用户跳转到支付宝完成付款,不需要在创建订单时绑定指定账户,可以根据终端类型选择对应接口:
// PC 网站支付
Factory::payment()
->page()
->pay($subject, $outTradeNo, $totalAmount, $returnUrl);
// 手机网站支付
Factory::payment()
->wap()
->pay($subject, $outTradeNo, $totalAmount, $returnUrl);
// App 支付
Factory::payment()
->app()
->pay($subject, $outTradeNo, $totalAmount);
具体参数请以当前 EasySDK 版本为准。选择支付产品时,要看接口是否符合实际付款流程:
- 任意用户扫码:使用
alipay.trade.precreate。 - 已知并且必须绑定某个支付宝用户:通过授权取得
user_id,再使用alipay.trade.create。 - PC 网站跳转支付:使用电脑网站支付。
- 手机浏览器跳转支付:使用手机网站支付。
- App 内唤起支付宝:使用 App 支付。
注意事项
以下内容都不能代替 $buyerId:
- 商户的
app_id - 商户支付宝账户 ID
- 登录手机号
- 邮箱地址
- OpenID
- 示例代码中的固定
2088...值 - 支付完成后异步通知中的其他账号字段
通过 OAuth 取得的 $buyerId 必须属于当前准备付款的用户。即使已经成功取得某个用户的 user_id,如果把订单二维码交给另一个账户扫描,仍可能出现账户不一致错误。
如果创建订单前无法确认实际付款账户,就不要调用必须传入 $buyerId 的 common()->create()。扫码付款应改用 faceToFace()->preCreate()。
备注:内容仅供参考。
