Paypal IPN问题与并行付款

时间:2012-01-28 20:57:21

标签: php codeigniter paypal paypal-ipn

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

基本上我正在使用上面的paypal库进行并行交易,以便当用户进行付款/捐赠时,它会向2个不同的帐户汇款。一旦交易完成,paypal就会将数据发送到我的ipn监听器并解析1位客户的信息,如果我将'IPNNotificationURL' => ''留在我的代码中并进入paypal并设置ipn url就可以了。

我正在尝试获取这两个帐户的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));

1 个答案:

答案 0 :(得分:3)

我想出了如何在PHP中解析自适应支付IPN。

我将donut2d 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%2C1DecodePayPalIPN()函数与paypal网站上的一个示例监听器结合使用,这是我的完整Codeigniter IPN侦听器,用于并行事务的自适应支付。 / p>

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