<?php
namespace app\index\controller;
// 引入ThinkPHP的Session门面(根据你的TP版本调整,TP5/6通用)
use think\facade\Session;
// 引入配置类
use think\facade\Config;
// 引入日志类,方便调试
use think\facade\Log;
class Test
{
/**
* 发送微信模板消息
* @param string $openid 接收消息用户的openid
* @param array $data 模板消息所需数据(create_time/site/order_cate_id/remark等)
* @return string 发送结果(成功/失败+原因)
*/
public function test()
{
// 这里是个人微信关注服务号之后产生的openid
$openid = 'oQ3jZ0QZH62lk1zpYUax4u5EIDXg';
// 1. 获取access_token
$access_token2 = '';
// 从Session获取缓存的token
if (Session::has('access_token')) {
$access_token2 = Session::get('access_token');
Log::info('从Session获取缓存的access_token');
} else {
// 从配置获取appid和appsecret
$appid = "wx002f60583b2b4ccc";
$secret = "892f79805bed29b4ce2c9a67523b3ad1";
if (empty($appid) || empty($secret)) {
Log::error('模板消息发送失败:appid或appsecret未配置');
return '发送失败:appid或appsecret未配置';
}
// 获取token的接口是GET请求
$token_url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$appid}&secret={$secret}";
$json_token = $this->curl_request($token_url);
if (empty($json_token)) {
Log::error('模板消息发送失败:获取access_token接口返回为空');
return '发送失败:获取access_token失败';
}
$access_token1 = json_decode($json_token, true);
// 校验token返回结果
if (json_last_error() !== JSON_ERROR_NONE) {
Log::error('模板消息发送失败:access_token返回值解析失败,原始数据:'.$json_token);
return '发送失败:access_token返回值解析失败';
}
if (isset($access_token1['errcode']) && $access_token1['errcode'] != 0) {
Log::error('模板消息发送失败:获取access_token出错,错误码:'.$access_token1['errcode'].',错误信息:'.$access_token1['errmsg']);
return '发送失败:'.$access_token1['errmsg'];
}
$access_token2 = $access_token1['access_token'] ?? '';
if (empty($access_token2)) {
Log::error('模板消息发送失败:access_token为空,原始返回:'.$json_token);
return '发送失败:access_token获取为空';
}
// 缓存token到Session,有效期7200秒(2小时)
Session::set('access_token', $access_token2, 7200);
Log::info('成功获取新的access_token并缓存到Session');
}
// 2. 发送模板消息
$json_template = $this->json_template($openid);
if (empty($json_template)) {
return '发送失败:模板消息JSON构建失败';
}
$send_url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$access_token2}";
// 模板消息发送是POST请求,传入JSON数据
$res = $this->curl_request($send_url, $json_template, 'POST');
if (empty($res)) {
Log::error('模板消息发送失败:接口返回为空,access_token:'.$access_token2);
return '发送失败:模板消息接口返回为空';
}
// 正确解析JSON返回结果
$res_arr = json_decode($res, true);
if (json_last_error() !== JSON_ERROR_NONE) {
Log::error('模板消息发送失败:返回值解析失败,原始数据:'.$res);
return '发送失败:返回值解析失败,原始数据:'.$res;
}
// 判断发送结果
if (isset($res_arr['errcode']) && $res_arr['errcode'] == 0) {
Log::info('模板消息发送成功,msgid:'.$res_arr['msgid']);
return '发送成功';
} else {
$err_msg = $res_arr['errmsg'] ?? '未知错误';
Log::error('模板消息发送失败:'.$err_msg.',错误码:'.$res_arr['errcode']);
return '发送失败:'.$err_msg;
}
}
/**
* 构建模板消息的JSON数据
* @param string $openid 用户openid
* @param array $data 模板数据
* @return string 格式化后的JSON字符串
*/
public function json_template($openid)
{
$template_id = "PDO8VNR5oyJ5ocGhuenGNH3gngVXzb8AqmeTiHpGgC0";
if (empty($template_id)) {
Log::error('模板消息构建失败:template_id未配置');
return '';
}
// 处理时间格式(确保create_time是时间戳)
// $create_time = isset($data['create_time']) ? $data['create_time'] : time();
$time = date("Y-m-d H:i:s");
// 获取跳转链接
$url = "pages/index/index";
// 构建模板数据
$template = [
'touser' => "oQ3jZ0QZH62lk1zpYUax4u5EIDXg",
'template_id' => $template_id,
'url' => $url,
'topcolor' => "#7B68EE",
'data' => [
'thing29' => ['value' => "用户名称", 'color' => "#FF0000"],
'character_string2' => ['value' => '订单号', 'color' => '#FF0000'],
'thing3' => ['value' =>$time, 'color' => '#FF0000'],
'amount30' => ['value' => '订单金额', 'color' => '#FF0000'],
'phone_number39' => ['value' =>'18328321035','color'=> '#FF0000'],
]
];
// 生成JSON(确保中文不转义,JSON_UNESCAPED_UNICODE)
$json_template = json_encode($template, JSON_UNESCAPED_UNICODE);
if (json_last_error() !== JSON_ERROR_NONE) {
Log::error('模板消息JSON构建失败:'.json_last_error_msg());
return '';
}
return $json_template;
}
/**
* 通用curl请求方法(支持GET/POST)
* @param string $url 请求地址
* @param string $post_data POST数据(JSON字符串)
* @param string $method 请求方式(GET/POST)
* @return string 接口返回数据
*/
function curl_request($url, $post_data = '', $method = 'GET')
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// 关闭SSL验证(生产环境建议开启,需配置CA证书)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// 设置超时时间
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
// POST请求处理
if (strtoupper($method) == 'POST' && !empty($post_data)) {
curl_setopt($ch, CURLOPT_POST, 1);
// 设置POST数据格式为JSON
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json; charset=utf-8',
'Content-Length: ' . strlen($post_data)
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
}
$output = curl_exec($ch);
// 捕获curl错误
if (curl_errno($ch)) {
Log::error('CURL请求错误:'.curl_error($ch).',URL:'.$url);
$output = '';
}
curl_close($ch);
return $output;
}
}注意:小程序要关联服务号才行
// 商户的openid(接收通知的管理员微信openid)
'merchant_openid' => 'oQ3jZ0QZH62lk1zpYUax4u5EIDXg', // 我自己的
//'merchant_openid'=>'oQ3jZ0Q3b54aYVbLb-qf9wnDlVc0', // 萌萌