<?php
defined('IN_WEB') or die('Include Error!');
/**
 * Google本地支付
 */

require_once( PATH_LIB.'GooglePlay/InAppBilling/RuntimeException.php' );
require_once( PATH_LIB.'GooglePlay/InAppBilling/InvalidArgumentException.php' );
require_once( PATH_LIB.'GooglePlay/InAppBilling/ResponseData.php' );
require_once( PATH_LIB.'GooglePlay/InAppBilling/ResponseValidator.php' );
require_once( PATH_LIB.'GooglePlay/InAppBilling/GooglePlayOrder.php' );

define('PUBLIC_KEY', 'MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqZUBuBzfOmvr/wBrkTDRx/SuOsuR2ohQQnlMAS/JG2AUEQI3MM5WMKQAfQgG/sRbfaByXAzVs7LzjdHPHZkbb/lI+TN92mSvF92PW9mWB7TDLiJc1esCbAZZQDJw4k85+LRkmNRI/S2l5HK0P7aYFCwth5O1ddO00CVuaudFrn3s5MJ4vH4T2mAhDa3KXzIUbWNLHUCtGVBgpeaKSoTAai3hIl/xtQiwAFXiO5pc+bDa5KN7VotJjqud96HCrNlgF3jSb+TCvxQEb09ZNEm4KLncGoVoUd8FXW+QXigeFpCdTnrWIgFyCOlGFgiaCFNPBkzUH3bRe8jarDVTib82gwIDAQAB');
define('PACKAGE_NAME', 'com.gworld.crazyspin');
define('PRIVATE_KEY','MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXzhnbAdMHIvH4\nwKa7z/QoRqgtigq6KXM6L9LVkzgGGNfjEKXm10nokoXUdVY8LmHNkkwShw6F0zTS\nJDuINeQiN/ovGgjEYvp1Fd43m7hAt74GSo/ie27ZHc5xO2SOIZdhCEePcALqIxuM\n6Dga0RUxHnT9D+HGLnfEwf/YifOIG0ye0aBPuTkGEE+cTr8bFUXIw5VaNGxDtrHx\nXYorMk/e8so+XF9wng+ZP1v0u1xp4bknl/HLIY9ZYAJ68SSJZOl6iWSk0QSJ9JR7\no500/7vEcbaWEs0d4q6F4nsJhIoY2/Be79iWjX54G1Hcf1IcmpiyA3WVVjoEtpa8\nQtu3+xtFAgMBAAECggEAFTM+0COelYoPUeaRwnvlxLQta4KyQdJlGbSxFIulUNCq\nYbci/CyH0VeZIhUq8Gen1/486n97Czx2TXyq5bhk/lRj960CmW6bPLvLl2eDYWJn\nwtgp5P7I+cBcYtrhDapqSi5OVB1YAtvZTqHlp/UYKQ5wVyEfLj6yEkPnl5WYcaLr\nSemqJcFH6l6/9D9b68KkxZdU6bQhh78vFPeCFmNTUAaIGMUowB75pxRj70Fv9oPd\ncHQztyZeaGESLLmTsF9IwmU6YjEzIVeFHRf72YnIkyao81YtQPvJovQ+I1LBZxUz\ngWPs3kKT6V+0viPd6nFY2/uFqGo95B1vJy3kolUAFwKBgQDJ8Xj3hkiMr++NsJbe\nYWdrSpQyc65HHsr9YaX262pfEsc/dG5QoOPcVa/pgI0mvbXCYENpo9b6jjVe1NY7\nYk9jBiA4I0sjRUer9VlkyXECOqxa/3SMWzM9eCfYe2Fh3/Mnnasy9Lq/aj0/57Qq\nea2CH9bSil5WP9xH5UiJ7dD/AwKBgQDAcNHIrO0b8tBnNmecnSInZ7xisJFTpgph\nOBU/M2Dn2eTbdhTITc/iO1mMKyrG8+EBGtUJnnw6LR6uK+UcpdVJiz/FC5jVvkXh\nVT2tXTufCbclWoiy/M6OMS9eBpE6jCkdJ0O3fHExwzX9/VXjDt70Yb8rn+LVVxZh\nkBXVbTNmFwKBgEbATEJkkKyBw2sf8GuvMp2bfnqCnw+Z0UKe4Je2+QigOqCXuUKU\na+C5QK2NdWaaVsDoGxY66cnU4wv7g6dAlVG7RrSEYQHVdvvfNNej3+0JA3PKRloa\nZcRmgYdOCttQrA84JU/wADGqFhV6p1uuT8TkRM503gJX02R5B0YTxQJjAoGBALfC\nw8BhyKU4j2MPo478yWFhgJWoz41V73F4cWmBcVbUTeJ29k9zZkA8tjzP97A1r7Uz\nXx0pVqzi6vocdlKN1Ia+zq0lbtMkN2x9zkCe19D9IQMtWX25RLCpLPcXRFTpBFWP\nae1rilefdg5MfFgumh44vKk2qw9XcsrFIORFu6APAoGAa6rO+XsIFVmSWuDyD6ja\nlblkFjJt69Weha5ZS4XadvhdMBjAAttNoBujCwm462stbMwl+96X1tMIfmdlcgQ5\nt4P3QQExWzUvbik2dG4S7B3dSUNbRKK/Mwlui6iq49V7u30ILW0XWJysrvhe5Igl\nQC8DPjn938JgI4PqRGvQLbg=');


class ModelPaymentgoogle
{
    //不同包的public key和package name
    private $_configList = [
        3 => [
            'publicKey' => PUBLIC_KEY,
            'packageName' => PACKAGE_NAME
        ],
    ];
    private $_publicKey;
    private $_packageName;

    public $subArr = [];

    public function __construct()
    {
        $this->_publicKey = PUBLIC_KEY;
        $this->_packageName = PACKAGE_NAME;
    }

    public function getPackageName() {
        return PACKAGE_NAME;
    }

    /**
     *	GooglePlay的支付请求验证
     */
    protected function verify( $publicKey, $packageName, $signedData, $signature, $sid = 1)
    {
        $key = "-----BEGIN PUBLIC KEY-----\n".chunk_split( $publicKey, 64, "\n" ).'-----END PUBLIC KEY-----';
        $key = openssl_get_publickey( $key );
        if ( empty( $key ) )
        {
            return 'Please pass a Base64-encoded public key from the Market portal';
        }
        $signature = str_replace('\\', '', $signature);
        $signature = str_replace(' ', '+', $signature);
        $signedData = str_replace('\\', '', $signedData);
        $array = json_decode( $signedData, true );
        if ( empty( $array ) )
        {
            return 'fail to decode signedData';
        }

        if ( empty( $array['packageName'] ) )
        {
            return 'packageName is null';
        }

        if ( $array['packageName'] != $packageName && $sid !== 1)
        {
            return 'packageName is not match';
        }

        $result = openssl_verify( $signedData, base64_decode( $signature ), $key, OPENSSL_ALGO_SHA1 );

        if ( 0 === $result )
        {
            oo::logs()->debug3('openssl error string:'.openssl_error_string(), 'payment_verify.php');
            return 'fail to verify';
        }
        else if ( 1 !== $result )
        {
            return 'Unknown error verifying the signature in openssl_verify '.$result;
        }

        return '';
    }

    /**
     *	验证Google支付
     */
    public function validateGooglePay($param)
    {
        $signature = $param['signature'];
        $signedData = base64_decode($param['signedData']);

        if(empty($param['uid'])){
            $sid = 1;
        }else{
            $sid = empty($param['sid']) ? oo::getDefinedSid(oo::functions()->uint($param['uid'])) : (int)$param['sid'];
        }

        $valid = $this->verify($this->_publicKey, $this->_packageName, $signedData, $signature, $sid);
        if (!empty($valid)) {
            oo::logs()->debug3(array('valid' => $valid, 'param' => $param), 'payment_verifyFail.log');
            return false;
        }
        return true;
    }

    /**
     *	Google下单接口
     */
    public function deliveryGooglePay($param){
        $data = array('code' => -1);
        $ret = $this->validateGooglePay($param);//验证失败
        if( !$ret ){
            return $data;
        }

        $uid = oo::functions()->uint($param['uid']);

        $signedData = base64_decode($param['signedData']);
        $signedData = json_decode($signedData, true);
        if( !is_array($signedData) ){
            return $data;
        }
        $orderId = $signedData['developerPayload'];//订单ID
        $productId = $signedData['productId'];//商品ID
        $serialNo = $signedData['orderId'] ?? 0;//谷歌支付的流水号
        $dbGoods = oo::commonOprModel('goods')->getGpidByOrderId($orderId);
        if ($productId != $dbGoods) {//验证商品对不对
            oo::logs()->debug3(array('ret' => 4, 'uid' => $uid, 'device' => 'google'),'verification.log');
            return $data;
        }

        $pubDeliveryRet = oo::commonOprModel('payment')->pubDelivery($uid, $orderId, $serialNo);
        if( $pubDeliveryRet == true ){
            $data['code'] = 1;
        }elseif( $pubDeliveryRet == -5){
            $data['code'] = 2;
        }else {
            $data['code'] = 1;
        }

        return $data;
    }


    public function signAssertion(){
        $header = [
            'alg' => 'RS256',
            'typ' => 'JWT',
        ];
        $claims = [
            'iss' => 'crazyspin@pc-api-7388114521835780492-935.iam.gserviceaccount.com',
            'scope' => 'https://www.googleapis.com/auth/androidpublisher',           // 订阅功能授权地址
            'aud' => 'https://www.googleapis.com/oauth2/v4/token',
            'exp' => time() + 3600,  // 1小时内有效
            'iat' => time(),
        ];

        $header = json_encode($header);
        $header = base64_encode($header);

        $claims = json_encode($claims);
        $claims = base64_encode($claims);

        $signature = $header . '.' . $claims;
        $private_key = str_replace('\n','',PRIVATE_KEY);
        $private_key = "-----BEGIN PRIVATE KEY-----\n".chunk_split( $private_key, 64, "\n" ).'-----END PRIVATE KEY-----';
        $private_key = openssl_get_privatekey( $private_key );
        $assertion = "";
        $algo = "SHA256";
        openssl_sign($signature,$assertion , $private_key, $algo);
        $assertion = base64_encode($assertion);
        return $header . '.' . $claims . '.' . $assertion;
    }

    public function getToken(){
        $token = oo::commonOprRedis('common')->get(okeys::subscriptionToken());
        if (!$token) {
            if(IS_DEBUF){
                $ret = funs::sendCurlPastThird("https://spin.crazyspin.vip/api/gateway.php",['sid'=>1,'lid'=>1,'mod'=>"Test",'act'=>"getGoogleSubscribeToken",'service'=>1]);
                $ret = json_decode($ret,true);
                $token = $ret['data']['token'];
            }else{
                $token = self::requestTokenFromGoogle();
            }
            oo::commonOprRedis('common')->setex(okeys::subscriptionToken(),$token,3600);
        }
        return $token;
    }

    function requestTokenFromGoogle()
    {
        $data = array(
            'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
            'assertion' => self::signAssertion()
        );
        $result = self::curl_post_https('https://www.googleapis.com/oauth2/v4/token', http_build_query($data));
        $result = json_decode($result, true);
        $token = $result['access_token'];
        return $token;
    }

    function curl_post_https($url,$data){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url); // 要访问的地址
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // 对认证证书来源的检查
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // 从证书中检查SSL加密算法是否存在
        curl_setopt($curl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); // 模拟用户使用的浏览器
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); // 使用自动跳转
        curl_setopt($curl, CURLOPT_AUTOREFERER, 1); // 自动设置Referer
        curl_setopt($curl, CURLOPT_POST, 1); // 发送一个常规的Post请求
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data); // Post提交的数据包
        curl_setopt($curl, CURLOPT_TIMEOUT, 30); // 设置超时限制防止死循环
        curl_setopt($curl, CURLOPT_HEADER, 0); // 显示返回的Header区域内容
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); // 获取的信息以文件流的形式返回
        $tmpInfo = curl_exec($curl); // 执行操作
        if (!IS_DEBUF && curl_errno($curl)) {
            echo 'Errno'.curl_error($curl);//捕抓异常
        }
        curl_close($curl); // 关闭CURL会话
        return $tmpInfo; // 返回数据，json格式
    }

    public function getUserSubscribeStatus($packageName, $productId, $purchaseToken){
        $cache = oo::commonOprRedis('common')->get($purchaseToken);
        if(!empty($cache)){
            return json_decode($cache,true);
        }
        $token = self::getToken();
        //token里面空格需要转译
        $purchaseToken2 = str_replace(' ', '%20', $purchaseToken);
        //注意参数
        $url = "https://www.googleapis.com/androidpublisher/v3/applications/{$packageName}/purchases/subscriptions/{$productId}/tokens/{$purchaseToken2}?access_token={$token}";
        $ret = funs::sendCurlPastThird($url);
        oo::commonOprRedis('common')->setex($purchaseToken,$ret,  60);
        return json_decode($ret, true);
    }


    /**
     * GOOGLE Oauth2.0 订单验证 -----------------------------------------------------------------------------------------
     */

    private $googleAppClientId     = "899550407867-8hqg8145kl3j0q1nah0cls53d2h8ahec.apps.googleusercontent.com";
    private $googleAppClientSecret = "17BI8p4w7vL8kPPvM_heAySx";
    private $refreshTokenUrl       = "https://www.googleapis.com/oauth2/v4/token";
    private $refreshTokenCode      = "1//0d5ldMMEjn5UfCgYIARAAGA0SNwF-L9Ir9Zi4rgBJbVsf2mWM7xW5BJQHswA0GN31B9r_aju2lTZXsg7498gCiFDzzZnVrMewtGI";
    private $accessTokenError      = '';

    /**
     * 获取Google AccessToken
     * @return bool|false
     * Created by: Owen
     * Created on: 2020/8/11 11:16
     */
    public function getAccessToken(){
        $cacheKey = okeys::GoogleAccessToken();
        $cache    = oo::commonOprRedis('Config')->get($cacheKey);
        if($cache){
            return $cache;
        }
        $ret = funs::sendCurl($this->refreshTokenUrl,[
            'refresh_token' => $this->refreshTokenCode,
            'grant_type'    => "refresh_token",
            'client_id'     => $this->googleAppClientId,
            'client_secret' => $this->googleAppClientSecret,
        ],'post');
        $ret = json_decode($ret,true);
        if(empty($ret) || isset($ret['code'])){
            $this->accessTokenError = $ret;
            return false;
        }
        $accessToken = $ret['access_token'];
        oo::commonOprRedis('Config')->setex($cacheKey,$accessToken,3500);
        return $accessToken;
    }

    /**
     * 获取订单信息
     * @param $sku
     * @param $orderToken
     * @param string $pageName
     * @return bool|mixed|string
     * Created by: Owen
     * Created on: 2020/8/11 12:13
     */
    public function getGoogleOrderInfo($sku,$orderToken,$pageName = 'com.gworld.crazyspin'){
        $accessToken = self::getAccessToken();
        if(!$accessToken){
            oo::commonOprModel('Enwechat')->send("【警报】获取谷歌token失败",[],[],1);
            oo::logs()->debug3(array('reason' => $this->accessTokenError, 'time' => time()),'GoogleAccessToken_fail.log');
            return true;
        }
        $url  = "https://www.googleapis.com/androidpublisher/v3/applications/{$pageName}/purchases/products/{$sku}/tokens/{$orderToken}?access_token={$accessToken}";
        $retTemp = funs::sendCurlPastThird($url);
        $ret  = json_decode($retTemp,true);
        if(empty($ret)){
            oo::logs()->debug3(array('reason' => $retTemp, 'time' => time()),'GoogleOrderInfo_fail.log');
            return false;
        }else{
            return $ret;
        }
    }

    /**
     * Google 验证
     * @param $signedData
     * @param $param
     * @return bool
     * Created by: Owen
     * Created on: 2020/8/11 21:00
     */
    public function validateGooglePayOauth($signedData,$param = []){
        $sku   = $signedData['productId'];
        $token = $signedData['purchaseToken'];
        if(strpos($sku,'subscription') !== false){
            $ret   = self::getUserSubscribeStatus('com.gworld.crazyspin',$sku,$token);
        }else{
            if(IS_DEBUF){
                return true;
            }
            $ret   = self::getGoogleOrderInfo($sku,$token);
        }
        if(!$ret){
            oo::logs()->debug3(array('param'=>$param,'signedData' => $signedData,"googleOrder"=>$ret,'time' => time()),'GoogleOrderSign_fail.log');
            return false;
        }
        if(strpos($ret['orderId'],$signedData['orderId']) === false){
            oo::logs()->debug3(array('param'=>$param,'signedData' => $signedData,"googleOrder"=>$ret,'time' => time()),'GoogleOrderSign_fail.log');
            return false;
        }
        return true;
    }
}
