11

以下の回答のコメントの1つに記載されているように、私はこのチュートリアルに従ってみました。だから今私は次のものを持っています:


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 = "oshirowanen@mail.com";
    $from = "me@desktop.com";

    $header  = 'MIME-Version: 1.0' . "\r\n";
    $header .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
    $header .= 'To: Oshirowanen <oshirowanen@mail.com>' . "\r\n";
    $header .= 'From: Me <me@desktop.com>' . "\r\n";

    mail($to,$subject,$message,$header);

?>

受信したメール:

Subject "invalid"
Message "bad"
4

9 に答える 9

14

編集:

出力した配列が表示されたので、これを置き換えて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

于 2012-08-02T18:38:43.523 に答える
6

問題は、HTTP応答コードをチェックしないため、「無効なホストヘッダー」をPayPal応答として解釈しているのに対し、Webサーバー応答(ステータスコード400の場合)であるということです。PayPalのドキュメント
を見ると、「fsockopen」、「fputs」、「fgets」関数を使用してPayPalサーバーと通信するため、コードに非常によく似たPHPの例があります。 しかし、「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)であることを確認しません。
また、上記の例に示すように、PayPalサーバーからの実際の応答は常に大文字であるため、「strtolower」関数の使用は正しくありません。
PayPalの例で「fsockopen」アプローチを使用している場合でも、PHPcURLライブラリを使用してIPNリスナーを実装する方がはるかに優れていると思います
次の回答もご覧ください。

ただし、本当に「fsockopen」関数を使用する場合は、次のコードスニペット( PHPマニュアルから取得)に示すように、POSTリクエストで常に「Host」ヘッダーフィールドを指定する必要があります。

<?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);
}
?>

アップデート

再帰的なストリップスラッシュ/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>
于 2012-08-03T21:14:35.390 に答える
2
  1. 基本的なサンプルコード4bを使用して動作しました。

  2. $ipnNotificationUrl = "";自分で追加した値がそこにあったので、基本的なサンプルコードからクリアしました。

  3. サンドボックスでビジネスプロアカウントの代わりにセラーアカウントを作成し、

  4. ipnurlを有効にするようにセラーアカウントを設定します。

  5. ipnリスナーに次のPHP5.2サンプルコードを使用しました

  6. ここで説明するように、リスナーに2行を追加しました。2行を以下に示します。

  7. ここcacert.pemから証明書をサーバーにダウンロードし、ipnリスナーと同じディレクトリに配置します。

ポイント6で述べた2行:

CURLOPT_SSL_VERIFYPEER => TRUE,
CURLOPT_CAINFO => 'cacert.pem',

サンドボックスビジネスプロアカウントでipnURLを設定できない理由はわかりませんが、セラーアカウントでは設定できます。

于 2012-08-16T09:55:21.977 に答える
1

これらのリンクはあなたの問題を解決するかもしれません、

Paypal:無効なIPNの問題

http://www.webmasterworld.com/ecommerce/4292847.htm

PaypalサンドボックスIPNは無効を返します

于 2012-08-03T13:18:22.163 に答える
1

あなたのコードの現在の正確な問題はわかりませんが、以前も同じように苦労していました。私の修正は、ヘッダーに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");

もちろん、ファイルcookies.txtが存在する必要があります。さらに、セッションデータを取得し、後で投稿データを送信するために、ページへの1つの接続を実行する必要がありました。

以下は、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";
于 2012-11-15T22:49:47.237 に答える
1

これは+文字の問題であり、誤ってフェッチされることが多いため、この回避策を作成しましたが、うまくいきました。

Payment_data=2016年6月4日土曜日15:11:16GMT+ 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));
}}
于 2016-06-04T13:32:59.000 に答える
0

これらのエラーを回避する方法は次のとおりです...

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";
 }
于 2012-08-09T13:21:34.673 に答える
0

イズディンの答えを見るまでの髪の毛を引っ張る時間。彼は正しいです..日付の+は転送されていませんでした。テストのために、シミュレーターの事前入力されたフィールドからそれを削除し、Verifiedついに取得しました。

于 2016-07-09T12:54:44.697 に答える
0

私はついにこの質問に対する更新された(2016年8月5日)実用的な答えを見つけました。このコードは、SandboxまたはLiveの最終的なIPNとして使用できます。次の点を考慮して:

  1. 必ずIPNリスナーを->販売ツール->即時支払い通知セクションに配置してください。
  2. サンドボックスでIPNシミュレータを使用しないでください。常にINVALIDが返されます。
  3. 実際のサンドボックスボタンを作成して使用しますが、「チェックアウトが完了したら、顧客をこのURLに誘導する」というページにIPNリスナーを配置しないでください。

以上です。これがお役に立てば幸いです。

そして、ここに動作するコードがあります:

<?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";
}

?>
于 2016-08-05T00:34:13.293 に答える