<?php
/**
 * Created by PhpStorm.
 * User: phperstar
 * Date: 2019/12/2
 * Time: 2:37 PM
 */

namespace JinDouYun\Controller\Common;

use Mall\Framework\Core\StatusCode;
use Mall\Framework\Factory;
use Mall\Framework\Core\ErrorCode;

use JinDouYun\Controller\BaseController;

use JinDouYun\Model\Enterprise\MEnterprise;
use JinDouYun\Model\System\MEnterpriseBindTemplate;

use JinDouYun\Model\Oem\MOem;

use Util\WeiXin\Oplatform;
use Util\WeiXin\Miniprogram;

class WeiXinOpen extends BaseController
{
    /**
     * 验证票据（component_verify_ticket）缓存
     */
    private $component_verify_ticket = 'componentVerifyTicket';

    private $location_uri = 'http://'.DOMAIN_WWW.'/#/AuthorizePage';

    // 授权回调地址
    private $redirect_uri = 'http://'.DOMAIN_WWW.'/AuthorizePage';

    /**
     * WeiXinOpen constructor.
     * @param bool $isCheckAcl
     * @param bool $isMustLogin
     * @param bool $checkToken
     */
    public function __construct($isCheckAcl = false, $isMustLogin = false, $checkToken = false)
    {
        parent::__construct($isCheckAcl, $isMustLogin, $checkToken);
    }

    /**
     * 授权事件接受URl
     * 官方文档地址: https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/api/component_verify_ticket.html
     */
    public function notifyAccess()
    {

        $postStr = file_get_contents('php://input');
        file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '回调数据' . var_export($postStr, true) . PHP_EOL, FILE_APPEND);
        if (empty($postStr)) {
            exit('faild');
        }

        $params['timestamp'] = $this->request->param('timestamp');
        $params['msg_signature'] = $this->request->param('msg_signature');
        $params['nonce'] = $this->request->param('nonce');

        foreach ($params as $key => $value) {
            if (empty($value) && $value !== 0) {
                exit('回调数据有误');
            }
        }

        libxml_disable_entity_loader(true);
        // 先做签名校验
        $data = json_decode(json_encode(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        /*
        $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
        if (empty($oplatformConfigData)) {
            exit('配置错误');
        }*/
        $objOem = new MOem();
        $oemData = $objOem->getOemInfoByWeiXinOpenAppId($data['AppId']);
        if(!$oemData->isSuccess()){
            file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '从oem表获取配置错误' . PHP_EOL, FILE_APPEND);
            exit('faild');
        }
        $oemData = $oemData->getData();
        if(empty($oemData)){
            file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '从oem表获取配置为空' . PHP_EOL, FILE_APPEND);
            exit('faild');
        }
        $oplatformConfigData = json_decode($oemData['weixinOpen'], true);
        if( empty($oplatformConfigData) ){
            file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '从oem表获取开放平台配置为空' . PHP_EOL, FILE_APPEND);
            exit('faild');
        }


        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);
        $result = $objOplatform->decryptMsg($params['msg_signature'], $params['timestamp'], $params['nonce'], $data);
        if (!$result->isSuccess()) {
            $this->sendOutput($result->getData(), $result->getErrorCode());
        }

        $xmlContent = $result->getData();
        $data = json_decode(json_encode(simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        if (!empty($data) && $data['InfoType'] == 'component_verify_ticket') {
            Factory::cache('default')->set($this->component_verify_ticket . ':' . $oplatformConfigData['appid'], $data['ComponentVerifyTicket']);
        }
        if(!empty($data) && isset($data['notify_third_fasteregister'])){
            // 修改当前企业的appid
            $enterpriseMd5Key = md5($data['name'].$data['code'].$data['legal_persona_wechat'].$data['legal_persona_name']);
            $objMEnterprise = new MEnterprise();
            $modelResult = $objMEnterprise->updateEnterprise(['appid' => $data['appid']], ['weChatProgramKey' => $enterpriseMd5Key]);
            if(!$modelResult->isSuccess()){
                $this->sendOutput($modelResult->getData(), $modelResult->getErrorCode());
            }
            $result = $objOplatform->apiQueryAuth($data['auth_code']);
            if (!$result->isSuccess()) {
                $this->sendOutput($result->getData(), $result->getErrorCode());
            }
        }

        exit('success');
    }

    /**
     * 消息与事件接收URL
     * 官方文档地址: https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/api/component_verify_ticket.html
     */
    public function notifyMessage()
    {
        $appid = $this->request->param('request_id');
        $postStr = file_get_contents('php://input');
        file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . $appid . '回调数据' . var_export($postStr, true) . PHP_EOL, FILE_APPEND);
        if (empty($postStr)) {
            exit('faild');
        }

        $params['timestamp'] = $this->request->param('timestamp');
        $params['msg_signature'] = $this->request->param('msg_signature');
        $params['nonce'] = $this->request->param('nonce');

        foreach ($params as $key => $value) {
            if (empty($value) && $value !== 0) {
                exit('回调数据有误');
            }
        }

        libxml_disable_entity_loader(true);
        // 先做签名校验
        $data = json_decode(json_encode(simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);

        /*
        $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
        if (empty($oplatformConfigData)) {
            exit('配置错误');
        }*/
        $objOem = new MOem();
        $oemData = $objOem->getOemInfoByWeiXinOpenAppId($data['AppId']);
        if(!$oemData->isSuccess()){
            file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '从oem表获取配置错误' . PHP_EOL, FILE_APPEND);
            exit('faild');
        }
        $oemData = $oemData->getData();
        if(empty($oemData)){
            file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '从oem表获取配置为空' . PHP_EOL, FILE_APPEND);
            exit('faild');
        }
        $oplatformConfigData = json_decode($oemData['weixinOpen'], true);
        if( empty($oplatformConfigData) ){
            file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . '从oem表获取开放平台配置为空' . PHP_EOL, FILE_APPEND);
            exit('faild');
        }

        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);
        $result = $objOplatform->decryptMsg($params['msg_signature'], $params['timestamp'], $params['nonce'], $data);
        if (!$result->isSuccess()) {
            echo($result->getData());exit();
        }

        $xmlContent = $result->getData();
        $data = json_decode(json_encode(simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s') . $appid . '回调数据' . var_export($data, true) . PHP_EOL, FILE_APPEND);

        $objMEnterpriseBindTemplate = new MEnterpriseBindTemplate(null, null);

        // 事件消息
        if (!empty($data) && isset($data['MsgType']) && $data['MsgType'] == 'event') {
            // 小程序审核通过事件
            if ($data['Event'] == 'weapp_audit_success') {
                $data['auditStatus'] = StatusCode::$wxAuditStatus['pass'];
                $objMEnterpriseBindTemplate->updateAuditStatus($data);
            }

            // 小程序审核失败事件
            if($data['Event'] == 'weapp_audit_fail'){
                $data['reason'] = [
                    'reason' => isset($data['Reason']) ? $data['Reason'] : '',
                ];
                $data['auditStatus'] = StatusCode::$wxAuditStatus['refuse'];
                $objMEnterpriseBindTemplate->updateAuditStatus($data);
            }
            exit('success');
        }

        // 注册审核时间
        if (!empty($data) && isset($data['InfoType']) && $data['InfoType'] == 'notify_third_fasteregister') {

        }

        // 文本消息
        if (!empty($data) && isset($data['MsgType']) && $data['MsgType'] == 'text') {
            // 第三方平台验证用的固定回复
            if($data['Content'] == 'TESTCOMPONENT_MSG_TYPE_TEXT'){
                $reponseData = [
                    'ToUserName'=>$data['FromUserName'],
                    'FromUserName' =>$data['ToUserName'],
                    'CreateTime'=>time(),
                    'MsgType' => 'text',
                    'Content' => 'TESTCOMPONENT_MSG_TYPE_TEXT_callback',
                ];
                $reponseData = arrayToWeiXinXml($reponseData);
                echo $reponseData;

                /*
                $result = $objOplatform->encryptMsg($reponseData, $params['timestamp'], $params['nonce']);
                if (!$result->isSuccess()) {
                    echo($result->getData());exit();
                }
                $xmlContent = $result->getData();
                file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s'). '回调数据' . var_export($xmlContent, true) . PHP_EOL, FILE_APPEND);
                */
            }

            // 第三方平台用的验证客服消息
            if(strpos($data['Content'],'QUERY_AUTH_CODE') !== false){
                $postContent = explode(':', $data['Content']);
                $query_auth_code = $postContent[1];

                unset($result);
                $result = $objOplatform->apiQueryAuth($query_auth_code);
                if (!$result->isSuccess()) {
                    echo($result->getData());exit();
                }

                $authorization_info = $result->getData();
                $authorizer_appid = $authorization_info['authorizer_appid'];
                $authorizer_access_token = $authorization_info['authorizer_access_token'];

                $miniprogramConfigData = Factory::config()->getAppoint('weixin','miniprogram');
                if(empty($miniprogramConfigData)){
                    echo('小程序配置项错误');exit();
                }

                unset($result);
                $objMiniprogram = new Miniprogram($miniprogramConfigData['appid'], $miniprogramConfigData['appSecret']);
                $sendMessage = $query_auth_code.'_from_api';
                $result = $objMiniprogram->messageCustomSend($authorizer_access_token, $sendMessage,$data['FromUserName']);
                file_put_contents('/www/wwwroot/logs/apiqnys.liuniukj.com/weixinopen.log', date('Y-m-d H:i:s'). '回调数据' . var_export($result, true) . PHP_EOL, FILE_APPEND);
                if (!$result->isSuccess()) {
                    echo($result->getData());exit();
                }
                exit('');
            }
        }

    }

    /**
     * 获取预授权码(pre_auth_code)
     * 官网文档地址: https://developers.weixin.qq.com/doc/oplatform/Third-party_Platforms/Authorization_Process_Technical_Description.html
     */
    public function preAuthCode()
    {
        //获取微信配置
        $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
        if (empty($oplatformConfigData)) {
            exit('配置错误');
        }

        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);

        $result = $objOplatform->preAuthCode();
        if (!$result->isSuccess()) {
            parent::sendOutput($result->getData(), $result->getErrorCode());
        }

        $pre_auth_code = $result->getData();

        $auth_url = 'https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=' . $oplatformConfigData['appid'] . '&pre_auth_code=' . $pre_auth_code . '&redirect_uri=' . $this->redirect_uri . '&auth_type=2';
        parent::sendOutput($auth_url);
    }

    /**
     * 接受授权码 authorization_code
     */
    public function authorizationCode()
    {
        $params = $this->request->getRawJson();
        $authData = [
            'auth_code'  => $this->request->param('auth_code'),
            'expires_in' => $this->request->param('expires_in'),
        ];

        foreach ($authData as $key => $value) {
            if (empty($value)) {
                parent::sendOutput($key . '参数为空!', ErrorCode::$paramError);
            }
        }

        /*
       $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
       if (empty($oplatformConfigData)) {
           parent::sendOutput('微信三方平台配置错误', ErrorCode::$paramError);
       }*/

        $objMOem = new MOem();
        $result = $objMOem->getOemInfoByApiDomain($_SERVER['HTTP_HOST']);
        if( !$result->isSuccess() ){
            parent::sendOutput($result->getData(), $result->getErrorCode());
        }
        $oemData = $result->getData();
        if( empty($oemData) ){
            parent::sendOutput('oem表中获取配置为空', ErrorCode::$contentNotExists);
        }
        $oplatformConfigData = json_decode($oemData['weixinOpen'], true);
        if( empty($oplatformConfigData) ){
            parent::sendOutput('oem表中获取微信开放平台配置为空', ErrorCode::$contentNotExists);
        }

        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);

        $result = $objOplatform->apiQueryAuth($authData['auth_code']);
        if (!$result->isSuccess()) {
            parent::sendOutput($result->getData(), $result->getErrorCode());
        }
        echo "<script>location.href='http://".$oemData['domain']."/#/AuthorizePage'</script>";
        //parent::sendOutput($result->getData());
    }

    /**
     * 创建小程序接口
     */
    public function fastregisterweapp()
    {
        $params = $this->request->getRawJson();
        $componentData = [
            'enterpriseId' => isset($params['enterpriseId']) ? $params['enterpriseId'] : '',//企业id
            'name'  => isset($params['name']) ? $params['name'] : '', // 企业名称
            'code' => isset($params['code']) ? $params['code'] : '', // 企业代码
            'code_type' => isset($params['code_type']) ? $params['code_type'] : 1, // 企业代码类型（1：统一社会信用代码2：组织机构代码3：营业执照注册号）
            'legal_persona_wechat' => isset($params['legal_persona_wechat']) ? $params['legal_persona_wechat'] : '', // 法人微信
            'legal_persona_name' => isset($params['legal_persona_name']) ? $params['legal_persona_name'] : '', // 法人姓名
            'component_phone' => isset($params['component_phone']) ? $params['component_phone'] : '', // 第三方联系电话
        ];

        foreach ($componentData as $key => $value) {
            if (empty($value)) {
                parent::sendOutput($key . '参数为空!', ErrorCode::$paramError);
            }
        }

        //根据企业id保存企业数据
        $objMEnterprise = new Menterprise();
        $update = [
            'weChatEnterpriseName' => $componentData['name'],//企业名称
            'weChatEnterpriseCode' => $componentData['code'],//企业代码
            'legalPersonaWeChat' => $componentData['legal_persona_wechat'],//法人微信
            'legalPersonaName' => $componentData['legal_persona_name'],//法人姓名
            'weChatProgramKey' => md5($componentData['name'].$componentData['code'].$componentData['legal_persona_wechat'].$componentData['legal_persona_name'])//唯一key
        ];

        $modelResult = $objMEnterprise->updateEnterprise($update,['id' => $componentData['enterpriseId']]);
        if(!$modelResult->isSuccess()){
            parent::sendOutput($modelResult->getData(),$modelResult->getErrorCode());
        }
        unset($componentData['enterpriseId']);

        $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
        if (empty($oplatformConfigData)) {
            parent::sendOutput('微信三方平台配置错误', ErrorCode::$paramError);
        }
        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);

        $result = $objOplatform->fastregisterweappCreate($componentData);
        if (!$result->isSuccess()) {
            parent::sendOutput($result->getData(), $result->getErrorCode());
        }
        parent::sendOutput($result->getData());
    }

    /**
     * 微信认证名称检测
     */
    public function checkwxverifynickname()
    {
        $params = $this->request->getRawJson();
        $data = [
            'appid' => isset($params['appid']) ? $params['appid'] : '',
            'nickName'  => isset($params['nickName']) ? $params['nickName'] : '', // 企业名称
        ];

        foreach ($data as $key => $value) {
            if (empty($value)) {
                parent::sendOutput($key . '参数为空!', ErrorCode::$paramError);
            }
        }

        $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
        if (empty($oplatformConfigData)) {
            parent::sendOutput('微信三方平台配置错误', ErrorCode::$paramError);
        }
        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);

        $result = $objOplatform->checkwxverifynickname($data['appid'], $data['nickName']);
        if (!$result->isSuccess()) {
            parent::sendOutput($result->getData(), $result->getErrorCode());
        }
        parent::sendOutput($result->getData());
    }

    /**
     * 设置小程序名称
     */
    public function setnickname()
    {
        $params = $this->request->getRawJson();
        $data = [
            'appid' => isset($params['appid']) ? $params['appid'] : '',
            'nickName'  => isset($params['nickName']) ? $params['nickName'] : '', // 企业名称
        ];

        foreach ($data as $key => $value) {
            if (empty($value)) {
                parent::sendOutput($key . '参数为空!', ErrorCode::$paramError);
            }
        }

        $oplatformConfigData = Factory::config()->getAppoint('weixin', 'oplatform');
        if (empty($oplatformConfigData)) {
            parent::sendOutput('微信三方平台配置错误', ErrorCode::$paramError);
        }
        $objOplatform = new Oplatform($oplatformConfigData['appid'], $oplatformConfigData['token'], $oplatformConfigData['encodingAesKey'], $oplatformConfigData['appSecret']);

        $result = $objOplatform->setnickname($data['appid'], $data['nickName']);
        if (!$result->isSuccess()) {
            parent::sendOutput($result->getData(), $result->getErrorCode());
        }
        parent::sendOutput($result->getData());
    }
}