Paypal IPN 并行支付问题

2021-12-29 00:00:00 php paypal paypal-ipn codeigniter

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

I'm using this http://www.binpress.com/app/paypal-adaptive-payments-pro-codeigniter-library/140 library and i'm using this as my ipn listener for a codeigniter project - http://pastebin.com/pMb7Zhz3.

基本上,我正在使用上面的 paypal 库进行并行交易,这样当用户进行付款/捐赠时,它就会向 2 个不同的帐户汇款.交易完成后,paypal 将数据发送到我的 ipn 侦听器,如果我保留此 'IPNNotificationURL' =>'' 在我的代码中,然后进入 paypal 并设置 ipn url.

Basically i'm doing a parallel transaction using the paypal library above so that when a user makes a payment/donation, it sends money to 2 different accounts. Once a transaction is complete, paypal sends data to my ipn listener and it parses info for 1 customer just fine if I leave this 'IPNNotificationURL' => '' in my code and go into paypal and set the ipn url.

我正在尝试获取两个帐户的 IPN 信息,而不必让两个帐户都在其贝宝设置中设置 IPN 网址.当我设置 'IPNNotificationURL' =>'http://example.com/paypal_ipn',我仍然得到了 1 帐户的 ipn 信息,但是我收到了这个警告 Array to string conversion on line 11 我的听众.我该如何解决这个问题,如果我解决了,我会从两个帐户中获取 IPn 信息吗?

I'm trying to get IPN information for both accounts, without having to have both accounts set the ipn url in their paypal settings. When I set 'IPNNotificationURL' => 'http://example.com/paypal_ipn', I still get the ipn information for the 1 account, but I get this warning Array to string conversion on line 11 of my listener. How can I fix this and if i do, will I get the ipn information from both accounts?

这是我用于并行支付的上述图书馆的支付方式

Here's the pay method from the library above that i'm using for the parallel payments

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

and line 11 is this from the pastebin above - $value = urlencode(stripslashes($value));

推荐答案

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

I figured out how to parse the adaptive payments IPN in PHP.

我使用了 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 结合贝宝网站上的一个示例监听器,这是我完整的 Codeigniter IPN 监听器,用于自适应支付并行事务.

I used the DecodePayPalIPN() function by 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%2C1 in combination with one of the example listeners that is on the paypal website and here is my complete Codeigniter IPN Listener for adaptive payments with a parallel transaction.

<?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
";
        $header .= "Content-Type: application/x-www-form-urlencoded
";
        $header .= "Content-Length: " . strlen($req) . "

";
        $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("","
"), '', $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()
}

相关文章