微信订阅通知开发 (小白教程)微擎
微擎复制可用
微擎访问绕过登陆校验请查看 https://blog.csdn.net/fuchto/article/details/118190252
文中 微擎 WeAccount::create($id); 等函数绕过绕过登陆校验直接使用是无法使用的会报错
需要溯源到对应的方法中 传参调用
如果让用户在同一个页点击两次 同意授权可能会发生 发送两条消息的情况 可以试试 location.reload(); 刷新一下试试
第一步 公众号配置 选择对应的模版
开发此功能必须是 服务号
官方文档 https://developers.weixin.qq.com/doc/offiaccount/Subscription_Messages/intro.html
设置公众号的 相关配置 业务域名 js域名 授权域名
第二步 创建数据库
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for ims_template_log
-- ----------------------------
DROP TABLE IF EXISTS `ims_template_log`;
CREATE TABLE `ims_template_log` (`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,`openid` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户openid',`template_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '模版id',`uniacid` int(11) NULL DEFAULT NULL COMMENT '公众号id',`status` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '订阅状态',`number` int(11) NULL DEFAULT 1 COMMENT '同意次数',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 61 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Table structure for ims_template_msg
-- ----------------------------
DROP TABLE IF EXISTS `ims_template_msg`;
CREATE TABLE `ims_template_msg` (`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,`uniacid` int(11) NULL DEFAULT NULL COMMENT '公众号id',`head_title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '网页标题',`headimage` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像地址',`content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '显示文案',`bg_image` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '背景图',`button_text` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '按钮内容',`herad_media_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像media_id',`bg_media_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '背景图media_id',`template` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '模版内容',`createtime` int(11) NULL DEFAULT NULL,PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Table structure for ims_template_sendLog
-- ----------------------------
DROP TABLE IF EXISTS `ims_template_sendLog`;
CREATE TABLE `ims_template_sendLog` (`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,`msg_id` int(11) NULL DEFAULT NULL COMMENT '消息id templat_msg',`uniacid` int(11) NULL DEFAULT NULL,`sum` int(11) NULL DEFAULT NULL COMMENT '推送数',`success` int(11) NULL DEFAULT NULL COMMENT '推送成功数',`start_time` int(11) NULL DEFAULT NULL COMMENT '开始数据',`end_time` int(11) NULL DEFAULT NULL COMMENT '结束时间',`status` int(2) NULL DEFAULT NULL COMMENT '推送状态:0=推送中,1=推送完成',`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '推送模版标题',PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 18 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;SET FOREIGN_KEY_CHECKS = 1;
template_msg 中的 template 格式为
[{"name":"模版名称","type":"跳转类型","appid":"小程序appid","pages":"小程序路径","jump_url":"跳转链接","template_id":"模版id","模版id":{"模版参数key":"模版参数value","模版参数key":"模版参数value","模版参数key":"模版参数value"}},{"name":"模版名称","type":"跳转类型","appid":"小程序appid","pages":"小程序路径","jump_url":"跳转链接","template_id":"模版id","模版id":{"模版参数key":"模版参数value","模版参数key":"模版参数value","模版参数key":"模版参数value"}}
]
生成对应的 授权页链接
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若提示“该链接无法访问”,请检查参数是否填写错误,是否拥有scope参数对应的授权作用域权限。
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 公众号的唯一标识 |
redirect_uri | 是 | 授权后重定向的回调链接地址, 请使用 urlEncode 对链接进行处理 |
response_type | 是 | 返回类型,请填写code |
scope | 是 | 应用授权作用域,snsapi_base (不弹出授权页面,直接跳转,只能获取用户openid),snsapi_userinfo (弹出授权页面,可通过openid拿到昵称、性别、所在地。并且, 即使在未关注的情况下,只要用户授权,也能获取其信息 ) |
state | 否 | 重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节 |
#wechat_redirect | 是 | 无论直接打开还是做页面302重定向时候,必须带此参数 |
官方网页
https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_webpage_authorization.html
第二步:通过code换取网页授权access_token
首先请注意,这里通过code换取的是一个特殊的网页授权access_token,与基础支持中的access_token(该access_token用于调用其他接口)不同。公众号可通过下述接口来获取网页授权access_token。如果网页授权的作用域为snsapi_base,则本步骤中获取到网页授权access_token的同时,也获取到了openid,snsapi_base式的网页授权流程即到此为止。
尤其注意:由于公众号的secret和获取到的access_token安全级别都非常高,必须只保存在服务器,不允许传给客户端。后续刷新access_token、通过access_token获取用户信息等步骤,也必须从服务器发起。
获取code后,请求以下链接获取access_token: https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
参数说明
参数 | 是否必须 | 说明 |
---|---|---|
appid | 是 | 公众号的唯一标识 |
secret | 是 | 公众号的appsecret |
code | 是 | 填写第一步获取的code参数 |
grant_type | 是 | 填写为authorization_code |
微擎代码
$id = $_GPC['uniacid'];$code = $_GPC['code'];$account_api = WeAccount::create($id);// 获取到用户 openid$OauthInfo = $account_api->getOauthInfo($code);$wechats_info = pdo_get("account_wechats",['uniacid'=>$id]);$appid = $wechats_info['key'];$openid = $OauthInfo['openid'];// 微信 jsapi_ticket$Ticket = $account_api->getJsApiTicket();// 生成时间戳$time = TIMESTAMP;// 随机字符串$noncestr = mt_rand(10000,99999);// 获取当前网页$thisUrl = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'].'?'.$_SERVER['QUERY_STRING'];// 拼接签名$str = "jsapi_ticket={$Ticket}&noncestr={$noncestr}×tamp={$time}&url={$thisUrl}";// 生成签名$signature=sha1($str);$info = pdo_get('template_msg',['uniacid'=>$id,'id'=>$_GPC['id']]);$template_info = json_decode($info['template'],true);// 获取所有已设置的模版// $templateList = getTemplateList($id);$templateId = '';foreach ($template_info as $key => $value){$templateId .=trim($value['template_id']).',';}// foreach ($templateList['data'] as $key => $value){// $templateId .=$value['priTmplId'].',';// }$templateId = substr($templateId,0,strlen($templateId)-1);template('platform/template_home');//获取私有模板列表
function getTemplateList($uniacid){$account_api = WeAccount::create($uniacid);$token = $account_api->getAccessToken();$url = "https://api.weixin.qq.com/wxaapi/newtmpl/gettemplate?access_token={$token}";$response = ihttp_get($url);$data = json_decode($response['content'],true);return $data;
}
html 文件中 使用 开放标签 拉起授权页
第一步 引入js文件
在需要调用JS接口的页面引入如下JS文件:http://res.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)
备注:支持使用 AMD/CMD 标准模块加载方法加载
<script src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
第二步 配置对应参数
$(document).ready(function() {wx.config({debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。appId: 'appid', // 必填,公众号的唯一标识timestamp: '{$time}', // 必填,生成签名的时间戳nonceStr: '{$noncestr}', // 必填,生成签名的随机串signature: '{$signature}',// 必填,签名jsApiList: ['addEventListener'], // 必填,需要使用的JS接口列表openTagList :['wx-open-subscribe'] // 必填 使用的 开放标签});})wx.ready(function () {// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中console.log('验证成功');});wx.error(function (res) {// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名console.log('验证失败');});
第三步 使用开放标签
{$templateId} 为获取到的 模版id 多个模版id用,隔开 开发标签中的按钮 只有在 手机端才显示 pc端不显示按钮
<wx-open-subscribe template="{$templateId}" id="subscribe-btn"><script type="text/wxtag-template" slot="style"><style>.subscribe-btn {border: none;padding: 10px;border-radius: 5px;color: #ff605e;background-color: #fff;font-size: 16px;}</style></script><script type="text/wxtag-template"><button class="subscribe-btn">这是按钮显示文字</button></script></wx-open-subscribe>
第四步 提交数据给后端接收
var btn = document.getElementById('subscribe-btn');// 加载成功btn.addEventListener('success', function (e) {console.log('success', e.detail);if(e.detail.errMsg == "subscribe:ok"){console.log('同意');console.log(e.detail.subscribeDetails);$.ajax({type : 'post',url : "url",async:false,data : {uniacid : "{$id}",openid : "{$openid}",template : e.detail.subscribeDetails,},dataType : 'json',success:function(datas){console.log(datas);if(datas.code == 1){alert(datas.msg);// WeixinJSBridge.call('closeWindow');}else{alert(datas.msg);}}})}else{console.log('不同意');}});// 加载失败btn.addEventListener('error',function (e) {alert("加载失败");console.log('fail', e.detail);});
注意在 授权也中 用户订阅几次则可以发送几次消息
和一次性订阅消息不一样 无论用户 同意几次 永远只能发送一次
如果用户在已发送的消息中 拒绝接收此消息则当前用户 无论发送几次给当前用户都不会 发送成功
如果用户在已发送的消息中 点击接收此消息 则用户在授权页点击一次授权按钮 无论取消还是允许 次数都会加一 在授权页面中 在外面允许的 模版消息不会在出现到 授权列表里
发送消息
$uniacid = $_GPC['uniacid'];if(empty($uniacid)){echo("uniacid 公众号id 不能为空");die;}if(empty($_GPC['id'])){echo("消息id 不能为空");die;}if(empty($_GPC['template_id'])){echo("模版id 不能为空");die;}$user = pdo_getall("template_log",['uniacid'=>$uniacid,'template_id'=>$_GPC['template_id'],'status'=>'accept','number >'=> 0]);$template_info = pdo_get("template_msg",['uniacid'=>$uniacid,'id'=>$_GPC['id']]);if($user){// 总人数$count = count($user);$i = 0;$send_data = ['sum' => $count,'msg_id' => $template_info['id'],'uniacid' => $uniacid,'start_time' => TIMESTAMP,'status' => 0];$template = json_decode($template_info['template'],true);foreach ($template as $k => $v){if($_GPC['template_id'] == $v['template_id']){$send_data['title'] = $v['name'];}}pdo_insert('template_sendLog',$send_data);$sendedid = pdo_insertid();foreach ($user as $key => $value){$status = send_template_msg($uniacid,$template,$value);if($status === true){$i = $i + 1;pdo_update("template_log",['number' => $value['number'] - 1],['id'=>$value['id']]);}}$sended = ['status' => 1,'success' => $i,'end_time' => TIMESTAMP,];pdo_update('template_sendLog',$sended,['id'=> $sendedid]);echo '发送完成';}else{echo "暂无符合条件用户";}function send_template_msg($uniacid,$template,$user){$account_api = WeAccount::create($uniacid);$token = $account_api->getAccessToken();$url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/bizsend?access_token={$token}";$data['touser'] = $user['openid'];$data['template_id'] = $user['template_id'];foreach ($template as $key => $value){if($value['template_id'] == $user['template_id']){if($value['type'] == 1){$data['page'] = ($value['jump_url']);}elseif($value['type'] == 2){$data['miniprogram']['appid'] = $value['appid'];$data['miniprogram']['pagepath'] = $value['pages'];}foreach ($value[$value['template_id']] as $k => $v){$data['data'][$k]['value'] = $v;}}}$response = ihttp_post($url,json_encode($data));$result = json_decode($response['content'],true);// 有一种情况是 已发送消息给 用户 用户在模版中 选择拒绝接收此类消息时 下次发送消息时 报错43101 因此设置此条消息可发送次数为0
// 当用户在已接收的模版中选择 接收此模版消息时则是永久接收 选择访问时则没有选择这个模版的选项 因此在add_log 方法中提交过来的数据 永久接收的消息数据为同意则当前模版可发送次数+1if($result['errcode'] == 43101){pdo_update('ims_template_log',['number' => 0],['id'=>$user['id']]);}if($result['errcode'] == 0){return true;}else{var_dump($result);return false;}}
有问题请联系我
微信订阅通知开发 (小白教程)微擎相关推荐
- 微信公众号开发入门教程第一篇
微信公众号开发入门教程第一篇 关键字:微信公众平台开发 作者:方倍工作室 在这篇微信公众平台开发教程中,我们假定你已经有了PHP语言程序.MySQL数据库.计算机网络通讯.及HTTP/XML/CSS/ ...
- C#微信公众号开发系列教程五(接收事件推送与消息排重)
C#微信公众号开发系列教程五(接收事件推送与消息排重) 原文:C#微信公众号开发系列教程五(接收事件推送与消息排重) 微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续 ...
- 微信公众号二次开发框架-微擎
一.微擎框架的下载(http://www.we7.cc/) 1.在自己的服务器或者虚拟主机上安装微擎的框架(免费开源的微信二次开发框架,类似ecshop和dz均可以部署在自己的服务器或虚拟主机内) 2 ...
- 微信小程序开发基础教程
文章目录 1.什么叫做微信小程序 2.微信小程序开发功能特点 3.微信小程序开发流程 3.1 微信公众平台注册 3.2 微信开发者工具下载 3.3 微信开发者工具界面上的基本功能介绍 3.3.1 开发 ...
- 视频教程-微信小程序开发培训教程-微信开发
微信小程序开发培训教程 本人计算机专业,毕业工作已经10多年,从事过的行业有,安防,通讯,Gps定位,信息统计分析,互联网电商等,从事过的职位. 代码工程师(使用过的语言C#,PHP,Java),Ap ...
- C#微信公众号开发系列教程三(消息体签名及加解密)
http://www.cnblogs.com/zskbll/p/4139039.html C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试) C ...
- 微信小程序开发系列教程三:微信小程序的调试方法
微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 这个教程的前两篇文章,介绍了如何用下图所示的微信开发者工具自动生成一个Hel ...
- C#微信公众号开发系列教程二(新手接入指南)
此系列前面已经更新了两篇博文了,都是微信开发的前期准备工作,现在切入正题,本篇讲解新手接入的步骤与方法,大神可直接跳过,也欢迎大神吐槽. 微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教 ...
- 微信公众号开发系列教程一(调试环境部署)
http://www.cnblogs.com/zskbll/p/4074855.html 目录 C#微信公众号开发系列教程一(调试环境部署) C#微信公众号开发系列教程一(调试环境部署续:vs远程调试 ...
最新文章
- 全球首个突破200种语言互译的翻译引擎,百度翻译打破世界沟通壁垒
- UVA11817 Tunnelling the Earth(计算几何、经纬度转空间坐标、球面距离)
- github访问太慢解决方案
- 查询oracle sql语句执行最慢和执行最多的语句!
- ubuntu 16.04 中配置Eclipse c++开发环境
- 加快vs2010的启动速度
- anaconda pycharm 动手学深度学习环境配置
- cygwin This indicates that the /etc/passwd (and possibly /etc/group) files should be rebuilt 问题解决办法
- linux中c语言延时毫秒函数,linux下写个C语言程序,要求有0.5微秒以下的延时,要怎样写...
- 2017年英国机器人周:身体有问题 就找机器人
- 第七次全国人口普查公报[1](第五号) ——人口年龄构成情况
- L2-026 小字辈 (25 分)
- Android中动画参数duration,Android基本动画设置
- 2020-04-03-功能性光学脑成像
- 2020电赛F题总结回顾(openmv实现视觉)
- ERC721: Non-fungible Token Standard
- 【树莓派】基于树莓派,实现无线路由功能
- 计算机组装与维修2版,计算机组装与维修2版.doc
- [思考的乐趣] 有趣的莫比乌斯带
- Ubuntu 16.04安装tomcat8
热门文章
- rabbit 的使用方法
- 中公教育12月04日内外盘分析
- USB转RS485代替PC/PPI通讯电缆
- 计算机专业有哪些有含金量的证书,大学最有含金量的6大类证书!你拥有哪几个?...
- 数位DP(期末机测题)
- .rvm/gems/ruby-2.4.1@global/gems/cocoapods-1.5.0/lib/cocoapods/executable.rb:89: warning: Insecure
- mac获取ios应用包名
- js输出sb (!(~+[]) + {})[--[~+][+[]] * [~+[]] + ~~!+[]] + ({} + [])[[~!+[]] * ~+[]] 图解
- First-hitting-time model
- java继承stu继承person_4.3 jmu-Java-03面向对象-06-继承覆盖综合练习-Person、Student、Employee、Company (20 分)中的一些问题...