看不懂建议接上一个看
实现框架操作
上传框架到宝塔 利用FTP 快速开发
框架上传宝塔
新建文件位置
新建域名绑定到指定位置
以上不会 别学PHP了 学不会
前期工作
1 微信开发账号密码必得
config 新建setting 用来封装 token app_id 等等
2.对象转数组 封装
在公共方法里面 封装
route 小改一下
3 代码实现
多了点 功能互相调用 简单明了
<?php
//declare (strict_types = 1);
namespace app\wetach\controller;
use app\BaseController;
use think\facade\Cache;
use think\Request;
class Index extends BaseController
{
/**
* 获取微信AccessToken
*/
public function getAccessToken()
{
$accessTokenKeyword = 'wxdev_home_wechat_get_access_token';
$accessToken = Cache::get($accessTokenKeyword);
if(!$accessToken) {
$url = config('setting.wechat.access_token_url');
$spUrl = sprintf($url, config('setting.wechat.app_id'), config('setting.wechat.app_secret'));
$accessJsonStr = file_get_contents($spUrl);
$accessJsonArr = json_decode($accessJsonStr, true);
if(isset($accessJsonArr['errcode'])) {
echo $accessJsonArr['errcode'], $accessJsonArr['errmsg'];
exit();
} else {
$accessToken = $accessJsonArr['access_token'];
Cache::set($accessTokenKeyword, $accessToken, config('setting.wechat.access_token_expire'));
}
}
return $accessToken;
}
public function valid()
{
if($this->request->has('echostr')) {
if($this->checkSignature()) {
echo $this->request->get('echostr');
exit;
}
} else {
return $this->responseMsg();
}
}
public function responseMsg()
{
//get post data, May be due to the different environments
$postStr = file_get_contents('php://input');
//extract post data
if (!empty($postStr)) {
file_put_contents('wx7.log', $postStr, FILE_APPEND);
/* libxml_disable_entity_loader is to prevent XML eXternal Entity Injection,
the best way is to check the validity of xml by yourself */
libxml_disable_entity_loader(true);
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$postObj = object_array($postObj);
$fromUsername = $postObj['FromUserName'];
$toUsername = $postObj['ToUserName'];
$keyword = isset($postObj['Content']) ? trim($postObj['Content']) : '';
$MsgId = isset($postObj['MsgId']) ? $postObj['MsgId'] : '';
$MsgType = $postObj['MsgType'];
$time = time();
switch ($MsgType) {
case 'text':
return $this->receiveText($postObj);
// return $this->tuling($postObj);
/*$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
if (!empty($keyword)) {
$msgType = "text";
$contentStr = "Welcome to wechat world!";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr, $MsgId);
return $resultStr;
} else {
return "Input something...";
}*/
break;
//图片
case "image":
return $this->receiveImage($postObj);
break;
//语音
case "voice":
return $this->receiveVoice($postObj);
break;
//位置
case "location":
//return $this->receiveLocation($postObj);
return $this->getLocation($postObj);
break;
case 'event':
return $this->receiveEvent($postObj);
break;
}
} else {
return "";
}
}
private function receiveEvent($object)
{
$content = "";
switch ($object['Event']) {
case "subscribe":
$content = "欢迎关注奥利给工作室 ";
$content .= (!empty($object['EventKey'])) ? ("\n来自二维码场景 " . str_replace("qrscene_", "", $object['EventKey'])) : "";
break;
case "unsubscribe":
$content = "取消关注";
break;
case "CLICK":
switch ($object['EventKey']) {
case "COMPANY":
$content = array();
$content[] = array("Title" => "方倍工作室", "Description" => "", "PicUrl" => "http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" => "http://m.cnblogs.com/?u=txw1958");
break;
default:
$content = "点击菜单:" . $object['EventKey'];
break;
}
break;
case "VIEW":
$content = "跳转链接 " . $object->EventKey;
break;
case "SCAN":
$content = "扫描场景 " . $object->EventKey;
break;
case "LOCATION":
$content = "上传位置:纬度 " . $object->Latitude . ";经度 " . $object->Longitude;
break;
case "scancode_waitmsg":
if ($object->ScanCodeInfo->ScanType == "qrcode") {
$content = "扫码带提示:类型 二维码 结果:" . $object->ScanCodeInfo->ScanResult;
} else if ($object->ScanCodeInfo->ScanType == "barcode") {
$codeinfo = explode(",", strval($object->ScanCodeInfo->ScanResult));
$codeValue = $codeinfo[1];
$content = "扫码带提示:类型 条形码 结果:" . $codeValue;
} else {
$content = "扫码带提示:类型 " . $object->ScanCodeInfo->ScanType . " 结果:" . $object->ScanCodeInfo->ScanResult;
}
break;
case "scancode_push":
$content = "扫码推事件";
break;
case "pic_sysphoto":
$content = "系统拍照";
break;
case "pic_weixin":
$content = "相册发图:数量 " . $object->SendPicsInfo->Count;
break;
case "pic_photo_or_album":
$content = "拍照或者相册:数量 " . $object->SendPicsInfo->Count;
break;
case "location_select":
$content = "发送位置:标签 " . $object->SendLocationInfo->Label;
break;
default:
$content = "receive a new event: " . $object->Event;
break;
}
if (is_array($content)) {
/*if (isset($content[0]['PicUrl'])) {
$result = $this->transmitNews($object, $content);
} else if (isset($content['MusicUrl'])) {
$result = $this->transmitMusic($object, $content);
}*/
} else {
$result = $this->transmitText($object, $content);
}
return $result;
}
//接收位置消息
private function receiveLocation($object)
{
$content = "你发送的是位置,经度为:".$object['Location_Y'].";纬度为:".$object['Location_X'].";缩放级别为:".$object['Scale'].";位置为:".$object['Label'];
$result = $this->transmitText($object, $content);
return $result;
}
//接收文本消息
private function receiveText($object)
{
$keyword = trim($object['Content']);
//多客服人工回复模式
if (strstr($keyword, "请问在吗") || strstr($keyword, "在线客服")) {
$result = $this->transmitService($object);
return $result;
}
//自动回复模式
if (strstr($keyword, "文本")) {
$content = "这是个文本消息";
} else if (strstr($keyword, "表情")) {
$content = "中国:" . $this->bytes_to_emoji(0x1F1E8) . $this->bytes_to_emoji(0x1F1F3) . "\n仙人掌:" . $this->bytes_to_emoji(0x1F335);
} else if (strstr($keyword, "单图文")) {
$content = array();
$content[] = array("Title" => "单图文标题", "Description" => "单图文内容", "PicUrl" => "https://dss2.baidu.com/6ONYsjip0QIZ8tyhnq/it/u=785279848,2909064810&fm=55&app=54&fmt=auto?w=1140&h=640", "Url" => "http://m.cnblogs.com/?u=txw1958");
} else if (strstr($keyword, "图文") || strstr($keyword, "多图文")) {
$content = array();
$content[] = array("Title" => "多图文1标题", "Description" => "", "PicUrl" => "http://discuz.comli.com/weixin/weather/icon/cartoon.jpg", "Url" => "http://m.cnblogs.com/?u=txw1958");
$content[] = array("Title" => "多图文2标题", "Description" => "", "PicUrl" => "http://d.hiphotos.bdimg.com/wisegame/pic/item/f3529822720e0cf3ac9f1ada0846f21fbe09aaa3.jpg", "Url" => "http://m.cnblogs.com/?u=txw1958");
$content[] = array("Title" => "多图文3标题", "Description" => "", "PicUrl" => "http://g.hiphotos.bdimg.com/wisegame/pic/item/18cb0a46f21fbe090d338acc6a600c338644adfd.jpg", "Url" => "http://m.cnblogs.com/?u=txw1958");
} else if (strstr($keyword, "音乐")) {
$content = array();
$content = array("Title" => "最炫民族风", "Description" => "歌手:凤凰传奇", "MusicUrl" => "https://music.taihe.com/song/T10047702312", "HQMusicUrl" => "https://music.taihe.com/song/T10047702312");
} else {
$content = date("Y-m-d H:i:s", time()) . "\nOpenID:" . $object['FromUserName'] . "\n技术支持 1812A全体同学";
}
if (is_array($content)) {
if (isset($content[0])) {
$result = $this->transmitNews($object, $content);
} else if (isset($content['MusicUrl'])) {
$result = $this->transmitMusic($object, $content);
}
} else {
$result = $this->transmitText($object, $content);
}
return $result;
}
//回复音乐消息
private function transmitMusic($object, $musicArray)
{
if (!is_array($musicArray)) {
return "";
}
$itemTpl = "<Music>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<MusicUrl><![CDATA[%s]]></MusicUrl>
<HQMusicUrl><![CDATA[%s]]></HQMusicUrl>
</Music>";
$item_str = sprintf($itemTpl, $musicArray['Title'], $musicArray['Description'], $musicArray['MusicUrl'], $musicArray['HQMusicUrl']);
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[music]]></MsgType>
$item_str
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time());
return $result;
}
//回复图文消息
private function transmitNews($object, $newsArray)
{
if (!is_array($newsArray)) {
return "";
}
$itemTpl = "<item>
<Title><![CDATA[%s]]></Title>
<Description><![CDATA[%s]]></Description>
<PicUrl><![CDATA[%s]]></PicUrl>
<Url><![CDATA[%s]]></Url>
</item>";
$item_str = "";
foreach ($newsArray as $item) {
$item_str .= sprintf($itemTpl, $item['Title'], $item['Description'], $item['PicUrl'], $item['Url']);
}
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>%s</ArticleCount>
<Articles>
$item_str
</Articles>
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(), count($newsArray));
return $result;
}
//字节转Emoji表情
function bytes_to_emoji($cp)
{
if ($cp > 0x10000) { # 4 bytes
return chr(0xF0 | (($cp & 0x1C0000) >> 18)) . chr(0x80 | (($cp & 0x3F000) >> 12)) . chr(0x80 | (($cp & 0xFC0) >> 6)) . chr(0x80 | ($cp & 0x3F));
} else if ($cp > 0x800) { # 3 bytes
return chr(0xE0 | (($cp & 0xF000) >> 12)) . chr(0x80 | (($cp & 0xFC0) >> 6)) . chr(0x80 | ($cp & 0x3F));
} else if ($cp > 0x80) { # 2 bytes
return chr(0xC0 | (($cp & 0x7C0) >> 6)) . chr(0x80 | ($cp & 0x3F));
} else { # 1 byte
return chr($cp);
}
}
//回复多客服消息
private function transmitService($object)
{
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[transfer_customer_service]]></MsgType>
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time());
return $result;
}
//回复文本消息
private function transmitText($object, $content)
{
if (!isset($content) || empty($content)) {
return "";
}
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time(), $content);
return $result;
}
//接收图片消息
private function receiveImage($object)
{
$content = ["MediaId"=>$object['MediaId']];
$result = $this->transmitImage($object, $content);
return $result;
}
/**
* 回复图片消息
* <xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
<Image>
<MediaId><![CDATA[media_id]]></MediaId>
</Image>
</xml>
*/
private function transmitImage($object, $imageArray)
{
$itemTpl = "<Image>
<MediaId><![CDATA[%s]]></MediaId>
</Image>";
$item_str = sprintf($itemTpl, $imageArray['MediaId']);
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[image]]></MsgType>
$item_str
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time());
return $result;
}
//接收语音消息
private function receiveVoice($object)
{
if (isset($object['Recognition']) && !empty($object['Recognition'])) {
$content = "你刚才说的是:" . $object['Recognition'];
$result = $this->transmitText($object, $content);
} else {
$content = array("MediaId" => $object['MediaId']);
$result = $this->transmitVoice($object, $content);
}
return $result;
}
//回复语音消息
private function transmitVoice($object, $voiceArray)
{
$itemTpl = "<Voice>
<MediaId><![CDATA[%s]]></MediaId>
</Voice>";
$item_str = sprintf($itemTpl, $voiceArray['MediaId']);
$xmlTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[voice]]></MsgType>
$item_str
</xml>";
$result = sprintf($xmlTpl, $object['FromUserName'], $object['ToUserName'], time());
return $result;
}
private function checkSignature()
{
//file_put_contents('wx.log', var_export($_GET, true), FILE_APPEND);
$signature = $this->request->get('signature');
$timestamp = $this->request->get('timestamp');
$nonce = $this->request->get('nonce');
$token = config('setting.wechat.token');
$tmpArr = array($token, $timestamp, $nonce);
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
//file_put_contents('wx.log', var_export([$tmpStr, $signature], true), FILE_APPEND);
if ($tmpStr == $signature) {
return true;
} else {
return false;
}
}
/**
* 自定义菜单
*/
public function creatMenu()
{
//组装请求的url地址
$accessToken = $this->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=" . $accessToken;
$data = [
// button下的每一个元素
"button" => [
//第一个一级菜单
['type' => 'click', "name" => "个人简介", "key" => "info"],
[
"name" => "语言排行",
"sub_button" => [
["name" => 'PHP', "type" => "view", 'url' => "https://m.php.cn/article/392978.html"],
['name' => 'c/c++', 'type' => 'pic_sysphoto', 'key' => 'sysptoto'],
['name' => 'java', 'type' => 'pic_weixin', 'key' => 'pic_weixin']
]
],
['type' => 'click', 'name' => '我的', 'key' => 'content']
]
];
// 将数据转换为json格式
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
$result = https_request($url, $data);
dump($result);
}
public function getMenu()
{
$accessToken = $this->getAccessToken();
$url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=" . $accessToken;
$res = https_request($url);
return $res;
}
public function delMenu()
{
$accessToken = $this->getAccessToken();
$url = 'https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=' . $accessToken;
$res = http_curl($url);
dd($res);
}
public function tuling($object)
{
$textTpl = $fromUsername = $toUsername = $time = $newsTpc = '';
//$keyword = '美女';
$keyword = trim($object['Content']);
$key = '96308475006241449b53013d66f8e387';
//针对没有匹配的关键词使用机器人回复
$url = "http://www.tuling123.com/openapi/api?key=$key&info=" . $keyword;
$result = file_get_contents($url);
$result = json_decode($result, true);
file_put_contents('wx_tuling.log', var_export([$object, $result], true), FILE_APPEND);
if ($result['code'] == 100000) {
// 回复文本消息
$resultStr = $result['text'];
} elseif ($result['code'] == 200000) {
$str = '<a href="' . $result['url'] . '">' . $result['text'] . '</a>';
// 机器人中区分为链接
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, 'text', $str);
} elseif ($result['code'] == 302000) {
// 机器人中的新闻
$data = $result['list'];
for ($i = 0; $i < 8; $i++) {
$Articles = "<item>
<Title><![CDATA[{$data[$i]['article']}]]></Title>
<Description><![CDATA[{$data[$i]['article']}]]></Description>
<PicUrl><![CDATA[{$data[$i]['icon']}]]></PicUrl>
<Url><![CDATA[{$data[$i]['detailurl']}]]></Url>
</item>";
}
$count = 1;
$resultStr = sprintf($newsTpc, $fromUsername, $toUsername, $time,
'news', $count, $Articles);
} else {
// 回复文本消息
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, 'text',
'抱歉没有理解,再说一遍问题');
}
$result = $this->transmitText($object, $resultStr);
return $result;
}
public function getLocation($postobj)
{
$Location_X = $postobj['Location_X'];
$Location_Y = $postobj['Location_Y'];
$ak = "F89ca0xP4mnnZarvQT9K3NZnNrrmc5Po";
//$url = "http://api.map.baidu.com/geocoder/v2/?location={$Location_X},{$Location_Y}&output=json&pois=1&ak={$ak}";
$url = "http://api.map.baidu.com/reverse_geocoding/v3/?ak={$ak}&output=json&coordtype=wgs84ll&location={$Location_X},{$Location_Y}";
$json = file_get_contents($url);
$result = json_decode($json, true);
file_put_contents('wx_tuling.log', var_export([$postobj, $url, $result], true), FILE_APPEND);
$contentStr = "位置为 {$result['result']['formatted_address']} 经度为 : {$Location_X} , {$Location_Y}";
$result = $this->transmitText($postobj, $contentStr);
return $result;
}
}
更多功能访问 微信开发