自定义菜单栏并自动回复
1)首先我们去微信公众号申请一个微信公众号测试账号申请测试号链接,申请完会出现如下图显示那样。修改js接口安全域名http://自己的域名/weixin,这里我用了tp5的路由Route::rule(‘weixin’, ‘Weixin/index’, ‘get|post’);token随便自己写,这里我写了token。
这里的token跟js接口域名的token保持一致,不然配置不会成功!
别忘了需要填写回调地址,不然获取不到code的。
3)配置微信公众号菜单栏代码如下
/**
* 公众号请求
*/
public function index()
{
$echostr = $this->request->get('echostr');
//调用验证方法
if (isset($echostr)) {
$this->valid($echostr);
} else {
$this->definedMenu();
$this->responseMsg();
}
}
/**
* 验证微信接口
*/
public function valid($echostr)
{
if ($this->checkSignature()) {
echo $echostr;
exit;
}
}
/**
* 验证签名是否正确
* @return bool
*/
public function checkSignature()
{
$tmpArr = array($this->token, $this->request->get('timestamp'), $this->request->get('nonce'));
sort($tmpArr, SORT_STRING);
$tmpStr = implode($tmpArr);
$tmpStr = sha1($tmpStr);
if ($tmpStr == $this->request->get('signature')) {
return true;
} else {
return false;
}
}
4)根据官方文档创建自定义菜单代码是通过请求https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN该链接
public function definedMenu()
{
$accessToken = $this->getAccessToken();
//定义菜单的请求路径Url
$url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={$accessToken}";
//定义菜单
$postData = array(
'button' => [
[
'name' => '百年仁合',
'sub_button' => [
['type' => 'view', 'name' => '仁合文化', 'url' => 'http://starworld.com/action?url=culture'],
['type' => 'view', 'name' => '仁合课程', 'url' => 'http://starworld.com/action?url=course'],
['type' => 'view', 'name' => '工具流', 'url' => 'http://starworld.com/action?url=tool'],
['type' => 'view', 'name' => '宣传片', 'url' => 'http://starworld.com/action?url=publicity'],
]
],
[
'name' => '前沿动态',
'sub_button' => [
['type' => 'view', 'name' => '平台资讯', 'url' => 'http://starworld.com/action?url=consult'],
['type' => 'view', 'name' => '市场快报', 'url' => 'http://starworld.com/action?url=newsflash'],
['type' => 'view', 'name' => '新品速递', 'url' => 'http://starworld.com/action?url=newsproduct'],
['type' => 'view', 'name' => '研发进展', 'url' => 'http://starworld.com/action?url=research'],
['type' => 'view', 'name' => '会议预约', 'url' => 'http://starworld.com/action?url=meetinglist'],
]
],
[
'name' => '我的',
'sub_button' => [
['type' => 'view', 'name' => '名单库', 'url' => 'http://starworld.com/action?url=customer'],
['type' => 'view', 'name' => '产品资料', 'url' => 'http://starworld.com/action?url=product'],
['type' => 'view', 'name' => '案例征集', 'url' => 'http://starworld.com/action?url=case_collection'],
['type' => 'view', 'name' => '个人中心', 'url' => 'http://starworld.com/action?url=personal'],
]
]
]
);
//请求接口
$result = Curl::httpRequest($url, json_encode($postData, JSON_UNESCAPED_UNICODE));
dump($result);
}
请求https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={KaTeX parse error: Expected 'EOF', got '}' at position 12: this->appid}̲&secret={this->appsecret}链接获取access_token。
/**
* 获取Access Token
*/
public function getAccessToken()
{
$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" . config('weixin.appid') . "&secret=" . config('weixin.appsecret');
$accessToken = Curl::httpRequest($url);
return $accessToken['access_token'];
}
5)关注公众号并自动回复功能,代码如下
/**
* 响应信息
*/
public function responseMsg()
{
$postStr = file_get_contents('php://input');
if (!empty($postStr)) {
$this->postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$type = strtolower($this->postObj->MsgType);
switch ($type) {
case 'event':
$result = $this->receiveEvent();
break;
case 'text':
$result = $this->receiveText();
break;
case 'image':
$result = $this->receiveImage();
break;
default:
$result = $this->receiveDefault();
break;
}
echo $result;
exit;
} else {
echo "";
exit;
}
}
/**
* 事件回复
* @return string
*/
public function receiveEvent()
{
switch (strtolower($this->postObj->Event)) {
case 'subscribe':
$content = "欢迎你关注此微信号!";
break;
case 'unsubscribe':
$content = "你取消了关注!";
break;
case 'click':
$content = "你点击了菜单!";
break;
}
return $this->transmitText($content);
}
/**
* 文本回复
* @return string
*/
public function receiveText()
{
//$content = "你发送的是文本,内容为:".$this->postObj->Content;
$redirectUrl = urlencode('http://www.luoshumai.cn');
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . config('weixin.appid') . "&redirect_uri={$redirectUrl}&response_type=code&scope=snsapi_userinfo &state=STATE#wechat_redirect";
$content = '<a href="' . $url . '">点我跳转</a>';
return $this->transmitText($content);
}
/**
* 回复消息
* 判断消息类型处理后,生成Xml回复消息
*/
private function transmitText($content)
{
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
$result = sprintf($textTpl, $this->postObj->FromUserName, $this->postObj->ToUserName, time(), 'text', $content);
return $result;
}
以上可以实现微信公众号自定义菜单栏问题。如下图
网页授权功能
授权功能,官方文档网页授权
按照微信开发文档步骤,实现微信公众号网页授权
1)通过请求https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . config(‘weixin.appid’) . "&redirect_uri={KaTeX parse error: Expected 'EOF', got '}' at position 13: redirect_url}̲&response_type=…state}#wechat_redirect这个链接获取code。scope参数有两种,一种是静默(snsapi_base),意思就是客户感受不到授权,但是只能获取openid;第二种是手动授权(snsapi_userinfo ),意思就是弹出授权页面经过客户同意才能实现授权问题,获取用户基本信息,包括openid。redirect_url就是你想要跳转到的方法,然后在这个方法里面你可以获取到code。
我的代码如下:
/**
*重定向url去获取code
*/
public function action($red_url = '')
{
if ($red_url) {
$action = $red_url;
} else {
$action = $this->request->get('url');
}
$url = request()->domain().'/'.$action;
$this->accredit($url,$action);
}
//拼接URL
public function accredit($redirect_url, $state)
{
$url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" . config('weixin.appid') . "&redirect_uri={$redirect_url}&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";
$this->redirect($url);
}
2)通过code换取网页授权access_token
请求https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code获取access_token,如下图代码
/**
* 获取Access Token
*/
public function getAccessToken($code)
{
$url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" . config('weixin.appid') . "&secret=" . config('weixin.appsecret') . "&code={$code}&grant_type=authorization_code";
$AccessToken = Curl::httpRequest($url);
return $AccessToken;
}
3)刷新access_token(如果需要)
由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。
请求方法
获取refresh_token后,请求以下链接重新获取access_token: https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=APPID&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
/**
* 判断token是否过期,过期则刷新token
*/
function checkToken()
{
$redis = \think\facade\Cache::store('redis');
$open_id = session('open_id');
$token = $redis->get('token');
$url = "https://api.weixin.qq.com/sns/auth?access_token={$token['access_token']}&openid={$open_id}";
$res = \app\common\controller\Curl::httpRequest($url);
if ($res['errcode'] != 0) {
getAccess($redis, $token);
}
}
/**
* 获取access_token数据
* @param $redis
* @param $token
* @return array
*/
function getAccess($redis, $token)
{
$url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" . config('weixin.appid') . "&grant_type=refresh_token&refresh_token=" . $token['refresh_token'];
$token_data = \app\common\controller\Curl::httpRequest($url);
//保存用户信息到session
session('open_id');
$redis->set('token', $token_data);
return $token_data;
}
附带获取用户信息
/**
* 获取用户信息
* @param unknown $openid
* @param unknown $access_token
* @return unknown
*/
public function getWeChatUserInfo($access_token, $openid)
{
$url = "https://api.weixin.qq.com/sns/userinfo?access_token={$access_token}&openid={$openid}&lang=zh_CN";
$weChatUserInfo = Curl::httpRequest($url);
return $weChatUserInfo;
}
以上流程可以完成网页授权。