环境与部署
基于Laravel5.4 和 easywechat 框架制作,以下说明了部署过程,框架使用,核心代码,一些问题解决方案。
环境需求
- PHP >= 5.5.9 (PHP 7 的时代了,我在开发中一直用的PHP7)
- PHP cURL 扩展
- PHP OpenSSL 扩展
- PHP fileinfo 拓展 素材管理模块需要用到(微信公众号权限不够暂时用不到)
开始部署
安装Laravel框架
1
| composer create-project laravel/laravel wechat --prefer-dist
|
安装laravel-wechat框架
1
| composer require "overtrue/wechat:~3.3" -vvv
|
配置
注册服务提供者
在目录 config/app.php下providers数组里添加:
1
| Overtrue\LaravelWechat\ServiceProvider::class,
|
创建配置文件:
1
| php artisan vendor:publish --provider="Overtrue\LaravelWechat\ServiceProvider"
|
修改应用根目录下的 config/wechat.php 中对应的项即可;
添加外观到 config/app.php 中的 aliases 部分:
1
| 'EasyWeChat' => Overtrue\LaravelWechat\Facade::class,
|
使用
Laravel 5.2 以后的版本默认启用了 web 中间件,意味着 CSRF 会默认打开,有两种方案:
- 在 CSRF 中间件里排除微信相关的路由,添加例外路由,在
app\Http\Middleware\VerifyCsrfToken.php1 2 3
| protected $except = [ 'wechat' ];
|
- 关掉 CSRF 中间件(极不推荐)
路由:
1
| Route::any('/wechat', 'WechatController@serve');
|
“开发者中心” 修改 “URL(服务器配置)” 为: http://codinger.cn/wechat
注意:一定是 Route::any, 因为微信服务端认证的时候是 GET, 接收用户消息时是 POST !
然后创建控制器 WechatController
1
| php artisan make:controller WechatController
|
载入第三方类库:
在控制器目录下创建一个Tools文件夹,放入第三方类库文件夹。这里我使用的是
PHPQuery一个爬网站的工具,写到WechatController里。
1
| require 'Tools\phpQuery\phpQuery.php';
|
实用composer自动加载,这样我们就可以直接在控制器里使用它了use phpQuery;
因为我要对Minecraft服务端进行获取服务器信息和在线人数,使用一个别人写好的库
1
| composer require xpaw/php-minecraft-query
|
现在开始写WechatController控制器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
| <?php
namespace App\Http\Controllers; use EasyWeChat\Message\Text; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; use xPaw\MinecraftPing; use xPaw\MinecraftPingException; require 'Tools\phpQuery\phpQuery.php'; class WechatController extends Controller {
public function serve() { $weChat = app('wechat'); $weChat->server->setMessageHandler(function($message){ switch ($message->MsgType){ case 'event': if ($message->Event == 'subscribe'){ $text = new Text([ 'content'=>"感谢您关注一言查询机器人\n例:正版玩家Player 查询Minecraft正版玩家\n例:服务器mc.Decraft.cc(默认端口25565) 查询游戏服务器\n还可以用语音来调教我XD\n文字召唤机器人需要在前面加上'小冰'即可" ]); return $text; } break; case 'text': return $this->pqText($message->Content); break; case 'image': return 'emmm,我没有对图片写相关功能,可以使用机器人查询你想要的图片 '; break; case 'voice': return $this->pqVoice($message->Recognition); break; case 'video': return '因为管理员很懒没有写对视频的功能,如果让我添加也可以哦!'; break; case 'location': return '因为管理员很懒没有写对坐标的功能,如果让我添加也可以哦!'; break; case 'link': return '因为管理员很懒没有写对链接的功能,如果让我添加也可以哦!'; break; default: return '暂时不支持其它消息'; break; } });
return $weChat->server->serve(); } public function pqText($content){ if (mb_substr($content,0,4)=='正版玩家'){ $playername = ltrim($content,'正版玩家'); $playername = str_replace(' ','',$playername); return $this->playerSearch($playername);
}else if (mb_substr($content,0,3)=='服务器'){ $address = ltrim($content,'服务器'); $address = str_replace(' ','',$address); return $this->serverQuery($address); }else if(mb_substr($content,0,2)=='小冰'){ $ice = ltrim($content,'小冰'); $ice = str_replace(' ','',$ice); return $this->bot($ice); }else if($content=='一言'){ $hitokoto= $this->hitokoto(); return $hitokoto['hitokoto']."\n ——".$hitokoto['from']; } else{ $another = "游戏查询功能例如下: \n"; $another.= "正版玩家Colorful_Ghost\n"; $another.= "服务器 mc.Decraft.cc\n"; $another.= "一言\n"; $another.= "额外功能:召唤小冰\n"; $another.= "小冰蚌埠天气怎样\n"; $another.= "小冰水瓶座今日运势\n"; $another.= "小冰蚌埠天气怎样\n"; $another.= "小冰讲个笑话\n"; $another.= "小冰讲个故事\n"; $another.= "小冰成语接龙一诺千金\n"; $another.= "小冰周杰伦这个名字好不好\n"; $another.= "小冰图灵的简介\n"; $another.= "小冰图灵的图片\n"; $another.= "小冰查询快递123456789\n"; $another.= "小冰说个绕口令~\n"; $another.= "现在小冰支持语音功能啦!直接对提问翻译都可以哦!\n"; $another.= "更多功能陆续添加等你测试~\n"; return $another; } }
public function pqVoice($content){ return $this->bot($content); } public function serverQuery($host,$port = 25565){ try{ $query = new MinecraftPing($host,$port); if (!$query->Connect()) { $status = $query->Query(); $result = "在线人数:" . $status['players']['online'] . '/' . $status['players']['max'] . "\n服务器版本:" . $status['version']['name'] . "\n服务器简介:" . $status['description']['text']; return $result; }else{ return '服务器不存在,或者IP地址错误!'; }
}catch (MinecraftPingException $e){ Log::info($e->getMessage()); }finally{ $query->Close(); } } public function playerSearch($player){ \phpQuery::newDocumentFile('https://mcuuid.net/?q='.$player); if(pq('h3:first')->html()=='Useful Minecraft Resources'){ return '用户不存在,或者请求过多稍后再试'; }else{ $playerdata['username'] = pq('h3:first')->html(); $playerdata['uuid'] = pq('input.form-control:last')->attr('value'); $playerdata['skin'] = pq('img:last')->attr('src');
$result = "玩家用户名:".$playerdata['username']."\n玩家UUID:".$playerdata['uuid']."\n玩家皮肤:".$playerdata['skin']; return $result; } }
public function hitokoto(){ $url = 'http://api.hitokoto.cn/?encode=json'; $json = file_get_contents($url); $objArr = json_decode($json); $hitokoto['hitokoto'] = $objArr->hitokoto; $hitokoto['from'] = $objArr->from; if ($objArr->hitokoto){ return $hitokoto; }else{ return '一言数据获取失败'; } }
public function bot($content){ $url = 'http://www.tuling123.com/openapi/api?key=d8f68602b1e32dc211a4d85a87e12c90&info='.$content; $json = file_get_contents($url); $objArr = json_decode($json);
switch ($objArr->code){ case 100000: $text = new Text(['content'=>$objArr->text]); return $text; break; case 200000: $text = new Text(['content'=>$objArr->text."\n".$objArr->url]); return $text; break; case 40001: $text = new Text(['content'=>'小冰KEY错误,请联系管理员']); return $text; break; case 40002: $text = new Text(['content'=>'小冰没听清你说的是什么?请说明白一些~']); return $text; break; case 40004: $text = new Text(['content'=>'小冰今天累了~明天再来和我玩吧']); return $text; break; case 40007: $text = new Text(['content'=>'小冰出现了一些异常,请认真对待我!']); return $text; break; default: $text = new Text(['content'=>"小冰并不想和你说话,并向你扔了一只猫!"]); return $text; break; } } }
|
其他调用SDK方法
可以通过容器自动注入
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php
namespace App\Http\Controllers;
use EasyWeChat\Foundation\Application;
class WechatController extends Controller {
public function demo(Application $wechat) { } }
|
使用门面(facades)
1 2
| $wechatServer = EasyWeChat::server(); $wechatUser = EasyWeChat::user();
|
问题解决
在实际上线的项目 ,有可能会遇到各种问题,所以要开启Log日志debug,我就遇见了SSL证书问题,这里请参考:easyWechat的官方疑难解答,来解决这个问题。
相关API
Minecraft Mojang 官方API:https://sessionserver.mojang.com/session/minecraft/profile/
第三方Minecraft皮肤查询接口:https://crafatar.com/
图灵机器人API: http://www.tuling123.com/
一言API : http://hitokoto.cn/api
演示
公众号:Game5Hei





