0

我正在使用 Drupal 7,并且通过在我的用户应该通过在 paypal 付款进行注册的地方进行编码来实现 paypal,当他返回时,如果付款得到验证,我必须在回调函数中注册他。我的回调函数根本不起作用,我想在回调中获得的所有变量值也都返回错误...

这是我的代码——

我用来将用户发送到带有值的贝宝的这个 -

function user_type_register_form_submit($form, &$form_state){
  global $base_url;
  $username = $form_state['values']['name'];
  $user_email = $form_state['values']['mail'];
  $user_type = $form_state['values']['user_type'];
  $user_first_name = $form_state['values']['field_first_name']['und'][0]['value'];
  $user_last_name = $form_state['values']['field_last_name']['und'][0]['value'];
  $user_company_name = $form_state['values']['field_company_name']['und'][0]['value'];
  $user_address_line_1 = $form_state['values']['field_address_line_1']['und'][0]['value'];
  $user_address_line_2 = $form_state['values']['field_address_line_2']['und'][0]['value'];
  $user_city = $form_state['values']['field_user_city']['und'][0]['value'];
  $user_state = $form_state['values']['field_user_state']['und'][0]['value'];
  $user_zip = $form_state['values']['field_user_zip']['und'][0]['value'];
  $user_phone_number = $form_state['values']['field_phone_number_']['und'][0]['value'];
  $user_mobile_number = $form_state['values']['field_mobile_number_']['und'][0]['value'];
  $user_fax_number = $form_state['values']['field_fax_number_']['und'][0]['value'];

  $paypal = array();
  $paypal['cmd'] = '_xclick';
  $paypal['business'] = 'rajeev_1359782736_biz@gmail.com';
  $paypal['page_style'] = 'Primary';
  $paypal['bn'] = 'PP-DonationsBF';
  $paypal['item_name'] = 'Membership';
  $paypal['currency_code'] = 'USD';
  $paypal['no_shipping'] = '1';
  $paypal['tax'] = '0';
  $paypal['lc'] = 'US';
  $paypal['rm'] = '1';
  $paypal['return'] = $base_url.'/?q=paypal/payment';
  $paypal['cancel_return'] = $base_url.'/?q=user/register';      
  $paypal['uname'] = $username;
  $paypal['email'] = $user_email;
  $paypal['user_type'] = $user_type;
  $paypal['first_name'] = $user_first_name;
  $paypal['last_name'] = $user_last_name;
  $paypal['comp_name'] = $user_company_name;
  $paypal['address1'] = $user_address_line_1;
  $paypal['address2'] = $user_address_line_2;
  $paypal['city'] = $user_city;
  $paypal['state'] = $user_state;
  $paypal['zip'] = $user_zip;
  $paypal['phone'] = $user_phone_number;
  $paypal['mobile'] = $user_mobile_number;
  $paypal['fax'] = $user_fax_number;
  switch($user_type){    
    case '0':
      dpm("General");
      $membership_price = 50;
      $paypal['amount'] = $membership_price;
      $paypal['item_number'] = 1;

      $query = http_build_query($paypal, '', '&');

      $form_state['redirect'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr?' .$query;

      break;

    case '1':
      dpm("Student");
      $membership_price = 50;
      $paypal['amount'] = $membership_price;
      $paypal['item_number'] = 2;

      $query = http_build_query($paypal, '', '&');

      $form_state['redirect'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr?' .$query;
      break;

    case '2':
      dpm("Government");
      $membership_price = 50;      
      $paypal['amount'] = $membership_price;
      $paypal['item_number'] = 3;

      $query = http_build_query($paypal, '', '&');

      $form_state['redirect'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr?' .$query;
      break;
  }
}

我调试了将用户发送到贝宝的查询,它看起来像 -

cmd=_xclick&business=rajeev_1359782736_biz%40gmail.com&page_style=Primary&bn=PP-DonationsBF&item_name=Membership&currency_code=USD&no_shipping=1&tax=0&lc=US&rm=1&return=http%3A%2F%2Fctaep-test.kr001.us%2F%3Fq%3Dpaypal%2Fpayment&cancel_return=http%3A%2F%2Fctaep-test.kr001.us%2F%3Fq%3Duser%2Fregister&uname=admin_list&email=rajeevkr.dei%40gmail.com&user_type=0&first_name=Rajeev&last_name=Kumar&comp_name=&address1=sector+27&address2=&city=noida&state=ky&zip=201301&phone=9650361380&mobile=&fax=&amount=50&item_number=1

我用来接收回调的这个函数——

function paypal_payment_paypal_ipn_callback($vars = array()){

  header("Content-type: text/html");
  header("Expires: Wed, 29 Jan 1975 04:15:00 GMT");
  header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  header("Cache-Control: no-cache, must-revalidate");
  header("Pragma: no-cache");

  watchdog('paypal', '1');

  // read the post from PayPal system and add 'cmd'
  $req = 'cmd=_notify-validate';

  foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
  }

  watchdog('paypal', '2');

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

  //Added - new
  // 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);

  //Added end

  if (!$fp) {
    watchdog('paypal', 'HTTP error');
  } else {
    fputs ($fp, $header . $req);
    watchdog('paypal', $header . $req);

    while (!feof($fp)) {
      $res = fgets ($fp, 1024);

      watchdog('paypal', '3');
      //dpm($res);
      watchdog('pay_status',$res);      
      if (strcmp ($res, "VERIFIED") == 0) {
      //if (strcmp ($res, "INVALID") == 0) {
        // assign posted variables to local variables
        //$txn_id = $_POST['txn_id'];
        watchdog('paypal', '4');

        //Information about you:
        $receiver_email = $_POST['business'];

        //Information about the transaction:
        $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'];

        dpm($receiver_email);

        //Information about your buyer:
        $user_email = $_POST['email'];
        $user_name = $_POST['uname'];
        $first_name = $_POST['first_name'];
        $last_name = $_POST['last_name'];
        $company_name = $_POST['comp_name'];
        $address_address_line_1 = $_POST['address1'];
        $address_address_line_2 = $_POST['address2'];
        $address_city = $_POST['city'];
        $address_state = $_POST['state'];
        $address_zip = $_POST['zip'];
        $user_phone = $_POST['phone'];
        $user_mobile = $_POST['mobile'];
        $user_fax = $_POST['fax'];

        //Information about the payment:
        $membership_type = $_POST['item_name'];

        //Other information about the transaction:

        //watchdog('paypal', '4');

        // 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
        $password = user_password(8);
        $fields = array(
          'name' => $user_name,
          'mail' => $user_email,
          'pass' => $password,
          'status' => 1,
          'init' => $user_email,
          'roles' => array(
            DRUPAL_AUTHENTICATED_RID => $membership_type,),
        );
       // user_save('', $fields);
      $account = user_save('', $fields);
      dpm("user registered");
      }
      else if (stripos($res, "VERIFIED") !== false) {
        watchdog('paypal', 'INVALID');
        // log for manual investigation
      }
    }
    fclose ($fp);
  }
  return 'Callback Complete';
}

这是我的看门狗错误——

inside-callback : 1
Notice: Undefined index: item_name in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: item_number in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: payment_status in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: mc_gross in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: mc_currency in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: txn_id in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: receiver_email in paypal_payment_paypal_ipn_callback()
Notice: Undefined index: payer_email in paypal_payment_paypal_ipn_callback()
inside-invalid : 4
4

2 回答 2

3

尽管 PayPal 将对 HTTP1.0 的支持延长到 2013 年 5 月 1 日,但他们可能已经更新了 Sandbox,仅支持 HTTP1.1。

https://www.x.com/content/bulletin-ipn-and-pdt-scripts-and-http-1-1

如果这是真的,您将需要按如下方式更新您的回调脚本。

// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.1\r\n"; // HTTP1.1 Update
$header .= "Content-Length: " . strlen($req) . "\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Host: www.sandbox.paypal.com\r\n"; // Sandbox Host
//$header .= "Host: ipnpb.paypal.com\r\n"; // Live Host
$header .= "Connection: close\r\n\r\n";

为了进一步的兼容性

https://ppmts.custhelp.com/app/answers/detail/a_id/926/

1) 您的 php 脚本还应该修剪 IPN 验证响应。

修改你的脚本:

//From:
if (strcmp ($res, "VERIFIED") == 0) {
..
else if (strcmp ($res, "INVALID") == 0) {

//To:
if (strcmp (trim($res), "VERIFIED") == 0) {
..
else if (strcmp (trim($res), "INVALID") == 0) {

2) 在 php 中,确保标题的最后一行包含双行尾标记: \r\n\r\n 如上例所示: $header .="Connection: close\r\n\r\ n";

3) 在 php 中,确保打开与标头中声明的同一主机的套接字连接。由于您的标头将主机声明为

$header .="Host: ipnpb.paypal.com\r\n";

您应该打开与同一主机的连接:

$fp = fsockopen ('ssl://ipnpb.paypal.com', 443, $errno, $errstr, 30);
于 2013-02-05T07:07:55.043 回答
0

问题在这里:

$paypal['return'] = $base_url.'/?q=paypal/payment';

您在那里定义的是用户付款后的最终位置;除非您启用了 PDT,否则它也不会传递事务标识符。

您需要使用notify_url来注册 IPN 处理程序:

$paypal['notify_url'] = $base_url.'/?q=paypal/payment';
于 2013-02-05T08:54:17.470 回答