Paypal并行付款的IPN问题

6
我正在使用这个http://www.binpress.com/app/paypal-adaptive-payments-pro-codeigniter-library/140库,并将其作为我的CodeIgniter项目的IPN监听器 - http://pastebin.com/pMb7Zhz3

基本上,我正在使用上述PayPal库进行并行交易,以便当用户进行付款/捐赠时,它会向2个不同的帐户发送资金。一旦交易完成,PayPal会向我的IPN监听器发送数据,并且如果我在代码中保留'IPNNotificationURL' => ''并进入PayPal设置IPN URL,则可以很好地解析1个客户的信息。

我正在尝试获取两个帐户的IPN信息,而不必让两个帐户在其PayPal设置中设置ipn网址。当我设置'IPNNotificationURL' => 'http://example.com/paypal_ipn'时,我仍然会收到1个帐户的ipn信息,但是我会收到这个警告Array to string conversion on line 11。我该如何解决这个问题?如果解决了,我是否可以从两个帐户获得IPN信息?
这是我正在使用并行支付的上面库中的付款方法。
function Pay()
    {
        // Prepare request arrays
        $PayRequestFields = array(
                                'ActionType' => 'PAY',                              // Required.  Whether the request pays the receiver or whether the request is set up to create a payment request, but not fulfill the payment until the ExecutePayment is called.  Values are:  PAY, CREATE, PAY_PRIMARY
                                'CancelURL' => '',      // Required.  The URL to which the sender's browser is redirected if the sender cancels the approval for the payment after logging in to paypal.com.  1024 char max.
                                'CurrencyCode' => 'USD',                            // Required.  3 character currency code.
                                'FeesPayer' => 'SENDER',                            // The payer of the fees.  Values are:  SENDER, PRIMARYRECEIVER, EACHRECEIVER, SECONDARYONLY
                                'IPNNotificationURL' => '',                         // The URL to which you want all IPN messages for this payment to be sent.  1024 char max.
                                'Memo' => '',                       // A note associated with the payment (text, not HTML).  1000 char max
                                'Pin' => '',                                        // The sener's personal id number, which was specified when the sender signed up for the preapproval
                                'PreapprovalKey' => '',                             // The key associated with a preapproval for this payment.  The preapproval is required if this is a preapproved payment.  
                                'ReturnURL' => '',      // Required.  The URL to which the sener's browser is redirected after approvaing a payment on paypal.com.  1024 char max.
                                'ReverseAllParallelPaymentsOnError' => '',      // Whether to reverse paralel payments if an error occurs with a payment.  Values are:  TRUE, FALSE
                                'SenderEmail' => '',                // Sender's email address.  127 char max.
                                'TrackingID' => ''                                  // Unique ID that you specify to track the payment.  127 char max.
                                );

        $ClientDetailsFields = array(
                                'CustomerID' => '',                                 // Your ID for the sender  127 char max.
                                'CustomerType' => '',                               // Your ID of the type of customer.  127 char max.
                                'GeoLocation' => '',                                // Sender's geographic location
                                'Model' => '',                                      // A sub-identification of the application.  127 char max.
                                'PartnerName' => ''                                 // Your organization's name or ID
                                );

        $FundingTypes = array('ECHECK', 'BALANCE', 'CREDITCARD');

        $Receivers = array();
        $Receiver = array(
                        'Amount' => '',                                             // Required.  Amount to be paid to the receiver.
                        'Email' => '',                              // Receiver's email address. 127 char max.
                        'InvoiceID' => '',                                          // The invoice number for the payment.  127 char max.
                        'PaymentType' => '',                                    // Transaction type.  Values are:  GOODS, SERVICE, PERSONAL, CASHADVANCE, DIGITALGOODS
                        'PaymentSubType' => '',                                     // The transaction subtype for the payment.
                        'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => ''), // Receiver's phone number.   Numbers only.
                        'Primary' => ''                                             // Whether this receiver is the primary receiver.  Values are:  TRUE, FALSE
                        );
        array_push($Receivers,$Receiver);

        $SenderIdentifierFields = array(
                                        'UseCredentials' => ''                      // If TRUE, use credentials to identify the sender.  Default is false.
                                        );

        $AccountIdentifierFields = array(
                                        'Email' => '',      // Sender's email address.  127 char max.
                                        'Phone' => array('CountryCode' => '', 'PhoneNumber' => '', 'Extension' => '')                               // Sender's phone number.  Numbers only.
                                        );

        $PayPalRequestData = array(
                            'PayRequestFields' => $PayRequestFields, 
                            'ClientDetailsFields' => $ClientDetailsFields, 
                            'FundingTypes' => $FundingTypes, 
                            'Receivers' => $Receivers, 
                            'SenderIdentifierFields' => $SenderIdentifierFields, 
                            'AccountIdentifierFields' => $AccountIdentifierFields
                            );  

        $PayPalResult = $this->paypal_adaptive->Pay($PayPalRequestData);

        if(!$this->paypal_adaptive->APICallSuccessful($PayPalResult['Ack']))
        {
            $errors = array('Errors'=>$PayPalResult['Errors']);
            $this->load->view('paypal_error',$errors);
        }
        else
        {
            $data['result'] = $PayPalResult;
            $this->load->view('success', $data);    
        }
    }

第11行代码来自上面的Pastebin - $value = urlencode(stripslashes($value));


你能提供那一行代码和其他相关部分吗? - Josh
希望这可以帮到你:http://stackoverflow.com/questions/8456218/paypal-parallel-payment-ipn - Josh
我也看了那篇帖子几次,但仍然遇到了问题。 - Catfish
从网上搜索来看,似乎与php无法处理像$_POST ['transaction [0] .amount']这样的变量有关。 我相当确定我只需要修改获取邮寄信息的方式和/或检索它的方式。 - Catfish
PHP手册中,"变量名中的点和空格被转换为下划线。例如,<input name="a.b"/>将变成$_REQUEST["a_b"]。". -- 做得好。 - Josh
1个回答

3
我已经学会了如何在PHP中解析自适应支付IPN。
我使用了donut2d的DecodePayPalIPN()函数https://www.x.com/developers/paypal/forums/adaptive-payments-api/php-technique-parsing-adaptive-payment-ipn-posts?page=0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C0%2C1,结合paypal网站上的一个示例监听器,这是我的完整的Codeigniter IPN监听器,用于自适应支付和并行交易。
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Paypal_ipn extends CI_Controller {

    public function index() {

        // read the post from PayPal system and add 'cmd'
        $req = 'cmd=_notify-validate&'.file_get_contents("php://input");
        $header = null;

        // post back to PayPal system to validate
        $header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
        $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

        $raw_post = file_get_contents("php://input");
        $post_array = $this->decodePayPalIPN($raw_post);

        //log_message('error', "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
        //$log1 = var_export($post_array, true);

        //log_message('error', $log1);
        //log_message('error', "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");

        if(isset($post_array['sender_email'])) {
            $sender_email = $post_array['sender_email'];
        }
        if(isset($post_array['status'])) {
            $status = $post_array['status'];
        }
        if(isset($post_array['payment_request_date'])) {
            $payment_request_date = $post_array['payment_request_date'];
        }
        if(isset($post_array['transaction'][0]['receiver'])) {
            $receiver0 = $post_array['transaction'][0]['receiver'];
        }
        if(isset($post_array['transaction'][1]['receiver'])) {
            $receiver1 = $post_array['transaction'][1]['receiver'];
        }
        if(isset($post_array['transaction'][0]['id'])) {
            $id0 = $post_array['transaction'][0]['id'];
        }
        if(isset($post_array['transaction'][1]['id'])) {
            $id1 = $post_array['transaction'][1]['id'];
        }
        if(isset($post_array['transaction'][0]['invoiceId'])) {
            $invoiceId0 = $post_array['transaction'][0]['invoiceId'];
        }
        if(isset($post_array['transaction'][1]['invoiceId'])) {
            $invoiceId1 = $post_array['transaction'][1]['invoiceId'];
        }
        if(isset($post_array['transaction'][0]['amount'])) {
            $amount0 = $post_array['transaction'][0]['amount'];
        }
        if(isset($post_array['transaction'][1]['amount'])) {
            $amount1 = $post_array['transaction'][1]['amount'];
        }
        if(isset($post_array['transaction'][0]['status'])) {
            $status0 = $post_array['transaction'][0]['status'];
        }
        if(isset($post_array['transaction'][1]['status'])) {
            $status1 = $post_array['transaction'][1]['status'];
        }
        if(isset($post_array['transaction'][0]['id_for_sender_txn'])) {
            $id_for_sender_txn0 = $post_array['transaction'][0]['id_for_sender_txn'];
        }
        if(isset($post_array['transaction'][1]['id_for_sender_txn'])) {
            $id_for_sender_txn1 = $post_array['transaction'][1]['id_for_sender_txn'];
        }
        if(isset($post_array['transaction'][0]['status_for_sender_txn'])) {
            $status_for_sender_txn0 = $post_array['transaction'][0]['status_for_sender_txn'];
        }
        if(isset($post_array['transaction'][1]['status_for_sender_txn'])) {
            $status_for_sender_txn1 = $post_array['transaction'][1]['status_for_sender_txn'];
        }
        if(isset($post_array['transaction'][1]['pending_reason'])) {
            $pending_reason0 = $post_array['transaction'][1]['pending_reason'];
        }
        if(isset($post_array['transaction'][1]['pending_reason'])) {
            $pending_reason1 = $post_array['transaction'][1]['pending_reason'];
        }


        if (!$fp) {
            // HTTP ERROR
        } else {
            $counter = 0;
            fputs ($fp, $header . $req);
            while (!feof($fp)) {
                $res = fgets ($fp, 1024);

                if (strcmp ($res, "VERIFIED") == 0) {

                    log_message('error', "sender_email = $sender_email");
                    log_message('error', "payment_request_date = $payment_request_date");
                    log_message('error', "status = $status");
                    log_message('error', "receiver0 = $receiver0");
                    log_message('error', "receiver1 = $receiver1");
                    log_message('error', "id0 = $id0");
                    log_message('error', "id1 = $id1");
                    log_message('error', "invoiceId0 = $invoiceId0");
                    log_message('error', "invoiceId1 = $invoiceId1");
                    log_message('error', "amount0 = $amount0");
                    log_message('error', "amount1 = $amount1");
                    log_message('error', "status0 = $status0");
                    log_message('error', "status1 = $status1");
                    log_message('error', "id_for_sender_txn0 = $id_for_sender_txn0");
                    log_message('error', "id_for_sender_txn1 = $id_for_sender_txn1");
                    log_message('error', "status_for_sender_txn0 = $status_for_sender_txn0");
                    log_message('error', "status_for_sender_txn1 = $status_for_sender_txn1");
                    log_message('error', "pending_reason0 = $pending_reason0");
                    log_message('error', "pending_reason1 = $pending_reason1");


                    // 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
                    $counter++;
                }
                else if (strcmp ($res, "INVALID") == 0) {
                    log_message('error', 'WE INVALIDDDDDDDDDDDDDDDDDD');
                    $test = var_export($res, true);
                    $test = str_replace(array("\r","\n"), '', $test);

                    log_message('error', $test);
                    log_message('error', "Problem with IPN. res = $test");
                }

            }
            fclose ($fp);
        }

    }

    function decodePayPalIPN($raw_post)
    {
        //log_message('error', "testing");
        if (empty($raw_post)) {
            return array();
        } # else:
        $post = array();
        $pairs = explode('&', $raw_post);
        foreach ($pairs as $pair) {
            list($key, $value) = explode('=', $pair, 2);
            $key = urldecode($key);
            $value = urldecode($value);
            # This is look for a key as simple as 'return_url' or as complex as 'somekey[x].property'
            preg_match('/(\w+)(?:\[(\d+)\])?(?:\.(\w+))?/', $key, $key_parts);
            switch (count($key_parts)) {
                case 4:
                    # Original key format: somekey[x].property
                    # Converting to $post[somekey][x][property]
                    if (!isset($post[$key_parts[1]])) {
                        $post[$key_parts[1]] = array($key_parts[2] => array($key_parts[3] => $value));
                    } else if (!isset($post[$key_parts[1]][$key_parts[2]])) {
                        $post[$key_parts[1]][$key_parts[2]] = array($key_parts[3] => $value);
                    } else {
                        $post[$key_parts[1]][$key_parts[2]][$key_parts[3]] = $value;
                    }
                    break;
                case 3:
                    # Original key format: somekey[x]
                    # Converting to $post[somkey][x] 
                    if (!isset($post[$key_parts[1]])) {
                        $post[$key_parts[1]] = array();
                    }
                    $post[$key_parts[1]][$key_parts[2]] = $value;
                    break;
                default:
                    # No special format
                    $post[$key] = $value;
                    break;
            }#switch
        }#foreach

        return $post;
    }#decodePayPalIPN()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接