PHP项目怎么对接微信接口?

wen PHP项目 10

本文目录导读:

PHP项目怎么对接微信接口?

  1. 前期准备
  2. 核心流程:获取 Access Token
  3. 对接常见业务接口
  4. 验证服务器地址(公众号初次接入)
  5. 安全与注意事项

在PHP项目中对接微信接口(如微信支付、公众号、小程序、企业微信等),核心流程通常分为两步:获取凭证(Access Token)调用具体业务接口

以下以最常用的微信公众号/小程序开发为例,给出详细步骤和关键代码示例。

前期准备

在编写代码前,必须完成以下准备:

  1. 注册账号:在 微信公众平台 注册服务号或小程序。
  2. 获取配置
    • AppID (应用ID)
    • AppSecret (应用密钥)
    • IP白名单:在后台将你的服务器IP加入白名单,否则无法获取Access Token。
    • 服务器配置:如果是公众号,需要配置URL(你的接口地址)和Token(用于验证)。
  3. 服务器环境
    • PHP 5.6+ (推荐7.4+)
    • 开启 curlopenssl 扩展
    • 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;
}

安全与注意事项

  1. 缓存Access Token:不要每次请求都去获取,2小时内有效,超限会被微信限流。
  2. 使用HTTPS:微信支付和获取用户敏感信息(如手机号)的接口强制要求HTTPS。
  3. 验证回调签名:接收微信通知(如支付结果、模板消息结果)时,必须验证签名,防止伪造请求。
  4. 错误处理:微信返回的错误码包括 errcodeerrmsg,建议记录日志以便排查。
  5. 推荐使用成熟库
    • 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 等成熟库,能省去大量底层细节处理工作。

抱歉,评论功能暂时关闭!