165 lines
5.6 KiB
PHP
165 lines
5.6 KiB
PHP
<?php
|
||
namespace app\index\controller;
|
||
|
||
use think\facade\Request;
|
||
use think\facade\Log;
|
||
use think\facade\Cache;
|
||
|
||
class WechatController extends BaseController
|
||
{
|
||
public function index()
|
||
{
|
||
// 检查请求方法
|
||
if (Request::method() == 'GET') {
|
||
// 首次验证服务器地址的有效性
|
||
$this->checkSignature();
|
||
} elseif (Request::method() == 'POST') {
|
||
// 接收消息并回复
|
||
$response = $this->receiveMessage();
|
||
// 直接输出回复的XML字符串
|
||
echo $response;
|
||
exit;
|
||
}
|
||
}
|
||
|
||
// 验证签名
|
||
protected function checkSignature()
|
||
{
|
||
$signature = Request::get('signature');
|
||
$timestamp = Request::get('timestamp');
|
||
$nonce = Request::get('nonce');
|
||
$echostr = Request::get('echostr');
|
||
$token = "token2024";
|
||
$tmpArr = array($token, $timestamp, $nonce);
|
||
sort($tmpArr, SORT_STRING);
|
||
$tmpStr = implode($tmpArr);
|
||
$tmpStr = sha1($tmpStr);
|
||
|
||
if ($tmpStr == $signature) {
|
||
echo $echostr;
|
||
exit;
|
||
}
|
||
}
|
||
|
||
// 接收消息
|
||
protected function receiveMessage()
|
||
{
|
||
$postStr = file_get_contents("php://input");
|
||
if (empty($postStr)) {
|
||
return '';
|
||
}
|
||
|
||
libxml_disable_entity_loader(true);
|
||
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
|
||
Log::write($postObj);
|
||
// 检查消息类型
|
||
$msgType = strtolower((string) $postObj->MsgType);
|
||
if ($msgType == 'text') {
|
||
// 提取消息内容
|
||
$fromUsername = (string) $postObj->FromUserName; // 微信用户openid
|
||
$toUsername = (string) $postObj->ToUserName; // 公众号id
|
||
$keyword = trim((string) $postObj->Content);
|
||
|
||
// 构造自动回复的文本消息
|
||
$time = time();
|
||
$textTpl = "<xml>
|
||
<ToUserName><![CDATA[%s]]></ToUserName>
|
||
<FromUserName><![CDATA[%s]]></FromUserName>
|
||
<CreateTime>%s</CreateTime>
|
||
<MsgType><![CDATA[text]]></MsgType>
|
||
<Content><![CDATA[%s]]></Content>
|
||
<FuncFlag>0</FuncFlag>
|
||
</xml>";
|
||
|
||
|
||
$responseContent = "消息标题";
|
||
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $responseContent);
|
||
// 假设已经确定要发送小程序卡片消息
|
||
$this->sendMiniProgramCard((string) $postObj->FromUserName);
|
||
|
||
return $resultStr;
|
||
}
|
||
// 如果需要处理其他类型的消息,可以在这里添加相应的逻辑
|
||
|
||
// 如果不是文本消息,可以返回一个空字符串或错误消息
|
||
return '';
|
||
}
|
||
|
||
// 发送小程序卡片消息的方法
|
||
private function sendMiniProgramCard($openid)
|
||
{
|
||
|
||
$accessToken = $this->getGZHAccessToken();
|
||
if (!$accessToken) {
|
||
// 处理获取access_token失败的情况
|
||
return;
|
||
}
|
||
$postData = json_encode([
|
||
'touser' => $openid, // 接收者(用户)的openid
|
||
'msgtype' => 'miniprogrampage',
|
||
'miniprogrampage' => [
|
||
'title' => '小程序标题',
|
||
'appid' => '小程序appid',
|
||
'pagepath' => '小程序路径',
|
||
'thumb_media_id' => '你的thumb_media_id'
|
||
]
|
||
], JSON_UNESCAPED_UNICODE);
|
||
$url = "https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={$accessToken}";
|
||
$result = json_decode(file_get_contents($url, false, stream_context_create([
|
||
'http' => [
|
||
'method' => 'POST',
|
||
'header' => "Content-type: application/json\r\n",
|
||
'content' => $postData,
|
||
'timeout' => 60 // 超时时间(单位:s)
|
||
]
|
||
])), true);
|
||
// 处理返回结果
|
||
if ($result['errcode'] == 0) {
|
||
// 发送成功
|
||
} else {
|
||
// 发送失败
|
||
}
|
||
}
|
||
|
||
// 获取公众号Access token
|
||
public function getGZHAccessToken()
|
||
{
|
||
$access_token = Cache::get('gzh_access_token');
|
||
if (!$access_token) {
|
||
$config = [
|
||
'appid' => 'appid',
|
||
'secret' => 'secret',
|
||
'grant_type' => 'client_credential'
|
||
];
|
||
$response = $this->curlPost('https://api.weixin.qq.com/cgi-bin/token', $config);
|
||
$data = json_decode($response, true);
|
||
$access_token = $data["access_token"];
|
||
Cache::set('gzh_access_token', $access_token, $data["expires_in"] - 200);
|
||
}
|
||
return $access_token;
|
||
}
|
||
|
||
// 发送请求
|
||
public function curlPost($url = '', $postData = '', $options = array())
|
||
{
|
||
if (is_array($postData)) {
|
||
$postData = http_build_query($postData);
|
||
}
|
||
$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, $postData);
|
||
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
|
||
if (!empty($options)) {
|
||
curl_setopt_array($ch, $options);
|
||
}
|
||
//https请求 不验证证书和host
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||
$data = curl_exec($ch);
|
||
curl_close($ch);
|
||
|
||
return $data;
|
||
}
|
||
} |