技术饭
微信开放平台中第三方平台api接口的对接与实现
copylian
0 评论
18441 浏览
2020.08.28
微信开放平台中第三方平台api接口的对接与实现,最近为了做微信开放平台的第三方平台也是花费了两周多的时间,中间碰到各种坑,以前如果要帮助第三方公众号做开放,也是直接把第三方的开发信息改成自己服务器的,但是这样不方便,不同服务商每做一个活动都要重新改一次,所以只能使用公众号授权第三方平台来实现这样的功能了。
一、申请微信第三方平台:微信开放平台中第三方平台账号申请与配置
二、微信第三方平台处理基类:主要对接微信第三方平台接口,获取相应信息
<?php /** * Author: [ CopyLian ] * Date: [ 2017.02.23 ] * Email: [ copylian@aikehou.com ] * Site: [ http://www.copylian.com ] * Description [ 微信第三方平台处理类 ] */ namespace wechat; class Thirdplatform { //前缀 private $prefix = 'test_'; //接口域名 private $url = 'https://api.weixin.qq.com/cgi-bin/'; //授权地址 private $auth_url = 'https://mp.weixin.qq.com/cgi-bin/'; //获取code地址 private $requestCodeURL = 'https://open.weixin.qq.com/connect/oauth2/authorize'; //权限api的地址 private $oauthApiURL = 'https://api.weixin.qq.com/sns'; //APPID private $appid; //APPSECRET private $appsecret; //消息校验Token private $token; //消息加解密Key private $key; /** * [__construct 构造函数] */ public function __construct($prefix = '') { //前缀 $this->prefix = !empty($prefix) ? $prefix : $this->prefix; //初始化数据 $this->appid = config('thirdplatform.' . $this->prefix . 'thirdplatform_account.appid'); $this->appsecret = config('thirdplatform.' . $this->prefix . 'thirdplatform_account.appsecret'); $this->token = config('thirdplatform.' . $this->prefix . 'thirdplatform_account.token'); $this->key = config('thirdplatform.' . $this->prefix . 'thirdplatform_account.key'); } /** * [get_thirdplatform_auth 授权注册页面扫码授权:注意此URL必须放置在页面当中用户点击进行跳转,不能通过程序跳转,否则将出现“请确认授权入口页所在域名,与授权后回调页所在域名相同....”错误] * @param [type] $redirect_uri [扫码成功后的回调地址] * @param integer $auth_type [要授权的帐号类型,1-则商户扫码后,手机端仅展示公众号;2-表示仅展示小程序;3-表示公众号和小程序都展示。如果为未指定,则默认小程序和公众号都展示。第三方平台开发者可以使用本字段来控制授权的帐号类型。] * @return [type] [description] */ public function get_thirdplatform_auth($redirect_uri = '', $auth_type = 3){ //请求地址 $url = $this->auth_url . "componentloginpage?component_appid=" . $this->appid . "&pre_auth_code=" . $this->get_pre_auth_code() . "&redirect_uri=" . urlencode($redirect_uri) . "&auth_type=" . $auth_type; return $url; } /** * [get_query_auth 使用授权码获取授权信息] * @param string $auth_code [授权码, 会在授权成功时返回给第三方平台,详见第三方平台授权流程说明] */ public function get_query_auth($auth_code = ''){ //请求地址 $url = $this->url . "component/api_query_auth?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => $this->appid, "authorization_code" => $auth_code ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 return ''; } else { return $res['authorization_info']; } } /** * [get_authorizer_info 获取授权方的帐号基本信息] * @param string $auth_appid [授权方 appid] */ public function get_authorizer_info($auth_appid = ''){ //请求地址 $url = $this->url . "component/api_get_authorizer_info?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => $this->appid, "authorizer_appid" => $auth_appid ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 return []; } else { return $res; } } /** * [get_authorizer_option 获取授权方选项信息] * @param string $auth_appid [授权方 appid] * @param string $option_name [选项名称:location_report(地理位置上报选项)、voice_recognize(语音识别开关选项)、customer_service(多客服开关选项)] */ public function get_authorizer_option($auth_appid = '', $option_name = ''){ //请求地址 $url = $this->url . "component/api_get_authorizer_option?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => $this->appid, "authorizer_appid" => $auth_appid, "option_name" => $option_name ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 return []; } else { return $res; } } /** * [set_authorizer_option 设置授权方选项信息] * @param string $auth_appid [授权方 appid] * @param string $option_name [选项名称:location_report(地理位置上报选项)、voice_recognize(语音识别开关选项)、customer_service(多客服开关选项)] * @param string $option_value [选项值:location_report(0-无上报、1-进入会话时上报、2-每5s上报)、voice_recognize(0-关闭语音识别、1-开启语音识别)、customer_service(0-关闭多客服、1-开启多客服)] */ public function set_authorizer_option($auth_appid = '', $option_name = '', $option_value = 0){ //请求地址 $url = $this->url . "component/api_set_authorizer_option?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => $this->appid, "authorizer_appid" => $auth_appid, "option_name" => $option_name, "option_value" => $option_value ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 return []; } else { return $res; } } /** * [clear_quota 第三方平台 API 调用次数清零] */ public function clear_quota($component_appid = ''){ //请求地址 $url = $this->url . "component/clear_quota?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => !empty($component_appid) ? $component_appid : $this->appid ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 return []; } else { return $res; } } /** * [get_agent_thirdplatform_auth description] * @param string $appid [授权第三方平台的appid] * @param string $back_url [重定向地址URL] * @param [type] $state [重定向后会带上 state 参数,开发者可以填写任意参数值,最多 128 字节] * @param string $scope [授权作用域,拥有多个作用域用逗号(,)分隔] * @param string $code [授权code] */ public function get_agent_thirdplatform_auth($appid = '', $back_url = '', $state = null, $scope = 'snsapi_userinfo', $code = ''){ //如果不存在code,则去授权 if(!isset($code) || empty($code)){ //获取授权code $url = $this->getRequestCodeURL($appid, $back_url, $state, $scope); //返回数据 $rdata['redirect_url'] = $url; $rdata['msg'] = '获取授权CODE成功'; $rdata['code'] = 2; return $rdata; } //获取 $access_token = $this->getAccessToken($appid, 'code', $code); if(isset($access_token['errcode'])) { //当前code已经被使用过了 if($access_token['errcode'] == 40163){ $rdata['code'] = 3; $rdata['back_url'] = $back_url; $rdata['msg'] = $access_token['errmsg']; } else { $rdata['code'] = 0; $rdata['msg'] = $access_token['errmsg']; } return $rdata; } //获取用户信息,如果是:snsapi_userinfo 则获取用户完整信息,如果是静默授权 snsapi_base 则只获取openid if($scope == 'snsapi_userinfo'){ $userinfo = $this->getUserInfo($access_token); if(isset($userinfo['errcode'])) { $rdata['code'] = 0; $rdata['msg'] = $userinfo['errmsg']; return $rdata; } } else { $userinfo['openid'] = $access_token['openid']; } //设置用户信息值 $userinfo['state'] = $state; $userinfo['code'] = $code; $userinfo['back_url'] = $back_url; $userinfo['unionid'] = (isset($userinfo['unionid']) && !empty($userinfo['unionid'])) ? $userinfo['unionid'] : ''; //返回数据 $rdata['code'] = 1; $rdata['data'] = $userinfo; $rdata['msg'] = '获取用户信息成功'; return $rdata; } /** * [getRequestCodeURL 获取授权code的URL] * @param string $appid [公众号的 appid] * @param [type] $redirect_uri [重定向地址,需要 urlencode,这里填写的应是服务开发方的回调地址] * @param [type] $state [重定向后会带上 state 参数,开发者可以填写任意参数值,最多 128 字节] * @param string $scope [授权作用域,拥有多个作用域用逗号(,)分隔] */ public function getRequestCodeURL($appid = '', $redirect_uri, $state = null, $scope = 'snsapi_userinfo'){ //参数 $query = array( 'appid' => $appid, 'redirect_uri' => $redirect_uri, 'response_type' => 'code', 'scope' => $scope, 'component_appid' => $this->appid ); //处理state if(!is_null($state) && preg_match('/[a-zA-Z0-9]+/', $state)){ $query['state'] = $state; } //组装url $query = http_build_query($query); //返回url return "{$this->requestCodeURL}?{$query}#wechat_redirect"; } /** * [getAccessToken 获取access_token,用于后续接口访问] * @param string $type [description] * @param [type] $code [description] * @return [type] [description] */ public function getAccessToken($appid = '', $type = 'client', $code = null){ //组装参数 $query = array( 'appid' => $appid, 'component_appid' => $this->appid, 'component_access_token' => $this->get_component_access_token() ); //判断类型 switch ($type) { case 'client': $query['grant_type'] = 'client_credential'; $url = "{$this->url}token"; break; case 'code': $query['code'] = $code; $query['grant_type'] = 'authorization_code'; $url = "{$this->oauthApiURL}/oauth2/component/access_token"; break; } //组装url $query = http_build_query($query); $url = $url ."?". $query; //请求并返回数据 $res = $this->https_get($url); return object_to_array(json_decode($res)); } /** * 获取授权用户信息 * @param string $token acess_token * @param string $lang 指定的语言 * @return array 用户信息数据,具体参见微信文档 */ public function getUserInfo($token = [], $lang = 'zh_CN'){ //组装参数 $query = array( 'access_token' => $token['access_token'], 'openid' => $token['openid'], 'lang' => $lang, ); //组装url $url = "{$this->oauthApiURL}/userinfo"; $query = http_build_query($query); $url = $url ."?". $query; //返回数据 $res = $this->https_get($url); return object_to_array(json_decode($res)); } /** * [get_authorizer_token 获取/刷新接口调用令牌] * @param string $authorizer_appid [第三方平台 appid] * @param string $authorizer_refresh_token [授权方 appid] * @return [type] [刷新令牌,获取授权信息时得到] */ public function get_authorizer_token($authorizer_appid = '', $authorizer_refresh_token = ''){ //获取缓存 $authorizer_access_token = cache('authorizer_access_token'); //如果不存在缓存则新生成 if(empty($authorizer_access_token)){ //请求地址 $url = $this->url . "component/api_authorizer_token?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => $this->appid, "authorizer_appid" => $authorizer_appid, "authorizer_refresh_token" => $authorizer_refresh_token ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 $authorizer_access_token = []; } else { $authorizer_access_token = $res; cache('authorizer_access_token', $authorizer_access_token, 7000); } } //返回数据 return $authorizer_access_token; } /** * [getSignPackage 获取签名信息] */ public function getSignPackage($authorizer_appid = '', $ticket = '', $url = '') { //验证 if(empty($authorizer_appid) || empty($ticket)){ return []; } //票据 $jsapiTicket = $ticket; // 注意 URL 一定要动态获取,不能 hardcode. if(empty($url)){ $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; $url = "$protocol$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; } else { //被转义过的url与当前网址保持一致 $url = htmlspecialchars_decode($url); } $timestamp = time(); $nonceStr = $this->createNonceStr(); // 这里参数的顺序要按照 key 值 ASCII 码升序排序 $string = "jsapi_ticket=$jsapiTicket&noncestr=$nonceStr×tamp=$timestamp&url=$url"; $signature = sha1($string); $signPackage = array( "appId" => $authorizer_appid, "nonceStr" => $nonceStr, "timestamp" => $timestamp, "url" => $url, "signature" => $signature, "rawString" => $string ); return $signPackage; } /** * [createNonceStr 创建随机数] * @param integer $length [长度] */ public function createNonceStr($length = 16) { //随机因子 $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; //生成随机字符串 $str = ""; for ($i = 0; $i < $length; $i++) { $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1); } //返回数据 return $str; } /** * [getJsApiTicket 获取微信JS接口的临时票据] * @param string $authorizer_appid [授权authorizer_appid] */ public function getJsApiTicket($authorizer_appid = '', $authorizer_refresh_token = '') { //获取/刷新接口调用令牌 $access_token = $this->get_authorizer_token($authorizer_appid, $authorizer_refresh_token); if(empty($access_token)){ $rdata['errcode'] = 52000; $rdata['errmsg'] = '获取access_token异常'; return $rdata; } //组装参数 $query = array( 'access_token' => $access_token['authorizer_access_token'], 'type' => 'jsapi' ); //组装url $url = "{$this->url}ticket/getticket"; $query = http_build_query($query); $url = $url ."?". $query; //返回数据 $res = $this->https_get($url); return object_to_array(json_decode($res)); } /** * [decryptMsg 消息解密] */ public function decryptMsg(){ //时间戳 $timeStamp = empty($_GET['timestamp']) ? '' : trim($_GET['timestamp']); //临时数据 $nonce = empty($_GET['nonce']) ? '' : trim ($_GET['nonce']); //消息签名 $msg_sign = empty($_GET['msg_signature']) ? "" : trim($_GET['msg_signature']); //获取加密的数据 $encryptMsg = file_get_contents('php://input'); //实例化加密类 $pc = new \wechat\crypt\WXBizMsgCrypt($this->token, $this->key, $this->appid); //xml对象解析 $postArr = xml2array($encryptMsg); //格式化xml $format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%s]]></Encrypt></xml>"; $from_xml = sprintf($format, $postArr['Encrypt']); //第三方收到公众号平台发送的消息 $msg = ''; //解密 $errCode = $pc->decryptMsg($msg_sign, $timeStamp, $nonce, $from_xml, $msg); //返回数据 if($errCode == 0) { //xml对象解析 $data = xml2array($msg); return $data; } else { return []; } } /** * [response 发送消息] * @param string $msg [消息] * @param array $dataMsg [接受的原始数据] * @param array $dataMsg [消息类型] */ public function response($msg = '', $dataMsg = [], $type = 'text'){ //时间戳 $timeStamp = time(); //临时 $nonce = time(); /* 基础数据 */ $data = array( 'ToUserName' => $dataMsg['FromUserName'], 'FromUserName' => $dataMsg['ToUserName'], 'CreateTime' => $timeStamp, 'MsgType' => $type, 'Content' => $msg ); //转换数据为XML $xml = new \SimpleXMLElement('<xml></xml>'); self::data2xml($xml, $data); $xml = $xml->asXML(); //加密 $pc = new \wechat\crypt\WXBizMsgCrypt($this->token, $this->key, $this->appid); $encryptMsg = ''; $pc->encryptMsg($xml, $timeStamp, $nonce, $encryptMsg); exit($encryptMsg); } /** * [custom_send 给指定用户推送信息] * @param string $authorizer_access_token [access_token] * @param array $dataMsg [消息数据] * @param string $type [类型] */ public function custom_send($authorizer_access_token ='', $dataMsg = [], $type = 'text'){ //基础数据 $send_data = array( 'touser' => $dataMsg['FromUserName'], 'msgtype' => $type, 'text' => [ 'content' => $dataMsg['query_auth_code'] . '_from_api' ] ); //file_put_contents('4.txt', json_encode($send_data), FILE_APPEND); //编码 $send_data = urldecode(json_encode($send_data)); //组装参数 $query = array( 'access_token' => $authorizer_access_token, ); //组装url $url = "{$this->url}message/custom/send"; $query = http_build_query($query); $url = $url ."?". $query; //file_put_contents('5.txt', json_encode($url), FILE_APPEND); //返回数据 $res = $this->https_post($url, $send_data); return object_to_array(json_decode($res)); } /** * [get_user_info 获取指定用户的详细信息] * @param string $openid [openid] * @param string $lang [语言] */ public function get_user_info($authorizer_appid = '', $authorizer_refresh_token = '', $openid = '', $lang = 'zh_CN'){ //获取/刷新接口调用令牌 $access_token = $this->get_authorizer_token($authorizer_appid, $authorizer_refresh_token); if(empty($access_token)){ return []; } //组装参数 $query = array( 'access_token' => $access_token['authorizer_access_token'], 'openid' => $openid, 'lang' => $lang ); //组装url $url = "{$this->url}user/info"; $query = http_build_query($query); $url = $url ."?". $query; //返回数据 $res = $this->https_get($url); return object_to_array(json_decode($res)); } /** * 数据XML编码 * @param object $xml XML对象 * @param mixed $data 数据 * @param string $item 数字索引时的节点名称 * @return string */ protected static function data2xml($xml, $data, $item = 'item') { foreach ($data as $key => $value) { /* 指定默认的数字key */ is_numeric($key) && $key = $item; /* 添加子元素 */ if(is_array($value) || is_object($value)){ $child = $xml->addChild($key); self::data2xml($child, $value, $item); } else { if(is_numeric($value)){ $child = $xml->addChild($key, $value); } else { $child = $xml->addChild($key); $node = dom_import_simplexml($child); $cdata = $node->ownerDocument->createCDATASection($value); $node->appendChild($cdata); } } } } /** * [get_component_access_token 获取令牌:component_access_token,每个令牌是存在有效期(2小时)的,且令牌的调用不是无限制的,请第三方平台做好令牌的管理,在令牌快过期时(比如1小时50分)再进行刷新。所以要对component_access_token做好本地缓存] */ private function get_component_access_token() { //保存 component_access_token $component_access_token = cache('component_access_token'); //空的情况下生成缓存 if(empty($component_access_token)){ //令牌请求地址 $url = $this->url . "component/api_component_token"; //验证票据 component_verify_ticket $where = []; $where[] = ['id', '=', 1]; $component_verify_ticket = \Db::name('wechat_thirdplatform_ticket')->where($where)->value('ticket'); //发送数据 $data = [ "component_appid" => $this->appid, "component_appsecret" => $this->appsecret, "component_verify_ticket" => $component_verify_ticket ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 $component_access_token = ''; } else { //获取 component_access_token $component_access_token = $res['component_access_token']; //生成缓存 cache('component_access_token', $component_access_token, 6600); } } //返回数据 return $component_access_token; } /** * [get_pre_auth_code 获取预授权码] */ private function get_pre_auth_code() { //请求地址 $url = $this->url . "component/api_create_preauthcode?component_access_token=" . $this->get_component_access_token(); //发送数据 $data = [ "component_appid" => $this->appid ]; //请求并返回数据 $res = $this->https_post($url, json_encode($data)); $res = object_to_array(json_decode($res)); if(isset($res['errcode']) && $res['errcode'] != 0) { //报错,返回空 return ''; } else { return $res['pre_auth_code']; } } /** * [https_post curl处理post] * @param [type] $url [地址] * @param [type] $data [json数据] */ private function https_post($url, $data) { //初始化curl $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); if (!empty($data)){ curl_setopt($curl, CURLOPT_POST, 1); curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } //设置选项 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $output = curl_exec($curl); curl_close($curl); //返回数据 return $output; } /** * [https_get curl处理get] * @param [type] $url [地址] */ private function https_get($url) { //初始化curl $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); curl_setopt($curl, CURLOPT_HEADER, FALSE) ; curl_setopt($curl, CURLOPT_TIMEOUT,60); if (curl_errno($curl)) { return 'Errno'.curl_error($curl); } else { $result = curl_exec($curl); } curl_close($curl); //返回数据 return $result; } }
三、微信第三方平台控制器类:实例化第三方平台处理基类来实现授权消息、公众号消息事件接收、获取第三方公众号授权、代公众号发起授权(保证是有授权权限,正常是认证过的服务号或者是国家机关媒体类订阅号)、代公众号的JSSDK实现
<?php /** * Author: [ CopyLian ] * Date: [ 2017.02.23 ] * Email: [ copylian@aikehou.com ] * Site: [ http://www.copylian.com ] * Description [ 微信第三方平台控制器 ] */ namespace app\wechat\controller; use wechat\Wechat; use wechat\WechatAuth; class Thirdplatform extends Base { //第三方平台前缀 private $prefix = 'test_'; //授权公众号前缀 //private $prefix_account = 'many_'; //正式机 private $prefix_account = ''; //测试机 //红包领取地址 private $redpacket = ''; /** * [initialize 初始化] */ public function initialize() { //继承 parent::initialize(); } /** * [getauth 获取红包领取微信授权] */ public function getauth(){ if($this->request->isPost()){ //获取参数 $params = $this->request->param(); //验证地址 if(!isset($params['back_url']) || empty($params['back_url'])){ $rdata['code'] = 0; $rdata['msg'] = lang('l_back_url_error'); return $rdata; } $state = 'hltt'; //处理带参数的url $back_url = htmlspecialchars_decode($params['back_url']); //获取授权,并获取用户信息 $auth_data = $this->auth($back_url, $state, 'snsapi_base', $this->prefix_account); if($auth_data['code'] == 1){ //将数据写入数据库 $userinfo = $auth_data['data']; //返回 $rdata['code'] = 1; $rdata['data'] = $userinfo; $rdata['msg'] = lang('l_setdata_success'); //返回数据 return json($rdata); } else { return json($auth_data); } } } /** * [getSign 获取微信签名包] */ public function getSign() { //获取参数 $params = $this->request->param(); //跨域 if(isset($params['url'])){ $url = $params['url']; } else{ $url = $this->redpacket; } //设置分享数据缓存 $cache_name = md5($url); $guess_share_data = cache($cache_name); if (empty($guess_share_data)) { $guess_share_data = $this->getSignPackage($url); //设置缓存 cache($cache_name, $guess_share_data, 7200); } //微信签名包 $data['code'] = 1; $data['msg'] = lang('l_get_data_success'); $data['data'] = $guess_share_data; return json($data); } /** * [sysmessage 授权事件接收URL] */ public function sysmessage() { //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //消息解密 $data = $Thirdplatform->decryptMsg(); if(!empty($data)){ switch ($data['InfoType']) { //授权凭证 case 'component_verify_ticket': $component_verify_ticket = $data['ComponentVerifyTicket']; //票据写入数据库 $update_data = []; $update_data['id'] = 1; $update_data['ticket'] = $component_verify_ticket; $update_data['update_time'] = date("Y-m-d H:i:s"); \Db::name('wechat_thirdplatform_ticket')->update($update_data); //返回成功消息 echo 'success'; break; //取消授权 case 'unauthorized': //查询数据是否存在 if(isset($data['AppId']) && isset($data['AuthorizerAppid'])){ $where = []; $where[] = ['appid', '=', $data['AppId']]; $where[] = ['authorizer_appid', '=', $data['AuthorizerAppid']]; $thirdplatform = \Db::name('wechat_thirdplatform')->field('id')->where($where)->find(); if(!empty($thirdplatform)){ //更新授权状态为-1 $update_data = []; $update_data['id'] = $thirdplatform['id']; $update_data['status'] = -1; $update_data['update_time'] = date("Y-m-d H:i:s"); \Db::name('wechat_thirdplatform')->update($update_data); } } break; //授权 case 'authorized': //无操作 break; //更新授权 case 'updateauthorized': //查询数据是否存在 if(isset($data['AppId']) && isset($data['AuthorizerAppid'])){ $where = []; $where[] = ['appid', '=', $data['AppId']]; $where[] = ['authorizer_appid', '=', $data['AuthorizerAppid']]; $thirdplatform = \Db::name('wechat_thirdplatform')->field('id')->where($where)->find(); if(!empty($thirdplatform)){ //更新授权次数 $update_data = []; $update_data['id'] = $thirdplatform['id']; $update_data['auth_count'] = \Db::raw('auth_count+1'); $update_data['update_time'] = date("Y-m-d H:i:s"); \Db::name('wechat_thirdplatform')->update($update_data); } } break; } } } /** * [eventmsg 消息与事件接收URL] */ public function eventmsg() { //获取参数 $params = $this->request->param(); if(!isset($params['appid']) || empty($params['appid'])){ exit(); } //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //消息解密 $data = $Thirdplatform->decryptMsg(); //file_put_contents('0.txt', json_encode($data), FILE_APPEND); //处理消息事件 if(!empty($data)){ //第三方平台全网审核发布模拟测试普通消息 if($data['MsgType'] == 'text' && isset($data['Content']) && $data['Content'] == 'TESTCOMPONENT_MSG_TYPE_TEXT'){ $Thirdplatform->response('TESTCOMPONENT_MSG_TYPE_TEXT_callback', $data); } //第三方平台全网审核发布模拟测试Api消息 if($data['MsgType'] == 'text' && isset($data['Content']) && preg_match('/QUERY_AUTH_CODE:/', $data['Content'])){ //获得模拟的auth_code $query_auth_code = str_replace("QUERY_AUTH_CODE:", "", $data['Content']); //file_put_contents('1.txt', json_encode($query_auth_code), FILE_APPEND); //通过code获取授权信息 $auth_code_info = $Thirdplatform->get_query_auth($query_auth_code); //file_put_contents('2.txt', json_encode($auth_code_info), FILE_APPEND); //发送客服消息 $data['query_auth_code'] = $query_auth_code; //file_put_contents('3.txt', json_encode($data), FILE_APPEND); $res = $Thirdplatform->custom_send($auth_code_info['authorizer_access_token'], $data); //file_put_contents('6.txt', json_encode($res), FILE_APPEND); exit(); } //1、查询当前授权appid的信息,确认是否已授权 $where = []; $where[] = ['authorizer_appid', '=', $params['appid']]; $where[] = ['status', '=', 1]; //已授权 $platform = \Db::name('wechat_thirdplatform')->field('id,appid,authorizer_appid,func_info,authorizer_info')->where($where)->findOrEmpty(); //file_put_contents('1.txt', json_encode($platform), FILE_APPEND); if(empty($platform)){ exit(); } //解析授权信息 if(!empty($platform['authorizer_info'])){ $platform['authorizer_info'] = json_decode($platform['authorizer_info'], true); } //2、验证是否有消息管理权限 if(empty($platform['func_info'])){ exit(); } //解析权限,参考:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/api/func_info.html $func_info = json_decode($platform['func_info'], true); //file_put_contents('2.txt', json_encode($func_info), FILE_APPEND); //验证权限集ID为1的消息管理权限 if(!in_array(1, $func_info)){ exit(); } //3、查询是否开通付费了权限功能 $now_time = date("Y-m-d H:i:s"); $where = []; $where[] = ['platform_id', '=', $platform['id']]; $where[] = ['start_time', '< time', $now_time]; //时间范围内 $where[] = ['end_time', '>= time', $now_time]; //时间范围内 $platform_access = \Db::name('wechat_thirdplatform_access')->where($where)->column('fun_id'); //file_put_contents('3.txt', json_encode($platform_access), FILE_APPEND); if(empty($platform_access)){ exit(); } //处理事件类型 switch ($data['MsgType']) { case 'text': //验证是否开通了口令红包(fun_id = 1)功能权限 if(in_array(1, $platform_access)){ //1、查询是否开通付费了权限功能:验证是否开通了口令红包(fun_id = 1)功能权限 $now_time = date("Y-m-d H:i:s"); $where = []; $where[] = ['platform_id', '=', $platform['id']]; $where[] = ['fun_id', '=', 1]; //口令红包(fun_id = 1) $where[] = ['start_time', '< time', $now_time]; //时间范围内 $where[] = ['end_time', '>= time', $now_time]; //时间范围内 $platform_access_red = \Db::name('wechat_thirdplatform_access')->field('id,config,start_time,end_time')->where($where)->find(); //file_put_contents('4.txt', json_encode($platform_access_red), FILE_APPEND); if(empty($platform_access_red)){ exit(); } //2、处理红包口令功能配置信息 if(empty($platform_access_red['config'])){ exit(); } $platform_access_red_config = json_decode($platform_access_red['config'], true); //file_put_contents('5.txt', $platform_access_red['config'], FILE_APPEND); //3、判断活动的开关是否已开 if($platform_access_red_config['open'] != 1){ //开关未开启 exit(); } //4、查询口令码 $where = []; $where[] = ['platform_id', '=', $platform['id']]; //当前平台 $where[] = ['code', '=', $data['Content']]; //$where[] = ['status', '=', 1]; //已发放 $code = \Db::name('wechat_thirdplatform_p'.$platform['id'].'_redpackets_code')->field('id,code,money,status,platform_id')->where($where)->findOrEmpty(); //file_put_contents('6.txt', json_encode($code), FILE_APPEND); if(empty($code)){ //未查到口令码 exit(); } //状态(0-未发放,1-已发放,2-已领取) if($code['status'] != 1){ $Thirdplatform->response('此红包已经被领取或已失效', $data); } //5、单个用户最多领取次数,在服务期限内有效,0表示不限制 if($platform_access_red_config['limit_receive_num'] > 0){ //查询某个用户领取的次数 $where = []; $where[] = ['platform_id', '=', $platform['id']]; //当前平台 $where[] = ['platform_openid', '=', $data['FromUserName']]; //第三方授权平台公众号的openid $where[] = ['status', '=', 2]; //已领取 //限制在多少天内限制最大领取次数,在服务期限内有效,0表示不限制。 if($platform_access_red_config['limit_days'] > 0){ //判断周期类型:1-几天内,领取时间点到点;2-隔天几天,0点初始化 if($platform_access_red_config['limit_days_type'] == 1){ //几天内,领取时间点到点:time() - N * 24*60*60 $start_date = date("Y-m-d H:i:s", time() - $platform_access_red_config['limit_days']*24*60*60); $end_date = date("Y-m-d H:i:s"); $where[] = ['receive_time', 'between time', [$start_date, $end_date]]; //时间范围内 } else if($platform_access_red_config['limit_days_type'] == 2){ //隔天几天,0点初始化:strtotime(date("Y-m-d 23:59:59")) - N * 24*60*60 $start_date = date("Y-m-d H:i:s", strtotime(date("Y-m-d 23:59:59")) - $platform_access_red_config['limit_days']*24*60*60); $end_date = date("Y-m-d 23:59:59"); $where[] = ['receive_time', 'between time', [$start_date, $end_date]]; //时间范围内 } } else { //为限制时间则表示在有效期内 $where[] = ['receive_time', 'between time', [$platform_access_red['start_time'], $platform_access_red['end_time']]]; //时间范围内 } //file_put_contents('7.txt', json_encode($where), FILE_APPEND); //统计领取次数 $count_ids = \Db::name('wechat_thirdplatform_p'.$platform['id'].'_redpackets_code')->where($where)->count('id'); //file_put_contents('8.txt', json_encode($count_ids), FILE_APPEND); if($count_ids >= $platform_access_red_config['limit_receive_num']){ //file_put_contents('9.txt', json_encode($count_ids), FILE_APPEND); $Thirdplatform->response('您已经领取达到最大次数了,感谢您的支持!', $data); } } //组装加密的串 $kldata = [ 'id' => $code['id'], 'code' => $code['code'], 'platform_id' => $code['platform_id'], 'openid' => $data['FromUserName'] //第三方授权平台公众号用户的openid ]; $klkey = encode(json_encode($kldata)); //file_put_contents('10.txt', $klkey, FILE_APPEND); //网页版授权 //$Thirdplatform->response($this->redpacket . "?klkey=" . $klkey, $data); $Thirdplatform->response('恭喜获得:'.$code['money'].' 元红包,<a href="' . $this->redpacket . "?klkey=" . $klkey .'">点击领取</a>。', $data); //服务器端授权 //$Thirdplatform->response(url('redpacket', ['klkey' => $klkey], false, true), $data); //$Thirdplatform->response('恭喜获得:'.$code['money'].' 元红包,<a href="' . url('redpacket', ['klkey' => $klkey], false, true) . '">点击领取</a>。', $data); } else if(in_array(2, $platform_access)){ //验证是否开通了关键词红包(fun_id = 2)功能权限 exit(); } break; case 'event': switch ($data['Event']) { case 'subscribe': //处理关注业务逻辑 //通过openid拉取用户信息 $userinfo = $Thirdplatform->get_user_info($platform['authorizer_appid'], $platform['authorizer_info']['authorization_info']['authorizer_refresh_token'], $data['FromUserName']); //file_put_contents('11.txt', json_encode($userInfo), FILE_APPEND); //拉取信息成功则处理逻辑 if(!empty($userinfo) && isset($userinfo['openid'])){ //存在则更新,不存在则新增 //查询是否以及存在记录 $where = []; $where[] = ['openid', '=', $userinfo['openid']]; $subscribe_user = \Db::name('wechat_thirdplatform_p'.$platform['id'].'_subscribe_user')->field('id,openid')->where($where)->findOrEmpty(); if(!empty($subscribe_user)){ //存在则更新 $update_data = []; $update_data['id'] = $subscribe_user['id']; $update_data['platform_id'] = $platform['id']; $update_data['unionid'] = isset($userinfo['unionid']) ? $userinfo['unionid'] : ''; $update_data['nickname'] = $userinfo['nickname']; $update_data['sex'] = $userinfo['sex']; $update_data['country'] = $userinfo['country']; $update_data['province'] = $userinfo['province']; $update_data['city'] = $userinfo['city']; $update_data['headimgurl'] = $userinfo['headimgurl']; $update_data['userinfo'] = json_encode($userinfo); $update_data['subscribe_count'] = \Db::raw('subscribe_count + 1'); $update_data['subscribe_last_ip'] = $this->request->ip(); $update_data['subscribe_status'] = 1; //已关注 $update_data['subscribe_time'] = date("Y-m-d H:i:s"); //关注时间 $update_data['update_time'] = date("Y-m-d H:i:s"); //更新 \Db::name('wechat_thirdplatform_p'.$platform['id'].'_subscribe_user')->strict(false)->update($update_data); } else { //不能存在则新增 $add_data = []; $add_data['platform_id'] = $platform['id']; $add_data['unionid'] = isset($userinfo['unionid']) ? $userinfo['unionid'] : ''; $add_data['openid'] = $userinfo['openid']; $add_data['nickname'] = $userinfo['nickname']; $add_data['sex'] = $userinfo['sex']; $add_data['country'] = $userinfo['country']; $add_data['province'] = $userinfo['province']; $add_data['city'] = $userinfo['city']; $add_data['headimgurl'] = $userinfo['headimgurl']; $add_data['userinfo'] = json_encode($userinfo); $add_data['subscribe_count'] = \Db::raw('subscribe_count + 1'); $add_data['subscribe_last_ip'] = $this->request->ip(); $add_data['subscribe_status'] = 1; //已关注 $add_data['subscribe_time'] = date("Y-m-d H:i:s"); //关注时间 //写入 \Db::name('wechat_thirdplatform_p'.$platform['id'].'_subscribe_user')->strict(false)->insert($add_data); } } break; case 'unsubscribe': //处理取消关注业务逻辑 //存在则更新,不存在则跳过 //查询是否以及存在记录 $where = []; $where[] = ['openid', '=', $data['FromUserName']]; $subscribe_user = \Db::name('wechat_thirdplatform_p'.$platform['id'].'_subscribe_user')->field('id,openid')->where($where)->findOrEmpty(); if(!empty($subscribe_user)){ //存在则更新 $update_data = []; $update_data['id'] = $subscribe_user['id']; $update_data['subscribe_status'] = 0; //未关注 $update_data['unsubscribe_count'] = \Db::raw('unsubscribe_count + 1'); $update_data['unsubscribe_last_ip'] = $this->request->ip(); $update_data['unsubscribe_time'] = date("Y-m-d H:i:s"); //取消关注时间 $update_data['update_time'] = date("Y-m-d H:i:s"); //更新 \Db::name('wechat_thirdplatform_p'.$platform['id'].'_subscribe_user')->strict(false)->update($update_data); } //file_put_contents('12.txt', json_encode($data), FILE_APPEND); break; case 'CLICK': //点击事件 //echo 'success'; break; } break; } } } /** * [get_thirdplatform_auth:获取平台授权地址] */ public function get_thirdplatform_auth() { //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //获取授权地址 $url = $Thirdplatform->get_thirdplatform_auth(url("auth_callback", [], '', true), 1); //赋值 $this->assign('url', $url); //生成授权页面 return $this->fetch(); } /** * [auth_callback 授权回调] */ public function auth_callback() { //获取参数 $params = $this->request->param(); //验证是否存在auth_code if(!isset($params['auth_code'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '授权异常'; return json($rdata); } //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //授权码获取授权信息 $auth_code_info = $Thirdplatform->get_query_auth($params['auth_code']); if(empty($auth_code_info) || !isset($auth_code_info['authorizer_appid'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '授权信息异常'; return json($rdata); } //通过授权方appid 获取授权方的帐号基本信息 $auth_info = $Thirdplatform->get_authorizer_info($auth_code_info['authorizer_appid']); if(empty($auth_info) || !isset($auth_info['authorizer_info']) || !isset($auth_info['authorization_info'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '授权方的帐号基本信息异常'; return json($rdata); } //写入数据 $add_data = []; //第三方平台appid $add_data['appid'] = config('thirdplatform.' . $this->prefix . 'thirdplatform_account.appid'); //授权方appid $add_data['authorizer_appid'] = $auth_info['authorization_info']['authorizer_appid']; //昵称 $add_data['nick_name'] = $auth_info['authorizer_info']['nick_name']; //头像 $add_data['head_img'] = $auth_info['authorizer_info']['head_img']; //公众号类型(-1-未知,0-订阅号,1-由历史老帐号升级后的订阅号,2-服务号公众号认证类型) $add_data['service_type_info'] = $auth_info['authorizer_info']['service_type_info']['id']; //公众号认证类型(-1-未认证,0-微信认证,1-新浪微博认证,2-腾讯微博认证,3-已资质认证通过但还未通过名称认证,4-已资质认证通过、还未通过名称认证,但通过了新浪微博认证,5-已资质认证通过、还未通过名称认证,但通过了腾讯微博认证) $add_data['verify_type_info'] = $auth_info['authorizer_info']['verify_type_info']['id']; //原始ID $add_data['user_name'] = $auth_info['authorizer_info']['user_name']; //主体名称 $add_data['principal_name'] = $auth_info['authorizer_info']['principal_name']; //公众号所设置的微信号,可能为空 $add_data['alias'] = $auth_info['authorizer_info']['alias']; //用以了解功能的开通状况(0-代表未开通,1-代表已开通) $add_data['business_info'] = json_encode($auth_info['authorizer_info']['business_info']); //二维码图片的URL,开发者最好自行也进行保存 $add_data['qrcode_url'] = $auth_info['authorizer_info']['qrcode_url']; //授权方的帐号基本信息 $add_data['authorizer_info'] = json_encode($auth_info); //授权给开发者的权限集列表 $func_info_list = []; $func_info = $auth_info['authorization_info']['func_info']; if(!empty($func_info)){ foreach ($func_info as $key => $value) { $func_info_list[$key] = $value['funcscope_category']['id']; } } $add_data['func_info'] = json_encode($func_info_list); //设置为已授权 $add_data['status'] = 1; //如果存在则更新,不存在这新增 $where = []; $where[] = ['authorizer_appid', '=', $auth_info['authorization_info']['authorizer_appid']]; $thirdplatform_id = \Db::name('wechat_thirdplatform')->where($where)->value('id'); if(!isset($thirdplatform_id) || empty($thirdplatform_id) || $thirdplatform_id <= 0){ //新增 $res = \Db::name('wechat_thirdplatform')->insert($add_data); } else { //更新 $add_data['id'] = $thirdplatform_id; $add_data['update_time'] = date("Y-m-d H:i:s"); $res = \Db::name('wechat_thirdplatform')->update($add_data); } //返回数据 if($res){ //跳转到授权结果页面 return redirect('auth_result', ['code' => 1]); } else { //跳转到授权结果页面 return redirect('auth_result', ['code' => 0]); } } /** * [auth_result 授权结果页面] */ public function auth_result() { //获取参数 $params = $this->request->param(); //设置授权信息 $res_msg = isset($params['code']) && $params['code'] == 1 ? '授权成功' : '授权失败'; //返回数据 $data['code'] = $params['code']; $data['msg'] = $res_msg; //赋值 $this->assign('data', $data); //渲染 return $this->fetch(); } /** * [get_authorizer_option 获取授权方选项信息] */ public function get_authorizer_option() { //获取测试授权平台信息 $where = []; $where[] = ['id', '=', 1]; $platform_info = \Db::name('wechat_thirdplatform')->where($where)->find(); //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //获取授权方选项信息 $data = $Thirdplatform->get_authorizer_option($platform_info['authorizer_appid'], 'voice_recognize'); p($data); } /** * [set_authorizer_option 获取授权方选项信息] */ public function set_authorizer_option() { //获取测试授权平台信息 $where = []; $where[] = ['id', '=', 1]; $platform_info = \Db::name('wechat_thirdplatform')->where($where)->find(); //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //获取授权方选项信息 $data = $Thirdplatform->set_authorizer_option($platform_info['authorizer_appid'], 'location_report', 2); p($data); } /** * [clear_quota 第三方平台调用次数清零] */ public function clear_quota() { //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //获取授权方选项信息 $data = $Thirdplatform->clear_quota(); p($data); } /** * [redpacket 红包领取页面:如果出现微信授权错误,可能是当前公众号没有配置当前域名] */ public function redpacket() { //获取参数 $params = $this->request->param(); if(!isset($params['klkey']) || empty($params['klkey'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '参数异常'; return json($rdata); } $kldata = json_decode(decode($params['klkey']), true); //默认带参数state $state = "redpacket_".$kldata['platform_id']; //处理带参数的url $back_url = url("redpacket", ["klkey" => $params['klkey']], false, true); //获取授权,并获取用户信息 $auth_data = $this->auth($back_url, $state, 'snsapi_base', $this->prefix_account); if($auth_data['code'] == 1){ //将数据写入数据库 $userinfo = $auth_data['data']; //请求红包接口获取红包信息并返回数据 //发送数据 $send_data = [ "klkey" => $params['klkey'], "openid" => $userinfo['openid'] //领取红包openid(支付公众号用户授权的openid) ]; $result = gethttp(url("get_red_packet", [], false, true), [], json_encode($send_data), "POST"); //赋值 $this->assign('data', json_decode($result, true)); //渲染模板 return $this->fetch(); } else if($auth_data['code'] == 2) { //去授权跳转 return redirect($auth_data['redirect_url']); } else if($auth_data['code'] == 3){ //授权code错误,请重新授权 return redirect($auth_data['back_url']); } else { //返回数据 $rdata['code'] = 0; $rdata['msg'] = '授权错误'; return json($rdata); } } /** * [get_red_packet 领取红包] */ public function get_red_packet() { //获取参数 $params = $this->request->param(); //验证参数 if(!isset($params['klkey']) || empty($params['klkey']) || !isset($params['openid']) || empty($params['openid'])) { //返回数据 $rdata['code'] = 0; $rdata['msg'] = '红包已领取或已过期'; return json($rdata); } //解密 $kldata = json_decode(decode($params['klkey']), true); //p($kldata); if(!isset($kldata['id']) || !isset($kldata['code']) || !isset($kldata['platform_id'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '红包已领取或已过期'; return json($rdata); } //查询授权平台信息 //1、查询当前授权appid的信息,确认是否已授权 $where = []; $where[] = ['id', '=', $kldata['platform_id']]; $where[] = ['status', '=', 1]; //已授权 $platform = \Db::name('wechat_thirdplatform')->field('id,appid,authorizer_appid,nick_name,head_img,func_info')->where($where)->findOrEmpty(); //p($platform); if(empty($platform)){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '公众号未授权'; return json($rdata); } //2、查询是否开通付费了权限功能:验证是否开通了口令红包(fun_id = 1)功能权限 $now_time = date("Y-m-d H:i:s"); $where = []; $where[] = ['platform_id', '=', $platform['id']]; $where[] = ['fun_id', '=', 1]; //口令红包(fun_id = 1) $where[] = ['start_time', '< time', $now_time]; //时间范围内 $where[] = ['end_time', '>= time', $now_time]; //时间范围内 $platform_access = \Db::name('wechat_thirdplatform_access')->field('id,config')->where($where)->find(); if(empty($platform_access)){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '未开通服务'; return json($rdata); } //3、处理红包口令功能配置信息 if(!empty($platform_access['config'])){ $platform_access['config'] = json_decode($platform_access['config'], true); } //p($platform_access); //设置背景图 $bg_img = isset($platform_access['config']['bg_img'][0]['photo']) && !empty($platform_access['config']['bg_img'][0]['photo']) ? $this->request->domain() . $platform_access['config']['bg_img'][0]['photo'] : ''; //4、查询红包信息 $where = []; $where[] = ['platform_id', '=', $kldata['platform_id']]; //当前平台 $where[] = ['code', '=', $kldata['code']]; $where[] = ['id', '=', $kldata['id']]; $where[] = ['status', '=', 1]; //已发放 $data = \Db::name('wechat_thirdplatform_p'.$platform['id'].'_redpackets_code')->where($where)->findOrEmpty(); //p($data); if(empty($data)){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '红包已领取或已过期'; return json($rdata); } //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //红包发送方式 $sen_type = isset($platform_access['config']['type']) && in_array($platform_access['config']['type'], [1, 2]) ? $platform_access['config']['type'] : 1; //企业支付到零钱 if($sen_type == 1){ //订单编号 $order_sn = create_order_sn(1, "hbkl".$platform['id']); //发送数据 $send_data = [ 'amount' => $data['money'] * 100, //单位分 'openid' => $params['openid'], 'order_sn' => $order_sn, 'desc' => $platform['nick_name']."的红包", 'check_name' => 'NO_CHECK', //NO_CHECK:不校验真实姓名、FORCE_CHECK:强校验真实姓名 're_user_name' => '', //收款用户真实姓名,如果check_name设置为FORCE_CHECK,则必填用户真实姓名 ]; //p($send_data); //exit(); //返回结果 $res = $WechatMmpaymk->sendMoneyToChange($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ //支付成功请修改红包口令码状态为已领取 $update_data = []; $update_data['id'] = $data['id']; $update_data['status'] = 2; //已发放 $update_data['platform_openid'] = $kldata['openid']; //第三方授权平台公众号用户的openid $update_data['order_sn'] = $order_sn; //订单编号 $update_data['receive_openid'] = $params['openid']; //领取红包openid(支付公众号用户授权的openid) $update_data['receive_ip'] = $this->request->ip(); //领取IP $update_data['receive_time'] = date("Y-m-d H:i:s"); //领取时间 $update_data['update_time'] = date("Y-m-d H:i:s"); \Db::name('wechat_thirdplatform_p'.$platform['id'].'_redpackets_code')->update($update_data); //返回数据 $rdata['code'] = 1; $rdata['msg'] = '支付成功'; $rdata['data'] = $res['data']; $rdata['redpacket_data'] = ['code' => $kldata['code'], 'money' => $data['money'], 'head_img' => $platform['head_img'], 'bg_img' => $bg_img]; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } else if($sen_type == 2){ //发红包 //订单编号 $order_sn = create_order_sn(1, "hbkl".$platform['id']); //发送数据 $send_data = [ 'amount' => $data['money'] * 100, //单位分 'openid' => $params['openid'], 'order_sn' => $order_sn, 'act_name' => isset($platform_access['config']['act_name']) ? $platform_access['config']['act_name'] : $platform['nick_name']."的红包", //活动名称 'send_name' => $platform['nick_name'],//红包发送者名称 'wishing' => isset($platform_access['config']['wishing']) ? $platform_access['config']['wishing'] : "恭喜发财", //红包祝福语 'remark' => isset($platform_access['config']['remark']) ? $platform_access['config']['remark'] : "抢到红包了,恭喜发财!" //备注 ]; //p($send_data); //exit(); //返回结果 $res = $WechatMmpaymk->redPacketPay($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ //支付成功请修改红包口令码状态为已领取 $update_data = []; $update_data['id'] = $data['id']; $update_data['status'] = 2; //已发放 $update_data['platform_openid'] = $kldata['openid']; //第三方授权平台公众号用户的openid $update_data['order_sn'] = $order_sn; //订单编号 $update_data['receive_openid'] = $params['openid']; //领取红包openid(支付公众号用户授权的openid) $update_data['receive_ip'] = $this->request->ip(); //领取IP $update_data['receive_time'] = date("Y-m-d H:i:s"); //领取时间 $update_data['update_time'] = date("Y-m-d H:i:s"); \Db::name('wechat_thirdplatform_p'.$platform['id'].'_redpackets_code')->update($update_data); //返回数据 $rdata['code'] = 1; $rdata['msg'] = '支付成功'; $rdata['data'] = $res['data']; $rdata['redpacket_data'] = ['code' => $kldata['code'], 'money' => $data['money'], 'head_img' => $platform['head_img'], 'bg_img' => $bg_img]; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } } /** * [agent_thirdplatform_auth 第三方平台代理公众号发起授权] * @param integer $platform_id [平台ID] * @param string $state [重定向后会带上 state 参数,也是做活动参数使用] * @param string $back_url [重定向地址,需要 urlencode,这里填写的应是服务开发方的回调地址] * @param string $scope [授权作用域,拥有多个作用域用逗号(,)分隔,snsapi_userinfo、snsapi_base] * @param string $code [跳转回来的返回码] * @return [type] [description] */ public function agent_thirdplatform_auth($platform_id = 0, $state = 'test', $back_url = '', $scope = 'snsapi_userinfo', $code = ''){ //验证平台ID参数 if($platform_id <= 0){ $rdata['code'] = 0; $rdata['msg'] = '平台不存在'; return json($rdata); } //验证地址 if(!isset($back_url) || empty($back_url)){ $rdata['code'] = 0; $rdata['msg'] = '重定向地址URL错误'; return json($rdata); } //处理带参数的url $back_url = htmlspecialchars_decode($back_url); //1、查询授权平台信息 $where = []; $where[] = ['id', '=', $platform_id]; $where[] = ['status', '=', 1]; //已授权 $platform = \Db::name('wechat_thirdplatform')->field('id,appid,authorizer_appid,nick_name,head_img,func_info')->where($where)->findOrEmpty(); if(empty($platform)){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '公众号未授权'; return json($rdata); } //2、验证是否有权限 if(empty($platform['func_info'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '公众号授权第三方平台权限'; return json($rdata); } //3、解析权限,参考:https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/api/func_info.html $func_info = json_decode($platform['func_info'], true); if(!in_array(4, $func_info)){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '公众号授权第三方平台权限'; return json($rdata); } //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //获取授权 $auth_data = $Thirdplatform->get_agent_thirdplatform_auth($platform['authorizer_appid'], $back_url, $state, $scope, $code); if($auth_data['code'] == 1){ //将数据写入数据库 $userinfo = $auth_data['data']; $data = $userinfo; $data['userinfo'] = json_encode($userinfo); $data['state'] = $state; //查询是否以及存在记录 $table_name = 'wechat_thirdplatform_p'.$platform['id'].'_'.$state.'_user'; $where = []; $where[] = ['openid', '=', $userinfo['openid']]; $user = \Db::name($table_name)->where($where)->find(); //写入数据 $data['count'] = \Db::raw('count+1'); if(!$user){ //添加 $res = \Db::name($table_name)->strict(false)->insert($data); } else { $data['id'] = $user['id']; $data['update_time'] = date("Y-m-d H:i:s"); $res = \Db::name($table_name)->strict(false)->update($data); } //处理头像跨域 if(isset($userinfo['headimgurl']) && !empty($userinfo['headimgurl'])){ $userinfo['headimgurl'] = url('base/getRouteImg',['url'=>encode($userinfo['headimgurl'])],false,true); } //返回 if($res){ $rdata['code'] = 1; $rdata['data'] = $userinfo; $rdata['msg'] = '获取用户信息成功'; } else { $rdata['code'] = 0; $rdata['msg'] = '获取用户信息失败'; } //返回数据 return json($rdata); } else { return json($auth_data); } } /** * [getSignPackage 获取签名] */ public function getSignPackage($platform_id = 0, $url = ''){ //验证平台ID参数 if($platform_id <= 0){ $rdata['code'] = 0; $rdata['msg'] = '平台不存在'; return json($rdata); } //验证地址 if(!isset($url) || empty($url)){ $rdata['code'] = 0; $rdata['msg'] = 'url错误'; return json($rdata); } //1、查询授权平台信息 $where = []; $where[] = ['id', '=', $platform_id]; $where[] = ['status', '=', 1]; //已授权 $platform = \Db::name('wechat_thirdplatform')->field('id,appid,authorizer_appid,nick_name,head_img,func_info,authorizer_info')->where($where)->findOrEmpty(); if(empty($platform)){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = '公众号未授权'; return json($rdata); } //解析授权信息 if(!empty($platform['authorizer_info'])){ $platform['authorizer_info'] = json_decode($platform['authorizer_info'], true); } //实例化第三方平台类 $Thirdplatform = new \wechat\Thirdplatform($this->prefix); //获取零时票据 $ticket = $Thirdplatform->getJsApiTicket($platform['authorizer_appid'], $platform['authorizer_info']['authorization_info']['authorizer_refresh_token']); if($ticket['errcode'] != 0 && !isset($ticket['ticket'])){ //返回数据 $rdata['code'] = 0; $rdata['msg'] = $ticket['errmsg']; return json($rdata); } //获取signPackage签名信息 return $Thirdplatform->getSignPackage($platform['authorizer_appid'], $ticket['ticket'], $url); } }
四、授权签名测试类:测试授权公众号的授权功能、测试授权公众号的JSSDK功能
<?php /** * Author: [ CopyLian ] * Date: [ 2017.02.23 ] * Email: [ copylian@aikehou.com ] * Site: [ http://www.copylian.com ] * Description [ 测试接口控制器 ] */ namespace app\wechat\controller; use wechat\Wechat; use wechat\WechatAuth; class Test extends Base{ //授权公众号前缀 //private $prefix_account = 'many_'; //正式机 private $prefix_account = ''; //测试机 /** * [initialize 初始化] */ public function initialize(){ parent::initialize(); } /** * [auth 测试第三方平台授权] */ public function getauth(){ if($this->request->isPost()){ //获取参数 $params = $this->request->param(); //验证地址 if(!isset($params['back_url']) || empty($params['back_url'])){ $rdata['code'] = 0; $rdata['msg'] = lang('l_back_url_error'); return $rdata; } //平台ID $platform_id = 2; //平台ID $state = 'test'; //重定向后会带上 state 参数、平台活动名称 //$scope = 'snsapi_userinfo'; //授权作用域:snsapi_userinfo、snsapi_base $scope = 'snsapi_base'; //授权作用域:snsapi_userinfo、snsapi_base $back_url = $params['back_url']; //重定向URL $code = isset($params['code']) ? $params['code'] : ''; //执行第三方的授权 $Thirdplatform = new \app\wechat\controller\Thirdplatform(); $data = $Thirdplatform->agent_thirdplatform_auth($platform_id, $state, $back_url, $scope, $code); return $data; } } /** * [getSign 测试第三方平台获取微信签名包] */ public function getSign() { //获取参数 $params = $this->request->param(); //跨域 if(isset($params['url'])){ $url = $params['url']; } else{ $url = 'https://h5test.ponyfamily.cn/wechat/index.html'; } //设置分享数据缓存 $cache_name = md5($url); $share_data = cache($cache_name); if(empty($share_data)){ //平台ID $platform_id = 2; //平台ID $code = isset($params['code']) ? $params['code'] : ''; //执行第三方的授权 $Thirdplatform = new \app\wechat\controller\Thirdplatform(); $share_data = $Thirdplatform->getSignPackage($platform_id, $url); //设置缓存 cache($cache_name, $share_data, 7200); } //微信签名包 $data['code'] = 1; $data['msg'] = lang('l_get_data_success'); $data['data'] = $share_data; return json($data); } /** * [changePay 企业付款到零钱] */ public function changePay() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'amount' => 60, //单位分 'openid' => 'oHL30wVEuI58Lgp8dkQmSSW4dU4g', 'order_sn' => create_order_sn(1, "qylq"), 'desc' => '企业付款到零钱', 'check_name' => 'NO_CHECK', //NO_CHECK:不校验真实姓名、FORCE_CHECK:强校验真实姓名 're_user_name' => '', //收款用户真实姓名,如果check_name设置为FORCE_CHECK,则必填用户真实姓名 ]; //返回结果 $res = $WechatMmpaymk->sendMoneyToChange($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '支付成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } /** * [queryChangePay 查询企业付款到零钱] */ public function queryChangePay() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'order_sn' => 'qylq00807115204001340' ]; //返回结果 $res = $WechatMmpaymk->queryChange($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '查询成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } /** * [redPacketPay 发送红包] */ public function redPacketPay() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'amount' => 30, //单位分 'openid' => 'oHL30wVEuI58Lgp8dkQmSSW4dU4g', 'order_sn' => create_order_sn(1, "qylq") ]; //返回结果 $res = $WechatMmpaymk->redPacketPay($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '支付成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } /** * [queryRedPacket 查询现金红包] */ public function queryRedPacket() { //1、获取红包链接 //实例化 $WechatMmpaymk = new \wechat\WechatMmpaymk($this->prefix_account); //发送数据 $send_data = [ 'order_sn' => 'qylq00807151840001406' ]; //返回结果 $res = $WechatMmpaymk->queryRedPacket($send_data); if($res['code'] == 0){ $rdata['code'] = 0; $rdata['msg'] = $res['msg']; return json($rdata); } else if($res['code'] == 1){ if($res['data']['return_code'] == 'SUCCESS' && $res['data']['result_code'] == 'SUCCESS'){ $rdata['code'] = 1; $rdata['msg'] = '查询成功'; $rdata['data'] = $res['data']; return json($rdata); } else { $rdata['code'] = 0; $rdata['msg'] = $res['data']['err_code_des']; $rdata['data'] = $res['data']; return json($rdata); } } } }
五、全网发布与检测:微信第三方平台全网发布返回Api、普通文本信息失败解决方案
总结:微信第三方平台很多,这类系统也很多,如:微擎、有赞等,如果时间充裕确实可以自己搞一搞,虽然微信第三方平台的接口有些很蛋疼,但是总归还是能实现,多积攒点经验。
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!
文明上网理性发言!