One of my clients decided to make the switch from Authorize.net to PayPal’s Payflow Pro gateway last week. I knew this would be a headache, but I decided to offer a reasonable time estimate for the task of integrating with the gateway API (knowing I’d likely go over budget).

Everything went smoothly until the very last step of submitting a payment request. So, I’m going to share my experience to save everyone else the trouble. I’ll list out the steps below, but also provide the full code at the end.

  1. Visit https://developer.paypal.com and create a sandbox application. You’ll need the client id and client secret.
  2. Get an authorization token. In true OAuth fashion, we exchange the client id and secret for an authorization token. This is actually pretty simple, once you figure out how to make it happen with ColdFusion’s CFHTTP tag.The trick was to actually pass the client id and secret in the username and password arguments of the CFHTTP call.
  3. Issue a request. In my case, I only needed to make a payment request. The PayPal documentation was a bit tricky, it’s syntax looked like this:Authorization: Bearer <access-token>So naturally, I wrapped the access token in <..> and the calls continued to fail. Once I formatted the Authorization header like this, everything worked:<cfhttpparam type=”header” name=”Authorization” value=”Bearer #accessToken#”>
  4. Setting up a test. Here’s where days went by with no solution. PayPal support was unfortunately unresponsive.  My test looked like this (calling a CFC method I created):
    
    <cfset response = paypal.capture(
    card_type = "visa",
    card_number = "4111111111111111",
    card_exp_month = "12",
    card_exp_year = "2016",
    card_firstname = "Bob",
    card_lastname = "Smith",
    amount = 5.25,
    description = "Order 1001")>
    

    Looks okay, right? Using “real-looking” data and the usual test credit card number that we’re all familiar with.

    Wrong! PayPal, for some reason, does not support the 4111… credit card #!After a couple days, I found this out on StackOverflow, and changed the test card number to 4556747948786484.

    That’s it! I got a valid response from PayPal.

So, with all that trial and error behind me, here’s the full code to the ColdFusion PayPal Payflow Pro REST API CFC that I created.

And, quick code to test against the CFC:

<cfset paypal = createObject("component", "components.PayPalPayFlow").init(
 client_id = "your_client_id",
 client_secret = "your_client_secret",
 sandbox = true)>

<cfset response = paypal.capture(
 card_type = "visa",
 card_number = "4556747948786484",
 card_exp_month = "12",
 card_exp_year = "2016",
 card_firstname = "Bob",
 card_lastname = "Smith",
 amount = 5.25,
 description = "Order 1001")>

<cfoutput>#response#</cfoutput>

 

Tags:

37 Comments

  1. Was there no documentation outlining the test credit card numbers? I recently implemented CyberSource’s Silent Order Post payment process and their documentation had a list of valid test CC numbers for all major cards. The problem that I ran into was they changed their API partway through development and if they notified my company, whomever in my company got the email didn’t notify me.

    1. Yeah, the 4111… is actually in the Payflow Developer’s Guide PDF. So that’s the one I chose as I’m used to using it with Authorize.net.

      But as you said, they must have changed their API at some point without updating their docs.

      Maybe someone out there actually got issued a real 4111… credit card # and that spoiled it as a testing card #!

    1. Glad to hear it Aaron, there’s a deficiency of ColdFusion blogging out there so every little bit helps!

    1. I honestly haven’t kept up with any changes to the PayPal API, but it still functions on the site’s I’m using it for.

      What’s the error?

      1. Thanks, that seemed to help some, but now another error here:
        JSON parsing failure at character 1:’C’ in Connection Failure

        79 :
        80 :
        81 :
        82 :
        83 :

  2. Hi – thanks for making a huge dent in what is some very confusing documentation over at PayPal – I have everything in a CFC, however getAuthToken() is returning utterly nothing. I have clientID, secret etc, the only thing I have changed is the func name and access type. Help anyone?

          1. Im calling my cfc with a standard ajax call, passing nvp as json including the method etc, standard method i use with all my projects, nothing special.

            The cfc contains your code verbatim, only changes as I mentioned were renaming the function to ‘pay’ and setting the access to remote as you would expect.

            Posting my code would be repeating what you have already, and what is mostly a textbook jquery ajax call:

            function fetch(meth,cb,cfc,args){
            var a = {method:meth,argumentCollection:args};
            $.ajaxSetup({async:true,cache:false});
            if (!cb){cb=function(data){return data;}}
            $.ajax({type: ‘GET’,url: ‘/cfc/’+cfc+’.cfc’,
            data: a,
            success: cb,
            error: function(e){
            if(e.responseText !=””)
            $.notifyClose();
            if(e.responseText!=””)
            notice(e.responseText,”danger”,9000);
            }
            })
            }

          2. Just trying to get a complete picture. Which CFC method are you actually calling with your AJAX call.

            You mentioned above that you were having issue with getAuthToken(). It seems odd to change that method name to “Pay”, since that’s not what it does.

            I’m not a jQuery guru, but I know sometimes that $.ajax call likes to know what format the response will be in.

            Maybe try serializeJSON on the results of your CFC method, and add dataType: ‘json’ to your AJAX call.

          3. Serialized or not, i should be able to dump or output the struct, however there is nothing to dump, still not sure what is going wrong with this thing. The actual error that I get is that access_token is not defined, which is only because there are no struct items.

          4. Suggestions? Also I have only renamed the main func, this should not effect anything. And, did you know you can set returnformat=”json” on the function, then append any variables to a struct to return clean json?

  3. Hi – I have started this again (no ajax or anything else), using your exact code to the letter, I still have the same issue with getting a token. I have triple checked my clientID and secret, not sure whats going on. If you have the time I would appreciate any help you could give me.

    1. I think, at this point, I would submit a ticket to PayPal Developer Support. I have used them before and found them knowledgeable and somewhat responsive.

      Another thing to try, is to use an SDK from another language and see if you have any issue connecting. That might inform you if the issue is with your PayPal account or the CF code.

        1. Nice find! How strange that it worked in my case without the Base64 encoding. Thanks for posting your fix.

  4. Hi,
    very helpful post

    i’m trying to pass billing address with paypal api but its throwing me error

    {“name”:”VALIDATION_ERROR”,”details”:[{“field”:”payer.funding_instruments[0].billing_address”,”issue”:”This field name is not defined for this resource type”}],”message”:”Invalid request – see details”,”information_link”:”https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR”,”debug_id”:”2dea65b2dc0b6″}

    Please help me

  5. this a great bit of code for you to openly share. Thanks.

    I am hitting an issue that I’m unsure how to resolve.

    I’m getting this error:

    Element ACCESS_TOKEN is undefined in RESPONSE.
    line 83.

  6. OK, I’ve spent the past day or so trying to figure out this error, returned from PayPal. It seems related to “amount” being passed to PayPal, but I’ve not changed anything the code and see no reason the amount being passed would not meet the criteria.

    {“name”:”VALIDATION_ERROR”,”details”:[{“field”:”transactions[0].amount.total”,”issue”:”Currency amount must be non-negative number, may optionally contain exactly 2 decimal places separated by ‘.’, optional thousands separator ‘,’, limited to 7 digits before the decimal point”}],”message”:”Invalid request – see details”,”information_link”:”https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR”,”debug_id”:”fcf1d532a3bc9

    1. What do you see when you the total? Does it contain any space padding? Is it, in fact rounded to 2 decimals?

      I would definitely cfdump the object you are passing in, right before you pass it to PayPal, to see if the total doesn’t match the format.

      1. Thanks for the response. I’m frankly not sure where to dump it.

        I’m still at the stage of passing the sample CFSET you supply, though I’ve fussed around with the amount trying to try different things.

        1. So, I just discovered that I can go into my PayPal developer account and under the Sandbox menu and Transactions, get more detail on what I’m passing.

          For total, I’m passing: “total”: “15.25|||” … so somehow, I have extra spaces there … don’t know why yet, but that appears to be the case.

          1. In the CFC at line 57 the total variable is set and formatted, part of the formating includes: ” & “|||”

            I removed that bit and the transaction processed successfully.

          2. Awesome, thanks for sharing! I haven’t had a need to connect to PayPal via CF anymore, so I unfortunately haven’t been able to stay up with this thread.

Leave a Reply to sitekickr Cancel reply

Your email address will not be published. Required fields are marked *