0

CodeIgniter を使用して、私のクラブが組織しているチャリティー サイクルにユーザーが登録できるページを作成しています。

登録ページでは、名前/生年月日/電話番号などの情報を受け取り、オンラインで支払うか、当日支払うかをユーザーに尋ねます。送信ボタンをクリックすると、情報が同じページに送信され、フォームの検証が実行され、情報がデータベースに挿入され (タイムスタンプを含む)、ユーザーがオンラインで支払うことを選択したかどうかが確認されます。その場合、ユーザーは PayPal 寄付ボタンのURLにリダイレクトされ、支払いが完了します。

私の質問は、URL を介して PayPal カスタム フィールドを送信するにはどうすればよいですか? ボタンの URL に &custom=whatever を追加しようとしましたが ('whatever' は新しいデータベースの行 ID とタイムスタンプです)、サンドボックス アカウントで寄付を完了した後は機能しません。

IPN:

public function ipn()
{
    // STEP 1: Read POST data

    // reading posted data from directly from $_POST causes serialization 
    // issues with array data in POST
    // reading raw POST data from input stream instead. 
    $raw_post_data = file_get_contents('php://input');
    $raw_post_array = explode('&', $raw_post_data);
    $myPost = array();
    foreach($raw_post_array as $keyval) 
    {
        $keyval = explode ('=', $keyval);
        if(count($keyval) == 2)
        {
            $myPost[$keyval[0]] = urldecode($keyval[1]);
        }
    }

    // read the post from PayPal system and add 'cmd'
    $req = 'cmd=_notify-validate';
    if(function_exists('get_magic_quotes_gpc')) 
    {
        $get_magic_quotes_exists = true;
    } 
    foreach($myPost 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";
    }


    // STEP 2: Post IPN data back to paypal to validate

    $ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');
    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_VERIFYPEER, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
    curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

    // In wamp like environments that do not come bundled with root authority certificates,
    // please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path 
    // of the certificate as shown below.
    // curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
    if(!($res = curl_exec($ch))) 
    {
        // error_log("Got " . curl_error($ch) . " when processing IPN data");
        curl_close($ch);
        exit;
    }
    curl_close($ch);


    // STEP 3: Inspect IPN validation result and act accordingly    

    if(strcmp($res, "VERIFIED") == 0) 
    {
        // PAYMENT VALIDATED & VERIFIED! 
        $custom = explode('_', $_POST['custom']);
        $reg_id = $custom[0];
        $date_registered = $custom[1];

        $query = $this->db->query('SELECT date_registered FROM registrations WHERE id=' . $reg_id);
        $array = $query->result_array();
        if($array['date_registered'] == $date_registered)
        {
            $data = array(
                'has_payed' => 1
            );
            $this->db->where('id', $reg_id);
            $this->db->update('registrations', $data);      
        }           
    }  
    elseif(strcmp($res, "INVALID") == 0) 
    {  
        // do whatever
    }           
}

データベースの「has_payed」フィールドを更新するには、これが機能する必要があることに注意してください。これには、登録ページの送信時に行 ID を送信する必要があります。

登録コントローラー:

// check payment online
if($this->input->post('pay_online') == 1) 
{
    // redirect to paypal depending on route
    switch($route)
    {
        case '80':
        case '40':
            // €20 for over 16s
            if($age >= 16)
            {
                redirect('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=H3PFP5GGN2X5J&custom=' . urlencode($reg_id . '_' . $sql['date_registered']));
            }
            // €10 for anyone under 16
            else 
            {
                redirect('a different button URL');
            }
            break;
        case '15':
            // €15 for family
            redirect('a different button URL');
            break;
    }
}

上記のコードは機能しており、フォームを適切な値 (つまり、80km または 40km のルートを実行し、16 歳以上) で送信すると、ボタンの URL にリダイレクトされます。PayPal ページで支払いを完了すると、データベースの「has_payed」フィールドが更新されません (IPN ページを参照)。

また、サンドボックス セラー アカウントで明らかに IPN が有効になっていることにも注意してください。

これに対する解決策を何時間も探しましたが、何も見つかりません。多分私は単純なものを見落としています!助けていただければ幸いです。

ありがとう!


アップデート

ユーザーを PayPal ボタンの URL にリダイレクトする代わりに、<form>コードを含む HTML ページと、ページの読み込み時にフォームを自動送信する Javascript にユーザーをリダイレクトしています。これは正常に機能していますが、ユーザーが寄付したときにデータベース フィールドがまだ更新されていません。

<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" id="paypal_form" method="post" target="_top">
    <input type="hidden" name="cmd" value="_s-xclick">
    <input type="hidden" name="hosted_button_id" value="H3PFP5GGN2X5J">
    <input type="hidden" name="notify_url" value="#IPN URL#" />
    <input type="hidden" name="custom" value="<?php echo urlencode($reg_id . '_' . $sql['date_registered']); ?>">
    <input type="image" src="https://www.sandbox.paypal.com/en_US/GB/i/btn/btn_donateCC_LG.gif" border="0" name="submit" alt="PayPal – The safer, easier way to pay online.">
    <img alt="" border="0" src="https://www.sandbox.paypal.com/en_GB/i/scr/pixel.gif" width="1" height="1">
</form>
4

2 に答える 2

0

もちろん、問題は単純でした。

CSRF 保護がconfig.php で有効化されていたため、IPN が機能しませんでした。無効にすると問題が解決しました。

于 2013-04-12T21:28:04.067 に答える