微信支付回调PHP怎么接收_处理微信异步通知数据教程【说明】

发布时间 - 2025-12-31 00:00:00    点击率:
微信支付回调必须用file_get_contents('php://input')读取原始XML,经simplexml_load_string转数组后按字典序拼接非空非sign字段+密钥MD5验签,成功后立即返回纯文本success。

微信支付回调必须用原生 php://input 读取原始 XML 数据

微信服务器发起的异步通知是 POST 请求,但**不带 Content-Type: application/x-www-form-urlencoded**,也不走 PHP 的 $_POST。它发的是纯 XML(Content-Type: text/xml),且不附带任何 URL 编码参数。直接读 $_POST$_REQUEST 一定是空的。

正确做法是:

  • file_get_contents('php://input') 获取原始请求体
  • 不能用 $HTTP_RAW_POST_DATA(PHP 7.0+ 已废弃,且默认关闭)
  • 必须在脚本开头就读,否则后续调用 php://input 会返回空
$xml = file_get_contents('php://input');
if (empty($xml)) {
    // 微信可能没发数据,或被中间件/代理截断
    exit('fail');
}

验签前先用 simplexml_load_string() 解析并转成数组

微信返回的 XML 结构固定,但字段名大小写敏感、存在嵌套(如 在根节点),直接用 DOM 或正则解析容易出错。推荐用 simplexml_load_string() + json_decode(json_encode(...), true) 转为关联数组。

注意两点:

  • XML 中的 会被自动剥离,内容直接作为字符串值
  • 如果 XML 格式非法(比如微信重试时传了乱码),simplexml_load_string() 会返回 false,必须判空并返回 fail
$data = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
if ($data === false) {
    exit('fail');
}
$notify = json_decode(json_encode($data), true);

验签必须按微信文档拼接字符串:字段名升序 + 不含 sign + 签名密钥末尾加

微信签名规则不是简单地把所有字段连起来,而是有严格顺序和过滤条件:

  • 只取 $notify 中值非空、且 key 不是 sign 的字段
  • key 按字典序(ASCII 升序)排序,不是中文拼音,也不是 PHP 数组键顺序
  • 每个 key=value& 连接,末尾**不加 &**
  • 最后拼上 &key=YOUR_MCH_KEY(你的商户平台「API 密钥」,32 位)

常见翻车点:

  • 漏掉 trade_typebank_type 等可选字段导致签名不一致
  • total_fee 当整数参与拼接(实际要原样字符串,如 "100"
  • md5() 但没转大写(微信要求大写 HEX)
$params = [];
foreach ($notify as $k => $v) {
    if ($k !== 'sign' && $v !== '' && !is_array($v)) {
        $params[$k] = $v;
    }
}
ksort($params);
$string = http_build_query($params, '', '&', PHP_QUERY_RFC3986);
$string .= '&key=your_32bit_mch_key';
$localSign = strtoupper(md5($string));
if ($localSign !== $notify['sign']) {
    exit('fail');
}

处理成功后必须立即返回 success 纯文本,且 HTTP 状态码为 200

微信服务器收到非 success(比如 FAIL、空响应、HTML 页面、JSON 字符串)或超时(>5 秒)、状态码非 200,就会持续重试(最多 10 次,间隔不断拉长)。你不能在返回前查数据库、发邮件、调第三方 API——这些必须异步做。

安全建议:

  • 先验签,再检查 $notify['result_code'] === 'SUCCESS'$notify['return_code'] === 'SUCCESS'
  • $notify['out_trade_no'] 查询本地订单是否存在且未支付,避免重复处理
  • 更新订单状态后,再返回 success;哪怕 DB 写失败,也应记录日志并返回 fail 触发重试
if ($notify['result_code'] === 'SUCCESS' && $notify['return_code'] === 'SUCCESS') {
    // 查单、更新、发消息等业务逻辑(建议丢进队列)
    updateOrderStatus($notify['out_trade_no'], $notify['transaction_id']);
}
// 必须无任何输出、无换行、纯文本
echo 'success';
微信回调最常卡在「以为能读 $_POST」和「签名字符串拼错顺序或漏字段」,这两处多打几个 var_dump() 对比微信文档里的示例签名,基本就能定位。


# php  # html  # js  # json  # 微信  # 编码  # app  # 微信支付  # ai  # 状态码  # 关联数组  # xml  # 字符串  # dom  # 异步  # input  # ASCII  # 数据库  # http  # 升序  # 回调  # 重试  # 的是  # 字段名  # 几个  # 就会  # 文档  # 是有  # 就能 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何记录日志_Laravel Logging系统配置与自定义日志通道  Python文件流缓冲机制_IO性能解析【教程】  JavaScript如何实现路由_前端路由原理是什么  Android自定义listview布局实现上拉加载下拉刷新功能  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  Midjourney怎么调整光影效果_Midjourney光影调整方法【指南】  夸克浏览器网页跳转延迟怎么办 夸克浏览器跳转优化  Laravel辅助函数有哪些_Laravel Helpers常用助手函数大全  Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧  Laravel如何配置中间件Middleware_Laravel自定义中间件拦截请求与权限校验【步骤】  Laravel如何使用Contracts(契约)进行编程_Laravel契约接口与依赖反转  Laravel如何实现多级无限分类_Laravel递归模型关联与树状数据输出【方法】  Laravel如何使用Livewire构建动态组件?(入门代码)  大型企业网站制作流程,做网站需要注册公司吗?  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  如何在万网ECS上快速搭建专属网站?  Laravel PHP版本要求一览_Laravel各版本环境要求对照  高性能网站服务器部署指南:稳定运行与安全配置优化方案  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  网页制作模板网站推荐,网页设计海报之类的素材哪里好?  Laravel如何创建自定义Facades?(详细步骤)  Laravel如何自定义错误页面(404, 500)?(代码示例)  如何在阿里云ECS服务器部署织梦CMS网站?  如何用JavaScript实现文本编辑器_光标和选区怎么处理  厦门模型网站设计制作公司,厦门航空飞机模型掉色怎么办?  如何基于云服务器快速搭建个人网站?  敲碗10年!Mac系列传将迎来「触控与联网」双革新  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  Win11怎样安装网易有道词典_Win11安装词典教程【步骤】  EditPlus中的正则表达式 实战(4)  html5的keygen标签为什么废弃_替代方案说明【解答】  HTML5打空格有哪些误区_新手常犯的空格使用错误【技巧】  PHP正则匹配日期和时间(时间戳转换)的实例代码  打开php文件提示内存不足_怎么调整php内存限制【解决方案】  Laravel集合Collection怎么用_Laravel集合常用函数详解  Laravel distinct去重查询_Laravel Eloquent去重方法  Laravel如何集成Inertia.js与Vue/React?(安装配置)  Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】  Laravel如何处理和验证JSON类型的数据库字段  如何快速查询域名建站关键信息?  如何在云服务器上快速搭建个人网站?  Laravel怎么配置自定义表前缀_Laravel数据库迁移与Eloquent表名映射【步骤】  Bootstrap整体框架之JavaScript插件架构  美食网站链接制作教程视频,哪个教做美食的网站比较专业点?  如何用已有域名快速搭建网站?  如何生成腾讯云建站专用兑换码?  Laravel项目怎么部署到Linux_Laravel Nginx配置详解  如何在HTML表单中获取用户输入并用JavaScript动态控制复利计算循环  php做exe能调用系统命令吗_执行cmd指令实现方式【详解】  Midjourney怎样加参数调细节_Midjourney参数调整技巧【指南】