├── .gitignore ├── .idea └── vcs.xml ├── README.md ├── payment.js └── WxController.class.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea* -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wxSendTemplateCode 2 | 3 | - 分享代码,实现微信小程序 发送服务通知的核心代码 4 | 5 | ##必读: 6 | 7 | - ①. 其中的 payment.js 文件,只摘取了三个核心方法,请对应博客进行提取操作 8 | - ②. WxController.class.php 文件 至少需要替换三个地方,尤其要注意对 方法 sendTemplatePaySuccess()的正确处理 9 | 10 | ##提示: 11 | - 服务端我用的是 `ThinkPHP3.2.3` 框架 12 | - 所以在使用 `php` 文件时,请对应改成适合自己框架的代码格式即可 13 | 14 | - 对应博文: [小程序 发送模板消息的功能实现](https://blog.csdn.net/u011415782/article/details/82379590) 15 | -------------------------------------------------------------------------------- /payment.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * 进行Form表单的提交 4 | */ 5 | bindPayFormSubmit: function(event) { 6 | console.log(event); 7 | var formId = event.detail.formId; 8 | this.setData({ 9 | formId: formId 10 | }); 11 | } 12 | 13 | /** 14 | * 微信支付成功后的 消息模板的发送 15 | */ 16 | sendTemplatePaySuccess: function() { 17 | var self = this; 18 | var postData = { 19 | //sn: self.data.order_sn, 20 | form_id: self.data.formId 21 | }; 22 | self.http_post('https://xxx.com/wx/sendTemplatePaySuccess', postData, (data) => { 23 | //TODO 此处可做跳转业务 24 | // wx.navigateTo({ 25 | // url: '/pages/cart/results/index?status=1&type=pay&orderInfo=' + JSON.stringify(self.data.orderInfo), 26 | }); 27 | }) 28 | }, 29 | 30 | /** 31 | * 封装 http 函数,默认‘GET’ 提交 32 | */ 33 | http_post:function(toUrl, postData, httpCallBack) { 34 | wx.request({ 35 | url: toUrl, 36 | data: postData, 37 | method: 'POST', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT 38 | header: { 39 | 'content-type': 'application/x-www-form-urlencoded;charset=utf-8', 40 | }, 41 | success: function (res) { 42 | //回调处理 43 | return typeof httpCallBack == "function" && httpCallBack(res.data); 44 | }, 45 | fail: function (error) { 46 | console.log(error); 47 | } 48 | }) 49 | }, -------------------------------------------------------------------------------- /WxController.class.php: -------------------------------------------------------------------------------- 1 | app_id = C('WeChat')['app_id']; //自行补充 26 | $this->app_secret = C('WeChat')['app_secret']; //自行补充 27 | $this->get_token_url = 'https://api.weixin.qq.com/cgi-bin/token?' 28 | .'grant_type=client_credential&appid=%s&secret=%s'; 29 | } 30 | 31 | /** 32 | * 微信获取 AccessToken 33 | */ 34 | public function getAccessToken(){ 35 | $access_token = $this->opGetAccessToken(); 36 | if(!$access_token){ 37 | $this->return_err('获取access_token时异常,微信内部错误'); 38 | }else{ 39 | $this->return_data(['access_token'=>$access_token]); 40 | } 41 | } 42 | 43 | /** 44 | * 提取公共方法 - 获取 AccessToken 45 | * @return bool 46 | */ 47 | public function opGetAccessToken(){ 48 | $get_token_url = sprintf($this->get_token_url, 49 | $this->app_id,$this->app_secret); 50 | $result = $this->curl_get($get_token_url); 51 | $wxResult = json_decode($result,true); 52 | if(empty($wxResult)){ 53 | return false; 54 | }else{ 55 | $access_token = $wxResult['access_token']; 56 | return $access_token; 57 | } 58 | } 59 | /** 60 | * 获取小程序模板库标题列表 61 | * TODO 没必要使用,小程序账号后台可以视图查看 62 | */ 63 | public function getAllTemplateList(){ 64 | $opUrl = 'https://api.weixin.qq.com/cgi-bin/wxopen/template/library/list?' 65 | .'access_token=%s'; 66 | $rawPost = ['count'=>20,'offset'=>0]; 67 | $this->opTemplateData($opUrl,$rawPost,'getAllTemplateList'); 68 | } 69 | 70 | /** 71 | * 获取模板库某个模板标题下关键词库 72 | * TODO 没必要使用,小程序账号后台可以视图查看 73 | */ 74 | public function getTemplateKey(){ 75 | $opUrl = "https://api.weixin.qq.com/cgi-bin/wxopen/template/library/get?access_token=%s"; 76 | $rawPost = ['id'=>'AT0002']; 77 | $this->opTemplateData($opUrl,$rawPost,'getTemplateKey'); 78 | } 79 | 80 | /** 81 | * 获取帐号下已存在的模板列表 82 | * TODO 没必要使用,小程序账号后台可以视图查看 83 | */ 84 | public function getExistTemplateList(){ 85 | $opUrl = "https://api.weixin.qq.com/cgi-bin/wxopen/template/list?access_token=%s"; 86 | $rawPost = ['count'=>20,'offset'=>0]; 87 | $this->opTemplateData($opUrl,$rawPost,'getExistTemplateList'); 88 | } 89 | 90 | /** 91 | * 提取公共方法 获取模板数据 92 | * @param string $opUrl 93 | * @param array $rawPost 94 | * @param string $method 95 | */ 96 | public function opTemplateData($opUrl = '',$rawPost = [],$method = ''){ 97 | $access_token = $this->opGetAccessToken(); 98 | if(!$access_token){ 99 | $this->return_err('获取 access_token 时异常,微信内部错误'); 100 | }else{ 101 | $templateUrl = sprintf($opUrl,$access_token); 102 | $listRes = $this->curl_post($templateUrl,$rawPost); 103 | $wxResult = json_decode($listRes,true); 104 | if($wxResult['errcode']){ 105 | $this->return_err($method.' - Failed!',$wxResult); 106 | }else{ 107 | //var_dump($wxResult); 108 | $this->return_data($wxResult); 109 | } 110 | } 111 | } 112 | 113 | /** 114 | * 支付成功后的 服务号通知消息的发送 115 | * form_id 表单提交场景下, 为 submit 事件带上的 formId; 116 | * 支付场景下,为本次支付的 prepay_id 117 | * $rawPost TODO 其参数解释请参考 sendTemplate()!!! 118 | */ 119 | public function sendTemplatePaySuccess(){ 120 | if (IS_POST){ 121 | $form_id = I('post.form_id'); 122 | /*-------------------此为项目的特定业务处理---------------------------*/ 123 | $order_sn = I('post.sn')?I('post.sn'):''; 124 | $orderModel = new OrderModel(); 125 | $sendTemplateData = $orderModel->getSendTemplateData($order_sn); 126 | /*-----------以上数据 $sendTemplateData 可根据自己的实际业务进行获取-----*/ 127 | $rawPost = [ 128 | 'touser' => $sendTemplateData['mini_openid'] , 129 | 'template_id' => 'yASr1SdzgV7_gRzKgqYI3t7um-3pIGXrpCcHUHVIJz4', 130 | 'form_id' => $form_id, 131 | 'data' => [ 132 | 'keyword1' => ['value' => $sendTemplateData['order_sn']], 133 | 'keyword2' => ['value' => $sendTemplateData['pay_time']], 134 | 'keyword3' => ['value' => $sendTemplateData['goodsMsg']], 135 | 'keyword4' => ['value' => $sendTemplateData['order_amount']], 136 | 'keyword5' => ['value' => $sendTemplateData['addressMsg']], 137 | 'keyword6' => ['value' => $sendTemplateData['tipMsg']], 138 | ] 139 | ]; 140 | $this->sendTemplate($rawPost,'sendTemplatePaySuccess'); 141 | }else{ 142 | return $this->return_err('Sorry,请求不合法'); 143 | } 144 | 145 | } 146 | /** 147 | * 发送模版消息 148 | * @param string $method_msg 方法名称 149 | * TODO @param array $rawPost 参数说明: 150 | * 参数 必填 说明 151 | * touser 是 接收者(用户)的 openid 152 | template_id 是 所需下发的模板消息的id 153 | page 否 点击模板卡片后的跳转页面,仅限本小程序内的页面。支持带参数,(示例index?foo=bar)。该字段不填则模板无跳转。 154 | form_id 是 表单提交场景下,为 submit 事件带上的 formId;支付场景下,为本次支付的 prepay_id 155 | data 是 模板内容,不填则下发空模板 156 | color 否 模板内容字体的颜色,不填默认黑色 【废弃】 157 | emphasis_keyword 否 模板需要放大的关键词,不填则默认无放大 158 | */ 159 | public function sendTemplate($rawPost = [],$method_msg = 'sendTemplate'){ 160 | $opUrl = "https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send?access_token=%s"; 161 | $this->opTemplateData($opUrl,$rawPost,$method_msg); 162 | } 163 | 164 | 165 | /** 166 | * 错误返回提示 167 | * @param string $errMsg 错误信息 168 | * @param string $errMsg 169 | * @param array $data 170 | */ 171 | protected function return_err($errMsg = 'fail',$data = array()) 172 | { 173 | exit(json_encode(array('status' => 0, 'result' => $errMsg, 'data' => $data))); 174 | } 175 | 176 | 177 | /** 178 | * 正确返回 179 | * @param array $data 要返回的数组 180 | * @return json的数据 181 | */ 182 | protected function return_data($data = array()) 183 | { 184 | exit(json_encode(array('status' => 1, 'result' => 'success', 'data' => $data))); 185 | } 186 | 187 | /** 188 | * PHP 处理 post数据请求 189 | * @param $url 请求地址 190 | * @param array $params 参数数组 191 | * @return mixed 192 | */ 193 | protected function curl_post($url,array $params = array()){ 194 | //TODO 转化为 json 数据 195 | $data_string = json_encode($params); 196 | $ch = curl_init(); 197 | curl_setopt($ch,CURLOPT_URL,$url); 198 | curl_setopt($ch,CURLOPT_HEADER,0); 199 | curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 200 | curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10); 201 | curl_setopt($ch,CURLOPT_POST,1); 202 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); 203 | curl_setopt($ch,CURLOPT_POSTFIELDS,$data_string); 204 | curl_setopt($ch,CURLOPT_HTTPHEADER, 205 | array( 206 | 'Content-Type: application/json' 207 | ) 208 | ); 209 | $data = curl_exec($ch); 210 | curl_close($ch); 211 | return ($data); 212 | } 213 | 214 | /** 215 | * @param string $url get请求地址 216 | * @param int $httpCode 返回状态码 217 | * @return mixed 218 | */ 219 | protected function curl_get($url,&$httpCode = 0){ 220 | $ch = curl_init(); 221 | curl_setopt($ch,CURLOPT_URL,$url); 222 | curl_setopt($ch,CURLOPT_RETURNTRANSFER,1); 223 | 224 | //不做证书校验,部署在linux环境下请改位true 225 | curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); 226 | curl_setopt($ch,CURLOPT_CONNECTTIMEOUT,10); 227 | $file_contents = curl_exec($ch); 228 | $httpCode = curl_getinfo($ch,CURLINFO_HTTP_CODE); 229 | curl_close($ch); 230 | return $file_contents; 231 | } 232 | } --------------------------------------------------------------------------------