在 PHP 项目中对接支付宝支付,第一步通常不是写业务代码,而是把沙箱环境的参数准备完整。支付宝沙箱环境与正式环境使用同一套接口协议,但网关地址、应用 ID、密钥和买家账号都独立,适合在本地进行支付流程联调。创建沙箱应用后,你会拿到 APPID、商户私钥、支付宝公钥和沙箱网关四个核心参数,后续 PHP 代码中的所有签名和请求都要依赖它们。

一、沙箱应用创建与密钥配置
进入支付宝开放平台并登录后,在控制台找到沙箱环境入口。沙箱环境不需要企业资质,个人开发者可以直接创建应用。创建完成后,系统会分配一个独立的 APPID,这个值需要在 PHP 代码中作为应用标识。与此同时,沙箱环境还提供买家账号和登录密码,买家账号可用于在沙箱收银台完成付款测试。
密钥配置是 PHP 对接支付宝最容易出错的地方。支付宝采用 RSA2 非对称签名机制,你需要先生成一对 RSA 密钥。可以在开放平台下载密钥生成工具,或者使用 OpenSSL 命令生成。生成后会得到应用私钥和应用公钥,私钥必须由开发者自行保管,不能上传到代码仓库或浏览器端;应用公钥需要粘贴到沙箱应用配置页面,由支付宝生成对应的支付宝公钥。这里要注意,PHP 代码中填入的是支付宝公钥,而不是应用公钥。私钥内容在代码中应保持完整,若使用文件方式加载,注意文件格式不要混入多余空格。
- APPID:沙箱应用的应用 ID
- 应用私钥:用于对请求参数签名
- 支付宝公钥:用于校验支付宝异步通知签名
- 沙箱网关:
https://openapi-sandbox.dl.alipaydev.com/gateway.do - 沙箱买家账号:沙箱环境页面直接提供
授权回调地址需要在沙箱应用配置中设置,可以是本地回环地址或内网穿透地址。支付宝在异步通知和同步跳转时会访问这些地址,如果本地网络不可达,异步通知就无法接收。建议使用内网穿透工具把本地服务暴露为公网 HTTPS 地址,再填入配置。
二、安装 PHP SDK 并封装支付请求
支付宝官方提供了 PHP 版 SDK,可以通过 Composer 安装。项目根目录执行 composer require alipay/alipay-sdk-php 即可引入。安装完成后,在入口文件中加载 autoload,再使用 AopClient 类完成签名和请求。AopClient 会读取网关、APPID、私钥等信息,对业务参数进行 RSA2 签名,并生成可自动跳转的支付表单。
以下是一个典型的电脑网站支付请求封装。业务参数中,out_trade_no 是商户订单号,同一商户下不能重复;total_amount 是以元为单位的金额;subject 是订单标题。设置好同步跳转地址和异步通知地址后,调用 pageExecute 方法,会返回一段 HTML 表单,浏览器打开即可跳转到支付宝收银台。
require_once 'vendor/autoload.php';
use Alipay\AopClient;
use Alipay\AlipayTradePagePayRequest;
$aop = new AopClient();
$aop->gatewayUrl = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do';
$aop->appId = '2021000000000000';
$aop->rsaPrivateKey = '你的应用私钥内容';
$aop->alipayPublicKey = '支付宝公钥内容';
$aop->signType = 'RSA2';
$aop->apiVersion = '1.0';
$aop->postCharset = 'UTF-8';
$aop->format = 'json';
$request = new AlipayTradePagePayRequest();
$request->setNotifyUrl('https://你的域名/notify.php');
$request->setReturnUrl('https://你的域名/return.php');
$bizContent = [
'out_trade_no' => date('YmdHis') . rand(1000, 9999),
'product_code' => 'FAST_INSTANT_TRADE_PAY',
'total_amount' => '0.01',
'subject' => 'PHP沙箱测试订单',
];
$request->setBizContent(json_encode($bizContent, JSON_UNESCAPED_UNICODE));
$result = $aop->pageExecute($request);
echo $result;
上述代码中的密钥建议通过环境变量或独立配置文件读取,不要在控制器中硬编码。同步跳转和异步通知地址需要与沙箱应用配置保持一致,否则订单支付成功后可能收不到回调。金额使用字符串类型,可以避免浮点精度问题,沙箱环境中 0.01 元足够完成支付验证。
三、同步返回与异步通知验签
支付宝支付完成后有两个回跳路径:同步 return_url 和异步 notify_url。同步跳转只用于页面展示,用户可能关闭页面或者网络中断,因此不能把订单状态改为已支付。异步通知是支付宝服务器主动 POST 到你的服务器,只有验签通过并且参数无误,才能更新订单状态。
异步通知验签的核心是使用支付宝公钥校验 sign 字段。验签前需要移除 sign 和 sign_type 两个参数,再对剩余参数进行字典序拼接。旧版 SDK 的 verify 方法可以简化这个过程,但底层逻辑仍然一致。收到通知后,建议先记录原始 POST 数据,再处理业务,以便后续排查。
require_once 'vendor/autoload.php';
use Alipay\AopClient;
$aop = new AopClient();
$aop->alipayPublicKey = '支付宝公钥内容';
$params = $_POST;
if (empty($params) || !isset($params['sign'])) {
echo 'fail';
exit;
}
$sign = $params['sign'];
unset($params['sign'], $params['sign_type']);
if (!$aop->verify($params, $sign)) {
echo 'fail';
exit;
}
$outTradeNo = $params['out_trade_no'];
$tradeStatus = $params['trade_status'];
$totalAmount = $params['total_amount'];
$appId = $params['app_id'];
if ($tradeStatus === 'TRADE_SUCCESS' || $tradeStatus === 'TRADE_FINISHED') {
// 根据 out_trade_no 查询订单,确认金额后更新为已支付
}
echo 'success';
验签通过后还需要核对 app_id 是否是自己的沙箱应用、订单号和金额是否与本地订单一致。支付宝可能会对同一订单发送多次异步通知,处理业务前应判断订单是否已经更新,避免重复发货或重复累加余额。业务处理完成后,必须输出 success 纯文本,支付宝收到 success 后才停止重试。
四、沙箱调试常见问题与排查
沙箱环境调试时,验签失败是最常见的提示。出现这个问题时,可以先检查私钥和支付宝公钥是否匹配,尤其要注意是否误把应用公钥当作支付宝公钥填入了代码。RSA2 签名要求密钥长度至少 2048 位,部分老版本 OpenSSL 生成的 1024 位密钥会直接导致签名失败。检查代码中的网关地址,沙箱和正式的网关完全不同,如果把正式密钥配到沙箱网关,请求也会直接失败。
异步通知收不到的问题通常和网络可达性有关。支付宝服务器无法访问 localhost,因此回调地址不能直接填写 127.0.0.1。可以使用内网穿透工具,将本地 80 或 443 端口映射为公网 HTTPS 地址,并且保证穿透服务稳定。调试过程中如果发现支付成功但没有回调,可以先检查沙箱应用配置的授权回调地址,再查看 Web 服务器访问日志,确认支付宝是否有发过 POST 请求。
支付页面提示订单参数错误时,优先检查 out_trade_no 是否重复、total_amount 是否为合法数字字符串、subject 是否为空。沙箱环境对订单金额有一定范围限制,过大的金额会被拦截。完成沙箱调试后,切换到正式环境只需要替换网关、APPID、密钥和回调地址,并重新生成正式环境的支付宝公钥,不建议复用沙箱密钥。