PayPal REST令牌请求api.paypal.com正常 api-m.paypal.com返回403问题
补遗2
Mozilla的请求行为与URL解析到的具体主机IP有关,问题末尾附加了可复现该问题的curl脚本。
补遗
该问题曾在约8小时后消失,且连续多日运行正常。但一周后重新运行页面测试时,问题再次反复出现:api.paypal.com请求正常,api-m.paypal.com请求失败。
我向api-m.paypal.com和api.paypal.com请求生产环境访问令牌时得到了不同的结果:向api.paypal.com发起请求可正常返回令牌,向api-m.paypal.com发起请求则返回403 Forbidden错误。请问该现象的成因是什么?官方文档中无论是通用接口还是令牌请求接口都将api和api-m域名混用,二者有什么区别?哪些请求应该路由到api域名,哪些应该路由到api-m域名?我在沙箱环境运行全量店铺业务时,所有请求都发往api-m域名,运行完全正常。我编写了一个测试程序循环请求令牌,依次调用api、api-m、api.sandbox、api-m.sandbox四个域名,仅api-m生产域名请求失败,其余三个场景均正常。我之前见过一次api和api-m差异的讨论但现在无法找到,且当时的讨论完全没有提到过该问题!
<?php include("../_private/ppinfo.php"); header('Content-type: text/plain'); $sandbox = 0; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = 1; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = 2; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = -1; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = 0; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = -1; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = 1; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = 0; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; $sandbox = 2; echo "sandbox $sandbox rv " . GetNewPPToken($sandbox) . " "; // 用于获取PayPal REST令牌支撑后续交易 function GetNewPPToken($sandbox) { global $G, $ppinfo; $headers = array( "Accept: application/json", "Accept-Language: en_US", "Content-Type: application/x-www-form-urlencoded" ); if ($sandbox > 1) { $clid = $ppinfo['sb_acct']; $secret = $ppinfo['sb_secr']; $url = "https://api.sandbox.paypal.com/v1/oauth2/token"; } else if ($sandbox > 0) { $clid = $ppinfo['sb_acct']; $secret = $ppinfo['sb_secr']; $url = "https://api-m.sandbox.paypal.com/v1/oauth2/token"; } else if ($sandbox < 0) { $clid = $ppinfo['acct']; $secret = $ppinfo['secr']; $url = "https://api.paypal.com/v1/oauth2/token"; } else { $clid = $ppinfo['acct']; $secret = $ppinfo['secr']; $url = "https://api-m.paypal.com/v1/oauth2/token"; }; $cvt = "grant_type=client_credentials"; $curl = newPPcurl($url, $cvt, $headers); curl_setopt($curl, CURLOPT_USERPWD, "$clid:$secret"); $resp = curl_exec($curl); $err = curl_error($curl) ; $json = json_decode($resp, true); if (0) { echo "response: "; print_r($resp); echo "err: "; print_r($err); echo "token '" . $ppinfo['token'] . "' "; }; $ppinfo['token'] = $json['access_token']; return ($ppinfo['token'] != '' ? 1 : 0); } function newPPcurl($url, $flds, $hdrs) { $user_agent = "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)"; $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_POST, 1); if ($flds != '') curl_setopt($curl, CURLOPT_POSTFIELDS, $flds); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_FORBID_REUSE, 1); curl_setopt($curl, CURLOPT_USERAGENT, $user_agent); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, TRUE); curl_setopt($curl, CURLOPT_TIMEOUT, 30); curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30); if ($hdrs != "") curl_setopt($curl, CURLOPT_HTTPHEADER, $hdrs); return $curl; }
测试输出
sandbox 0 rv 0 sandbox 1 rv 1 sandbox 2 rv 1 sandbox -1 rv 1 sandbox 0 rv 0 sandbox -1 rv 1 sandbox 1 rv 1 sandbox 0 rv 0 sandbox 2 rv 1
复现方法
以下是可复现该行为的curl命令:当api-m.paypal.com解析到184.87.90.6时,使用Mozilla User-Agent可正常获取令牌(命令1);当该域名解析到151.101.1.35时,使用Mozilla User-Agent的请求失败(命令2),使用curl默认User-Agent的请求正常(命令3)。注意测试时需要替换为你自己的id:pwd凭证。
curl -v https://api-m.paypal.com/v1/oauth2/token \ --user-agent "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" \ --resolve api-m.paypal.com:443:184.87.90.6 \ -H "Accept: application/json" \ -H "Accept-Language: en_US" \ -u "<id:pwd>" \ -d "grant_type=client_credentials"
curl -v https://api-m.paypal.com/v1/oauth2/token \ --user-agent "Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)" \ --resolve api-m.paypal.com:443:151.101.1.35 \ -H "Accept: application/json" \ -H "Accept-Language: en_US" \ -u "<id:pwd>" \ -d "grant_type=client_credentials"
curl -v https://api-m.paypal.com/v1/oauth2/token \ --user-agent "curl/7.55.1" \ --resolve api-m.paypal.com:443:151.101.1.35 \ -H "Accept: application/json" \ -H "Accept-Language: en_US" \ -u "<id:pwd>" \ -d "grant_type=client_credentials"
内容的提问来源于stack exchange,提问作者dajoke

