本文目录导读:

在PHP项目中对接微信接口(如微信支付、公众号、小程序、企业微信等),核心流程通常分为两步:获取凭证(Access Token) 和 调用具体业务接口。
以下以最常用的微信公众号/小程序开发为例,给出详细步骤和关键代码示例。
前期准备
在编写代码前,必须完成以下准备:
- 注册账号:在 微信公众平台 注册服务号或小程序。
- 获取配置:
AppID(应用ID)AppSecret(应用密钥)IP白名单:在后台将你的服务器IP加入白名单,否则无法获取Access Token。服务器配置:如果是公众号,需要配置URL(你的接口地址)和Token(用于验证)。
- 服务器环境:
- PHP 5.6+ (推荐7.4+)
- 开启
curl、openssl扩展 - HTTPS证书(微信支付及部分高级接口强制要求)
核心流程:获取 Access Token
几乎所有微信接口(除了获取Token本身)都需要一个access_token作为全局唯一接口调用凭据。Access Token有效期为2小时,需要缓存起来,避免频繁刷新。
下面是一个封装好的获取Access Token的类(使用文件缓存):
<?php
// WechatApi.php
class WechatApi {
private $appId;
private $appSecret;
private $cacheFile; // 用于缓存access_token的文件路径
private $tokenUrl = 'https://api.weixin.qq.com/cgi-bin/token';
public function __construct($appId, $appSecret) {
$this->appId = $appId;
$this->appSecret = $appSecret;
$this->cacheFile = __DIR__ . '/access_token.json';
}
// 获取 access_token(带缓存)
public function getAccessToken() {
// 1. 检查本地缓存是否有效
$data = $this->getCache();
if ($data && isset($data['access_token']) && $data['expires_time'] > time()) {
return $data['access_token'];
}
// 2. 缓存失效,重新请求微信服务器
$url = sprintf('%s?grant_type=client_credential&appid=%s&secret=%s',
$this->tokenUrl, $this->appId, $this->appSecret);
$result = $this->httpGet($url);
if ($result === false) {
throw new Exception('请求微信服务器失败');
}
$json = json_decode($result, true);
if (isset($json['access_token'])) {
// 3. 存入缓存,提前5分钟过期以应对网络延迟
$this->saveCache([
'access_token' => $json['access_token'],
'expires_time' => time() + $json['expires_in'] - 300 // 有效期两小时,提前5分钟
]);
return $json['access_token'];
} else {
throw new Exception('获取access_token失败: ' . $json['errmsg']);
}
}
// 通用 GET 请求
private function httpGet($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // 本地测试可关闭,生产建议开启
$result = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $httpCode == 200 ? $result : false;
}
// 通用 POST 请求
private function httpPost($url, $data) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data, JSON_UNESCAPED_UNICODE));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
// 简单文件缓存(生产环境建议使用 Redis 或 Memcache)
private function getCache() {
if (file_exists($this->cacheFile)) {
return json_decode(file_get_contents($this->cacheFile), true);
}
return null;
}
private function saveCache($data) {
file_put_contents($this->cacheFile, json_encode($data));
}
}
使用方法:
$wechat = new WechatApi('你的AppID', '你的AppSecret');
try {
$token = $wechat->getAccessToken();
// 接下来就可以用这个 $token 去调其他接口了
echo $token;
} catch (Exception $e) {
echo '错误: ' . $e->getMessage();
}
对接常见业务接口
有了access_token,就可以对接各种业务接口了,下面列举几个典型场景:
公众号发送模板消息
$url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=' . $token;
$data = [
'touser' => '用户OpenID',
'template_id' => '模板ID',
'data' => [
'first' => ['value' => '您好,您的订单已更新', 'color' => '#173177'],
'keyword1' => ['value' => '订单号123'],
'keyword2' => ['value' => '已发货'],
'remark' => ['value' => '感谢您的惠顾']
]
];
$result = $wechat->httpPost($url, $data);
小程序获取用户OpenID(通过code)
// 前端 wx.login() 后得到的 code $code = $_GET['code']; $url = 'https://api.weixin.qq.com/sns/jscode2session?appid=AppID&secret=AppSecret&js_code=' . $code . '&grant_type=authorization_code'; $result = $wechat->httpGet($url); $json = json_decode($result, true); // $json['openid'] 和 $json['session_key']
微信支付(JSAPI支付)
微信支付比其它接口复杂,包括:统一下单、生成签名、调起支付、接收回调。
关键步骤示例(统一下单):
$orderData = [
'appid' => '你的AppID',
'mch_id' => '你的商户号',
'nonce_str' => md5(time()), // 随机字符串
'body' => '商品描述',
'out_trade_no' => '订单号', // 需确保唯一
'total_fee' => 1, // 单位:分
'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
'notify_url' => 'https://你的域名/notify.php', // 回调地址
'trade_type' => 'JSAPI',
'openid' => '用户的OpenID'
];
// 生成签名(微信支付签名算法)
$orderData['sign'] = generateSign($orderData, '你的API密钥');
// XML格式请求
$xmlData = arrayToXml($orderData);
$url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
$response = httpPostXml($url, $xmlData);
$result = xmlToArray($response);
if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
$prepayId = $result['prepay_id'];
// 生成前端调起支付需要的参数
$paySignData = [
'appId' => '你的AppID',
'timeStamp' => (string)time(),
'nonceStr' => md5(time()),
'package' => 'prepay_id=' . $prepayId,
'signType' => 'MD5'
];
$paySignData['paySign'] = generateSign($paySignData, '你的API密钥');
echo json_encode($paySignData);
}
注意:微信支付涉及签名的生成、XML格式转换、处理异步通知,建议使用官方或成熟第三方 SDK(如 EasyWeChat)来降低出错概率。
验证服务器地址(公众号初次接入)
当你第一次在微信公众平台配置服务器URL时,需要先验证消息来自微信服务器。
// 入口文件 index.php
$token = '你在后台设置的Token';
// 1. 验证签名(仅第一次配置时)
$signature = $_GET["signature"];
$timestamp = $_GET["timestamp"];
$nonce = $_GET["nonce"];
$echostr = $_GET["echostr"];
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $signature) {
// 如果请求中包含 echostr,则是验证请求,直接返回
if ($echostr) {
echo $echostr;
exit;
}
// 否则是正常消息处理
handleMsg();
} else {
echo "signature error";
exit;
}
安全与注意事项
- 缓存Access Token:不要每次请求都去获取,2小时内有效,超限会被微信限流。
- 使用HTTPS:微信支付和获取用户敏感信息(如手机号)的接口强制要求HTTPS。
- 验证回调签名:接收微信通知(如支付结果、模板消息结果)时,必须验证签名,防止伪造请求。
- 错误处理:微信返回的错误码包括
errcode和errmsg,建议记录日志以便排查。 - 推荐使用成熟库:
- EasyWeChat(PHP 最流行的微信 SDK,支持公众号、小程序、支付等)
- WxManager(轻量级)
使用成熟SDK可以让代码更简洁、更稳定,例如使用EasyWeChat,调用获取Access Token只用一行:
$app = Factory::officialAccount($config); $accessToken = $app->access_token->getToken(); // ['access_token' => 'xxx', 'expires_in' => 7200]
对接微信接口的核心思路是:获取并缓存Access Token -> 使用Token调用具体业务接口 -> 处理好签名验证和回调通知,如果是新项目,建议直接使用 EasyWeChat 等成熟库,能省去大量底层细节处理工作。