yunzer/app/index/controller/WechatController.php
2025-06-05 21:38:57 +08:00

203 lines
6.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\index\controller;
use think\facade\Request;
use think\facade\Log;
use think\facade\Cache;
use GuzzleHttp\Client;
use app\index\model\AdminConfig;
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 = AdminConfig::where('config_name', 'wechat_token')->value('config_value');
$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();
print_r($accessToken);
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()
{
// 从数据库获取配置
$appid = AdminConfig::where('config_name', 'wechat_appid')->value('config_value');
$secret = AdminConfig::where('config_name', 'wechat_appsecret')->value('config_value');
if (empty($appid) || empty($secret)) {
throw new \Exception('微信配置信息未设置');
}
// 构建请求URL
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
try {
// 使用 GuzzleHttp 发送请求
$client = new Client();
$response = $client->get($url);
$data = json_decode($response->getBody(), true);
$response = $client->get($url);
$data = json_decode($response->getBody(), true);
if (!isset($data['access_token'])) {
throw new \Exception("获取access_token失败: {$data['errmsg']}", $data['errcode'] ?? -1);
}
return $data['access_token'];
} catch (\Exception $e) {
Log::error('获取access_token失败' . $e->getMessage());
throw $e;
}
}
//获取登录二维码的 ticket
public function getLoginTicket()
{
// 获取access_token
$access_token = $this->getGZHAccessToken();
// 构建请求URL
$url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token={$access_token}&type=image";
// 准备二维码图片文件
$file = request()->file('qrcode');
if (!$file) {
return json(['code' => 1, 'msg' => '请上传二维码图片']);
}
// 将文件转换为CURLFile对象
$file_path = $file->getPathname();
$file_name = $file->getOriginalName();
$file_type = $file->getMime();
$data = [
'media' => new \CURLFile($file_path, $file_type, $file_name)
];
// 发送请求获取ticket
$result = $this->curlPost($url, $data);
$response = json_decode($result, true);
if (isset($response['errcode']) && $response['errcode'] != 0) {
return json(['code' => 1, 'msg' => '获取ticket失败' . $response['errmsg']]);
}
return json([
'code' => 0,
'msg' => '获取ticket成功',
'data' => [
'media_id' => $response['media_id'],
'created_at' => $response['created_at'],
'type' => $response['type']
]
]);
}
}