5

Ok, I haven't worked with hosted buttons before, but it makes sense as they are a lot more secure.

I have looked around and been reading the docs (which aren't all that helpful) and best help I have found so far is here; though I am still confused on where exactly to put that code?

Also, I technically don't want a "button", but the idea behind them seems what I want.

All I want to do is use the same query vars every time but just want to change the price - the price is dynamic depending on what the user selects in the form.

Additionally, I don't want a button per se, I would much prefer to redirect the user to paypal with the appropriate data but not sure how to go about doing that whilst setting a dynamic price?

If I didn't have to set a dynamic price I know I could just append the query vars for a hosted button onto a URL and then redirect to that URL, but I need to change the price and hence my question...

Community
  • 1
  • 1
Brett
  • 19,449
  • 54
  • 157
  • 290
  • I _don't_ use it but [this reference](https://developer.paypal.com/docs/classic/api/#bm) should help. Seems you 'll have to make a _server side_ request (`NVP` or `SOAP`) to "create a button". The response to that request will either contain [HTML, a link, or an ID](https://developer.paypal.com/docs/classic/api/button-manager/BMCreateButton_API_Operation_NVP/) Hth. – EdSF Feb 14 '16 at 17:20
  • Yeah I seen those pages but it looked to me like all it does is create the html output for a button; I guess I can always just load the html onto a page and automatically submit the page via JS or something. Was hoping there would be something a bit more user friendly to use. – Brett Feb 15 '16 at 12:30
  • You _shouldn't_ do any of the hashing/encryption client side (Javascript) because if you did, you pretty much break what you're looking for - _securing_ the transaction from tampering. That's what hosted buttons do - protect from tampering. Any type of hashing/encrypting should be done server side, beyond the reach of any browser/client. Only _after_ that (already hashed/encrypted) should you consider any client side flow. – EdSF Feb 15 '16 at 17:03
  • I'm aware of that - that is why I wanted to use a hosted "button"; but not actually use the button - and hence is why I said perhaps I could load the generated button code onto a page and automatically submit it. Not ideal though. – Brett Feb 16 '16 at 11:30

3 Answers3

2

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.

Brett
  • 19,449
  • 54
  • 157
  • 290
0

You need to use their button designer if you're going to do hosted buttons.

https://www.paypal.com/us/cgi-bin/webscr?cmd=_button-designer

The security comes from IPN verification after the transaction.

See:

https://www.paypal.com/us/cgi-bin/webscr?cmd=p/acc/ipn-info-outside

Validate that IPN call is from PayPal?

The answer on this post is a better way to do it:

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

Community
  • 1
  • 1
Matt
  • 5,315
  • 1
  • 30
  • 57
  • Thanks but I'm aware of how to create the buttons - what I'm trying to work out is how to get the correct data to pass to paypal so I can send to them via a redirect with query vars. So instead of it returning html to me to put a button on my site I would just like a query string returned or JSON or something more workable. – Brett Feb 19 '16 at 14:07
0

Button code is HTML form tags based so you would easily convert it to a string query and assemble your dynamic payloads with this format:

https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=yourAccount@email.com&item_name=itemNameTest&item_number=123&amount=1&currency_code=USD&no_shipping=1

Customize it and append vars per the varliables listed HERE, and use it with your redirection method.

Button manager API is more comprehensive except it won't return you a query string URL like this, though the idea behind is identical to an HTML form code snippet

pp_pduan
  • 3,392
  • 1
  • 9
  • 15