2013-06-20 09:03 阅读 71


I have a PayPal business account. I generated an API username, password, and signature, and copied some PHP code from a previously-made website that would process payment fields on a form.

In the previously-made website, everything runs fine, to this day. However, in this new website, as long as the credit card number is valid, I can make up a name, input the wrong expiration date, input a bogus card security code, and make up an address, and the payment still goes through! I see my PayPal balance increase, and I also see the charge on my credit card! I'm not using the sandboxed environment at the moment.

How can that be possible? Also, perhaps worth noting, the charge comes up on my credit card's pending transactions as some irrelevant business, "Sally Beauty Supply." Nowhere in my code have I written these words! I tried both an American Express and a Visa Card.

Here's my code. Everything is copied from the previously-made website, except where noted by <REPLACED>. Code has been simplified a little bit.

$paypal = array(
    'version'   => '85.0',
    'endpoint'  => 'https://api-3t.paypal.com/nvp',
    'username'  => '<REPLACED>',
    'password'  => '<REPLACED>',
    'signature' => '<REPLACED>',

$request_params = array
                      'METHOD' => 'DoDirectPayment',
                      'USER' => $paypal['username'],
                      'PWD' => $paypal['password'],
                      'SIGNATURE' => $paypal['signature'],
                      'VERSION' => $paypal['version'],
                      'PAYMENTACTION' => 'Sale',
                      'IPADDRESS' => $_SERVER['REMOTE_ADDR'],
                      'ACCT' => $_POST['form_PaymentCardNumber'],
                      'EXPDATE' => $_POST['form_PaymentCardExpiryMonth'].$_POST['form_PaymentCardExpiryYear'],
                      'CVV2' => $_POST['form_PaymentCardCVV2'],
                      'FIRSTNAME' => $_POST['form_PaymentFirstName'],
                      'LASTNAME' => $_POST['form_PaymentLastName'],
                      'STREET' => $_POST['form_PaymentAddressLine1'],
                      'STREET2' => $_POST['form_PaymentAddressLine2'],
                      'CITY' => $_POST['form_PaymentCity'],
                      'STATE' => $_POST['form_PaymentStateProvince'],
                      'COUNTRYCODE' => $_POST['form_PaymentCountry'],
                      'ZIP' => $_POST['form_PaymentZipPostalCode'],
                      'AMT' => $_POST['form_PaymentAmount'],
                      'CURRENCYCODE' => 'USD',
                      'DESC' => "<REPLACED>"

$nvp_string = '';
foreach($request_params as $var=>$val)
   $nvp_string .= '&'.$var.'='.urlencode($val);

$curl = curl_init();
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
curl_setopt($curl, CURLOPT_URL, $paypal['endpoint']);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $nvp_string);
$result = curl_exec($curl);

function NVPToArray($str)
   $proArray = array();
      // name
      $keypos= strpos($str,'=');
      $keyval = substr($str,0,$keypos);
      // value
      $valuepos = strpos($str,'&') ? strpos($str,'&'): strlen($str);
      $valval = substr($str,$keypos+1,$valuepos-$keypos-1);
      // decoding the respose
      $proArray[$keyval] = urldecode($valval);
      $str = substr($str,$valuepos+1,strlen($str));
   return $proArray;

$result = NVPToArray($result);

$paid = false;

if (strtoupper($result['ACK']) === 'SUCCESS' ||
    strtoupper($result['ACK']) === 'SUCCESSWITHWARNING')
    $paid = true;

Should I not have copied 'version' => '85.0' and/or 'endpoint' => 'https://api-3t.paypal.com/nvp'? Or, what is it?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    douban5644 douban5644 2013-06-20 14:18

    That should be all that you need to do if you are using the same type of payment service. As for the payment going through with incorrect information, this can happen. First there is no check that looks at the name that is provided. The only checks are the CSC and AVS checks. So regardless if you enter in the incorrect name or expiration date, the payment can still go throgh. For example, the exp date gets passed over to the processor and then on to the card issuing bank. So they may or may not even look at the exp date, there is no real check to make sure it matches. I have seen some cards get approved and others get declined.

    As for the AVS and CSC checks, keep in mind that the gateway sends them to the processor who in turns sends them to the card issuing bank. Then the response is sent back to the processor > gateway > merchants website. Again the bank will approve these transactions, they simply send back if it matches or not. Its then up to you to reject the transaction based on the response. The only way the bank declines them is if the card holder has some time of security checks set up on their acct stating the AVS and CSC must match. When you get the response back on your side that they dont match, you can either code the logic into your system to reject/credit/void these transactions or you can add on and set up filters on your PayPal or Payflow account to automatically do this for you.

    点赞 评论 复制链接分享