Dynamic Paypal Button Generation - Isn't It Very Insecure

Dynamic PayPal button generation - isn't it very insecure?

You should use the PayPal Button API such as below:

$sendPayData = array(
"METHOD" => "BMCreateButton",
"VERSION" => "65.2",
"USER" => "username",
"PWD" => "password",
"SIGNATURE" => "abcdefg",
"BUTTONCODE" => "ENCRYPTED",
"BUTTONTYPE" => "BUYNOW",
"BUTTONSUBTYPE" => "SERVICES",
"BUTTONCOUNTRY" => "GB",
"BUTTONIMAGE" => "reg",
"BUYNOWTEXT" => "BUYNOW",
"L_BUTTONVAR1" => "item_number=$invoiceNumber",
"L_BUTTONVAR2" => "item_name=$invoiceType",
"L_BUTTONVAR3" => "amount=$invoiceTotal",
"L_BUTTONVAR4" => "currency_code=GBP",
"L_BUTTONVAR5" => "no_shipping=1",
"L_BUTTONVAR6" => "no_note=1",
"L_BUTTONVAR7" => "notify_url=http://www.abc.co.uk/paypal/ipn.php",
"L_BUTTONVAR8" => "cancel_return=http://www.abc.co.uk/paypal/thanks",
"L_BUTTONVAR9" => "return=http://www.abc.co.uk/paypal/return.php"
);

You can then send that with cURL to their API

$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_URL, 'https://api-3t.paypal.com/nvp?'.http_build_query($sendPayData));
$nvpPayReturn = curl_exec($curl);
curl_close($curl);

To then generate a encrypted HTML button that cannot be edited

<form action="https://www.paypal.com/cgi-bin/webscr" method="post"> 
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----
">
<input type="image" src="https://www.paypal.com/en_US/i/btn/btn_paynow_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online.">
<img alt="Sample Image" border="0" src="https://www.paypal.com/en_GB/i/scr/pixel.gif" width="1" height="1">

These links should help you with the button options:

https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_nvp_BMCreateButton

https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_api_ButtonMgrAPIIntro

Dynamic Paypal button encryption

maybe you could try putting those variables in a temporary table with a unique id. then use that id for the buttons. querying the variables from the table whenever the customer clicks the paypal buttons. I just hope i understood your statement right xD

Dynamically generating PayPal buttons

Doing it that way isn't very secure because people can still view source and see the end-result on your page. Then they could take that, make changes to it, load it in their own browser and pay you for an item at a much lower price.

You can utilize IPN to help flag orders that don't look accurate by cross-references your pricing, but this can be a hassle.

You could use the Button Manager API to generate your buttons as hosted buttons on PayPal. This way people can't see the details in the source code and wouldn't be able to make changes.

Alternatively, you could use the Express Checkout API which is what I prefer and recommend if you know how to work with web service API's.

Dynamically generating PayPal buttons

Doing it that way isn't very secure because people can still view source and see the end-result on your page. Then they could take that, make changes to it, load it in their own browser and pay you for an item at a much lower price.

You can utilize IPN to help flag orders that don't look accurate by cross-references your pricing, but this can be a hassle.

You could use the Button Manager API to generate your buttons as hosted buttons on PayPal. This way people can't see the details in the source code and wouldn't be able to make changes.

Alternatively, you could use the Express Checkout API which is what I prefer and recommend if you know how to work with web service API's.

Setting dynamic amounts securely with Paypal payments with a redirection and not button?

Ok, I finally found out that not only does the response from the BMUpdateButton API return the HTML to create a form, it also returns other data as well within the returned array.

Once you make the request it will return an array with three keys as per the BMUpdateButton Response section on the API page linked above.

These are:

  • WEBSITECODE

    HTML code for web pages

    • EMAILLINK

This is what I was looking for; a plain link you can redirect users to

  • HOSTEDBUTTONID

The id of the button.

Be advised when altering the contents of a hosted button you need to pass all the details of the button to it as when you created it; so as an example, if you leave out passing it an item name the item name will be blank and Paypal will allow the user to set it.

Also, an important note is that when you update the button details, it isn't just updated for that users session, it updates it within your paypal account - so the new name/price etc will affect all users that attempt to use it.

If you still would like to update the details of the button you can do that with the below:

I personally started with this class:

<?php

class Paypal
{
/**
* Last error message(s)
* @var array
*/
protected $_errors = array();

/**
* API Credentials
* Use the correct credentials for the environment in use (Live / Sandbox)
* @var array
*/
protected $_credentials = array(
'USER' => 'seller_1297608781_biz_api1.lionite.com',
'PWD' => '1297608792',
'SIGNATURE' => 'A3g66.FS3NAf4mkHn3BDQdpo6JD.ACcPc4wMrInvUEqO3Uapovity47p',
);

/**
* API endpoint
* Live - https://api-3t.paypal.com/nvp
* Sandbox - https://api-3t.sandbox.paypal.com/nvp
* @var string
*/
protected $_endPoint = 'https://api-3t.sandbox.paypal.com/nvp';

/**
* API Version
* @var string
*/
protected $_version = '74.0';

/**
* Make API request
*
* @param string $method string API method to request
* @param array $params Additional request parameters
* @return array / boolean Response array / boolean false on failure
*/
public function request($method, $params = array())
{
$this->_errors = array();
if (empty($method)) { //Check if API method is not empty
$this->_errors = array('API method is missing');
return false;
}

//Our request parameters
$requestParams = array(
'METHOD' => $method,
'VERSION' => $this->_version
) + $this->_credentials;

//Building our NVP string
$request = http_build_query($requestParams + $params);

//cURL settings
$curlOptions = array(
CURLOPT_URL => $this->_endPoint,
CURLOPT_VERBOSE => 1,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
CURLOPT_CAINFO => dirname(__FILE__) . '/cacert.pem', //CA cert file
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => $request
);

$ch = curl_init();
curl_setopt_array($ch, $curlOptions);

//Sending our request - $response will hold the API response
$response = curl_exec($ch);

//Checking for cURL errors
if (curl_errno($ch)) {
$this->_errors = curl_error($ch);
curl_close($ch);
return false;
//Handle errors
} else {
curl_close($ch);
$responseArray = array();
parse_str($response, $responseArray); // Break the NVP string to an array
return $responseArray;
}
}
}

?>

Credit: https://www.smashingmagazine.com/2011/09/getting-started-with-the-paypal-api/

Then I did the below:

include(dirname(__FILE__) . '/includes/paypal.class.php');

$paypal = new Paypal();

// Set our method
$method = 'BMUpdateButton';

// Set our params
$params = array(
'HOSTEDBUTTONID' => 'your_button_id',
'BUTTONTYPE' => 'BUYNOW',
'BUTTONSUBTYPE' => 'SERVICES',
'L_BUTTONVAR0' => 'item_name=Your Description',
'L_BUTTONVAR1' => 'amount=999.00',
'L_BUTTONVAR2' => 'currency_code=AUD',
'L_BUTTONVAR3' => 'cancel_return=http://www.example.com/cancel.html',
'L_BUTTONVAR4' => 'return=http://www.example.com/success.html'
);

// Make request to change button details
$result = $paypal->request($method, $params);

Note that while Paypal say that BUTTONSUBTYPE is optional, you will likely get an error if you don't include it.

Paypal dynamic button and Linking with IPN

I'm just going to answer my OWN question. The solution is to just compare the "item_name" and "amount" variables and make sure they are exactly the same if say I generated using a database. And if someone tampers it and pays me $1.00 instead of $100.00 then thats a free donation and bad luck for them :P

What I will be doing is this:

  1. Create a database to store item name, amount, currency etc.
  2. On the shopping page I will dynamically generate it using the item_name and amount
  3. Set up my paypal to send transactions made to the IPN listener that I will make
  4. Using the database to compare the item_name and amount, it will validate whether it is a valid form submission or not.

Simple! I like it! WOO!



Related Topics



Leave a reply



Submit