微信公众号开发文档
1. 概述
微信公众号模块是系统中负责微信公众号集成和管理的核心功能,支持微信公众号的配置管理、菜单管理、回复管理、素材管理等功能,为系统提供与微信公众号的深度集成能力。
2. 功能模块
2.1 微信配置管理
2.1.1 基本配置
- 公众号名称
- 原始ID
- AppID
- AppSecret
- 公众号二维码
- Token
- EncodingAESKey
- 加解密模式
2.1.2 静态信息
- 服务器地址
- 业务域名
- JS安全域名
- 网页授权域名
2.2 微信菜单管理
2.2.1 菜单配置
- 一级菜单(最多3个)
- 二级菜单(每个一级菜单最多5个)
- 菜单类型(点击、跳转链接、小程序等)
2.2.2 菜单同步
- 同步菜单到微信公众号
- 查看当前菜单状态
2.3 回复管理
2.3.1 关键词回复
- 关键词设置
- 匹配类型(完全匹配、模糊匹配)
- 回复方式(文本、图片、图文等)
- 回复内容配置
2.3.2 默认回复
- 未匹配到关键词时的默认回复内容
2.3.3 关注回复
- 新用户关注时的回复内容
2.4 素材管理
2.4.1 图片素材
- 上传图片素材
- 管理图片素材
2.4.2 视频素材
- 上传视频素材
- 管理视频素材
2.4.3 图文同步
- 同步微信公众号图文素材
2.5 消息模板管理
2.5.1 模板列表
- 查看可用的消息模板
- 设置模板参数
2.5.2 模板配置
- 配置模板ID
- 设置模板变量
2.6 消息记录
2.6.1 消息记录列表
- 查看微信模板消息发送记录
- 按条件筛选记录
2.6.2 消息详情
- 查看消息发送状态
- 查看消息内容
3. 代码实现
3.1 路由配置
php
// 微信公众号模块路由配置
Route::group('wechat', function () {
/***************************************************** 微信配置 ****************************************************/
Route::get('config', 'wechat.Config/get');
// 设置微信配置
Route::put('config', 'wechat.Config/set');
// 微信设置的静态信息
Route::get('static', 'wechat.Config/static');
/***************************************************** 微信菜单 ****************************************************/
/**
* 微信菜单
*/
// 获取微信菜单
Route::get('menu', 'wechat.Menu/info');
// 设置微信菜单
Route::put('menu', 'wechat.Menu/edit');
/***************************************************** 关键词回复 ****************************************************/
// 关键词回复列表
Route::get('reply/keywords', 'wechat.Reply/getKeywordLists');
// 关键词回复详情
Route::get('reply/keywords/:id', 'wechat.Reply/keyword');
// 新增关键词回复
Route::post('reply/keywords', 'wechat.Reply/addKeyword');
// 更新关键词回复
Route::put('reply/keywords/:id', 'wechat.Reply/editKeyword');
// 删除关键词回复
Route::delete('reply/keywords/:id', 'wechat.Reply/delKeyword');
/***************************************************** 默认回复 ****************************************************/
// 默认回复
Route::get('reply/default', 'wechat.Reply/default');
// 更新默认默认回复
Route::put('reply/default', 'wechat.Reply/editDefault');
/***************************************************** 关注回复 ****************************************************/
// 关注回复
Route::get('reply/subscribe', 'wechat.Reply/subscribe');
// 更新关注回复
Route::put('reply/subscribe', 'wechat.Reply/editSubscribe');
/***************************************************** 图文素材回复 ****************************************************/
// 素材列表
Route::get('media', 'wechat.Media/lists');
// 上传图片素材
Route::post('media/image', 'wechat.Media/image');
// 上传视频素材
Route::post('media/video', 'wechat.Media/video');
/***************************************************** 消息模板 ****************************************************/
Route::get('template', 'wechat.Template/lists');
// 设置微信模板
Route::put('template', 'wechat.Template/set');
// 同步图文
Route::get('sync/news', 'wechat.Media/syncNews');
/***************************************************** 消息记录 ****************************************************/
// 获取微信模板消息记录列表
Route::get('log', 'wechat.WechatLog/lists');
// 获取微信模板消息记录详情
Route::get('log/:id', 'wechat.WechatLog/info');
});3.2 微信配置控制器
php
<?php
namespace app\adminapi\controller\wechat;
use app\service\admin\wechat\WechatConfigService;
use core\base\BaseAdminController;
use think\Response;
class Config extends BaseAdminController
{
/**
* 获取微信配置信息
* @description 获取微信配置信息
* @return Response
*/
public function get()
{
return success((new WechatConfigService())->getWechatConfig());
}
/**
* 设置微信配置信息
* @description 设置微信配置信息
* @return Response
*/
public function set()
{
$data = $this->request->params([
['wechat_name', ''],
['wechat_original', ''],
['app_id', ''],
['app_secret', ''],
['token', ''],
['encoding_aes_key', ''],
['qr_code', ''],
['encryption_type', ''],
['base_uri', '']
]);
$this->validate($data, 'app\validate\channel\Wechat.set');
(new WechatConfigService())->setWechatConfig($data);
return success('SET_SUCCESS');
}
/**
* 获取微信静态资源
* @description 获取微信静态资源
* @return Response
*/
public function static()
{
return success((new WechatConfigService())->getWechatStaticInfo());
}
}3.3 微信配置服务
php
<?php
namespace app\service\admin\wechat;
use app\dict\common\CommonDict;
use app\model\sys\SysConfig;
use app\service\core\wechat\CoreWechatConfigService;
use core\base\BaseAdminService;
use think\Model;
/**
* 微信配置模型
*/
class WechatConfigService extends BaseAdminService
{
/**
* 获取配置信息
* @return array|null
*/
public function getWechatConfig()
{
$config_info = (new CoreWechatConfigService())->getWechatConfig();
foreach ($config_info as $k => $v) {
if ($v !== '' && in_array($k, ['app_secret', 'encoding_aes_key'])) {
$config_info[$k] = CommonDict::ENCRYPT_STR;
}
}
return $config_info;
}
/**
* 设置配置
* @param array $data
* @return SysConfig|bool|Model
*/
public function setWechatConfig(array $data){
$config = (new CoreWechatConfigService())->getWechatConfig();
foreach ($data as $k => $v) {
if ($v == CommonDict::ENCRYPT_STR) {
$data[$k] = $config[$k];
}
}
return (new CoreWechatConfigService())->setWechatConfig($data);
}
/**
*查询微信需要的静态信息
* @return array
*/
public function getWechatStaticInfo(){
return (new CoreWechatConfigService())->getWechatStaticInfo();
}
}3.4 核心微信配置服务
php
<?php
namespace app\service\core\wechat;
use app\dict\channel\WechatDict;
use app\dict\sys\ConfigKeyDict;
use app\model\sys\SysConfig;
use app\service\core\sys\CoreConfigService;
use app\service\core\sys\CoreSysConfigService;
use core\base\BaseCoreService;
use think\Model;
/**
* 微信配置模型
*/
class CoreWechatConfigService extends BaseCoreService
{
/**
* 获取微信公众号配置
* @return array
*/
public function getWechatConfig()
{
$info = (new CoreConfigService())->getConfig(ConfigKeyDict::WECHAT)['value'] ?? [];
return [
'wechat_name' => $info['wechat_name'] ?? '',//公众号名称
'wechat_original' => $info['wechat_original'] ?? '',//原始ID
'app_id' => $info['app_id'] ?? '',//AppID
'app_secret' => $info['app_secret'] ?? '',//AppSecret
'qr_code' => $info['qr_code'] ?? '',//公众号二维码
'token' => $info['token'] ?? '',
'encoding_aes_key' => $info['encoding_aes_key'] ?? '',
'encryption_type' => $info['encryption_type'] ?? 'not_encrypt',//加解密模式 not_encrypt 明文 compatible 兼容 safe 安全
'is_authorization' => $info['is_authorization'] ?? 0,
'base_uri' => $info['base_uri'] ?? ''
];
}
/**
* 设置微信公众号配置
* @param array $data
* @return SysConfig|bool|Model
*/
public function setWechatConfig(array $data)
{
$old = $this->getWechatConfig();
$config = [
'wechat_name' => $data['wechat_name'] ?? '',//公众号名称
'wechat_original' => $data['wechat_original'] ?? '',//原始ID
'app_id' => $data['app_id'] ?? '',//AppID
'app_secret' => $data['app_secret'] ?? '',//AppSecret
'qr_code' => $data['qr_code'] ?? '',//公众号二维码
'token' => $data['token'] ?? '',
'encoding_aes_key' => $data['encoding_aes_key'] ?? '',
'encryption_type' => $data['encryption_type'] ?? '',
'is_authorization' => $data['is_authorization'] ?? $old['is_authorization']
];
return (new CoreConfigService())->setConfig(ConfigKeyDict::WECHAT, $config);
}
/**
* 查询微信需要的静态信息
* @return array
*/
public function getWechatStaticInfo()
{
$wap_domain = (new CoreSysConfigService())->getSceneDomain()['wap_domain'] ?? '';
$wap_domain = str_replace('http://', '', $wap_domain);
$wap_domain = str_replace('https://', '', $wap_domain);
return [
'serve_url' => (string)url('/api/wechat/serve', [], '', true),
'business_domain' => $wap_domain,
'js_secure_domain' => $wap_domain,
'web_auth_domain' => $wap_domain,
'encryption_type' => WechatDict::getEncryptionType()
];
}
/**
* 获取小程序授权信息
* @return mixed
*/
public function getWechatAuthorizationInfo()
{
return (new CoreConfigService())->getConfigValue(ConfigKeyDict::WECHAT_AUTHORIZATION_INFO);
}
/**
* 设置小程序授权信息
* @param array $config
* @return SysConfig|bool|Model
*/
public function setWechatAuthorizationInfo(array $config)
{
return (new CoreConfigService())->setConfig(ConfigKeyDict::WECHAT_AUTHORIZATION_INFO, $config);
}
/**
* 清除授权信息
* @return mixed
*/
public function clearWechatAuthorizationInfo()
{
return (new CoreConfigService())->clearConfig(ConfigKeyDict::WECHAT_AUTHORIZATION_INFO);
}
}3.5 微信菜单控制器
php
<?php
namespace app\adminapi\controller\wechat;
use app\service\admin\wechat\WechatMenuService;
use core\base\BaseAdminController;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;
use think\Response;
/**
* 微信公众号管理菜单
*/
class Menu extends BaseAdminController
{
/**
* 获取微信菜单
* @description 获取微信菜单
* @return Response
*/
public function info()
{
$wechat_menu_service = new WechatMenuService();
return success($wechat_menu_service->getInfo());
}
/**
* 更新微信菜单
* @description 更新微信菜单
* @return Response
* @throws InvalidConfigException
* @throws GuzzleException
*/
public function edit()
{
$wechat_menu_service = new WechatMenuService();
$data = $this->request->params([
['button', []]
]);
$wechat_menu_service->edit($data['button']);
return success('EDIT_SUCCESS');
}
}3.6 微信菜单服务
php
<?php
namespace app\service\admin\wechat;
use app\model\sys\SysConfig;
use app\service\core\sys\CoreConfigService;
use app\service\core\wechat\CoreWechatApiService;
use core\base\BaseAdminService;
use core\exception\WechatException;
use EasyWeChat\Kernel\Exceptions\InvalidConfigException;
use GuzzleHttp\Exception\GuzzleException;
use think\Model;
/**
* 微信菜单
*/
class WechatMenuService extends BaseAdminService
{
/**
* 获取微信菜单
* @return array|mixed
*/
public function getInfo(){
$core_config_service = new CoreConfigService();
return $core_config_service->getConfig('WECHAT_MENU')['value'] ?? [];
}
/**
* 更新微信菜单
* @param array $data
* @return SysConfig|bool|Model
* @throws GuzzleException
* @throws InvalidConfigException
*/
public function edit(array $data){
$core_wechat_api_service = new CoreWechatApiService();
$menu_result = $core_wechat_api_service->menuCreate($data);
if(!empty($menu_result['errcode']) && $menu_result['errcode'] != 0)
throw new WechatException($menu_result['errmsg']);
//先尝试改变微信接口菜单
$core_config_service = new CoreConfigService();
return $core_config_service->setConfig('WECHAT_MENU', $data);
}
}3.7 微信回复控制器
php
<?php
namespace app\adminapi\controller\wechat;
use app\service\admin\wechat\WechatReplyService;
use core\base\BaseAdminController;
use think\Response;
/**
* 微信公众号管理回复
*/
class Reply extends BaseAdminController
{
/**
* 关键词回复
* @description 关键词回复
* @return Response
*/
public function keyword($id)
{
$wechat_reply_service = new WechatReplyService();
return success($wechat_reply_service->getKeywordInfo($id));
}
public function getKeywordLists()
{
$data = $this->request->params([
[ 'keyword', '' ],
[ 'name', '' ]
]);
$wechat_reply_service = new WechatReplyService();
return success($wechat_reply_service->getKeywordPage($data));
}
/**
* 新增关键词回复
* @description 新增关键词回复
* @return Response
*/
public function addKeyword()
{
$wechat_reply_service = new WechatReplyService();
$data = $this->request->params([
[ 'name', '' ],
[ 'keyword', '' ],
[ 'matching_type', '', false ],
[ 'reply_method', '' ],
[ 'content', '' ],
[ 'sort', '' ],
]);
$wechat_reply_service->addKeyword($data);
return success('ADD_SUCCESS');
}
/**
* 更新关键词回复
* @description 更新关键词回复
* @return Response
*/
public function editKeyword($id)
{
$wechat_reply_service = new WechatReplyService();
$data = $this->request->params([
[ 'name', '' ],
[ 'keyword', '' ],
[ 'matching_type', '', false ],
[ 'reply_method', '' ],
[ 'content', '' ],
[ 'sort', '' ],
]);
$wechat_reply_service->editKeyword($id, $data);
return success('EDIT_SUCCESS');
}
/**
* 删除关键字回复
* @description 删除关键字回复
* @return Response
*/
public function delKeyword($id)
{
$wechat_reply_service = new WechatReplyService();
$wechat_reply_service->delKeyword($id);
return success('DELETE_FAIL');
}
/**
* 获取默认回复
* @description 获取默认回复
* @return Response
*/
public function default()
{
$wechat_reply_service = new WechatReplyService();
return success($wechat_reply_service->getDefault());
}
/**
* 更新默认回复
* @description 更新默认回复
* @return Response
*/
public function editDefault()
{
$data = $this->request->params([
[ 'content', '' ],
]);
$wechat_reply_service = new WechatReplyService();
$wechat_reply_service->editDefault($data);
return success('SET_SUCCESS');
}
/**
* 获取关注回复
* @description 获取关注回复
* @return Response
*/
public function subscribe()
{
$wechat_reply_service = new WechatReplyService();
return success($wechat_reply_service->getSubscribe());
}
/**
* 更新关注回复
* @description 更新关注回复
* @return Response
*/
public function editSubscribe()
{
$data = $this->request->params([
[ 'content', '' ],
]);
$wechat_reply_service = new WechatReplyService();
$wechat_reply_service->editSubscribe($data);
return success('SET_SUCCESS');
}
}3.8 微信回复服务
php
<?php
namespace app\service\admin\wechat;
use app\model\wechat\WechatReply;
use app\service\core\wechat\CoreWechatReplyService;
use core\base\BaseAdminService;
/**
* 微信回复
*/
class WechatReplyService extends BaseAdminService
{
protected CoreWechatReplyService $core_wechat_reply_service;
public function __construct()
{
parent::__construct();
$this->core_wechat_reply_service = new CoreWechatReplyService();
}
/**
*关键字回复列表
* @return array
*/
public function getKeywordPage(array $data = []){
return $this->core_wechat_reply_service->getKeywordPage($data);
}
/**
* 获取关键词回复信息
* @param int $id
* @return array
*/
public function getKeywordInfo(int $id){
return $this->core_wechat_reply_service->getKeywordInfo($id);
}
/**
* 新增关键词回复
* @param array $data
* @return true
*/
public function addKeyword(array $data){
return $this->core_wechat_reply_service->addKeyword($data);
}
/**
* 更新关键词回复
* @param int $id
* @param array $data
* @return WechatReply
*/
public function editKeyword(int $id, array $data){
return $this->core_wechat_reply_service->editKeyword($id, $data);
}
/**
* 删除关键词回复
* @return void|null
*/
public function delKeyword(int $id){
return $this->core_wechat_reply_service->delKeyword($id);
}
/**
* 获取默认回复
* @return void|null
*/
public function getDefault(){
return $this->core_wechat_reply_service->getDefault();
}
/**
* 更新默认回复
* @param array $data
* @return void|null
*/
public function editDefault(array $data){
return $this->core_wechat_reply_service->editDefault($data);
}
/**
* 获取关注回复
* @return array
*/
public function getSubscribe(){
return $this->core_wechat_reply_service->getSubscribe();
}
/**
* 更新关注回复
* @param array $data
* @return void|null
*/
public function editSubscribe(array $data){
return $this->core_wechat_reply_service->editSubscribe($data);
}
}4. 微信公众号配置流程
4.1 基本配置流程
- 登录微信公众平台(https://mp.weixin.qq.com/)
- 进入开发 -> 基本配置
- 获取AppID和AppSecret
- 设置服务器地址(URL):填写系统提供的服务器地址
- 设置Token:与系统中配置的Token保持一致
- 设置EncodingAESKey:与系统中配置的EncodingAESKey保持一致
- 选择加解密模式:与系统中配置的加解密模式保持一致
- 点击提交,完成配置
4.2 菜单配置流程
- 登录系统后台
- 进入微信公众号 -> 菜单管理
- 配置菜单结构(一级菜单和二级菜单)
- 设置菜单类型和内容
- 点击保存并同步到微信公众号
4.3 回复配置流程
- 登录系统后台
- 进入微信公众号 -> 回复管理
- 配置关键词回复、默认回复和关注回复
- 设置回复内容和回复方式
- 保存配置
4.4 素材管理流程
- 登录系统后台
- 进入微信公众号 -> 素材管理
- 上传图片、视频等素材
- 管理已上传的素材
- 同步微信公众号图文素材
5. 数据模型
5.1 微信回复模型
- 表名:
wechat_reply - 主要字段:
id:回复IDname:回复名称keyword:关键词matching_type:匹配类型reply_method:回复方式content:回复内容sort:排序type:回复类型(关键词、默认、关注)create_time:创建时间update_time:更新时间
5.2 微信消息记录模型
- 表名:
wechat_log - 主要字段:
id:记录IDtemplate_id:模板IDopenid:用户OpenIDdata:消息数据status:发送状态error_msg:错误信息create_time:发送时间
5.3 微信素材模型
- 表名:
wechat_media - 主要字段:
id:素材IDmedia_id:微信素材IDtype:素材类型name:素材名称url:素材URLcreate_time:创建时间
6. 开发注意事项
6.1 安全考虑
- AppSecret和EncodingAESKey等敏感信息应加密存储
- 微信公众号的Token应定期更新
- 验证微信消息的真实性,防止伪造消息
6.2 性能优化
- 微信接口调用应设置合理的缓存策略
- 消息处理应采用异步处理,避免阻塞主流程
- 定期清理微信消息记录,避免数据量过大
6.3 错误处理
- 微信接口调用失败时应进行重试机制
- 记录详细的错误信息,便于排查问题
- 对用户友好的错误提示
6.4 最佳实践
- 合理设置菜单结构,便于用户操作
- 回复内容应简洁明了,符合用户预期
- 定期更新微信公众号素材,保持内容新鲜
- 关注微信公众号平台的规则变化,及时调整策略
7. 常见问题
7.1 服务器配置失败
- 检查服务器地址是否正确
- 确认Token是否一致
- 检查网络连接是否正常
- 查看服务器日志,排查错误原因
7.2 菜单同步失败
- 检查菜单结构是否符合微信规范
- 确认AppID和AppSecret是否正确
- 检查网络连接是否正常
- 查看微信接口返回的错误信息
7.3 消息回复不生效
- 检查回复配置是否正确
- 确认关键词匹配类型是否正确
- 检查微信公众号是否已启用相应的回复功能
- 查看消息记录,排查发送状态
7.4 素材上传失败
- 检查素材格式是否符合微信要求
- 确认素材大小是否在限制范围内
- 检查网络连接是否正常
- 查看微信接口返回的错误信息
8. 总结
微信公众号模块是系统中重要的社交互动工具,通过本文档的指导,开发人员可以了解微信公众号管理的核心功能和实现逻辑,从而更好地集成和扩展微信公众号功能。系统支持微信公众号的配置管理、菜单管理、回复管理、素材管理等功能,为企业提供了与用户进行互动的有效渠道。
