title: Paypal IPN Callback not working with sandbox
body: <p>I am working with Drupal 7 &amp; have implemented paypal by coding at one place where my user is suppose to register by paying at paypal &amp; when he returns back I have to register him in callback function if payment is verified.
  My callback function is simply not working &amp; all the variables values which I am suppose to get in callback is also returning me false...</p>
  
  <p>Here is my code --</p>
  
  <p>This one I am using to send user to paypal with values--</p>
  
  <pre><code>function user_type_register_form_submit($form, &amp;$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, '', '&amp;');
  
        $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, '', '&amp;');
  
        $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, '', '&amp;');
  
        $form_state['redirect'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr?' .$query;
        break;
    }
  }
  </code></pre>
  
  <p>I debugged the query which sending user to paypal &amp; it's look like --</p>
  
  <pre><code>cmd=_xclick&amp;business=rajeev_1359782736_biz%40gmail.com&amp;page_style=Primary&amp;bn=PP-DonationsBF&amp;item_name=Membership&amp;currency_code=USD&amp;no_shipping=1&amp;tax=0&amp;lc=US&amp;rm=1&amp;return=http%3A%2F%2Fctaep-test.kr001.us%2F%3Fq%3Dpaypal%2Fpayment&amp;cancel_return=http%3A%2F%2Fctaep-test.kr001.us%2F%3Fq%3Duser%2Fregister&amp;uname=admin_list&amp;email=rajeevkr.dei%40gmail.com&amp;user_type=0&amp;first_name=Rajeev&amp;last_name=Kumar&amp;comp_name=&amp;address1=sector+27&amp;address2=&amp;city=noida&amp;state=ky&amp;zip=201301&amp;phone=9650361380&amp;mobile=&amp;fax=&amp;amount=50&amp;item_number=1
  </code></pre>
  
  <p>This function I am using to receive the callback -- </p>
  
  <pre><code>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 =&gt; $value) {
      $value = urlencode(stripslashes($value));
      $req .= "&amp;$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('&amp;', $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 =&gt; $value) {        
      if($get_magic_quotes_exists == true &amp;&amp; get_magic_quotes_gpc() == 1) { 
          $value = urlencode(stripslashes($value)); 
      } else {
          $value = urlencode($value);
      }
      $req .= "&amp;$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' =&gt; $user_name,
            'mail' =&gt; $user_email,
            'pass' =&gt; $password,
            'status' =&gt; 1,
            'init' =&gt; $user_email,
            'roles' =&gt; array(
              DRUPAL_AUTHENTICATED_RID =&gt; $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';
  }
  </code></pre>
  
  <p>Here is my watchdog errors --</p>
  
  <pre><code>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
  </code></pre>