Paypal SandBox IPN всегда возвращает INVALID
Как упоминалось в одном из комментариев в ответе ниже, я попытался выполнить этот учебник. Итак, теперь у меня есть следующее:
Файл ipn.php:
<?php
$ipn_post_data = $_POST;
$url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
// Set up request to PayPal
$request = curl_init();
curl_setopt_array($request, array
(
CURLOPT_URL => $url,
CURLOPT_POST => TRUE,
CURLOPT_POSTFIELDS => http_build_query(array('cmd' => '_notify-validate') + $ipn_post_data),
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_HEADER => FALSE,
CURLOPT_SSL_VERIFYPEER => TRUE,
CURLOPT_CAINFO => 'cacert.pem',
));
// Execute request and get response and status code
$response = curl_exec($request);
$status = curl_getinfo($request, CURLINFO_HTTP_CODE);
// Close connection
curl_close($request);
if($status == 200 && $response == 'VERIFIED')
{
$subject = "valid";
$message = "good";
}
else
{
$subject = "invalid";
$message = "bad";
}
$to = "[email protected]";
$from = "[email protected]";
$header = 'MIME-Version: 1.0' . "\r\n";
$header .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
$header .= 'To: Oshirowanen <[email protected]>' . "\r\n";
$header .= 'From: Me <[email protected]>' . "\r\n";
mail($to,$subject,$message,$header);
?>
Полученное письмо:
Subject "invalid"
Message "bad"
Ответы
Ответ 1
-
Сработал с использованием базового образца кода 4b,
-
Снято $ipnNotificationUrl = "";
из базового образца кода, так как у меня было значение, которое я добавил сам,
-
Создал учетную запись продавца вместо учетной записи business pro в песочнице,
-
Установите учетную запись продавца, чтобы включить URL-адрес ipn,
-
Использовал следующий PHP 5.2 образец кода для прослушивателя ipn
-
Добавлено 2 строки в слушатель, как описано здесь, две строки можно увидеть ниже:
-
Загрузил сертификат cacert.pem
на мой сервер из здесь и поместил его в тот же каталог, что и прослушиватель ipn:
2 строки, упомянутые в пункте 6:
CURLOPT_SSL_VERIFYPEER => TRUE,
CURLOPT_CAINFO => 'cacert.pem',
Я понятия не имею, почему учетная запись proxy sandbox не позволяет мне установить URL-адрес ipn, но учетная запись продавца делает.
Ответ 2
Edit:
Теперь, когда я вижу массив, который вы вывели, попробуйте заменить это, чтобы избавиться от ошибки массива PHP:
foreach ($_POST as $key => $value) {
if (!is_array($value)) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
else if (is_array($value)) {
$paymentArray = explode(' ', $value[0]);
$paymentCurrency = urlencode(stripslashes($paymentArray[0]));
$paymentGross = urlencode(stripslashes($paymentArray[1]));
$req .= '&mc_currency=' . $paymentCurrency . '&mc_gross=' . $paymentGross;
}
}
Вот отредактированный код в полном объеме:
// read the post from PayPal system and add 'cmd'
$req = 'cmd=' . urlencode('_notify-validate');
foreach ($_POST as $key => $value) {
if (!is_array($value)) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}
else if (is_array($value)) {
$paymentArray = explode(' ', $value[0]);
$paymentCurrency = urlencode(stripslashes($paymentArray[0]);
$paymentGross = urlencode(stripslashes($paymentArray[1]);
$req .= '&mc_currency=' . $paymentCurrency . '&mc_gross=' . $paymentGross;
}
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://www.paypal.com/cgi-bin/webscr');
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Host: www.paypal.com'));
$res = curl_exec($ch);
curl_close($ch);
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
if (strcmp ($res, "VERIFIED") == 0) {
// check the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process payment
}
else if (strcmp ($res, "INVALID") == 0) {
// log for manual investigation
}
Проверьте это!
Изменить: ознакомьтесь с советами по устранению неполадок PayPal:
https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_admin_IPNTesting
Ответ 3
Проблема в том, что вы не проверяете код ответа HTTP, поэтому вы вводите "Недопустимый заголовок хоста" в качестве ответа PayPal, в то время как он отвечает за веб-сервер (для кода состояния 400).
Если вы посмотрите документацию PayPal, есть пример PHP, который очень похож на ваш код, так как он использует "fsockopen" , fputs "и" fgets "для связи с сервером PayPal.
Но если вы внимательно посмотрите на замечание после вызова "fsockopen", вы можете прочитать:
// Process validation from PayPal
// TODO: This sample does not test the HTTP response code. All
// HTTP response codes must be handled or you should use an HTTP
// library, such as cUrl
И это точно ваша проблема: вы не проверяете, что код ответа HTTP составляет 200 (OK), прежде чем разбирать тело ответа.
Кроме того, использование функции "strtolower" неверно, так как реальный ответ с сервера PayPal всегда занимает верхний регистр, как показано в приведенном выше примере.
Даже если в примере PayPal используется подход "fsockopen", я считаю, что лучше использовать библиотеку PHP cURL для реализации вашего прослушивателя IPN.
Также рассмотрите следующие ответы:
Однако, если вы действительно хотите использовать функцию fsockopen, вы всегда должны указывать поле заголовка "Host" в POST запрос, как показано в следующем фрагменте кода (взято из Руководство по PHP):
<?php
$fp = fsockopen("www.example.com", 80, $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
$out = "GET / HTTP/1.1\r\n";
$out .= "Host: www.example.com\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($fp, $out);
while (!feof($fp)) {
echo fgets($fp, 128);
}
fclose($fp);
}
?>
UPDATE
Вот простая функция для рекурсивных stripslashes/urlencoding:
<html>
<body>
<pre>
<?
$post = Array (
"transaction" => Array("USD 20.00"),
"payment_request_date" => "Sun Aug '05 08:49:20 PDT 2012",
"return_url" => "http://000.000.000.000/success.php"
);
echo "before myUrlencode...\n";
print_r($post);
function myUrlencode($post) {
foreach ($post as $key => $val) {
if (is_array($val)) {
$post[$key] = myUrlencode($val);
} else {
$post[$key] = urlencode(stripslashes($val));
}
}
return($post);
}
echo "\nafter myUrlencode...\n";
print_r(myUrlencode($post));
?>
</pre>
</body>
</html>
Ответ 4
Эти ссылки могут решить вашу проблему,
Paypal: неверная проблема с IPN
http://www.webmasterworld.com/ecommerce/4292847.htm
Песочница Paypal IPN возвращает INVALID
Ответ 5
Я не уверен, что сейчас неправильно с вашим кодом, но я боролся с этим же, но мои исправления заключались в том, чтобы добавить HOST в заголовок, а хозяин должен быть www.paypal.com. Я использовал метод fsockopen и теперь отлично работаю.
В Curl у меня была проблема с ssl. И решение было поставить эти строки:
curl_setopt($curl, CURLOPT_COOKIEJAR, dirname(__FILE__) . "/cookies.txt");
curl_setopt($curl, CURLOPT_COOKIEFILE, dirname(__FILE__) . "/cookies.txt");
где, конечно, файл cookie.txt должен существовать.
и более того я должен был запустить одно соединение на страницу, чтобы получить данные сеанса, а затем отправить данные post.
Ниже приведен заголовок, который отлично работает для меня с помощью метода fsockopen
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
Ответ 6
Это проблема с символом +, она часто ошибочно набирается, поэтому я сделал это обходное решение, и это сработало для меня.
payment_data = Сб Июн 04 2016 15:11:16 GMT + 0200 (CEST)
foreach ($_POST as $key => $value) {
if($key !== "payment_date"){
$req .= '&' . $key . '=' . rawurlencode(html_entity_decode($value, ENT_QUOTES, 'UTF-8'));
}else{
$req .= '&' . $key . '=' . rawurlencode(str_replace(array('GMT '),array('GMT+'),$value));
}}
Ответ 7
Здесь, как избежать этих ошибок...
foreach ($_POST as $key => $value) {
if ($key=='transaction')
foreach ($value as $key2=>$value2) {
$value['transaction'][$key2] = urlencode(stripslashes($value2));
}
else {
$value = urlencode(stripslashes($value));
}
$req .= "&$key=$value";
}
Ответ 8
Часы вытягивания волос, пока я не увидел ответ Идзудина. Он прав... + дата не переносится. Чтобы проверить, я удалил его из предварительно заполненного поля в симуляторе и наконец получил Verified
.
Ответ 9
Наконец, я нашел обновленный (5 августа 2016) рабочий ответ на этот запрос. Вы можете использовать этот код в качестве своего последнего IPN для песочницы или Live. Со следующим соображением:
- Обязательно поместите ваш прослушиватель IPN в → Мои инструменты для продажи → раздел уведомлений мгновенного платежа.
- Не используйте IPN Simulator в песочнице, он всегда будет возвращать INVALID.
- Создайте и используйте настоящую кнопку "Песочница", но НЕ помещайте ваш прослушиватель IPN на страницу RETURN PAGE, в которой говорится: "Возьмите клиентов по этому URL-адресу, когда они завершат проверку".
Это все. Надеюсь, это поможет.
И вот рабочий код:
<?php
$post_data = file_get_contents('php://input');
$post_array = explode('&', $post_data);
$dataFromPayPal = array();
foreach ($post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$dataFromPayPal[$keyval[0]] = urldecode($keyval[1]);
}
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($dataFromPayPal as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
//use https://www.sandbox.paypal.com/cgi-bin/webscr in case you are testing this on a PayPal Sanbox environment
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
if( !($res = curl_exec($ch)) ) {
curl_close($ch);
exit;
}
curl_close($ch);
if (strcmp ($res, "INVALID") == 0) {
echo "INVALID";
}
else if (strcmp ($res, "VERIFIED") == 0) {
echo "VALID";
}
?>