前段时间做毕设用到过,怕以后会忘记,特地记录下,主要是发送模板信息和批量收集formid
一.发送模板信息
效果图
首先小程序发送模板信息需要以下几样参数
1.access_token
2.模板id
3.openid
4.formid
官方文档
https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/template-message.html
1.获取access_token (需要知道小程序的appid和appsecret)
接口地址:
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
返回格式:
{"access_token": "ACCESS_TOKEN", "expires_in": 7200}
当然,由于调用token接口的次数是有限制的。。所以可以先将获取到的token缓存起来,要用的时候先检测缓存是否过期(2个小时),如果没过期就直接使用缓存中的token,过期就调用接口。此处用的是TP5框架
public function access_token(){$appid = 'xxxxxxxx';$appsecret = 'xxxxxxxx';$access_token=Cache::get('weixin_access_token');if($access_token){return json(['access_token'=>$access_token]);}else{$url_get ='https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appid.'&secret='.$appsecret;$ch1 = curl_init ();$timeout = 5;curl_setopt ( $ch1, CURLOPT_URL, $url_get );curl_setopt ( $ch1, CURLOPT_RETURNTRANSFER, 1 );curl_setopt ( $ch1, CURLOPT_CONNECTTIMEOUT, $timeout );curl_setopt ( $ch1, CURLOPT_SSL_VERIFYPEER, FALSE );curl_setopt ( $ch1, CURLOPT_SSL_VERIFYHOST, false );$accesstxt = curl_exec ( $ch1 );curl_close($ch1 );$access = json_decode ( $accesstxt, true );// 缓存数据7200秒Cache::set('weixin_access_token',$access['access_token'],7200);return json(['access_token'=>$access['access_token']]);}}
2.获取模板id
在微信公众平台搜索选择你所需要的模板信息,
可以调整关键词的顺序,提交之后可直接在详情查看复制模板id
3.获取openid(需要appid和appsecret)
获取openid的方法网上有很多,这里贴几个博主的写的
https://blog.csdn.net/qq_27626333/article/details/54614037
https://blog.csdn.net/qq_34328404/article/details/80624577
https://www.cnblogs.com/YSPyishuihan/p/6885242.html
注:如果是单纯获取openid,可直接获取,不需要用户授权。。。接下来放上我自己的写法(仅供参考)
小程序端
onLoad: function (options) {// 登录wx.login({success: res => {// 发送 res.code 到后台换取 openId, sessionKey, unionIdvar code = res.code;var that=this;//console.log(code);wx.request({url: "https://后台接口地址",data: {"code": code},header: {'content-type': 'application/json'},method: 'GET',success: function (res) {// success console.log(res.data.openid);that.setData({openid:res.data.openid})}})}})},
后台接口端(TP5)
public function login($code)
{$code=Request::instance()->param('code');$appid = 'xxxxxxxxx';$appsecret = 'xxxxxxx';$url = 'https://api.weixin.qq.com/sns/jscode2session?appid='.$appid.'&secret='.$appsecret.'&js_code=' . $code . '&grant_type=authorization_code'; $info = file_get_contents($url);//发送HTTPs请求并获取返回的数据,推荐使用curl $json = json_decode($info,true);//对json数据解码$openid=$json['openid'];if($openid){return json(['status'=>0,'openid'=>$openid]);}else{return json(['status'=>1,'msg'=>"error"]);}}
4.form_id
首先formid有两种获取途径。一是支付行为,二是用户在真机上提交表单,官方文档写得很清楚了。这里获取到formid后可以存到数据库中,等待使用。formid有效期是七天,一个formid只能使用一次,使用后就相当于过期了。但是多个formid互相独立,相当于你提交十个表单就有十个formid
这里再贴几个博主的文章
https://www.cnblogs.com/YSPyishuihan/p/6891262.html
https://segmentfault.com/a/1190000016214784
https://blog.csdn.net/u011415782/article/details/82379590
https://blog.csdn.net/lgj199505/article/details/82425425
接下来放上我自己的写法(仅供参考)
小程序端:
<form bindsubmit="formSubmit" report-submit='true'><input name="openid" class="weui-input" value="{{openid}}" /><view class="weui-btn-area"><button class="weui-btn" type="primary" formType="submit">提交</button></view></view>
</form>
formSubmit:function(e){var form_id = e.detail.formId;var openid = e.detail.value.openid;wx.request({url: 'https://后台地址',data: {"form_id": form_id,"openid":openid},header: {'content-type': 'application/json'},method: 'GET',success: function (res) {console.log(res.data);}})
}
后台接口端:(将openid一起存入数据库)
public function reg()
{$play_data['form_id'] = Request::instance()->param('form_id');$play_data['openid'] = Request::instance()->param('openid');$play_res = db('表名')->insert($play_data);if($play_res){return json(['status'=>0,'msg'=>"注册成功"]);}else{return json(['status'=>1,'msg'=>"注册失败"]);}}
发送模板信息(推送单个用户)
public function send_cet(){$openid="这里填推送用户的openid";$token=json_decode($this->access_token()->getContent(),true);$template_id=""; //模板id$page=""; //点击模板信息后进入的页面 例如 pages/xxx/xxx?id={$id}&name={$name}$res=db('formid_pool')->where('openid',$openid)->find();$data_temp=array("touser"=>$openid,"template_id"=>$template_id,"form_id"=>$res['form_id'],"page"=>$page,"data"=>array("keyword1"=>array("value"=>"陈独秀"),"keyword2"=>array("value"=>"12345678910"),"keyword3"=>array("value"=>"英语四级"),"keyword4"=>array("value"=>"222"),"keyword5"=>array("value"=>"222"),"keyword6"=>array("value"=>"222"),"keyword7"=>array("value"=>"666")));$data_string=json_encode($data_temp);$url="https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=".$token['access_token'];$curl = curl_init($url);curl_setopt($curl, CURLOPT_HEADER, false);curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);curl_setopt($curl, CURLOPT_HTTPHEADER, array("Content-type: application/json"));curl_setopt($curl, CURLOPT_POST, true);curl_setopt($curl, CURLOPT_POSTFIELDS, $data_string);$r=curl_exec($curl);curl_close($curl);$status=json_decode($r,true);if($status['errcode']==0){db('formid_pool')->where('openid',$openid)->where('form_id',$res['form_id'])->delete(); //使用完之后删除echo "success";}else{print_r($status);die;}die;}
二.批量收集formid
这里在网上查了挺多方法的
http://www.51xuediannao.com/xiaochengxu/0cba78ba.html (主要用的是这个骚操作)
https://blog.csdn.net/jensen_yao/article/details/83341054
button::after{border:none;}
.aa{width: 120rpx;height: 120rpx;position:fixed;}
<form bindsubmit="test" report-submit="{{true}}"><button formType="submit" class='btn'><view class='aa'><form bindsubmit="test" report-submit="true"><button formType="submit" class='btn'><view class='aa'><form bindsubmit="test" report-submit="true"><button formType="submit" class='btn'><view class='aa'>这里可以嵌套着写,目前这种三层格式可以获取7个</view></button></form></view></button></form></view></button></form>
test:function(e){if (e.detail.formId != 'the formId is a mock one') {this.setData({formIdString: e.detail.formId + "," + this.data.formIdString})}console.log(this.data.formIdString)},
这种方法可用在注册上,但是这样收集的也还不够,你可以在用户有可能点击的地方改写为上面的结构,每点击一次,就向后台发送一起请求,将用户的openid和formid发过去,再构建一个formid池(建一个数据表存着),记录下用户的openid和formid和该formid过期的时间,大概是这样
public function save()
{$openid=Request::instance()->param('openid');$formid=Request::instance()->param('formid');$time=date("Y-m-d H:i:s",strtotime('+7 days'));if($formid=="the formId is a mock one"||empty($openid)){return json(['status'=>0,'msg'=>'no']);}else{db('formid_pool')->insert(['openid'=>$openid,'form_id'=>$formid,'time'=>$time]);return json(['status'=>0,'msg'=>'yes']);}}
另外,我当时在改写结构的过程中遇到了个问题,就是安卓机有时候无法获取到formid,苹果却没影响。最后在某个博主的文章找到一点头绪
https://blog.csdn.net/eaglewyy/article/details/80023829
查看了下自己的结构,我在用户有可能点击的地方都改造为上面的结构,但是点击的地方大多数是用navigator标签进行跳转操作,所有有可能navigator打断了小程序bindsubmit事件,直接将原来的navigator标签删掉,并在form中加一个data-fn='页面地址',后台进行跳转
这是原来的
<form bindsubmit="test" report-submit='true'><button formType="submit"><view class='aa'><navigator url='xxxx'><view style="font-size:14px">测试</view></navigator></view></button></form>
改为
<form bindsubmit="test" report-submit='true' data-fn='跳转页面地址'><button formType="submit"><view class='aa'><view style="font-size:14px">测试</view></view></button></form>
js端
test:function(e){wx.navigateTo({url: e.currentTarget.dataset.fn,})
}