技术饭
微信开放平台中第三方平台api接口的对接与实现
copylian
0 评论
24416 浏览
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、普通文本信息失败解决方案
总结:微信第三方平台很多,这类系统也很多,如:微擎、有赞等,如果时间充裕确实可以自己搞一搞,虽然微信第三方平台的接口有些很蛋疼,但是总归还是能实现,多积攒点经验。
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!
文明上网理性发言!