11

I need a function that will correctly parse NVP into PHP array. I have been using code provided by paypal but it did not work for when string length was specified next to the name.

Here is what i have so far.

private function parseNVP($nvpstr)
{
    $intial=0;
    $nvpArray = array();

    while(strlen($nvpstr))
    {
        //postion of Key
        $keypos= strpos($nvpstr,'=');
        //position of value
        $valuepos = strpos($nvpstr,'&') ? strpos($nvpstr,'&'): strlen($nvpstr);

        /*getting the Key and Value values and storing in a Associative Array*/
        $keyval=substr($nvpstr,$intial,$keypos);
        $vallength=$valuepos-$keypos-1;
        // check if the length is explicitly specified
        if($braketpos = strpos($keyval,'['))
        {
            // override value length
            $vallength = substr($keyval,$braketpos+1,strlen($keyval)-$braketpos-2);
            // get rid of brackets from key name
            $keyval = substr($keyval,0,$braketpos);
        }
        $valval=substr($nvpstr,$keypos+1,$vallength);
        //decoding the respose
        if (isValidXMLString("<".urldecode($keyval).">".urldecode( $valval)."</".urldecode($keyval).">"))
            $nvpArray[urldecode($keyval)] =urldecode( $valval);
        $nvpstr=substr($nvpstr,$keypos+$vallength+2,strlen($nvpstr));
     }
    return $nvpArray;
}

This function works most of the time.

Mike Starov
  • 7,000
  • 7
  • 36
  • 37

2 Answers2

16

The best way is the parse_str function. It will parse a URLencoded string into a PHP array.

So your code would look like:

private function parseNVP($nvpstr)
{
  $paypalResponse = array();
  parse_str($nvpstr,$paypalResponse);
  return $paypalResponse;
}
Josh
  • 10,961
  • 11
  • 65
  • 108
  • 1
    This is incorrect since parse_str on "note[6]=aaaaa stuff=2" will result in array('note'=>array(5=>'aaaaa '),'stuff'=>2) the result should be array('note'=>'aaaaa ', 'stuff'=>2) – Mike Starov Mar 31 '10 at 17:29
  • 4
    No. The result should not be `array('note'=>'aaaaa ', 'stuff'=>2)`. for that you'd have "note=aaaaa&stuff=2". My answer is not incorrect. I have built a paypal payment gateway integration in PHP using the code I sent. It processes thousands of transactions a month just fine. – Josh Mar 31 '10 at 19:19
  • 2
    The string length should not be specified next to the string like that. It's not how PayPal NVP works. Read their manual. "The request and response are URL-encoded" https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_NVPAPIOverview – Josh Mar 31 '10 at 19:22
  • 3
    The result for note[6]=aaaaa &stuff=2 should be array('note'=>'aaaaa ', 'stuff'=>2). What you use works 99% of the time. And the manuals are great but they don't match code at times. I know for a fact that PayPal sometimes sends NVP with length specified, Usually it happens when customers enter notes on PayPal page. – Mike Starov Jul 15 '10 at 23:28
  • 2
    I've been using the code supplied in production for years with no issues whatsoever... – Josh Jul 17 '10 at 14:04
  • Please note that - starting from PHP 5.3.9 - the number of variables parsed by parse_str is subject to the `max_input_vars` configuration option ( [Manual](http://php.net/manual/en/info.configuration.php#ini.max-input-vars) ) with a default of 1000. Parsing large TransactionSearch-results are very likely to fail. – tillz May 09 '15 at 12:05
0

Googling a lot I've found this:

function deformatNVP($nvpstr) {

    $intial=0;
    $nvpArray = array();


    while(strlen($nvpstr)){
        //postion of Key
        $keypos= strpos($nvpstr,'=');
        //position of value
        $valuepos = strpos($nvpstr,'&') ? strpos($nvpstr,'&'): strlen($nvpstr);

        /*getting the Key and Value values and storing in a Associative Array*/
        $keyval=substr($nvpstr,$intial,$keypos);
        $valval=substr($nvpstr,$keypos+1,$valuepos-$keypos-1);
        //decoding the respose
        $nvpArray[urldecode($keyval)] =urldecode( $valval);
        $nvpstr=substr($nvpstr,$valuepos+1,strlen($nvpstr));
     }
     return $nvpArray;
}

Source.

I DO NOT own this code and I don't have tested it, so use it with care.

xdola
  • 562
  • 2
  • 8
  • 23