美文网首页
Google退款通知 PHP

Google退款通知 PHP

作者: 码农工号9527 | 来源:发表于2022-01-26 10:22 被阅读0次

    Voided Purchases API

    Google OAuth 2.0 系统支持服务器到服务器的交互

    class GP
    {
        private $key = "";//JSON里的密钥
        private $client_email = "";//JSON里的client_email
        private $token_uri = "";//JSON里的token_uri
        private $scope = 'https://www.googleapis.com/auth/androidpublisher';//以空格分隔的应用程序请求的权限列表。
        private $package_name = "";//包名
    
        public $st;//开始时间戳
        public $et;//开始时间戳
    
        public function __construct($st, $et)
        {
            $this->st = $st * 1000;//开始时间转毫秒
            $this->et = $et * 1000;//开始时间转毫秒
        }
    
        /**
         * 谷歌退款
         * 获取access_token 接口请求文档 https://developers.google.com/identity/protocols/oauth2/service-account
         * @return mixed
         */
        private function getGPAccessToken()
        {
            //头部 标头包括两个字段,指示签名算法和确认格式。这两个字段都是必需的,每个字段只有一个值。随着其他算法和格式的引入,此标题将相应更改。
            $header = [
                'alg' => 'RS256', //生成signature的算法
                'typ' => 'JWT'    //类型
            ];
            /**
             * JWT 请求集中所需的要求如下所示。它们可以按任何顺序出现在声明集中。
    
            名称  描述
            iss 服务帐户的电子邮件地址。
            scope   应用程序请求的以空格分隔的权限列表。
            aud 断言的预期目标的描述。发出访问请求时,此值始终为。https://oauth2.googleapis.com/token
            exp 确认的过期时间,以 1970 年 1 月 1 日 00:00:00 UTC 起的秒数指定。此值最长为发出时间后 1 小时。
            iat 确认时间已给出,以 1970 年 1 月 1 日 00:00:00 UTC 起的秒数指定。
             */
            $payload = ['iss' => $this->client_email, 'scope' => $this->scope, 'aud' => $this->token_uri, 'iat' => time(), 'exp' => time() + 1800];
            //  {Base64url encoded JSON header}
            $jwtHeader = $this->base64url_encode(json_encode($header));
            //  {Base64url encoded JSON claim set}
            $jwtClaim = $this->base64url_encode(json_encode($payload));
            //  The base string for the signature: {Base64url encoded JSON header}.{Base64url encoded JSON claim set}
            openssl_sign($jwtHeader . "." . $jwtClaim, $jwtSig, $this->key, "sha256WithRSAEncryption");
            $jwtSign = $this->base64url_encode($jwtSig);
            //  {Base64url encoded JSON header}.{Base64url encoded JSON claim set}.{Base64url encoded signature}
            $jwtAssertion = $jwtHeader . "." . $jwtClaim . "." . $jwtSign;
            
            return $this->requireByCurlQueryFun($this->token_uri, 'POST', urldecode(http_build_query([
                    'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
                    'assertion' => $jwtAssertion,
                ]))
            );
        }
    
        private function base64url_encode($data)
        {
            return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
        }
    
        public function rawData()
        {
            // 将原始数据直接存入数据库
            try {
                $access_token = json_decode($this->getGPAccessToken(), true);
    
                if(isset($access_token['access_token'])) {
                    $access_token = $access_token['access_token'];
                    $data = $this->requireByCurlQueryFun('https://www.googleapis.com/androidpublisher/v3/applications/' .$this->package_name
                        .'/purchases/voidedpurchases?access_token='.$access_token.'&endTime='.$this->et.'&startTime='.$this->st, 'GET');
    
                    $data = json_decode($data, true);
                    if (is_null($data) || empty($data)) {
                        Log::info(__CLASS__.';'.__FUNCTION__.' No data');
                    } else {
    
                        if(isset($data['voidedPurchases'])) {
                            do {
    
                                // TODO 插入到表或其他逻辑
                                if(isset($data['tokenPagination']['nextPageToken']) && !empty($data['tokenPagination']['nextPageToken'])) {
                                    $nextPageToken = $data['tokenPagination']['nextPageToken'];
                                    $data = $this->requireByCurlQueryFun('https://www.googleapis.com/androidpublisher/v3/applications/'.$this->package_name
                                        .'/purchases/voidedpurchases?access_token='.$access_token.'&endTime='.$this->et.'&startTime='.$this->st
                                        .'&token='.$nextPageToken, 'GET');
                                    $data = json_decode($data, true);
                                } else {
                                    $nextPageToken = '';
                                }
    
                            } while(!empty($nextPageToken));
                            Log::info(__CLASS__.';'.__FUNCTION__.'success');
                        } else {
                            Log::error(__CLASS__.';'.__FUNCTION__.'fail:re='.json_encode($data));
                        }
    
                    }
                } else {
                    Log::error(__CLASS__.';'.__FUNCTION__.'fail:token is empty; access_token='.json_encode($access_token));
                }
    
            } catch (\Exception $e) {
                Log::error(__CLASS__.';'.__FUNCTION__.";获取gp退款回调失败,err=".$e->getMessage().';line:'.$e->getLine());
            }
        }
    
        /**
         * @param string $url           URL地址
         * @param string $mode          GET or POST
         * @param string $params        请求参数
         * @param string $userAgent     是否设置useragent
         * @param string $caFile        是否引用ca加密文件
         * @param bool $needHeader
         * @param int $timeout
         * @return array|bool|string
         */
        private function requireByCurlQueryFun($url, $mode, $params = '', $userAgent = "", $caFile = "", $needHeader = false , $timeout = 10)
        {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
            if(!empty($userAgent)){
                curl_setopt($ch, CURLOPT_USERAGENT, $userAgent);
            }
            if(!empty($caFile)){
                curl_setopt($ch, CURLOPT_CAINFO, $caFile);
            }
    
            if ($needHeader) {
                curl_setopt($ch, CURLOPT_HEADER, true);
            }
    
            if ($mode == 'POST') {
                curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
                curl_setopt($ch, CURLOPT_POST, true);
                if (is_array($params)) {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
                } else {
                    curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
                }
            } else {
                if (is_array($params)) {
                    $url .= (strpos($url, '?') === false ? '?' : '&') . http_build_query($params);
                } else {
                    $url .= (strpos($url, '?') === false ? '?' : '&') . $params;
                }
            }
    
            curl_setopt($ch, CURLOPT_URL, $url);
    
            $result = curl_exec($ch);
    
            if ($needHeader) {
                $tmp = $result;
                $result = array();
                $info = curl_getinfo($ch);
                $result['header'] = substr($tmp, 0, $info['header_size']);
                $result['body'] = trim(substr($tmp, $info['header_size']));  //直接从header之后开始截取,因为 1.body可能为空   2.下载可能不全
                //$info['download_content_length'] > 0 ? substr($tmp, -$info['download_content_length']) : '';
            }
    
            $errno = curl_errno($ch);
            if ($errno) {
                Log::channel('curl_err_log')->error("curl异常:", [
                    'url' => $url,
                    'mode' => $mode,
                    'params' => $params,
                    'errno' => $errno,
                ]);
            }
    
            curl_close($ch);
            return $result;
        }
    }
    

    相关文章

      网友评论

          本文标题:Google退款通知 PHP

          本文链接:https://www.haomeiwen.com/subject/wxfnhrtx.html