公众号端基本配置

image.png

公众号端设置

image.png

域名要备案,文件下载上传至tp6的public目录下

image.png

composer require overtrue/wechat -vvv

微信相关路由配置

//微信

Route::group('wechat', function () use($version){

Route::get('',"{$version}.Wechat/index");//微信首页

Route::any('me',"{$version}.Wechat/me");//微信首页

Route::any('oauth_callback',"{$version}.Wechat/oauth_callback");//微信首页

Route::get('test',"{$version}.Wechat/test");//微信首页

Route::get('menu',"{$version}.Wechat/menuList");//微信菜单列表

Route::post('menu',"{$version}.Wechat/menuAdd");//微信菜单添加

Route::get('resource',"{$version}.Wechat/resource");//资源

});

config/wechat.php配置文件

return [

/**

* 账号基本信息,请从微信公众平台/开放平台获取

*/

'app_id' => env('WECHAT_OFFICIAL_ACCOUNT_APPID', ''), // AppID

'secret' => env('WECHAT_OFFICIAL_ACCOUNT_SECRET', ''), // AppSecret

'token' => env('WECHAT_OFFICIAL_ACCOUNT_TOKEN', ''), // Token

'aes_key' => env('WECHAT_OFFICIAL_ACCOUNT_AES_KEY', '

'), // EncodingAESKey

/**

* 指定 API 调用返回结果的类型:array(default)/collection/object/raw/自定义类名

* 使用自定义类名时,构造函数将会接收一个 `EasyWeChat\Kernel\Http\Response` 实例

*/

'response_type' => 'array',

/**

* 日志配置

*

* level: 日志级别, 可选为:

* debug/info/notice/warning/error/critical/alert/emergency

* path:日志文件位置(绝对路径!!!),要求可写权限

*/

'log' => [

'default' => 'dev', // 默认使用的 channel,生产环境可以改为下面的 prod

'channels' => [

// 测试环境

'dev' => [

'driver' => 'single',

'path' => ROOT_PATH.'logs/'.date('Y-m-d').'/easywechat.log',

'level' => 'debug',

],

// 生产环境

'prod' => [

'driver' => 'daily',

'path' => ROOT_PATH.'logs/'.date('Y-m-d').'/easywechat.log',

'level' => 'info',

],

],

],

/**

* 接口请求相关配置,超时时间等,具体可用参数请参考:

* http://docs.guzzlephp.org/en/stable/request-config.html

*

* - retries: 重试次数,默认 1,指定当 http 请求失败时重试的次数。

* - retry_delay: 重试延迟间隔(单位:ms),默认 500

* - log_template: 指定 HTTP 日志模板,请参考:https://github.com/guzzle/guzzle/blob/master/src/MessageFormatter.php

*/

'http' => [

'max_retries' => 1,

'retry_delay' => 500,

'timeout' => 5.0,

// 'base_uri' => 'https://api.weixin.qq.com/', // 如果你在国外想要覆盖默认的 url 的时候才使用,根据不同的模块配置不同的 uri

],

/**

* OAuth 配置

*

* scopes:公众平台(snsapi_userinfo / snsapi_base),开放平台:snsapi_login

* callback:OAuth授权完成后的回调页地址

*/

'oauth' => [

'scopes' => ['snsapi_userinfo'],

'callback' => '/api/wechat/oauth_callback',

],

];

// +----------------------------------------------------------------------

// | 微信逻辑【业务层】

// +----------------------------------------------------------------------

// | Author: DragonersLi<865196792@qq.com>

// +----------------------------------------------------------------------

// | Date: 2020/07/23

// +----------------------------------------------------------------------

namespace app\common\logic;

use EasyWeChat\OpenPlatform\Server\Guard;

use EasyWeChat\Factory;

use EasyWeChat\Kernel\Messages\Text;

use EasyWeChat\Kernel\Messages\Image;

use EasyWeChat\Kernel\Messages\Video;

use EasyWeChat\Kernel\Messages\Voice;

use EasyWeChat\Kernel\Messages\News;

use EasyWeChat\Kernel\Messages\NewsItem;

use EasyWeChat\Kernel\Messages\Article;

use app\common\service\RedisService;

use app\common\model\UserWeixin;

use app\common\model\Keyword;

use app\common\model\Notice;

use think\facade\Log;

class WechatLogic extends BaseLogic

{

public function initialize()

{

parent::initialize();

}

public function __construct()

{

$this->app = Factory::officialAccount(config('wechat'));

}

/**

* 微信首页

* @return array

* @throws \think\db\exception\DataNotFoundException

* @throws \think\db\exception\DbException

* @throws \think\db\exception\ModelNotFoundException

*/

public function index(){

try{

$this->app->server->push(function ($message){

$user_openid = $message['FromUserName'];

switch ($message['MsgType']) {

case 'event':

$message['user'] = $this->app->user->get($user_openid);

return $result = $this->event($message);//处理点击事件

break;

case 'text':

return $this->text($message['Content']);//处理被动回复文本

break;

case 'image':

return $image = new Image($mediaId = '0b69zmxmX9VQ1WOyimslclMr3f2YbnNgrMkjS2KxWZM');

break;

case 'voice':

return $voice = new Voice($mediaId = 'Rwqz1xLYDNwFvTJ254fBstYU1rY3aKiN-z7aqEpiWic');

break;

case 'video':

return $video = new Video($mediaId = 'Rwqz1xLYDNwFvTJ254fBsmzRm-HXa-ilLRc028v-Ar0', [

'title' => $title = '标题',

'description' => '简介...',

]);

break;

case 'location'://收到坐标消息,微信目前不支持回复坐标消息

return $text = new Text("您好!openid:{$message['FromUserName']},{$message['MsgType']},收到坐标消息,微信目前不支持回复坐标消息");

break;

case 'link'://收到链接消息,微信目前不支持回复链接消息

return $text = new Text("您好!openid:{$message['FromUserName']},{$message['MsgType']},收到链接消息,微信目前不支持回复链接消息");

break;

case 'file':

return $text = new Text("您好!openid:{$message['FromUserName']},{$message['MsgType']},收到文件消息");

// ... 其它消息

default:

return '收到其它消息';

break;

}

});

}catch(\Exception $e){

dlog('wechat',$e->getMessage());

}

$response = $this->app->server->serve()->send();

}

/*

* 菜单列表

*/

public function menuList()

{

$list = $this->app->menu->list();//读取(查询)已设置菜单

$current = $this->app->menu->current();//获取当前菜单

return [

'list'=>$list,

'current'=>$current

];

}

/*

* 菜单创建

*/

public function menuAdd(){

$buttons = [

[

"type" => "view",

"name" => "下载APP",

"url" => config('system.api.url')."/download.html"

],

[

"type" => "view",

"name" => "个人中心",

"url" => config('system.api.url')."/h5"

]

];

return $this->app->menu->create($buttons);

}

/*

* $type 素材的类型,图片(image)、视频(video)、语音 (voice)、图文(news)

* $offset 从全部素材的该偏移位置开始返回,可选,默认 0,0 表示从第一个素材 返回

* $count 返回素材的数量,可选,默认 20, 取值在 1 到 20 之间

*/

public function resource($type = 'image'){

$user = $this->app->user->list($nextOpenId = null); // $nextOpenId 可选

$stats = $this->app->material->stats();//获取各类素材总数

//$item = $this->app->material->get($mediaId='');//获取单个素材

$resource = $this->app->material->list($type, $offset= 0, $count= 20);

// $this->app->material->delete($mediaId='');//删除素材

return [

'count'=>$stats,

'list'=>$resource,

'user'=>$user

];

}

/**

* 授权页面

* @return mixed

*/

public function me(){

if (!cookie('wechat_user')) {// 未登录

cookie('target_url',config('system.api.url').'/api/wechat/me');

return $this->app->oauth->redirect()->send();

}

$url = config('system.api.url').'/h5';

header('location:'. $url);

}

/**

* 回调页面

*/

public function oauth_callback(){

$user = $this->app->oauth->user(); // 获取 OAuth 授权结果用户信息

cookie('wechat_user',json_encode($user));

dlog('wechat_user',$user);

RedisService::redis()->set('weixin_user:'.$user->id,json_encode([

'openid'=>$user->id,

'nickname'=>$user->nickname,

'avatar'=>$user->avatar

]));

$url = cookie('target_url') ? cookie('target_url') : config('system.api.url').'/h5';

header('location:'. $url);

}

/**

* 回复事件

* @param array $message

* @return Image|string

*/

private function event($message = []){

$user_openid = $message['user']['openid'];

switch ($message['Event']) {

case "subscribe"://关注微信用户表新增记录

return '欢迎关注派金花公众号,有疑问请联系在线客服!' ;

break;

case "unsubscribe"://取消关注时执行的操作,要把记录该用户从记录微信用户信息的表中删掉

$msg = "{$user_openid}:取消关注!清除微信信息:";

$msg.= UserWeixin::destroy(function($query) use($user_openid){

$query->where(['wxOpenid'=>$user_openid]);

}) ? 'success' : 'failed';

dlog('wechat',$msg);//取消关注时执行的操作,要把记录该用户从记录微信用户信息的表中删掉

break;

case "CLICK":

switch ($message['EventKey']) {

case "V1000":

break;

case "V1001":

default:

return $image = new Image($mediaId = 'Rwqz1xLYDNwFvTJ254fBspGO-4KAaoUILJIKRzwUBrE');

break;

}

break;

case "SCAN":

case "LOCATION":

case "VIEW":

default:

break;

}

}

/**

* 回复文本

* @param string $content

* @return Image|News|Text|Video|Voice

*/

private function text($content = ''){

$result = config('wechatreply.keywords');

if(empty($result[$content])){ //关键词匹配失败

$other = config('wechatreply.other');

if(empty($other[$content])){//其它关键词也匹配失败,则返回关键词列表

$content = "输入序号快捷获取回复!\n";

foreach($result as $k=>$v){

$content .= "【{$k}】{$v['title']}\n";

}

return $text = new Text($content);

}else{ //匹配其它关键词

$result = $other;

}

}

switch ($result[$content]['type']){

case 'image'://图片

return $image = new Image($result[$content]['content']);

break;

case 'video'://视频

return $video = new Video($mediaId = $result[$content]['content'], [

'title' => $result[$content]['title'],

'description' => '视频描述...',

// 'thumb_media_id'=>'Rwqz1xLYDNwFvTJ254fBsiuqJw5ZV9dZF2jNu34_bPU' // 封面资源 ID

]);

break;

case 'voice'://声音

return $voice = new Voice($mediaId = $result[$content]['content']);

break;

case 'news'://资讯

$data = Notice::where(['id'=>$result[$content]['content']])->field('id,title,content')->find();

return $news = new News([

new NewsItem([

'title' => $result[$content]['title'],

'description' =>$result[$content]['content'],

'url' =>$result[$content]['id'],

//'image' => 'https://www.easywechat.com/img/logo-black.svg',

// ...

]),

]);

break;

case 'text'://文本

default:

$result[$content]['content'] = htmlspecialchars_decode($result[$content]['content']);

$result[$content]['content'] = str_replace('

','',$result[$content]['content']);

$result[$content]['content'] = str_replace('

',"\r",$result[$content]['content']);

$result[$content]['content'] = str_replace('
',"\r",$result[$content]['content']);

return $text = new Text($result[$content]['content']);

break;

}

}

/**

* 发送模板消息[静态方法方便调用]

* @param array $data

* @return mixed

*/

public static function tpl($data = []){

// $data['openid'] = 'o9soys5-em4VBQD78uy4_dyZx_Pg';

// $data['type'] = 'test';

// $data['url'] = config('system.api.url').'/h5';

// $data['data'] =[

// 'first'=>'hello,world',

// 'keyword1' => '220.30元',

// 'keyword2' => '荣事达旗舰店',

// 'keyword3' => '2014年7月21日 18:36',

// ];

// $this->tpl($data);

$result = Factory::officialAccount(config('wechat'))->template_message->send([

'touser'=>$data['openid'],

'template_id'=>config("system.wechat_tpl.{$data['type']}"),

'url' => $data['url'],

'data' => $data['data'],

]);

if(!$result['errcode']){//发送成功

return ['code'=>1,'msg'=>$result['errmsg'],'data'=>['msgid'=>$result['msgid']]];

}else{//发送失败记录日志

dlog('wechat_tpl',['data'=>$data,'result'=>$result]);

return ['code'=>0,'msg'=>$result['errmsg'],'data'=>['result'=>$result]];

}

}

}

开通模版消息,配置模版ID

//微信模板ID

'wechat_tpl'=>[

'test'=>'tGy9UXpXz97cv7SygOnVR6S-kqOZtnEDblTnN5QwkJs',//测试

'register'=>'pxIIRpFWFZu-02103RmVIxCmqS-LdyDJIpPcNbwVupo',//注册模板ID

],

完全按官网demo接入,菜单资源等接口都能正常运作,自动回复却提示:该公众号暂时无法提供服务,请稍后再试

tail -f tp6.xxx.com.log查看日志,看到是post请求,返回错误404 Not Found!

排查结果:路由请求方式由get改成any解决!

223.166.222.120 - - [22/Aug/2020:14:12:37 +0800] "POST /api/wechat?signature=acd16cbad48ae6bad1df96b27e302d979eb454cd&timestamp=1598076757&nonce=1560311832&openid=o9soys5-em4VBQD78uy4_dyZx_Pg&encrypt_type=aes&msg_signature=26a0a9c431a2a56fca7e5e0db794e4a98e7b4617 HTTP/1.1" 404 21487 "-" "Mozilla/4.0"

laraval下请求方式错误返回405 Method Not Allowed

"The POST method is not supported for this route. Supported methods: GET, HEAD."

easywechat php例子,thinkphp6使用easywechat笔记!相关推荐

  1. ThinkPHP6+swoole+easywechat使用教程

    前言 在结合think-swoole+easywechat扩展使用的时候,需要考虑curl兼容swoole携程问题,request兼容swoole框架,因为easywechat底层还是通过$_POST ...

  2. easywechat (在thinkphp5中使用easywechat完成微信网页认证)

    由于在easywechat中没有提及在thinkphp中的使用,后来我在http://www.thinkphp.cn/topic/45416.html中找到了有人已经封装了一下,我把自己使用的过程写下 ...

  3. java jms例子_JMS 教程 学习笔记 (九)JMS 样例代码

    本章给出了一些展示JMS 客户端如何使用JMS API 的代码样例.也解释了如何使用几个消息类型.这些例子使用了支持统一消息模型的方法:这些例子使用点对点或发布/订阅进行工作.用JMS API 进行工 ...

  4. thinkPHP6.0入门笔记(四)——删除和修改用户信息

    thinkPHP6.0实现删除和修改用户信息 1.删除用户信息 2.优化bootstrap资源引入方式 3.浏览器的cookie与session机制 4.token令牌原理 5.利用token防止表单 ...

  5. uml边界类例子_面向对象UML笔记

    配套课程:中国大学MOOC 华东师范大学 面向对象设计与分析 UML概念模型 最重要的五种图:用例图,类图,顺序图,活动图,状态图 四种关系:关联关系,实现关系,依赖关系,继承关系 常见图例 用例图 ...

  6. thinkPHP6.0入门笔记(七)——关联模型

    thinPHP6.0的关联模型及关联方法 1.一对一关联 1.1一对一关联查询 1.2一对一关联新增 1.3一对一关联删除 1.4一对一关联修改 2.一对多关联 2.1一对多关联模型常用方法 3.多对 ...

  7. java里氏替换原则例子_java设计模式学习笔记——里氏替换原则

    oo中的继承性的思考和说明 1.继承包含这样一层含义:父类中凡是已经实现好的方法,实际上是在设定规范和契约,虽然它不强制要求所有的子类必须遵循这些七月,但是如果子类对这些已经实现的方法任意修改,就会对 ...

  8. easywechat Api大全

    一.入门 文档 1.1 安装 环境要求: PHP >= 7.0 PHP cURL 扩展 PHP OpenSSL 扩展 PHP SimpleXML 扩展 PHP fileinfo 拓展 使用 co ...

  9. DirectX9 ShadowMap例子学习笔记

    本文版权归博客园  mavaL所有,如有转载请按如下方式详细标明原创作者及出处,以示尊重!! 原创作者:mavaL 原文链接:DirectX9 ShadowMap例子学习笔记 学习SDK例子真是快速加 ...

最新文章

  1. 自定义堆栈(回文检测)
  2. 2020年班级管理html,2020年七年级班主任工作计划
  3. linq 实现查询字符串拼接 : And 和 OR 两种方式
  4. 纯正价格正则表达式,请指正
  5. 05-session-会话跟踪技术
  6. 综合学生信息管理系统(JSP+JDBC)
  7. 2010年亚运会前广州将大力推广清洁能源公交
  8. linux addr2line
  9. 查看daemon使用技巧
  10. 程序员有多少读过《人性的弱点》?项目经理呢?
  11. 怎样在电脑上面简单的记账,了解账户收支
  12. 驱动程序安装全攻略1
  13. 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest A Toda2 贪心
  14. 模拟T1数字number
  15. [NXP.iMX6UL] 驱动开发
  16. SAR 三点回波模拟 正侧视RD算法(经典好用)
  17. TSGCTF 2021 Welcome to TSG CTF! WP
  18. 国仁网络资讯:视频号怎么剪辑制作视频;都有哪些剪辑软件好用。
  19. linux中的链路聚合之team方式
  20. 波斯文组合规则,波斯语变形规则,波斯语组合规范,波斯文变形规则

热门文章

  1. 网站管理助手 mysql_网站管理助手 mysql
  2. vimium常用指令
  3. .chm手册怎么打开以及打开显示空白修复
  4. Android 实现图片点击切换
  5. 光谱分辨率单位_A1、光谱及基本单位
  6. uni-app学习(八)mapMutations和Mutations
  7. H5新特性之sessionStorage
  8. Kotlin 学习 高阶函数
  9. 眼睛卫士Linux版
  10. 【通俗易懂的解释】HttpSession session = request.getSession(false);中的false是什么意思