<?php

namespace app\adminapi\controller\v1\merchant;

use app\models\merchant\MerchantCodeAudit;
use app\models\merchant\MerchantMiniprogram;
use app\Request;
use crmeb\services\UploadService;
use crmeb\services\UtilService;
use Psr\SimpleCache\InvalidArgumentException;
use think\db\exception\DbException;
use think\Exception;

/**
 * 小程序代码管理类
 * Class MiniProgram
 * @package app\badminapi\controller\merchant
 */
class Third extends Open
{
    public function initialize($escape = false)
    {
        parent::initialize(); // TODO: Change the autogenerated stub
    }


    /**
     * 快速创建小程序(不一定用)
     * 注意： 该接口创建小程序的类目选择建议参考以下类目表，部分暂未开放类目将会被驳回，详情请参考：快速创建小程序接口-类目参考表。 https://docs.qq.com/sheet/DVnpOUlJZZGJaSUVY
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function createMiniProgram(Request $request)
    {
        $data = UtilService::postMore([
            ['name', '', '', '', 'empty_check', '请输入企业名'],
            ['code', '', '', '', 'empty_check', '请输入企业代码'],
            ['code_type', 1, '', '', ['empty_check',
                function ($var) {
                    //企业代码类型（1：统一社会信用代码， 2：组织机构代码，3：营业执照注册号）
                    if (!in_array($var, [1, 2, 3])) {
                        return true;
                    }
                    return false;
                }], ['请选择企业代码类型', '请选择正确的企业代码类型']],
            ['legal_persona_wechat', '', '', '', 'empty_check', '请输入法人微信'],
            ['legal_persona_name', '', '', '', 'empty_check', '请输入法人姓名'],
            ['component_phone', '', '', '', 'empty_check', '请输入第三方联系电话'],
        ], $request, false);
        try {
            $component_access_token = $this->getComponentAccessToken();
            $url = 'https://api.weixin.qq.com/cgi-bin/component/fastregisterweapp?action=create&component_access_token=' . $component_access_token;
            $res = json_decode(doRequest($url, [], null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', '已提交创建，请联系企业法人认证。');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }


    //TODO 其他部分慢慢补全
    //----

    //TODO =====基础信息设置start==========
    /**
     * 设置服务器域名
     * 授权给第三方的小程序，其服务器域名只可以为在第三方平台账号中配置的小程序服务器域名，当小程序通过第三方平台发布代码上线后，小程序原先自己配置的服务器域名将被删除，只保留第三方平台的域名，所以第三方平台在代替小程序发布代码之前，需要调用接口为小程序添加第三方平台自身的域名。 详见https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/Server_Address_Configuration.html
     */
    public function modifyDomain($mer_id, Request $request)
    {
        $data = UtilService::postMore([
            ['action', ''],
            ['requestdomain', []],
            ['wsrequestdomain', []],
            ['uploaddomain', []],
            ['downloaddomain', []],
        ]);
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/modify_domain?access_token=' . $access_token;
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', $res);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }
    //TODO =====基础信息设置end==========

    //TODO =====代码管理部分start==========
    //todo ----代码模板库设置start--------
    /**
     * 获取代码草稿列表
     * 通过本接口，可以获取草稿箱中所有的草稿（临时代码模板）；草稿是由第三方平台的开发小程序在使用微信开发者工具上传的，详见 https://developers.weixin.qq.com/miniprogram/dev/devtools/ext.html
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getTemplateDraftList()
    {
        try {
            $component_access_token = $this->getComponentAccessToken();
            $url = 'https://api.weixin.qq.com/wxa/gettemplatedraftlist?access_token=' . $component_access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', $res['draft_list']);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 将草稿添加到代码模板库
     * 可以通过获取草稿箱中所有的草稿得到草稿ID；调用本接口可以将临时草稿选为持久的代码模板。
     * @param int $draft_id 草稿ID
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function addToTemplate($draft_id = '')
    {
        if ($draft_id == '') {
            return app('json')->fail('请选择要添加的草稿');
        }
        try {
            $component_access_token = $this->getComponentAccessToken();
            $url = 'https://api.weixin.qq.com/wxa/addtotemplate?access_token=' . $component_access_token;
            $data = [
                'draft_id' => $draft_id
            ];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('添加成功');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 获取代码模板列表
     * 第三方平台运营者可以登录 open.weixin.qq.com 或者通过将草稿箱的草稿选为代码模板接口，将草稿箱中的某个代码版本添加到代码模板库中
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getTemplateList()
    {
        try {
            $component_access_token = $this->getComponentAccessToken();
            $url = 'https://api.weixin.qq.com/wxa/gettemplatelist?access_token=' . $component_access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', $res['template_list']);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 删除指定代码模板
     * 因为代码模板库的模板数量是有上限的，当达到上限或者有某个模板不再需要时，可以调用本接口删除指定的代码模板
     * @param int $template_id 模板ID
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function deleteTemplate($template_id = '')
    {
        if ($template_id == '') {
            return app('json')->fail('请选择要删除的模板');
        }
        try {
            $component_access_token = $this->getComponentAccessToken();
            $url = 'https://api.weixin.qq.com/wxa/deletetemplate?access_token=' . $component_access_token;
            $data = [
                'template_id' => $template_id
            ];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('删除完成');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }
    //todo ----代码模板库设置end--------

    //todo ----代码管理start--------
    /**
     * 上传小程序代码
     * 第三方平台需要先将草稿添加到代码模板库，或者从代码模板库中选取某个代码模板，得到对应的模板 id（template_id）； 然后调用本接口可以为已授权的小程序上传代码。
     * @param $mer_id
     * @param int $template_id
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function commitCode($mer_id, $template_id, Request $request)
    {
        $data = UtilService::postMore([
            ['ext_json', []],
            ['user_version', '', '', '', ['empty_check',
                function ($var) {
                    return (!is_string($var) || strlen($var) >= 64);
                }], ['代码版本号', '版本号太长或输入错误']],
            ['user_desc', '', '', '', 'empty_check', '请输入代码描述'],
        ], $request, false);

        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/commit?access_token=' . $access_token;
            $data['template_id'] = (int)$template_id;
            $data['ext_json'] = json_encode($data['ext_json'], JSON_UNESCAPED_UNICODE);
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('上传完成');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 获取已上传的代码的页面列表
     * 通过本接口可以获取由第三方平台上传小程序代码的页面列表；用于提交审核的审核项 的 address 参数
     * @param int $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getPageList($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/get_page?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', $res['page_list']);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 获取体验版二维码
     * 调用本接口可以获取小程序的体验版二维码
     * @param int $mer_id 商户号
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     * @throws \Exception
     */
    public function getQrCode($mer_id, Request $request)
    {
        $path = $request->get('path');
        if ($path) {
            $path = urlencode($path);
        }
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/get_qrcode?access_token=' . $access_token;
            if ($path) {
                $url .= "&path=" . $path;
            }
            $res = doRequest($url, [], null, false);
            if (!isset(json_decode($res, true)['errcode'])) {
                $filename = "mer_" . $mer_id . "_" . time() . random_int(1000, 9999) . ".jpg";//要生成的图片名字
                $file_url = 'test_qrcode/' . $mer_id;
                $upload = UploadService::init(1);
                $uploadRes = $upload->to($file_url)->validate()->stream($res, $filename);
                if ($uploadRes === false) {
                    return app('json')->fail($upload->getError());
                }
                MerchantMiniprogram::vaildWhere()->where('mer_id', $mer_id)->update(['test_qrcode_url' => $file_url . '/' . $filename, 'update' => time()]);
                return app('json')->success('ok', ['url' => sys_config('site_url') . '/uploads/' . $file_url . '/' . $filename]);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 提交审核
     * 在调用上传代码接口为小程序上传代码后，可以调用本接口，将上传的代码提交审核。请求参数几乎都不是必须，具体详见文档 https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Mini_Programs/code/submit_audit.html#%E5%AE%A1%E6%A0%B8%E9%A1%B9%E8%AF%B4%E6%98%8E
     * @param $mer_id
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function submitAudit($mer_id, Request $request)
    {
        $data = UtilService::postMore([
            ['item_list', []],
            ['preview_info', []],
            ['version_desc', ''],
            ['feedback_info', ''],
            ['feedback_stuff', ''],
            ['ugc_declare', []],
        ]);
        //var_dump($data);
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/submit_audit?access_token=' . $access_token;
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                $ret = MerchantCodeAudit::create(['mer_id' => $mer_id, 'auditid' => $res['auditid'], 'commit_time' => time()]);
                if ($ret) {
                    return app('json')->success('提交审核完成');
                } else {
                    return app('json')->success(MerchantCodeAudit::getErrorInfo('审核记录失败，请手动记录'), ['auditid' => $res['auditid']]);
                }
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * @param $mer_id
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     * @throws \Exception
     */
    public function addAuditMedia($mer_id, Request $request)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            //$filename = "mer_" . $mer_id . "_" . time() . random_int(1000, 9999) . $file_info->getOriginalName();//要生成的图片名字
            $file_url = 'upload_media/' . $mer_id;
            $upload = UploadService::init(1);
            $uploadRes = $upload->to($file_url)->validate()->move('media');
            if ($uploadRes === false) {
                return app('json')->fail($upload->getError());
            }
            $res = $upload->getUploadInfo();
            $real_path = ltrim($res['thumb_path'], '/');
            if (!$real_path) app('json')->fail('资源路径错误！');

            $url = "https://api.weixin.qq.com/wxa/uploadmedia?access_token=" . $access_token;

            $res = json_decode(doRequest($url, ['media' => new \CURLFile(realpath($real_path))], null, true, false, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success(['mediaid' => $res['mediaid'], 'type' => $res['type'], 'origin' => $real_path]);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }


    /**
     * 获取审核列表
     * @param Request $request
     * @return mixed
     * @throws \Exception
     */
    public function getAuditList(Request $request)
    {
        $where = UtilService::getMore([
            ['mer_id', ''],
            ['page', 1],
            ['limit', 10],
            ['auditid', ''],
            ['status', '']
        ], $request, false);
        return app('json')->success('ok', MerchantCodeAudit::getList($where));
    }


    /**
     * 查询指定发布审核单的审核状态
     * 提交审核后，调用本接口可以查询指定发布审核单的审核状态
     * @param $mer_id
     * @param $auditid
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getAuditStatus($mer_id, $auditid)
    {
        if (!$auditid) {
            return app('json')->fail('请输入提交审核时获得的审核ID');
        }
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/get_auditstatus?access_token=' . $access_token;
            $data = ['auditid' => $auditid];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                $data = [
                    'status' => $res['status'],
                    'reason' => $res['reason'] ?? '',
                    'screenshot' => $res['screenshot'] ?? '',
                ];
                $ret = MerchantCodeAudit::where('auditid', $auditid)->update($data);
                if ($ret) {
                    return app('json')->success('查询完成', $data);
                } else {
                    return app('json')->success('记录失败，请手动记录', $res);
                }
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 查询最新一次审核单的审核状态
     * 调用本接口可以查询最新一次提审单的审核状态
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getLatestAuditStatus($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/get_latest_auditstatus?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                $data = [
                    'status' => $res['status'],
                    'reason' => $res['reason'] ?? '',
                    'screenshot' => $res['ScreenShot'] ?? '',
                ];
                $ret = MerchantCodeAudit::where('auditid', $res['auditid'])->update($data);
                if ($ret) {
                    return app('json')->success('查询完成', $data);
                } else {
                    return app('json')->success('记录失败，请手动记录', $res);
                }
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 小程序审核撤回
     * 调用本接口可以撤回当前的代码审核单
     * 注意： 单个帐号每天审核撤回次数最多不超过 1 次，一个月不超过 10 次。
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function undoAudit($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/undocodeaudit?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                MerchantCodeAudit::where('mer_id', $mer_id)->where('status', 2)->update(['status' => 3]);
                return app('json')->success('已撤回');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 发布已通过审核的小程序
     * 调用本接口可以发布最后一个审核通过的小程序代码版本
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function release($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/release?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, true, true, false, JSON_FORCE_OBJECT), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('发布成功');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 版本回退
     * 调用本接口可以将小程序的线上版本进行回退
     * 注意：
     * 1.如果没有上一个线上版本，将无法回退
     * 2.只能向上回退一个版本，即当前版本回退后，不能再调用版本回退接口
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function revertCodeRelease($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/revertcoderelease?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('回退成功');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 分阶段发布
     * 发布小程序接口 是全量发布，会影响到现网的所有用户。而本接口时创建一个灰度发布的计划，可以控制发布的节奏，避免一上线就影响到所有的用户。可以多次调用本次接口，将灰度的比例（gray_percentage）逐渐增大
     * @param $mer_id
     * @param int $gray 灰度比例
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function grayRelease($mer_id, $gray)
    {
        if (!$gray || $gray > 100 || $gray < 1) {
            return app('json')->fail('请输入正确的灰度值');
        }
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/grayrelease?access_token=' . $access_token;
            $data = ['gray_percentage' => (int)$gray];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('分阶段发布成功');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 查询当前分阶段发布详情
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getGrayReleasePlan($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/getgrayreleaseplan?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', $res['gray_release_plan']);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 取消分阶段发布
     * 在小程序分阶段发布期间，可以随时调用本接口取消分阶段发布。取消分阶段发布后，受影响的微信用户（即被灰度升级的微信用户）的小程序版本将回退到分阶段发布前的版本
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function revertGrayRelease($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/revertgrayrelease?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('已取消');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 修改小程序线上代码的可见状态（仅供第三方代小程序调用）
     * @param $mer_id
     * @param $action
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function changeVisitStatus($mer_id, $action)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/change_visitstatus?access_token=' . $access_token;
            $data = ['action' => $action];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('修改成功');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 查询当前设置的最低基础库版本及各版本用户占比
     * 调用本接口可以查询小程序当前设置的最低基础库版本，以及小程序在各个基础库版本的用户占比
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getWeAppSupportVersion($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/getweappsupportversion?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', ['percentage' => $res['percentage'], 'version' => $res['version']]);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 设置最低基础库版本
     * 调用本接口可以设置小程序的最低基础库支持版本，可以先查询当前小程序在各个基础库的用户占比来辅助进行决策
     * @param $mer_id
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function setWeAppSupportVersion($mer_id, Request $request)
    {
        $version = $request->post('version');
        if (!$version) {
            return app('json')->fail('请填写要设置的版本');
        }
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/cgi-bin/wxopen/setweappsupportversion?access_token=' . $access_token;
            $data = ['version' => $version];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('设置成功');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 查询服务商的当月提审限额（quota）和加急次数
     * 服务商可以调用该接口，查询当月平台分配的提审限额和剩余可提审次数，以及当月分配的审核加急次数和剩余加急次数。（所有旗下小程序共用该额度）
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function queryQuota($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/queryquota?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                unset($res['errcode']);
                unset($res['errmsg']);
                return app('json')->success('ok', $res);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 加急审核申请
     * 有加急次数的第三方可以通过该接口，对已经提审的小程序进行加急操作，加急后的小程序预计2-12小时内审完。
     * @param $mer_id
     * @param $auditid
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function speedUpAudit($mer_id, $auditid)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/speedupaudit?access_token=' . $access_token;
            $data = ['auditid' => $auditid];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {

                return app('json')->success('加急完成');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 获取审核时可填写的类目信息
     * 本接口可获取已设置的二级类目及用于代码审核的可选三级类目。使用过程中如遇到问题，可在开放平台服务商专区发帖交流。
     * @param $mer_id
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function getCategory($mer_id)
    {
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/get_category?access_token=' . $access_token;
            $res = json_decode(doRequest($url, [], null, false), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                return app('json')->success('ok', $res['category_list']);
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    //todo ----代码管理end--------

    //todo ----体验者start--------
    /**
     * 绑定微信用户为体验者
     * 第三方平台在帮助旗下授权的小程序提交代码审核之前，可先让小程序运营者体验，体验之前需要将运营者的个人微信号添加到该小程序的体验者名单中。
     * 注意： 如果运营者同时也是该小程序的管理员，则无需绑定，管理员默认有体验权限。
     * @param $mer_id
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function bindTester($mer_id, Request $request)
    {
        $wechatid = $request->post('wechatid');
        if (!$wechatid) {
            return app('json')->fail('请输入微信号');
        }
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/bind_tester?access_token=' . $access_token;
            $data = ['wechatid' => $wechatid];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                $info = MerchantMiniprogram::vaildWhere()->where('mer_id', $mer_id)->find();
                $info->save(['tester' => $info['tester'] ? ($info['tester'] . ',' . $wechatid . ':' . $res['userstr']) : $wechatid . ':' . $res['userstr'], 'update' => time()]);
                return app('json')->success('绑定完成');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }

    /**
     * 解除绑定体验者
     * 调用本接口可以将特定微信用户从小程序的体验者列表中解绑
     * @param $mer_id
     * @param Request $request
     * @return mixed
     * @throws InvalidArgumentException
     */
    public function unbindTester($mer_id, Request $request)
    {
        list($wechatid, $userstr) = UtilService::postMore([
            ['wechatid', '', '', '', 'empty_check', '请输入要解绑的微信号'],
            ['userstr', '', '', '', 'empty_check', '请输入要解绑的人员对应的唯一字符串']
        ], $request, true);
        try {
            $access_token = $this->getAuthorizerAccessToken(['mer_id' => $mer_id]);
            $url = 'https://api.weixin.qq.com/wxa/unbind_tester?access_token=' . $access_token;
            $data = ['wechatid' => $wechatid, 'userstr' => $userstr];
            $res = json_decode(doRequest($url, $data, null, true, true), true);
            if (isset($res['errcode']) && $res['errcode'] == 0) {
                $info = MerchantMiniprogram::vaildWhere()->where('mer_id', $mer_id)->find();
                $member = explode(',', $info['tester']);
                foreach ($member as $k => $v) {
                    if (($wechatid . ":" . $userstr) == $v) {
                        unset($member[$k]);
                    }
                }
                $member = implode(',', $member);
                $info->save(['tester' => $member, 'update' => time()]);
                return app('json')->success('绑定完成');
            } else {
                return app('json')->fail($res['errmsg'] ?? $res['msg'] ?? '请求错误');
            }
        } catch (Exception $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        } catch (DbException $e) {
            return app('json')->fail($e->getMessage(), ['file' => $e->getFile(), 'line' => $e->getLine()]);
        }
    }
    //todo ----体验者end--------
    //TODO =====代码管理部分end===========
}