介绍
在做微信开放平台第三方应用开发的时候,每次都要登录到微信开放平台中操作,如果多了的话,很不方便,所以想到集成到自己后台操作,这样就可以同时管理n个开放平台里面的n个第三方应用了。
犹豫代码涉及逻辑会比较复杂,所以只提取了相关部分。
步骤
获取cookie和token
在操作第三方之前,需要获取token和cookie,获取方式如下代码:
<?php
namespace App\Utils\Wx;
use App\Models\WxOpen;
use EasyWeChat\Factory;
use Illuminate\Support\Facades\Cache;
/**
* Description:
* Class WxOpenUtils
* User: Vijay <1937832819@qq.com>
* Site: https://www.choudalao.com/
* Date: 2022/1/11
* Time: 11:43
* @package App\Utils\Wx
*/
class WxOpenUtils extends WxBaseUtils
{
protected $msg = null;
private $openApp = null;
protected static $instance = null;
// 登录前的cookie
// CACHE_BEFORE_COOKIE_KEY_openAppId
const CACHE_BEFORE_COOKIE_KEY = 'CACHE_BEFORE_COOKIE_KEY_';
// CACHE_LOGIN_COOKIE_KEY_openAppId
const CACHE_LOGIN_COOKIE_KEY = 'CACHE_LOGIN_COOKIE_KEY_';
// CACHE_LOGIN_TOKEN_KEY_openAppId
const CACHE_LOGIN_TOKEN_KEY = 'CACHE_LOGIN_TOKEN_KEY_';
// CACHE_APPLIST_COOKIE_KEY_openAppId
const CACHE_APPLIST_COOKIE_KEY = 'CACHE_APPLIST_COOKIE_KEY_';
const OPEN_BASE_URL = 'https://open.weixin.qq.com';
public function __construct()
{
// 首先要获取open对象
$this->openApp = $this->getOpenApp();
if (!$this->openApp) {
$this->msg = '开放平台获取失败';
return false;
}
}
/**
* 获取开放平台登录token
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/26
* Time: 21:13
* @param bool $isCache
* @return bool|mixed
*/
public function getLogin($isCache = false)
{
$cacheTokenName = self::CACHE_LOGIN_TOKEN_KEY . $this->openApp['id'];
$token = Cache::get($cacheTokenName);
$cacheCookieName = self::CACHE_LOGIN_COOKIE_KEY . $this->openApp['id'];
$cookie = Cache::get($cacheCookieName);
$list = [
'token' => $token,
'cookie' => $cookie
];
if (!$token || !$cookie || $isCache == true) {
$res = $this->setLogin($isCache);
if ($res === false) {
return false;
}
$list = array_merge($list, $res);
}
return $list;
}
/**
* 获取开放平台(根据第三方来得到开放平台信息,开放平台只有后台用到,没有做缓存处理)
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/26
* Time: 21:38
* @return array|null
*/
public function getOpenApp()
{
if (is_null($this->openApp)) {
$this->openApp = [];
// 根据自己的数据库设计,查询出开放平台数据,主要是账号密码等数据
$openApp = WxOpen::query()
->where('id', 1)
->first();
if (!empty($openApp)) {
$this->openApp = $openApp->toArray();
}
}
return $this->openApp;
}
/**
* Description:获取登录token
* User: Vijay
* Date: 2022/1/10
* Time: 22:23
* @param bool $isCache
* @return bool|mixed
*/
public function getLoginToken($isCache = false)
{
$cacheTokenName = self::CACHE_LOGIN_TOKEN_KEY . $$this->openApp['id'];
$token = Cache::get($cacheTokenName);
if (!$token) {
$loginList = $this->getLogin($isCache);
if ($loginList == false) {
return false;
}
$token = $loginList['token'];
}
return $token;
}
/**
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/28
* Time: 21:19
* @param bool $isCache
* @return array|bool
*/
private function setLogin($isCache = false)
{
$cookie = $this->getBeforeCookie($isCache);
$passwd = md5(trim($this->openApp['password']));
$account = $this->openApp['account'];
$param = [
'account' => $account,
'passwd' => $passwd,
'f' => 'json',
'lang' => 'zh_CN',
'ajax' => '1',
'key' => '1',
// 'token' => null,
];
$url = self::OPEN_BASE_URL . '/cgi-bin/login';
$response = $this->curlExecute($url, 'POST', $param, self::OPEN_BASE_URL, self::OPEN_BASE_URL, $cookie);
list($header, $body) = explode("\r\n\r\n", $response, 2);
$preg_cookie = '/Set-Cookie: (.*?);/m';
preg_match_all($preg_cookie, $header, $cookie);
$cacheCookieName = self::CACHE_LOGIN_COOKIE_KEY . $this->openApp['id'];
$cookieStr = implode(';', $cookie[1]);
Cache::put($cacheCookieName, $cookieStr, 3600);
$data = json_decode($body, true);
if (!isset($data['base_resp']['err_msg'])) {
$this->msg = 'base_resp获取失败';
return false;
}
if ($data['base_resp']['err_msg'] != 'ok') {
$this->msg = $data['base_resp']['err_msg'];
return false;
}
$cacheTokenName = self::CACHE_LOGIN_TOKEN_KEY . $this->openApp['id'];
$token = $data['base_resp']['token'];
Cache::put($cacheTokenName, $token, 3600);
return [
'token' => $token,
'cookie' => $cookieStr
];
}
/**
* 设置cookie
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/26
* Time: 19:29
* @return string
*/
private function setBeforeCookie()
{
$cacheName = self::CACHE_BEFORE_COOKIE_KEY . $this->openApp['id'];
$response = $this->curlExecute(self::OPEN_BASE_URL);
$preg_cookie = '/Set-Cookie: (.*?);/m';
preg_match_all($preg_cookie, $response, $cookie);
$cookieStr = implode(';', $cookie[1]);
Cache::put($cacheName, $cookieStr, 3600);
return $cookieStr;
}
/**
* 获取cookie
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/26
* Time: 20:49
* @param bool $isCache true 更新缓存
* @return mixed|string
*/
public function getBeforeCookie($isCache = false)
{
$cacheName = self::CACHE_BEFORE_COOKIE_KEY . $this->openApp['id'];
$cookieStr = Cache::get($cacheName);
if (empty($cookieStr) || $isCache == true) {
return $this->setBeforeCookie();
}
return $cookieStr;
}
/**
* Description:
* User: Vijay
* Date: 2022/1/10
* Time: 22:29
* @param bool $isCache
* @return array|bool
*/
public function appList($isCache = false)
{
$loginList = $this->getLogin($isCache);
if ($loginList == false) {
return false;
}
$url = self::OPEN_BASE_URL . '/cgi-bin/applist?t=manage/list&page=0&num=20&openapptype=1&lang=zh_CN&token=' . $loginList['token'];
$response = $this->curlExecute($url, 'GET', [], '', '', $loginList['cookie']);
list($header, $body) = explode("\r\n\r\n", $response, 2);
$preg_cookie = '/Set-Cookie: (.*?);/m';
preg_match_all($preg_cookie, $header, $cookie);
$cacheCookieName = self::CACHE_APPLIST_COOKIE_KEY . $this->openApp['id'];
$cookieStr = implode(';', $cookie[1]);
Cache::put($cacheCookieName, $cookieStr, 3600);
return [
'token' => $loginList['token'],
'cookie' => $cookieStr . ';' . $loginList['cookie']
];
}
/**
* curl请求
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/28
* Time: 17:26
* @param string $url 请求地址
* @param string $method 请求方式 GET|POST
* @param array $param 请求参数
* @param string $origin origin
* @param string $referer referer
* @param null $cookie
* @return bool|string
*/
public function curlExecute($url, $method = 'GET', $param = [], $origin = '', $referer = '', $cookie = null)
{
$curl = curl_init();
$header = [
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36',
'Accept: application/json, text/javascript, */*; q=0.01',
'Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding: gzip, deflate, br',
'X-Requested-With: XMLHttpRequest',
'Connection: keep-alive',
'Sec-Fetch-Dest: empty',
'Sec-Fetch-Mode: cors',
'Sec-Fetch-Site: same-origin ',
'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
];
if ($origin) {
$header[] = 'Origin: ' . $origin;
}
if ($referer) {
$header[] = 'Referer: ' . $referer;
}
if ($cookie) {
$header[] = 'Cookie: ' . $cookie;
}
$curloptArr = [
CURLOPT_SSL_VERIFYPEER => 0,
CURLOPT_HEADER => 1,
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => $method,
CURLOPT_HTTPHEADER => $header,
];
if ($method == 'POST') {
$curloptArr[CURLOPT_POSTFIELDS] = http_build_query($param);
}
curl_setopt_array($curl, $curloptArr);
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
/**
* User: Vijay <1937832819@qq.com>
* Date: 2021/12/26
* Time: 17:38
* @return null|string
*/
public function getMsg()
{
return $this->msg;
}
}
使用方式
调用 $appList = WxOpenUtils::getInstance()->appList();
来获取token和cookie.
后面请求中要带上token和cookie,第三方操作中全部大写的代表参数,用到的几个变量分别如下,
$appList = WxOpenUtils::getInstance()->appList();
COOKIE:$appList['cookie'] . ';__CURRENT_TOKEN__=' . $appList['token'];
TOKEN:$appList['token']
APPID: POST添加应用返回该应用的APPID
第三方操作
拿到token和cookie后,接下来的工作就比较简单啦,这里只提供接口和参数,自己去实现吧。
POST添加应用
地址:
https://open.weixin.qq.com/cgi-bin/component_acct?action=create_component&token=TOKEN
请求头:
referer:https://open.weixin.qq.com/wxaopen/createThirdAccount?token=TOKEN&lang=;
origin:https://open.weixin.qq.com;
数据包:
{
"name":"应用名称",
"desc":"描述",
"icon_url":"图片地址",
"official_site_url":"首页(随机编个域名吧)",
"industry_tag_id_list":[
2001
],
"type":0
}
添加应用成功会返回该应用的APPID,把它取出来后面要用。
GET获取第三方详情
地址:
https://open.weixin.qq.com/cgi-bin/component_acct?action=detail&t=manage/plugin_detail&token=TOKEN&appid=APPID&f=json';
POST修改ip和公众号
地址:
https://open.weixin.qq.com/cgi-bin/component_acct?action=detail&t=manage/plugin_detail&token=TOKEN&appid=APPID;
请求头:
referer:https://open.weixin.qq.com/wxaopen/serviceprovider/APPID?token=TOKEN;
origin:https://open.weixin.qq.com;
数据包:
{
"token":TOKEN,
"action":"direct_modify",
"white_acct":"公众号原始id",
"white_ip":"ip白名单",
}
POST修改权限集(这一步就是添加公众号网页授权)
地址:
https://open.weixin.qq.com/cgi-bin/component_acct?action=modify_funcscopecategory&category_list=4
请求头:
referer: https://open.weixin.qq.com/wxaopen/authoritylist/APPID?token=TOKEN&lang=zh_CN';
origin:https://open.weixin.qq.com;
数据包:
category_list=4&appid=APPID&token=TOKEN
POST修改开发资料
地址:
https://open.weixin.qq.com/cgi-bin/component_acct?action=modify_dev_info&token=TOKEN&appid=APPID
请求头:
referer: https://open.weixin.qq.com/wxaopen/createThirdAccount/modifyDevInfo?appId=APPID&token=TOKEN;
origin:https://open.weixin.qq.com;
数据包:
{
"token":"这个token是消息加解密token",
"auth_domain":"授权发起域名",
"allow_container_domain":false,
"ticket_url":"授权事件接收URL",
"msg_url":"消息与事件接收URL",
"white_ip":"白名单IP",
"white_acct":[
"公众号ID"
],
"symmetric_key":"消息加解密Key",
"sns_domain":"我们用的分享域名;号分割",
"wxa_server_domain":"",
"jump_h5_domain":"",
"ticket_url_qbase":{
"enable":false,
"container":{
"env":"",
"path":"",
"service":""
},
"function":{
"env":"",
"function_name":""
}
},
"msg_url_qbase":{
"enable":false,
"container":{
"env":"",
"path":"",
"service":""
},
"function":{
"env":"",
"function_name":""
}
}
}
POST删除第三方
地址:
https://open.weixin.qq.com/cgi-bin/component_acct?action=del_component;
请求头:
referer: https://open.weixin.qq.com/cgi-bin/applist?t=manage/list&page=0&num=20&openapptype=2048&token=TOKEN;
origin:https://open.weixin.qq.com;
数据包:
{
"appid":APPID,
"token":TOKEN,
"action":"del_component",
"lang":"zh_CN",
"f":"json",
"ajax":"1",
"key":"1",
}