本文目录导读:

- 微信支付/微信小程序 回调校验(加密签名)
- 支付宝回调校验(RSA2 签名)
- 通用 HMAC-SHA256 签名校验(自定义开发)
- 简化版:使用框架验证(Laravel / Symfony 等)
- 校验的通用原则(重要提示)
- 建议
在 PHP 中,回调地址校验(通常用于微信支付、支付宝等第三方接口)是安全关键环节,主要目的是确认请求确实来自对方服务器,防止伪造回调。
以下是几种常见的校验方式和完整代码示例:
微信支付/微信小程序 回调校验(加密签名)
微信的回调通常包含 signature、timestamp、nonce 三个参数,需要按以下步骤校验。
<?php
/**
* 微信回调地址校验(GET 请求用于URL验证,POST 用于业务通知)
* 适用于微信支付、公众号、小程序等
*/
// 你的 Token(在微信公众平台/商户平台设置)
$token = 'your_wechat_token_here';
// 获取请求参数(GET 用于首次配置验证,POST 用于后续业务回调)
$signature = $_GET['signature'] ?? '';
$timestamp = $_GET['timestamp'] ?? '';
$nonce = $_GET['nonce'] ?? '';
$echostr = $_GET['echostr'] ?? '';
// 1. 将 token、timestamp、nonce 三个参数进行字典序排序
$tmpArr = [$token, $timestamp, $nonce];
sort($tmpArr, SORT_STRING);
// 2. 将三个参数字符串拼接成一个字符串进行 sha1 加密
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
// 3. 开发者获得加密后的字符串可与 signature 对比
if ($tmpStr === $signature) {
// 签名验证通过
// 如果是 URL 验证(GET 请求),直接返回 echostr
if (!empty($echostr) && $_SERVER['REQUEST_METHOD'] === 'GET') {
echo $echostr;
exit;
}
// 如果是业务回调(POST),继续处理业务逻辑
// $postData = file_get_contents('php://input');
// $xml = simplexml_load_string($postData, 'SimpleXMLElement', LIBXML_NOCDATA);
echo 'success';
exit;
} else {
// 验证失败
http_response_code(403);
echo 'Invalid signature';
exit;
}
支付宝回调校验(RSA2 签名)
支付宝使用 RSA2 算法验证签名,需要用到支付宝公钥。
<?php
/**
* 支付宝回调验签(RSA2)
*/
// 支付宝公钥(从支付宝开放平台获取,非应用私钥)
$alipayPublicKey = '-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A...
-----END PUBLIC KEY-----';
// 获取 POST 请求的参数(支付宝以 POST 表单形式提交)
$postData = $_POST;
// 移除 sign 和 sign_type 参数
$sign = $postData['sign'] ?? '';
unset($postData['sign'], $postData['sign_type']);
// 1. 将所有参数按 key 升序排序
ksort($postData);
// 2. 拼接成 URL 查询字符串
$content = urldecode(http_build_query($postData));
// 3. 使用支付宝公钥验证签名
$result = openssl_verify(
$content,
base64_decode($sign),
$alipayPublicKey,
OPENSSL_ALGO_SHA256 // RSA2 使用的算法
);
if ($result === 1) {
// 验签成功
// 检查 is_success / trade_status 等业务参数
if ($postData['trade_status'] === 'TRADE_SUCCESS' || $postData['trade_status'] === 'TRADE_FINISHED') {
// 处理业务逻辑...
echo 'success'; // 必须返回 success,支付宝才认为处理成功
exit;
}
echo 'success';
exit;
}
// 验签失败
http_response_code(400);
echo 'fail';
exit;
通用 HMAC-SHA256 签名校验(自定义开发)
如果你是自己开发的系统(如开放平台 API),推荐使用 HMAC 签名。
<?php
/**
* 通用 HMAC-SHA256 回调校验
* 签名规则:HMAC-SHA256(secret, query_string 排序拼接)
*/
// 预设的共享密钥(与调用方约定)
$secret = 'your_shared_secret_key';
// 获取请求头或参数中的签名
$providedSign = $_SERVER['HTTP_X_SIGNATURE'] ?? ($_GET['sign'] ?? '');
// 获取所有 POST 参数(排除 sign 字段)
$params = $_POST;
if (isset($params['sign'])) {
unset($params['sign']);
}
// 1. 将参数按 key 排序
ksort($params);
// 2. 拼接成字符串
$data = [];
foreach ($params as $key => $value) {
$data[] = $key . '=' . $value;
}
$signStr = implode('&', $data);
// 3. 计算 HMAC-SHA256
$computedSign = hash_hmac('sha256', $signStr, $secret);
// 4. 安全比较(防止时序攻击)
if (hash_equals($computedSign, $providedSign)) {
// 签名有效,继续处理业务
echo 'ok';
exit;
}
http_response_code(401);
echo 'Invalid signature';
exit;
简化版:使用框架验证(Laravel / Symfony 等)
如果你使用 Laravel,可以创建自定义中间件来统一处理:
// app/Http/Middleware/VerifyCallbackSignature.php
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
class VerifyCallbackSignature
{
public function handle(Request $request, Closure $next)
{
$secret = config('services.callback_secret');
$signature = $request->header('X-Callback-Signature');
// 按你自己的规则计算签名
$payload = $request->getContent();
$computed = hash_hmac('sha256', $payload, $secret);
if (!hash_equals($computed, $signature)) {
return response()->json(['error' => 'Invalid signature'], 403);
}
return $next($request);
}
}
然后在路由中使用:
Route::post('payment/callback', [PaymentController::class, 'callback'])
->middleware('verify.signature');
校验的通用原则(重要提示)
| 原则 | 说明 |
|---|---|
使用 hash_equals() |
不用 比较签名,使用 hash_equals() 防止时序攻击 |
| 验签后不要立刻信任数据 | 还要验证金额、订单号、商户号等业务数据是否匹配 |
| 幂等处理 | 回调可能重复发送,需使用订单状态判断重复请求 |
| 返回特定响应 | 如微信需返回 success,支付宝返回 success,否则会重试 |
| 限制 IP | 可配置白名单 IP(微信/支付宝固定 IP 段) |
| HTTPS 必备 | 回调地址必须支持 HTTPS |
| 日志记录 | 记录所有回调请求(保留原始数据)便于排查 |
建议
- 使用官方 SDK:微信和支付宝都有官方 PHP SDK,里面封装了验签逻辑,避免自己实现出错。
- 测试环境:上线前使用沙箱环境测试回调。
- 安全审计:定期检查回调日志,防止重放攻击。
如果需要针对某个具体平台(微信支付、支付宝、银联等)做详细配置,可以告诉我,我提供更详细的配置步骤。