Laravel微信公众号游戏查询

环境与部署

基于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.phpproviders数组里添加:

    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 会默认打开,有两种方案:

  1. 在 CSRF 中间件里排除微信相关的路由,添加例外路由,在app\Http\Middleware\VerifyCsrfToken.php

    1
    2
    3
    protected $except = [
    'wechat'
    ];
  2. 关掉 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
<?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
{
/**
* 处理微信的请求消息
*
* @return string
*/
public function serve()
{
# Log::info('响应请求.'); # Log 为 Laravel 组件,所以它记的日志去 Laravel 日志看,而不是 EasyWeChat 日志
$weChat = app('wechat');//// 从项目实例中得到服务端应用实例。
$weChat->server->setMessageHandler(function($message){//使用 setMessageHandler(callable $callback) 来设置消息处理函数
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;
}
});
# Log::info('返回请求完成');

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){//对Minecraft服务器进行查询,使用了composer第三方包xpaw/php-minecraft-query
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){//对Minecraft 正版玩家的信息查询,包括玩家用户名 ,UUID,皮肤数据
\phpQuery::newDocumentFile('https://mcuuid.net/?q='.$player);//对mcuuid这个网站进行数据采集工作
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(){//调用一言API,具体API调用方法参考一言API : http://hitokoto.cn/api
$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)
{
// $wechat 则为容器中 EasyWeChat\Foundation\Application 的实例
}
}

使用门面(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

微信消息

微信小冰

一言

功能翻译

高铁路线

去哪儿