Tuesday, 10 January 2012

Salesforce - Paypal Masspay Integration

It took me less than two hours to get processing test transactions with the PayPal Sandbox and Salesforce.com. This blog will cover how I setup the MassPay API, to allow my Salesforce application to send money to customer accounts, on demand.

Very quickly, first of all, MassPay is the Paypal API for transacting money from one Paypal account to many others, it is called MassPay because it can handle up to 250 accounts and transaction amounts in one go. If you want to integrate a "customers paying for stuff" shopping experience, maybe give this blog a read as well, http://techsahre.blogspot.com/2011/01/simple-paypal-integration-with.html

The basic process of integrating with the PayPal API involves dispatching an XML request to their web-service endpoint, interpreting the response, and then listening out yourself for incoming IPN messages from PayPal, which deliver status updates and information on your transactions as they are processed. This UML model roughly outlines the experience.


In this blog post, I will discuss the first half of the process. If you'd like to skip off and discover more about the IPN update messages, there is a second blog post by myself called Salesforce Paypal IPN Integration.

So first of all let's head over to the Paypal sandbox at https://developer.paypal.com/ and first register ourselves a PayPal developer account. Once you're in, create yourself two preconfigured accounts, make sure one is described a PayPal Payments Pro account - which will become the source of your money (so give it a chunky balance). The other can be a Buyer or Seller account, and this will be the test account that will receive the money. You can create as many of these as you like, depending on how thoroughly you like to test!

Now, we need to activate API access to the Pro account. So from the PayPal accounts list, select the Pro account and click "Enter Sandbox Test Site" and log in. Follow these steps:
  • Click "Profile" (the last item on the second menu under "My Account")
  • Click "Request API Credentials" underneath "Account Information"
  • In Option 1 click "Setup PayPal API credentials and permissions"
  • In Option 2 click "View API Signature"
  • Copy out your API Username, API Password and Signature.

We're now done on the PayPal side of things. So log in to your Salesforce.com account. As this blog is just about integration, I will talk you through a fairly simple demo, and you can then deploy the knowledge it gives you as you see fit.

For this demo, we are going to work with one simple custom object, called Paypal_obj. The MetaData for this is on the GitHub repository for this project, in the folder demo/pages


 https://github.com/srlawr/PaypalSFDC/tree/master/demo/objects


But for ease of click-development, here it is in UML for you to work through.


I set the label to "Paypal Payment" and the Record name to "Payment number" - as an Auto-numbering field, format:




PP-{0000}


and starting at "1".


 Once you have this custom object set up, you can go ahead and create a few records. Make sure your Paypal_status field is defaulting correctly to "Unpaid" and in the Paypal_email field, put (mostly) the e-mail addresses associated with the test buyer and seller accounts you created in PayPal above. Any e-mail addresses that arn't in that list, will be your test cases for failure, because they won't work!

With a bunch of unpaid PayPal payments in our app though, we'd best create the payment processing class to deal with them...

Click on Your Name > Setup > Develop > Apex Classes and select "New" (or, if you use an IDE, create a new class file). Now, head over the the GitHub repository for this integration and get hold of a copy of the PaypalProcessor.cls. 

https://github.com/srlawr/PaypalSFDC


Copy all this this code into the file, and give it a good read. It is explained through the comments. Most importantly, copy your API user details and signature (collected above) into the relevant fields in the generateRequest function. (Note: For production, please move these out to at least a Custom Setting Object!).

Before we can interact with the PayPal servers, you need to grant your organisation access to the Paypal web services. Click Your name -> Setup -> Security Controls -> Remote Site Settings, now add the following site to the list:


Paypal_SOAP:    https://api-3t.sandbox.paypal.com/2.0/

At this point, we basically have a functioning back end integration with PayPal. But.. it'd probably be nice to have a little UI for executing payments, not least for testing. So before we start firing SOAP requests all over the place, lets set up a page and controller to give us something to look at.

First, lets add the custom controller class to our application. Create a new Apex class and copy the contents of the approvedPaypalController.cls into it from GitHub

https://github.com/srlawr/PaypalSFDC/tree/master/demo/classes


Once that is saved, click through Your name -> Setup -> Develop -> Pages and set up a new page called Payment_List. Copy the contents of the Payment_List.page file on GitHub into the body of the page:

https://github.com/srlawr/PaypalSFDC/tree/master/demo/pages


 I personally then like to create a new custom Visualforce Tab to access this page, which is a lot easier than having to navigate to the URL over and over again.

With this page, controller, and tab, and a handful of test records, you should find yourself with a setup not a million miles away from this:




Now, I would imagine you are very excited right now about that custom action button "Pay out"... and so long as you have everything appropriately set up (in Sandbox) you should be able to click it. Go ahead!

The result should be a green success message at the top of the page, and all of your payment objects will have been updated to status "Sent".. much like below:



If you now log into your PayPal Payments pro account and have a look (click on "All account activity" or "Payments sent"), you should see a transaction appear for the total amount of your payments, and also the PayPal Fees amount the request would have cost.

 If you only paid out to e-mail addresses in your list of sandbox accounts, I would expect the transaction Payment Status to be "Completed" - but if (like in the screenshots above) you had other accounts involved in the mix, it will be "Processed" - because technically, PayPal will still be waiting for those accounts to collect their money - which in Sandbox they can actually never do.

So that's it! We're kind of there. The PayPal Mass Payments API has been invoked, and we have sent potentially thousands of pounds (or dollars) out into the Internet.

Of course, when we send money out on to the internet, most people want to know what has happened to it, and that is the second half of the process, which I will cover in a subsequent post, called Salesforce Paypal IPN Integration.

(by the way, if you have clicked "Pay Out" reverting the processing is as easy as editing the records and setting their status back to "Unpaid" - a testing loop you're probably going to become very familiar with.)

20 comments:

  1. Was searching for something else and can't say how I ended here. But really informative and useful stuff that certainly is useful for me and every one alike.
    Thanks a lot.

    ReplyDelete
    Replies
    1. Thank you very much Suri. I'm glad the information was useful to you. I will be presenting this Salesforce/PayPal integration work on the developer track at DreamForce 2012 in San Fransisco if you are interested :)

      Delete
  2. Hi there
    If I received an error: "Failure". Can you help me with debugging. Some starting points would be great.

    Thanks
    Sean

    ReplyDelete
    Replies
    1. Hi Sean.

      I take it you are getting "Failure" immediately after the first HTTP request for the payment?

      This "Failure" message comes from line 46 of the approvedPayPalController, and is driven from the boolean result of processNewPayments on line 30 of PaypalProcessor.

      Typically, this failing will have generated a System.debug message in Salesforce, so I would suggest checking that, it'll probably tell you straight away what's up. Other than that, I would check:

      Remote Site Settings
      Paypal sandbox API access enabled
      Paypal API credentials

      Hope that helps..

      Simon

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hi Uzair. Did you find a solution to your problem??!! Was it just a timing issue perhaps?

      Cheers.

      Delete
    2. Thanks for your reply.

      The issue which I mentioned in my previous comment is solved. I have other problem; The Paypal status is not updating to 'Completed'. Even in the paypal sandbox IPN History page I'm not getting any transaction ID.

      Could you please help me with this new issue

      Delete
  4. This comment has been removed by the author.

    ReplyDelete
  5. This was worth it Simon, what if someone has a requirement for billing on their customers/contacts on monthly basis using their customers credit card number stored in salesforce?

    ReplyDelete
    Replies
    1. Hi Reshu,

      You can use recurring payments as part of the standard Paypal API (i.e. use that instead of Mass Payments) but the IPN system would remain the same as far as I know, you would simply get a message back telling you the request was successful and established. You'd have to consult the documentation to see how to stop a recurring payment! I imagine it is just another payment message, which would also be confirmed by IPN.

      Is there a reason you would use Paypal for this rather than a credit card gateway installed on Salesforce? I would check the App Exchange for one of those, or get in touch with me and we can see if Desynit can help you out.

      Simon

      Delete
    2. Thanks for your reply.

      No there is no such exact requirement for paypal,yes it would be great help if you can suggest any credit card gateway app, very simple and basic which can automate billing on customers stored as contact on monthly/weekly basis.

      Delete
  6. Hi Simon,
    I am getting the error after clicking on the pay out button.
    I have checked the debug log but couldn't get anything from there which can tell me from where the error is originating.
    Do we have to use the 'purl' as it is or make changes to it too according to our paypal app?
    Thankyou

    ReplyDelete
  7. Also I didn't understand the use of Test.isRunningTest() in the 31st line of the approvedPaypalController.cls. When does it avaluates to true? and do we have to create a test class for the processor class and maybe thats why I am getting the error?

    ReplyDelete
  8. Hi Simon, Can you help me with the error I encountered? Thanks!

    Visualforce Error
    Help for this Page

    System.XmlException: ParseError at [row,col]:[7,3] Message: The element type "p" must be terminated by the matching end-tag
    Error is in expression '{!pay}' in component in page payment_list

    Class.PaypalProcessor.processSOAPPayments: line 74, column 1
    Class.PaypalProcessor.processNewPayments: line 12, column 1
    Class.approvedPaypalController.makePayment: line 37, column 1
    Class.approvedPaypalController.pay: line 16, column 1

    ReplyDelete
  9. Hi simon can u help me....
    How to integrate the paypal masspay in django

    ReplyDelete
    Replies
    1. I'm afraid not, as I'm not a Python developer! The philosophy of these blog posts will be the same though - regarding the paypal setup and SOAP/post/get structures and contents. It must be quite possible to consume SOAP web services on django?

      Delete
  10. Hi Simon your articles are really helpful ,i am struggling to know one thing is that,can we integrate SALESFORCE to SURVEYGIZMO as it is already INTEGRATE with STRIPE.

    any help is much appreciate .
    thank you

    ReplyDelete
    Replies
    1. Yes, I have no doubt you can integrate SurveyGizmo with Salesforce, as outlined in their API documentation here http://apisurveygizmo.helpgizmo.com/help - it appears that this facilitates OAuth to to SurveyGizmo, and then the ability to create polls and questions, and to pull response data from SurveyGizmo.

      Looks very well thought out and structured. (I wish all integrations had documentation and examples like that).

      Delete
  11. Hi I followed this and all was a success - THANK YOU! NOW i need to make all LIVE - assuming anywhere 'sandbox' is referenced needs to be changed?! help.. thanks!

    ReplyDelete
  12. Hi Simon,
    I am getting "Error: Failure" after clicking on the pay out button.
    I checked the debug log but I couldn't get anything from there.
    Could you help me, please?
    Thank you

    ReplyDelete