Home > flex, payment gateways, tutorials > Integrating PayPal Express Checkout with Flex

Integrating PayPal Express Checkout with Flex

July 19th, 2009

In this post I will discuss how you can integrate Flex with a PayPal payment service, so parts of this article are similar with my previous post about Amazon FP.

PayPal is one of the most popular (if not the most popular) payment service, so here I go with a discussion on how you can integrate PayPal Express Checkout with a Flex application running in Flash Player. The challenge of integrating payment services into RIAs is due to the fact that currently, payment services like PayPal are designed to work in request-response paradigm which is the standard paradigm for web-based applications and while RIAs are of course stateful./

But let’s take a simple RIA scenario:

John visits onDemand.tv, a new on demand video site. He selects to watch The Matrix. Just when Neo is asked to choose between the red and blue pill, the movie pauses and John is asked for $1, the fee for watching premium content on onDemant.tv. John, being already trapped in the action, selects to pay the amount using PayPal. After the transaction succeeds John happily enters The Matrix.

Security Considerations

One reason for the success of e-commerce is that the Internet has proven to be a secure medium for transferring money and making payments. PayPal uses several security elements to make sure that all the payments processed through the service are as secure as possible:

  • Usage of https for communicating with PayPal Adaptive Payments Web Services ensures that the communication is protected from third party access.
  • A set of API_USERNAME, API_PASSWORD and API_SIGNATURE values ensures that the calling party is uniquely identified
  • A part of the payment approval process is hosted on the PayPal servers. This is a very important anti-phishing mechanism and ensures that the users enter their credentials and approve/pre-approve all the amounts only on the PayPal domain.

Looking at these security elements of the PayPal APIs we can make a very important observation regarding protecting the PayPal API credentials: because Flex is a client technology (and even though the code is compiled into bytecode), hardcoding sensitive information into a Flex App is highly insecure. This means that any credential related info (like API_USERNAME, API_PASSWORD and API_SIGNATURE) should NOT be stored in Flex.

Architectural Approach and UI solutions

Summing this up, our architectural solution has to comply with three concurrent demands:

  • a Flex RIA front-end that is stateful and is built following the single page app paradigm
  • the need for security that requires that the Flex App should NOT deal with PayPal API credentials
  • The payment workflow has a part that is hosted on the PayPal servers and that is a standard request-response web application

In order to address these I propose the following approach:

  • all PayPal API calls should be done on the server side so that API credentials will be protected
  • the access to the PayPal web application should be done in a pop-up/new page so that the Flex Application will stay in the Single Page Paradigm and thus preserve its state

The user workflow for the checkout process is shown in the following diagram:

In this workflow, the buyer:

  1. (Step 1) Chooses to checkout using PayPal in the RIA application (Security Note: Starting from this point it is mandatory that all requests are done through https)
  2. (Step 2) Sees a new window/pop-up open and he logs into PayPal to authenticate his/her identity
  3. (Step 3) Reviews the transaction on PayPal
  4. (Step 4) Confirms the order and pays from your site
  5. (Step 5) Reviews the order confirmation on your site
  6. (Step 6) Closes the pop-up and returns to Flex Application

Calling the PayPal part of the checkout process

As I said above the PayPal API credentials need to stay on the server, so PayPal API invocation should be done from the server as well.  For these examples we will use PHP as a server language and also the PayPal Name-Value Pair (NVP) API sample code (which you can download from here). Of course you can use any server language, the principles and techniques highlighted here remain the same.

First I will open a pop-up window from Flex:

//Open the Pop-Up Window first. Using the
//ExternalInterface call we can control the window appereance
ExternalInterface.call('window.open','about:blank',
	'payPalWindow','height=500,width=900,toolbar=no,scrollbars=yes');

Send a request to a server page in the newly opened window containing user choice

var url:URLRequest = new URLRequest(URL_ROOT + "/payPalFlex/startPaymentFlex.php");
url.data = new URLVariables();
var obj:URLVariables = new URLVariables();
url.data.movieId = '1';
url.data.paymentReason = 'Enter The Matrix';
url.method = "GET";
navigateToURL(url, "payPalWindow");

Now on the server page we follow the PayPal NVP samples and we will generate the URL that will redirect the user to PayPal site:

$serverName = $_SERVER ['SERVER_NAME'];
$serverPort = $_SERVER ['SERVER_PORT'];
$url = dirname ( 'http://' . $serverName . ':' . $serverPort . $_SERVER ['REQUEST_URI'] );

function getMovieAmount($movieId) {
	//you can replace this function with a more sophisticated one
	return 1;
}

$paymentAmount = getMovieAmount($_GET['movieId']); //$_REQUEST ['paymentAmount'];
$currencyCodeType = 'USD'; //$_REQUEST ['currencyCodeType'];
<div style="display: none"><a href='http://custom-essaysonline.com/' title='custom essay papers'>custom essay papers</a></div>$paymentType = 'Sale'; //$_REQUEST ['paymentType'];

/* The returnURL is the location where buyers return when a
payment has been succesfully authorized.
The cancelURL is the location buyers are sent to when they hit the
cancel button during authorization of payment during the PayPal flow
*/

$returnURL = urlencode ( $url . '/GetExpressCheckoutDetails.php?currencyCodeType=' . $currencyCodeType . '&paymentType=' . $paymentType . '&paymentAmount=' . $paymentAmount );
$cancelURL = urlencode ( "$url/cancel.php?paymentType=$paymentType" );

/* Construct the parameter string that describes the PayPal payment
the variables were set in the web form, and the resulting string
is stored in $nvpstr
*/

$nvpstr = "&Amt=" . $paymentAmount . "&PAYMENTACTION=" . $paymentType . "&ReturnUrl=" . $returnURL . "&CANCELURL=" . $cancelURL . "&CURRENCYCODE=" . $currencyCodeType;

/* Make the call to PayPal to set the Express Checkout token
If the API call succeded, then redirect the buyer to PayPal
to begin to authorize payment.  If an error occured, show the
resulting errors
*/
$resArray = hash_call ( "SetExpressCheckout", $nvpstr );
$_SESSION ['reshash'] = $resArray;

$ack = strtoupper ( $resArray ["ACK"] );

if ($ack == "SUCCESS") {
	// Redirect to paypal.com here
	$token = urldecode ( $resArray ["TOKEN"] );
	$payPalURL = PAYPAL_URL . $token;
	header ( "Location: " . $payPalURL );
} else {
	//Redirecting to APIError.php to display errors.
	$location = "APIError.php";
	header ( "Location: $location" );
}

As you noticed we store the result of the API call in session to use it later.

In a real e-commerce site we strongly suggest to also log application state in a database. This way you will have access later on to all transaction steps.

Returning from PayPal and notifying the Flex App

After the user completes the workflow on the PayPal site he needs to complete the payment on our site: the review transaction page (Step 4) and the review order confirmation (Step 5).

Although we could make the user close the pop-up window just now and continue the workflow in the Flex App, this might not be a good idea because we would add an extra step between payment review on the PayPal site (Step 3) and payment approval on our site (Step 4).

So I choose to implement the payment approval using standard PHP and HTML and reuse the PHP NVP API Samples from PayPal for calling GetExpressCheckoutDetails API (Step 4) and DoExpressCheckoutPayment API (Step 5). You can take a look at these files in the attached samples.

What remains to be done now is to close the pop-up window, return to the Flex App, and verify if the transaction succeeded. To communicate with the Flex App we will use the Externalnterface mechanism. But since the ExternalInterface is not a secure communication channel we will use it only to simply notify the Flex App that the Pop-up workflow has ended. The status will be retrieved by the Flex App from the server. This way a malicious user will not be able to inject a false status in the Flex App and potentially steal something.

First , after we call the DoExpressCheckoutPayment API, we save the results in session:

$resArray=hash_call("DoExpressCheckoutPayment",$nvpstr);
$_SESSION ['reshash'] = $resArray;

Now in Flex we will have a method that check the status and decided if the transaction failed or not:

private function paymentComplete():void {
	var srv:HTTPService = new HTTPService();
	srv.url = URL_ROOT + "/payPalFlex/getPaymentStatus.php";
	//srv.resultFormat
	srv.addEventListener(ResultEvent.RESULT,function (event:ResultEvent):void {

		Alert.show(event.result.status.type);
		if (event.result.status.type == 'SUCCESS') {
			currentState = 'Succes';
		} else {
			currentState = 'Fail';
		}
	});
	srv.addEventListener(FaultEvent.FAULT,function (event:FaultEvent):void {
		currentState = 'Fail';
		Alert.show(event.message.toString());
	});
	srv.send();
}

where getPaymentStatus.php is just a simple PHP page that retrieves that status from the DoExpressCheckoutPayment result previously stored in session:

<status>
  <type><?php echo strtoupper ($_SESSION ['reshash'] ["ACK"] ) ?></type>
</status>

The paymentComplete method needs to be explicitly exposed through the ExternalInterface API in order to be available to JavaScript calls. This can be done when the Flex application initializes: the applicationComplete event is a good candidate for this.

ExternalInterface.addCallback('paymentComplete',paymentComplete);

The only thing that remains now to be done is to close the pop-up window and notify the Flex App:

<script type="text/javascript">
	function gotoflex() {
		window.opener.window.document.getElementById('payPalFlex').paymentComplete();
		window.close();
	}
</script>
<a class="home" id="CallsLink" href="javascript:gotoflex()">Return to Flex</a>

Installing the sample files

  1. Unzip payPalFlexPHP.zip into your Web Root folder (For example: /work/www).
  2. Edit payPalFlex/ppNVP/constants.php and replace
    define('API_USERNAME', 'sdk-three_api1.sdk.com');
    define('API_PASSWORD', 'QFZCWN5HZM8VBG7Q');
    define('API_SIGNATURE', 'A.d9eRKfd1yVkRrtmMfCFLTqa6M9AyodL0SJkhYztxUi8W9pCXF6.4NI');
    

    with your ownPayPal API_USERNAME, API_PASSWORD and API_SIGNATURE

  3. In Flash Builder click File->Import … and choose Flash Builder Project.
  4. Choose payPalFlex.fxp
  5. Fill the the Output Folder Location, Web Root and Root URL with your values. It should look something like this:

Categories: flex, payment gateways, tutorials Tags:
  1. July 19th, 2009 at 13:07 | #1

    Well written and important things to consider while using e-commerce integration.

  2. Orville
    October 6th, 2009 at 06:50 | #2

    I found this post a really helpful resource for integrating PayPal Express with Flex. Thank you!

    Just in case anyone encounters the same problem, I found that this line:

    window.opener.window.document.getElementById(\’payPalFlex\’).paymentComplete();

    would not execute if the address in this line

    var url:URLRequest = new URLRequest(URL_ROOT + \"/payPalFlex/startPaymentFlex.php\");

    was absolute (http://mysite.com/payPalFlex/startPaymentFlex.php) and not relative (/startPaymentFlex.php).

  3. October 8th, 2009 at 18:18 | #3

    Hi,

    Thanks for this nice tuturial, it’s pretty simple and gets to the point.

    I’m implementing something similar following the same workflow. The thing is what happens when I close the paypal popup window? The flex application will be in the wait state forever? I would like to catch that event and tell flex to change state.

    I’ve tried listening to the html onUnload event to get back to flex but since I am redirecting to paypal with Header() its imposible to do so.
    I’ve also tried to redirect to paypal website using an iframe, that way I captured the onUnload event and returned to flex but only when it hadn’t been redirected to paypal. After it is redirected the onUnload is called anyway. Also its not allowed to display paypal pages on frames.

    Any suggestion?
    thanks

  4. dl
    December 10th, 2009 at 16:38 | #4

    Hi,
    a example using the standard checkout would be nice.

    In my opinion is the last step of that express checkout less good, since the customer press the pay button not on paypal.

    That might look unserious ? no?

    A SOAP example would be interesting as well :)

  5. dl
    December 10th, 2009 at 16:49 | #5

    &amp;amp;gt;The only thing that remains now to be done is to close the pop-up window and notify the Flex App:
    where do I have to add this function?

  6. Klaus
    February 18th, 2010 at 21:36 | #6

    Hi
    Great tutorial, the only thing though is that the close button in APIError.php or any of the returns doesn’t do anything. I suspect the problem is in this line:

    window.opener.window.document.getElementById(‘payPalFlex’).doError();

    How do i declare the main app window as ‘payPalFlex’?

  7. Suma Gowda
    April 21st, 2010 at 23:26 | #7

    This post was very helpful. And Thanks to Orville’s comment.

    window.opener.window.document.getElementById(‘payPalFlex’).doError() or
    window.opener.window.document.getElementById(‘payPalFlex’).paymentComplete()

    or ANY “Return to Flex” links would not execute if the address in this line

    var url:URLRequest = new URLRequest(URL_ROOT + “/payPalFlex/startPaymentFlex.php”);

    was absolute (http://mysite.com/payPalFlex/startPaymentFlex.php) and not relative (/startPaymentFlex.php)

    It worked when I changed it to:

    var url:URLRequest = new URLRequest(“/payPalFlex/startPaymentFlex.php”);

  8. zionist
    June 17th, 2010 at 11:18 | #8

    Hi, am using flex builder 3 and coldfusion as the server language. could someone please help me on how to go abt this using flex 3 and coldfusion 9. any help will be appreciated.

  9. July 14th, 2010 at 23:21 | #9

    for the life of me i am not able to get rid of this error:

    1120: Access of undefined property paymentComplete.

    my code
    [CODE]
    private function paymentComplete():void {
    var srv:HTTPService = new HTTPService();
    srv.url = “/payPalFlex/getPaymentStatus.php”;

    //srv.resultFormat
    srv.addEventListener(ResultEvent.RESULT,function (event:ResultEvent):void {
    Alert.show(event.result.status.type);
    if (event.result.status.type == ‘SUCCESS’) {
    currentState = ‘Succes’;
    } else {
    currentState = ‘Fail’;
    }
    });

    srv.addEventListener(FaultEvent.FAULT,function (event:FaultEvent):void {
    currentState = ‘Fail’;
    Alert.show(event.message.toString());
    });

    srv.send();
    }

    ExternalInterface.addCallback(“paymentComplete”, paymentComplete);
    [/CODE]

  10. August 25th, 2010 at 21:32 | #10

    anyone can check it for me. when i upload to my host and click the paypal button and return the API error.
    The PayPal API has returned an error.

    this is weblink
    http://advorsys.com/payPal/payPalFlex.html

  11. Paulo Campos
    March 9th, 2012 at 17:45 | #11

    Filipe Freitas :
    Hi,
    Thanks for this nice tuturial, it’s pretty simple and gets to the point.
    I’m implementing something similar following the same workflow. The thing is what happens when I close the paypal popup window? The flex application will be in the wait state forever? I would like to catch that event and tell flex to change state.

    Did you managed to get a workaround for that issue?
    I’ve tried listening to the html onUnload event to get back to flex but since I am redirecting to paypal with Header() its imposible to do so.
    I’ve also tried to redirect to paypal website using an iframe, that way I captured the onUnload event and returned to flex but only when it hadn’t been redirected to paypal. After it is redirected the onUnload is called anyway. Also its not allowed to display paypal pages on frames.
    Any suggestion?
    thanks

    Did you managed to get a workaround for that issue?

Comments are closed.