fopen POST via proxy (paiements adaptatifs Paypal)
-
29-10-2019 - |
Question
J'essaye de réécrire une requête POST fopen () pour travailler avec un proxy.
Le code est basé sur un exemple sur le site Paypal ( https://www.x.com/developers/PayPal/documentation-tools/code-sample/216632 ).
Mes solutions de contournement par défaut pour fopen () ainsi que pour file_get_contents () et cURL lib ne fonctionnent pas pour l'en-tête et le contenu de l'article relativement complexes. (Soit vous ne parvenez pas à passer par le proxy, soit vous obtenez une requête non valide: {0}, même si aucun proxy n'est défini) Voici le code d'exemple de publication (simplifié):
$url = trim('https://svcs.sandbox.paypal.com/AdaptiveAccounts/AddBankAccount');
$API_UserName = "sbapi_1287090601_biz_api1.paypal.com"; //TODO
$API_Password = "1287090610"; //TODO
$API_Signature = "ANFgtzcGWolmjcm5vfrf07xVQ6B9AsoDvVryVxEQqezY85hChCfdBMvY"; //TODO
$API_SANDBOX_EMAIL_ADDRESS = "rishaque@paypal.com"; //TODO
$API_DEVICE_IPADDRESS = "127.0.0.1"; //TODO
$API_AppID = "APP-80W284485P519543T";
$API_RequestFormat = "XML";
$API_ResponseFormat = "XML";
$xml = simplexml_load_string($xml_str);
$contents = $xml->asXML();
try
{
$params = array("http" => array(
"method" => 'POST',
"content" => $contents,
'header' => 'X-PAYPAL-SECURITY-USERID: ' . $API_UserName ."\r\n" .
'X-PAYPAL-SECURITY-PASSWORD: ' . $API_Password . "\r\n" .
'X-PAYPAL-SECURITY-SIGNATURE: ' . $API_Signature . "\r\n" .
'X-PAYPAL-REQUEST-DATA-FORMAT: ' . $API_RequestFormat . "\r\n" .
'X-PAYPAL-RESPONSE-DATA-FORMAT: ' . $API_ResponseFormat . "\r\n" .
'X-PAYPAL-APPLICATION-ID: ' . $API_AppID . "\r\n" .
'X-PAYPAL-SANDBOX-EMAIL-ADDRESS: ' . $API_SANDBOX_EMAIL_ADDRESS . "\r\n" .
'X-PAYPAL-DEVICE-IPADDRESS: ' . $API_DEVICE_IPADDRESS . "\r\n" ));
$ctx = stream_context_create($params);
$fp = @fopen($url, 'r', false, $ctx); // PROXIFY!
$response = stream_get_contents($fp);
if ($response === false) {
throw new Exception("php error message = " . "$php_errormsg");
}
fclose($fp);
// ... handle the response content ...
}
catch(Exception $e)
{
echo 'Message: ||' .$e->getMessage().'||';
}
?>
Mon proxy file_get_contents ():
if (!empty($_context_params)) {
$http_arr = $_context_params['http'];
$http_arr['proxy'] = $proxy_path;
$http_arr['request_fulluri'] = true;
$_context_params['http'] = $http_arr;
}
else
{
$_context_params = array( 'http' => array( 'proxy' => $proxy_path, 'request_fulluri' => true ) );
}
return file_get_contents( $_url, false, stream_context_create( $_context_params ) );
Ma fopen mandatée:
$parsed_proxy_path = parse_url($proxy_path);
$_proxy_name = $parsed_proxy_path['host'];
$_proxy_port = $parsed_proxy_path['port'];
$proxy_fp = fsockopen( $_proxy_name, $_proxy_port );
if ( !$proxy_fp )
return false;
$parsed_url = parse_url($_url);
$host = $parsed_url['host'];
$request = "GET $_url HTTP/1.0\r\nHost:$host\r\n\r\n";
fputs( $proxy_fp, $request );
return $proxy_fp;
Mon expérience cURL: (CodeIgniter curl lib s'occupe du proxy pour moi)
$http_params = $params['http'];
$this->curl->create($this->cfg->paypal_req_url);
$this->curl->option('header', true);$this->curl->option('verbose', true);
$this->curl->option('useragent', 'cURL/PHP');
$this->curl->http_header($http_params['header']);
$this->curl->http_header("Content-length: ".strlen($contents));
$this->curl->post(array("content"=> $contents));
$res = $this->curl->execute();
Des idées vers où aller à partir d'ici? Je suis un peu coincé ..
Comment déboguer la requête provenant de cURL? La demande est-elle même reproductible avec cURL? Fonctionnera-t-il avec GET au lieu de POST? XMLRPC est-il une option?
Remarque: l'exemple de code fonctionne pour moi lorsque je ne suis pas derrière un proxy.
Merci d'avance,
Alex
La solution
Voici le code que j'ai utilisé pour le faire fonctionner avec cURL.
Remarque: il utilise le codeigniter cURL lib de Phil Sturgeon.
Remarque: j'ai décidé de passer du XML à la chaîne de requête pour le contenu.
$contents = array(
"actionType"=>"PAY",
"cancelUrl"=>$cancel_url,
"returnUrl"=>$return_url,
"currencyCode"=>$currency,
"sender"=>$sendingmail,
"memo"=>$memo,
"requestEnvelope.errorLanguage"=>$error_lang,
"receiverList.receiver.amount"=>$amount,
"receiverList.receiver.email"=>$receivingmail,
);
if (isset($notification_url)) { $contents["ipnNotificationUrl"]=$notification_url; }
if ($receivingmail == $this->cfg->paypal_email) { $contents["feesPayer"]="SENDER"; }
if ($sendingmail == $this->cfg->paypal_email) { $contents["senderEmail"]=$sendingmail; }
// ------------------------------
// create request and add headers
// ------------------------------
$options = array( "useragent" => "cURL/PHP" );
$this->curl->create($this->cfg->paypal_req_url);
$this->curl->http_header("Content-type", "application/x-www-form-urlencoded");
$this->curl->http_header("X-PAYPAL-SECURITY-USERID", $this->cfg->paypal_user_name);
$this->curl->http_header("X-PAYPAL-SECURITY-SIGNATURE", $this->cfg->paypal_signature);
$this->curl->http_header("X-PAYPAL-SECURITY-PASSWORD", $this->cfg->paypal_password);
$this->curl->http_header("X-PAYPAL-APPLICATION-ID", $this->cfg->paypal_app_id);
$this->curl->http_header("X-PAYPAL-REQUEST-DATA-FORMAT", "NV");
$this->curl->http_header("X-PAYPAL-RESPONSE-DATA-FORMAT", "XML");
$this->curl->post($contents, $options);
$response = $this->curl->execute();
Pour ceux qui sont bloqués avec PHP4, il pourrait être utile de répondre à la question initiale de le faire fonctionner via un proxy avec fopen?
Salutations,
Alex