Paypal Express Checkout with Java

Introduction

Last weekend a friend wanted to enable Paypal payments on his jee website. He didnt have a lot of time himself so he asked me to figure out how to do that.

For some time, I have been thinking about starting a blog about integrating different java technologies and third-party apis with each other, and I figured sharing my experience with integrating Paypal into a website might make for a nice first entry.

So, who are you?

This article is aimed at Java Web developers who have a need to integrate Paypal in their current project. The reader should know the Java programming language quite well, and have at least a basic understanding of servlets and Java web applications. Knowledge about web services and Axis in particular is not required, but definitely recommended.

What we are going to do

We will add a “Buy now”-button to a website for a particular good or service. This button will take us to the paypal site, where a customized checkout page will be shown. The user will be able to pay directly from that page, after which he will be returned to our website, where the order will be further processed, for example, by enabling the service on the spot or by adding the order for the good to a processing queue.

Note that we will be working on a particular use case made possible by the api. It is also possible to let the user only authorize the payment on the paypal site(instead of paying directly), after which he will complete the order and actually press the “pay now”-button on our own website. This alternate use case is not covered by this article.

Available material

The documentation on the subject can be found at Paypal API Documentation.
This tutorial is almost solely based on the Express Checkout Integration Guide, which is in my opinion the most relevant document for most paypal integrations.

The decision that needs to be taken here first is whether to choose for the name-value pair api or the soap web service api. Since I am quite familiar with soap and web services, I decided to go with this option.

So, if you want to go through with this tutorial, you need to download the PayPal API: SOAP Interface for Java on the page mentioned above.

Optional: Generating the soap client yourself.

Note that this skip can be skipped, since the downloaded soap interface is up to date with the wsdl.

The two most important files in the downloaded soap interface above are paypal-base.jar and paypal-stubs.jar. The first contains the compiled sdk while the latter contains the compiled soap client.

All the necessary wsdls and xsd schemas can be found at:

https://www.paypal.com/wsdl/PayPalSvc.wsdl

https://www.paypal.com/wsdl/eBLBaseComponents.xsd

https://www.paypal.com/wsdl/CoreComponentTypes.xsd

https://www.paypal.com/wsdl/EnhancedDataTypes.xsd

To generate a client for these files, we will use the wsdl2java tool.

If you are using Eclipse IDE, an easy way to do this is to install the Jboss Tools Eclipse Plugin, copy the above files into your IDE, rightclick on the main wsdl file and then select Web Services > Generate Client.

A better way however, is to incorporate the client generation into your production build process. When using the build tool Maven for example, you can use the axistools maven plugin to directly generate the client from the specified urls(axistools:wsdl2java). By incorporating it into your build, you make sure that your client will always be up to date.
For example, setOrderTotal for the SetExpressCheckoutService is deprecated right now, in favor of adding an array of PaymentDetails on the object passed to the service, and setting the order totals on those different PaymentDetails. It is likely that this deprecated part of the api will be removed at some point, and if your code would still be using this, would cause the soap call to fail. If this happens – you should be notified by your unit tests of this – you would need to download the most current version again and incorporate it into your project, which will be more time consuming then than having the client generation in your build process.

Step by step tutorial

First of all, I wanted to keep this article free of any other api or framework not included in the standard JDK, so we will discuss all code from easy to run java classes, which unfortunately, you will have to download through Easy Share, because WordPress does not allow uploading zip files. Setting up the actual html pages with forms mapped to the actual actions would just clutter the text and should be trivial for you anyway.

Now, I stole the following diagram from the documentation on the Paypal site. It gives a clear overview on what we are going to do.

The user sends a request to our server by pressing some “buy now with paypal” button on our site. This button is most likely part of a form on a html page, of which the action is mapped to an url like http://www.ourserver.com/buy_our_service_now.xhtml.

Our server receives the request. The server then performs the action mapped to this url, which will first execute the SetExpressCheckoutDetails method, providing Paypal with all the necessary details to render an appropriate checkout page. This method will return a token, which the server will use right away as a request parameter when redirecting to the paypal site.

The user – redirected to the paypal site – authenticates with the paypal site, is shown the appropriate checkout page and does or does not agree to pay for the offered goods or services. In the basic use case, we will assume that the user presses “Pay now” on the paypal site, agreeing to pay for the goods/services, after which the paypal site redirects to our server, probably to an url like http://www.ourserver.com/process_checkout.xhtml?token=tokenvalue. The token is automatically appended by Paypal.

Our server receives the request. The server then performs the action mapped to this url, which will first execute the GetExpressCheckoutDetails method, to get all details from paypal again that were initially passed to paypal by our own server. We then invoke the DoExpressCheckout method, providing the necessary details we just got back, to accept the payment of the user and complete the express checkout. If this method returns “Completed”, we process the checkout further on our server.

Doing SetExpressCheckoutDetails

We assume that the user has clicked our “buy now with paypal” button and the server received his/her request. So, obviously, with regard to the flow we mentioned in the previous section, we do not discuss step 1 since setting it up is trivial and we jump straight to step 2. We execute the SetExpressCheckoutDetails method, providing Paypal with all the necessary details to render an appropriate checkout page, as in the following class.

Note: the most simple way to run this class is to make a project in your IDE and add the class code to a test source folder; go the map in which you extracted the contents of the PayPal API: SOAP Interface and put all the files in the lib folder on the classpath. Then all the necessary dependencies will be satisfied.

The code is pretty self-explanatory. In the main method, we pass all necessary parameters to setup the checkout page at Paypal, after which we use those to build the request and execute it. Paypal responds with a token, unique for this order.

Setting the profile

In the code, a profile is set. This profile determines whether we execute our request on the sandbox or production environment, and as what shop/seller we authenticate with the Paypal server, together with the credentials for that shop/seller. Obviously, if these credentials are incorrect or do not exist, the request will not succeed. In the example, we use the default test account Paypal provides. As we will see later, you will need to create a developer account on http://developer.paypal.com to be able to create “test buyer” accounts, and it is probably better to authenticate with the credentials of that developer account, since then you will be able to customize “the test shop” and consult its transaction memory.

Constructing the details

A few things can be said about the construction of the details object. We pass along 4 things. The paymentDetails, the returnUrl, the cancelUrl and the userId. The paymentDetails object contains the orderspecific information, and in the example, we pass along what is like a minimal set: the description of the order, the invoiceId which should be unique per seller account, the price of the order and the paymentActionType, which is Sale in our example.
The returnUrl is the url paypal will forward the user to after payment and the cancelUrl is the url paypal will forward to upon cancellation of the payment by the user.
We also pass the userId in the custom part of the details. Although this is not necessary, it might help us when Paypal redirects to our returnUrl. We might need to be able to link our buyer to the user on our site then. We could store this information ourself, like link the token returned by Paypal to a particular user in our database, but by putting all information at the Paypal server, our own server does not need to remember anything about the initiated order process so far.

Redirecting to paypal

should have appeared on your console. This is the url the server should redirect to after setting up the checkout page as discussed in the previous section.

Rendering the checkout page on the sandbox

Please copy-paste this url into your webbrowser.

You will get a message that you need to log onto the sandbox first. This is the time you will need to register a developer account at http://developer.paypal.com. Please do so, and once finished, log in with the newly created account.

Once logged in, you will see a tab “Test accounts”.
Make one test account, of account type “Buyer”, and remember its username and password. This test account will be the account with which you shall simulate the buyer on the sandbox.
Make another test account, this time of type “Seller”. Replace the credentials we used so far in the code pointing to the generic merchant with the credentials of this test merchant account. These credentials can be found under the “API Credentials” tab from within your developer account. Do not fail to replace this code. When trying to do the doExpressCheckout method with the generic merchant account, you cant make assumptions about its current configuration, which might lead to unexpected behavior I believe.

Now, copy-paste the url again in your webbrowser and login to the sandbox with the test buyer account.
If everything went well, you should see a page like:

As you can see, the checkout page was rendered according to the order details provided to the SetExpressCheckout method.

The redirect url

Every passed parameter is essential. The cmd parameter tells Paypal it has to render the checkout page. The useraction parameter tells Paypal the payment should occur right now. Because of this, Paypal will also render a “Pay now” button to the user, and also show all details about the order. If this parameter is not passed, the default of useraction=continue is assumed, making paypal believe the order itself will be processed on the site of the seller, and because of this, paypal will not render the order details such as the description and the price whatsoever. The token parameter of course, tells Paypal what order this request is about.

Doing GetExpressCheckoutDetails and DoExpressCheckout

We will assume that our buyer pressed “Buy now” on the checkout page for his particular order. He was redirected to the returnUrl, but in this tutorial, since we do not have a webserver running, nothing happened.

Now, what we would want our webserver to do, is, when receiving the returnUrl request, process the checkout right away.

First, we use the token to fetch all the expressCheckoutDetails from Paypal.

If the paymentstatus after doExpressCheckout returns “Completed”, you should take additional actions, like activating the requested service on your website or adding the order to some queue. If the paymentstatus is something else, pending for example, additional code should be written, for example, to poll Paypal again after 24 hours.

Note: note that doExpressCheckout can only be executed once.
Note also that using the by Paypal provided API credentials will cause the doExpressCheckout to end in “Pending” most of the time. Use the credentials of one of your test merchant accounts.

Comments

8-31-10

Obermaier Dominik says:

Thanks for your useful article on this topic. I really like your blog and you very good articles. Keep up the good work!

Do you know if it’s possible to abort/invalidate a started transaction between SetExpressCheckoutRequest and the redirection of the customer to the PayPal page. Or should I simply let it timeout?

Also I would like to know if it’s possible to roll back a transaction, for example when the customer has been banned from your business before. The problem here is that you don’t know whom you’re selling to, until you get the data from PayPal. :-/

Until you call DoExpressCheckout the transaction is not complete, and even then everything has to match, token, data and no errors. So if someone went to paypal, logged in and paid, and on the round trip you needed to kill the transaction you could, just don’t call DoExpressCheckout.

SetExpressCheckout is an API call and gives you a token to transact with and will send the user to paypal.

Some transactions are not instant payment, such as funding source CC/Bank account since there may not be funds available. Since paypal supports users using multiple email addresses the system could be circumvented, though you do get a payerId back. Not sure if that stays constant with each transaction. Point being, if you really want to block someone, just reject their payment. If they are a merchant, again tough to know if they are banned because they could use a different email address.

You can buy multiple items, I think the limit per transaction is $10,000USD. For each person receiving payment you can have a list of items that are purchased, at least with the NVP version. Not sure why anyone uses SOAP anymore.

Keep in mind, if buying multiple items, if some part of the transaction is incorrect the whole transaction will fail (item amounts, quantities). PayPal’s documentation is pretty terrible, but gives a little insight.

I tried the express checkout flow using sandbox and also played with it further. I set the amount during call to SetExpressCheckoutDetails() to $100, redirected the user to paypal and the buyer confirmed it, after that I called GetExpressCheckout() followed by DoExpressCheckout().
However I specified $200 in DoExpressCheckout and I was expecting an error, but the operation succeeded. The money was also debited from buyer’s account and credited to seller’s account($200). Can you explain this? I am a bit confused