<?php
/**
 * 微信小程序相关接口类
 * Created by PhpStorm.
 * User: phperstar
 * Date: 2019/10/26
 * Time: 11:44 AM
 */
namespace Util\WeiXin;

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

class Miniprogram
{
    /**
     * 小程序 appId
     * @var string $appid
     */
    private $appid;
    /**
     * 小程序 appSecret
     * @var string $appSecret
     */
    private $appSecret;

    /**
     * 促销卡
     * @var string $cardid
     */
    private $cardid;

    /**
     * openId 和 session_key关联关系缓存key
     */
    private $openidAndSessionKey = 'openidAndSessionKey';

    /**
     * path和打开小程序二维码地址关联关系缓存key
     */
    private $pathAndWxaqrcodeKey = 'pathAndWxaqrcodeKey';

    /**
     * path和小程序码地址关联关系缓存key
     */
    private $pathAndWxacodeunlimitKey = 'pathAndWxacodeunlimitKey';

    /**
     * 微信小程序接口主域名
     * @var string $apiUrl
     */
    private $apiUrl = 'https://api.weixin.qq.com/sns/';

    /**
     * 微信公众号接口主域名
     * @var string $apiUrl
     */
    private $baseUrl = 'https://api.weixin.qq.com/cgi-bin/';


    public function __construct($appid='', $appsecret='', $cardid='')
    {
        $this->appid = $appid;
        $this->appSecret = $appsecret;
        $this->cardid = $cardid;
    }


    /**
     * 获取小程序二维码
     * 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html
     */
    public function getwxacodeunlimit($access_token, $parms)
    {
        $key = md5($this->appid.$parms['path'].$parms['params']);
        $imgsrc = Factory::cache('default')->hget($this->pathAndWxacodeunlimitKey, $key);
        if(!empty($imgsrc)){
            return ResultWrapper::success($imgsrc);
        }

        $apiUrl = 'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token='.$access_token;

        $postData = [
            'scene' => $parms['params'],
            'page' => $parms['path'],
            'width' => 430,
            'auto_color' => true,
        ];

        $reponse =  request($apiUrl, json_encode($postData));
        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
        }else{
            if(!is_object($reponse['content'])){
                $base64   = 'data:'.$reponse['content_type'].';base64,'.base64_encode($reponse['content']);
                $upload = Factory::baseImg();
                $upload->move($base64);
                $imgsrc = $upload->getSaveName();
                Factory::cache('default')->hset($this->pathAndWxacodeunlimitKey, $key, $imgsrc);
                return ResultWrapper::success($imgsrc);
            }
            $reponseData = json_decode($reponse['content'], true);
            if( isset($reponseData['errcode']) ){
                return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
            }
        }
    }

    /**
     * 获取小程序码
     * 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/qr-code/wxacode.createQRCode.html
     */
    public function createwxaqrcode($access_token, $path)
    {
        $key = md5($this->appid.$path);
        $imgsrc = Factory::cache('default')->hget($this->pathAndWxaqrcodeKey, $key);
        if(!empty($imgsrc)){
            return ResultWrapper::success($imgsrc);
        }

        $apiUrl = $this->baseUrl.'wxaapp/createwxaqrcode?access_token='.$access_token;

        $postData = [
            'access_token' => $access_token,
            'path' => $path,
            'width' => 430,
        ];
        $reponse =  request($apiUrl, json_encode($postData));

        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
        }else{
            if(!is_object($reponse['content'])){
                $base64   = 'data:image/jpeg;base64,'.base64_encode($reponse['content']);
                $upload = Factory::baseImg();
                $upload->move($base64);
                $imgsrc = $upload->getSaveName();
                Factory::cache('default')->hset($this->pathAndWxaqrcodeKey, $key, $imgsrc);
                return ResultWrapper::success(URL_UPLOAD.$imgsrc);
            }
            $reponseData = json_decode($reponse['content'], true);
            if( isset($reponseData['errcode']) ){
                return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
            }
        }
    }

    /**
     * 发送客服消息给用户
     * 官网地址：https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/customer-message/customerServiceMessage.send.html
     */
    public function messageCustomSend($access_token, $content, $openid)
    {
        $apiUrl = $this->baseUrl.'message/custom/send?access_token='.$access_token;
        $postData = [
            'access_token' => $access_token,
            'touser' => $openid,
            'msgtype' => 'text',
            'text' => ['content'=>$content],
        ];
        $reponse =  request($apiUrl, json_encode($postData));

        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
        }else{
            $reponseData = json_decode($reponse['content'], true);
            if( isset($reponseData['errcode']) && $reponseData['errcode'] != 0){
                return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
            }

            return ResultWrapper::success($reponseData['errmsg']);
        }
    }

    /**
     * 发送订阅消息
     * 官网地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
     */
    public function subscribeMessageSend($access_token, $templateId, $openid, $page, $data)
    {
        $apiUrl = $this->baseUrl.'message/subscribe/send?access_token='.$access_token;
        $postData = [
            'access_token' => $access_token,
            'touser' => $openid,
            'template_id' => $templateId,
            'data' => $data
        ];

        if($page){
            $postData['page'] = $page;
        }

        $reponse =  request($apiUrl, json_encode($postData));

        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
        }else{
            $reponseData = json_decode($reponse['content'], true);
            if( isset($reponseData['errcode']) && $reponseData['errcode'] != 0){
                return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
            }

            return ResultWrapper::success($reponseData['errmsg']);
        }
    }

    /**
     * 组合模板并添加至帐号下的个人模板库
     * 官网地址: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.addTemplate.html
     */
    public function addtemplate($access_token, $tid, $kidList, $sceneDesc)
    {
        $apiUrl = 'https://api.weixin.qq.com/wxaapi/newtmpl/addtemplate?access_token='.$access_token;
        $postData = [
            'tid' => $tid,
            'kidList' => $kidList,
            'sceneDesc' => $sceneDesc,
        ];

        $curl_option = [
            CURLOPT_HTTPHEADER => [
                'content-type: application/json'
            ],
        ];

        $reponse =  request($apiUrl, json_encode($postData), 10, false, $curl_option);

        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
        }else{
            $reponseData = json_decode($reponse['content'], true);
            if( isset($reponseData['errcode']) && $reponseData['errcode'] != 0){
                return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
            }

            return ResultWrapper::success($reponseData['priTmplId']);
        }
    }


    /**
     * 登录凭证校验
     * 官方文档对应地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
     * @param string $jsCode 通过 wx.login 接口获得临时登录凭证 code
     * @return ResultWrapper
     */
    public function jscode2session($jsCode)
    {
        $apiUrl = $this->apiUrl.'jscode2session?appid='.$this->appid.'&secret='.$this->appSecret.'&js_code='.$jsCode.'&grant_type=authorization_code';
        $reponse =  request($apiUrl);

        if($reponse['httpcode'] != 200){
            return ResultWrapper::fail('请求外部系统接口报错', ErrorCode::$apiNotResult);
        }else{
            $reponseData = json_decode($reponse['content'], true);
            if( isset($reponseData['errcode']) ){
                return ResultWrapper::fail($reponseData['errmsg'], $reponseData['errcode']);
            }
            Factory::cache('default')->hset($this->openidAndSessionKey, $reponseData['openid'], $reponseData['session_key']);
            return ResultWrapper::success(['openid'=>$reponseData['openid'],'unionid'=> isset($reponseData['unionid']) ? $reponseData['unionid'] : '']);
        }
    }

    /**
     * 数据解密算法
     * 官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/getPhoneNumber.html
     * @param string $iv 加密算法的初始向量
     * @param string $encryptedData 包括敏感数据在内的完整用户信息的加密数据
     * @param string $openid 用户标识
     * @return ResultWrapper
     */
    public function decryptData($iv, $encryptedData, $openid)
    {
        $session_key = Factory::cache('default')->hget($this->openidAndSessionKey, $openid);
        if(empty($session_key)){
            return ResultWrapper::fail('登陆会话session_key过期', ErrorCode::$notAllowAccess);
        }

        if (strlen($session_key) != 24) {
            return ResultWrapper::fail('无效的session_key', ErrorCode::$paramError);
        }
        $aesKey=base64_decode($session_key);


        if (strlen($iv) != 24) {
            return ResultWrapper::fail('无效的iv', ErrorCode::$paramError);
        }
        $aesIV=base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

        $dataObj=json_decode( $result, true);
        if( $dataObj  == NULL )
        {
            return ResultWrapper::fail('解密后得到的buffer非法', ErrorCode::$paramError);
        }
        if( $dataObj['watermark']['appid'] != $this->appid )
        {
            return ResultWrapper::fail('解密后得到的buffer非法', ErrorCode::$paramError);
        }

        return ResultWrapper::success($dataObj);
    }
}