因项目需要做推送服务。小程序推送太多限制。因此,改为服务号通知。
首先,公众号回调地址在另外的服务器上,获取不到。所以采用的思路是,获取全部用户的openid,存入数据库。(之后做定时,获取新增用户。)
项目主要涉及 消息回复。
当用户回复消息时,进入数据库获取unionid,再取公众号的openid,取到之后再进行推送。
实现步骤:
1.将小程序与公众号绑定(绑定后才可获取unionid),官方文档:小程序与公众号绑定获取unionid
2.通过微信公众号的AppId和AppSecret
获取微信公众号的access_token(7200秒有效) 这边需要自己做缓存
地址:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
//获取公众号access_token 2个小时过期
public function getAccessToken()
{
$url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=111&secret=111';
$data = $this->httpRequest($url);
$access_token = $data['access_token'];
//存入缓存
$mc = &load_cache('redis');
$mc->save('access_token', $access_token, 7200);
return $access_token;
}
3.通过刚才获取到的access_token去获取所有用户的openId 官方文档:获取公众号用户列表
地址:https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID
(NEXT_OPENID为超出10000个取10001继续请求,这个会在每次请求后返回的json字符串中有)
4.将所有的openId全部放在一个新的数组中,然后for
循环,循环次数为openId的数组的长度,循环请求每个用户的基本信息
地址:https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
(第一次,获取全部用户的openid。这边比较耗时,8000个用户,我花了2.5个小时。获取后删除代码,重写为定时代码)
5.定时获取新增用户
//获取公众号全部用户的openid
public function getPublicUserOpenid()
{
ini_set('max_execution_time','200');
$mc = &load_cache('redis');
$access_token =$mc->get('access_token');
if (empty($access_token)){
$access_token = $this->getAccessToken();
}
$url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=$access_token&next_openid=";
$data = $this->httpRequest($url);
//token失效
if ($data['errcode']==40001){
$this->getAccessToken();
$this->getPublicUserOpenid();
}
$openidList = $data['data']['openid'];
//返回的数据是无序的,只能做数组对比,取出差集,再保存到数据库。
$result = $this->AppPublicUserModel->select('','','','','openid');
foreach ($result as $item){
$List[]=$item['openid'];
}
//取差集
foreach ($openidList as $key => $item) {
if (in_array($item, $List, true)) {
unset($openidList[$key]);
}
}
foreach ($openidList as $key=>$v){
$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=$access_token&openid=$v&lang=zh_CN";
$userData = $this->httpRequest($url);
//两种情况1已关注和0未关注
if ($userData['subscribe']==1){
$saveData=[
'openid'=>$userData['openid'],
'nickname'=>$userData['nickname'],
'unionid'=>$userData['unionid'],
'headimg'=>$userData['headimgurl'],
];
//保存
$this->AppPublicUserModel->add($saveData);
}
}
return $this->success('','同步成功');
}
6.推送服务号消息。官方文档:公众号发送模版消息
//公众号消息推送
public function pushMessages($fid,$name,$msg)
{
//取openid
$fData = $this->AppUserModel->get(array('id'=>$fid));
$unionId = $fData['unionid'];
$openid = $this->AppPublicUserModel->get(array('unionid'=>$unionId))['openid'];
$mc = &load_cache('redis');
$access_token =$mc->get('access_token');
if (empty($access_token)){
$access_token = $this->getAccessToken();
}
$url = 'https://api.weixin.qq.com/cgi-bin/message/template/send?access_token='.$access_token ;
$data = [
'touser'=>$openid,
'template_id'=>'ZK7ZfM3r02Iyv-xe4UoaBPt9FmjJ4jzC9k-cASM3M84',
'url' => '',
'miniprogram' => array(
'appid'=>'111',
'pagepath'=>'/pages/message'
),
'data' => array(
'first' => array('value' => '你有一条新的消息'),
'keyword1' => array('value' => $name),
'keyword2' => array('value' => date('Y-m-d H:i:s',time())),
'keyword3' => array('value' => $msg),
//'remark' => array('value' => '这是备注'),
)
];
$result = $this->httpPostJson($url, urldecode(json_encode($data)));
$returnData = json_decode($result[1],1);
if ($returnData['errcode']==0){
return $this->success('','发送模板消息成功');
}else{
return $this->fail($returnData['errcode'],'发送模板消息失败');
}
}
备注:以上内容参考以下地址,侵删
https://blog.csdn.net/qq_39687901/article/details/85243514
https://www.jianshu.com/p/5a388a5afac7