微信开放平台第三方接口集成

臭大佬 2021-12-28 15:45:49 1742
php 
简介 微信开放平台第三方接口

介绍

在做微信开放平台第三方应用开发的时候,每次都要登录到微信开放平台中操作,如果多了的话,很不方便,所以想到集成到自己后台操作,这样就可以同时管理n个开放平台里面的n个第三方应用了。

犹豫代码涉及逻辑会比较复杂,所以只提取了相关部分。

步骤

在操作第三方之前,需要获取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",
}