Archive

Archive for the ‘flex’ Category

Skinning a list in Flex 4 – Magnifier Effect

August 16th, 2009 8 comments

Here’s a little video about how to use different Spark components to make a magnifier effect for a list. To create this effect I did the following:

  • used the Spark Component model with Skins and States
  • employed the new Spark item renderer that support Designer/Developer workflow
  • Parametrize Spark Skins with CSS

You can download the final project from here and watch the video here.


Categories: flex, video Tags:

Integrating PayPal Express Checkout with AIR and Flex

July 30th, 2009 1 comment

This article continues the series about integrating Flex and AIR with payment gateway services. Parts of this article are very similar with the other posts about this subject:
Integrating PayPal Express Checkout with Flex(which I recommend reading before this article),Using Amazon Flexible Payment System with Flex and Using Amazon Flexible Payment System with Flex & AIR.

I will focus mainly on how to take the PayPal + Flex workflow (described here) out of the browser and into an AIR application.

Although AIR applications run on the desktop and the local security constraints are different from those in the browser, from a payment gateway point of view things don’t change at all. As a result, we can conclude that because AIR is a client technology hardcoding sensitive information into an AIR app is highly insecure (even though the code is compiled into bytecode). This means that any credential related info (like API_USERNAME, API_PASSWORD and API_SIGNATURE) should NOT be stored in the AIR application.

Architectural Approach and UI solutions

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

  • an AIR front-end that is stateful and is built following the single page app paradigm
  • the need for security that requires that the AIR 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 browser page. IMPORTANT SECURITY NOTE: Although technically it might be possible to use the HTML container of the AIR runtime this is an unsecure practice because the end user cannot visually verify that he is entering his credentials on the PayPal site. In the browser he can check the URL and the security certificate.

So the buyer workflow becomes:

  1. (Step 1) Chooses to checkout using PayPal in the AIR application (Security Note: Starting from this point it is mandatory that all requests are done through https)
  2. (Step 2) Sees a browser window open and 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) Returns to the AIR application

 

Calling the PayPal part of the checkout process

So the PayPal workflow should be open in a browser window. Here is how to do that in the AIR app:

var url:URLRequest = new URLRequest(URL_ROOT + "/payPalAIR/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, "new");
currentState='Wait';

Everything else is pretty similar with how you call the PayPal workflow from a Flex app.

Returning from PayPal and notifying the AIR application

Here again we follow an approach similar with how you return from PayPal to a Flex application (Step 4 and Step 5).

The only thing that differs is how we get back to the AIR application (Step 6). ExternalInterface is not suited for this job but we can use instead the LocalConnection to make the browser application communicate with the AIR one. LocalConnection, while being more secure than ExternalIterface, can still be exploited using techniques like DNS rewriting so we can’t pass sensitive information through it. Furthermore, since the AIR app is independent from the browser this means that our browser app has a different server session than the AIR App. So a simple notification is not enough: we need to also pass the session id. This is not sensitive information, but it will allow the AIR application to retrieve from the server any sensitive information that the browser application has set.

Let’s take a look on what we need to do right after we call the PAY operation in our return page. In the transaction detail page we will link to a little Flex application that will only communicate with the AIR application. We can use this little application to also forward the error and cancel messages. We will call it using an anchor parameter:

<a class="home" id="CallsLink" href="payPalAIRReturn.html#method=doStatus">Return to AIR</a>

This little application will only contain some code that will get the cookie string from the browser (remember we need this to make the AIR application connect to the same server session) and send a message through LocalConnection to the AIR application:

private var outbound:LocalConnection = new LocalConnection();
protected function application1_applicationCompleteHandler(event:FlexEvent):void
{
	var browserManager:IBrowserManager = BrowserManager.getInstance();
	browserManager.init();
	var urlObj:Object = URLUtil.stringToObject(browserManager.fragment);
	if (urlObj.method) {
		//get the cookie string
		ExternalInterface.call('eval','window.cookieStr = function () {return document.cookie};')
			var cookieStr:String = ExternalInterface.call('cookieStr');
		outbound.connect("paymentSample");
		outbound.send("app#payPalAIR:paymentSample",urlObj.method,cookieStr);
		outbound.close();
	}
}

Please notice that when launching from Flex Builder the AIR Application has no Publisher ID so the connection name is “app#payPalAIR:paymentSample”. After packaging and installation the AIR app will get a Publisher ID so the connection name becomes something like this: app#payPalAIR.F0B3F68E1857B8A07069FED1D0638CAF200F76EB.1:paymentSample

You can get the publisher ID of the installed AIR app by looking at the META-INF/AIR/publisherid file within the application install directory.

Back in the AIR application we need to expose the functions through local connection:

private function initApp():void {
	//only allow connections from localhost
	//you need to replace "localhost" with the final domain
	//where your application will be hosted
	inbound.allowDomain("localhost");
	inbound.client = new Object();
	//this is the function that will be called by the Browser App
	inbound.client.doStatus = doStatus;
	inbound.client.doError = doError;
	inbound.client.doCancel = doCancel;

	//inbound.client.
	inbound.connect("paymentSample");

}

All methods (doStatus, do Error and doCancel) will receive the cookie string as a parameter. In do Status we need to check the transaction status on the server:

private function doStatus(cookieStr:String):void {
	var srv:HTTPService = new HTTPService();
	srv.headers.Cookie = cookieStr;
	srv.url = URL_ROOT + "/payPalAIR/getPaymentStatus.php";
	srv.addEventListener(ResultEvent.RESULT,function (event:ResultEvent):void {

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

where getPaymentStatus.php is just a simple page that gets the status from the session and serialize it in a simple XML format:

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

Installing the sample files

  1. In Flash Builder click File->Import .. and choose Flash Builder Project
  2. Choose payPalAIR.fxp
  3. Unzip payPalAIR.zip into your Web Root folder (For example: /work/www).
  4. Edit payPalAIR/ppNVP/constants.php and replace
  5. 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

  6. In Flash Builder click File->Import … and choose Flash Builder Project.
  7. Choose payPalAIRReturn.fxp
  8. Fill the Output Folder Location (this one should point to where you have unzipped payPalAIR.zip, in your web root), Web Root and Root URL with your values. It should look something like this:


Categories: air, flex, payment gateways, tutorials Tags:

Using Amazon Flexible Payment System with Flex & AIR

July 26th, 2009 2 comments

I’ve already talked about using Flex with Amazon FPS, so now let’s see what is involved in taking this out of the browser into an AIR app. I recommend reading that article before reading this one, since many of the security considerations described there in detail are valid for AIR applications also. In this article I will only highlight the differences between building a Flex application that runs in the browser and one that runs on the desktop.

Although AIR applications run on the desktop and the local security constraints are different from those in the browser, from a payment gateway point of view things don’t change at all. As a result, we can conclude that because AIR is a client technology hardcoding sensitive information into an AIR app is highly insecure (even though the code is compiled into bytecode). This means that any signature related computation should NOT be made in AIR and the Amazon Secret Key should NOT under any circumstance be put into an AIR App.

Architectural Approach and UI solutions

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

  • an AIR front-end that is stateful and is built following the single page app paradigm
  • the security need that the AIR app should NOT deal with Amazon Security Key plus the need to go to the Amazon co-branded page to authenticate the users
    In order to address these I propose the following approach:

  • All payment related processing should be done on the server side to protect the Amazon Secret Key. Of course this means that the AIR app must be on-line when the payment takes place.
  • The access to the co-branded page should be done in a browser page. IMPORTANT SECURITY NOTE:  Although technically it might be possible to use the HTML container of the AIR runtime this is an unsecure practice because the end user cannot visually verify that he is entering his credentials on the Amazon site. In the browser he can check the URL and the security certificate.

Calling the Amazon Co-Branded User Interface

So the Amazon co-branded UI should be open in a browser window. Here is how to do that in the AIR app.

var url:URLRequest = new URLRequest("http://localhost/amazonAIR/startPayment.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, "new");

Everything else is pretty similar with how you call the Amazon co-branded UI from a Flex app that runs in the browser.

Exactly the same goes with returning from Amazon and making the Pay request.

Using LocalConnection to notify the AIR App

The only thing left now is to notify the AIR application and bring it to front.

To do that we need to communicate between the browser app and the AIR app. In order to achieve this we can use the LocalConnection mechanism. LocalConnection objects can communicate among files that are running on the same client computer, but they can be running in different applications — for example, a file running in a browser and a SWF file running in Adobe AIR.

Now there is one important thing to remember about LocalConnection. It can be tricked using techniques like DNS rewriting. So we will not pass any sensitive information through LocalConnection. However, since the AIR app is independent from the browser this means that our browser app has a different server session than the AIR App. So a simple notification is not enough, we need to also pass the session id. This is not sensitive information, but it will allow the AIR application to retrieve from the server any sensitive information that the browser application has set.

Let’s take a look what we need to do right after the return.php page made the PAY operation.

For simplicity the returnAir.php page will have a link to a little Flex app that will communicate with the AIR app. All it needs to do is to get the cookie information and send it through LocalConnection to the AIR app:

private var outbound:LocalConnection = new LocalConnection();

private function gotoAIR():void {
	//get the cookie string
	ExternalInterface.call('eval','window.cookieStr = function () {return document.cookie};')
	var cookieStr:String = ExternalInterface.call('cookieStr');

	outbound.connect("paymentSample");
	outbound.send("app#amazonAIR:paymentSample","notifyPayment",cookieStr);
	//outbound.send("app#testAmazonAir.F0B3F68E1857B8A07069FED1D0638CAF200F76EB.1:paymentSample","notifyPayment",cookieStr);
	outbound.close();
}

Please notice that when launching from Flex Builder the AIR Application has no Publisher ID so the connection name is “app#amazonAIR:paymentSample”. After packaging and installation the AIR app will get a Publisher ID so the connection name becomes something like this: app#amazonAIR.F0B3F68E1857B8A07069FED1D0638CAF200F76EB.1:paymentSample

You can get the publisher ID of the installed AIR App by looking at the META-INF/AIR/publisherid file within the application install directory.

Back in our AIR app we need to expose a function to be available on LocalConnection.

//This will be used by return.php to notify the AIR App
//that the payment has been made
private var inbound:LocalConnection = new LocalConnection();

private function initApp():void {
	//only allow connections from localhost
	//you need to replace "localhost" with the final domain
	//where your application will be hosted
	inbound.allowDomain("localhost");
	inbound.client = new Object();
	//this is the function that will be called by the Browser App
	inbound.client.notifyPayment = paymentNotification;
	inbound.connect("paymentSample");
}

Where paymentNotification is a function that receives the cookie string as parameters and queries the server to check the transaction status:

public function paymentNotification(cookieStr:String):void {
	var srv:HTTPService = new HTTPService();
	srv.headers.Cookie = cookieStr;
	srv.url = "http://localhost/amazonAIR/paymentStatus.php";
	srv.addEventListener(ResultEvent.RESULT,function (event:ResultEvent):void {
		nativeApplication.activate();
		if (event.result.status == 'OK') {
			currentState = 'Succes';
		} else {
			currentState = 'Fail';
		}
	});
	srv.send();
}

Installing the sample files

  1. In Flash Builder click File->Import .. and choose Flash Builder Project
  2. Choose AmazonAIR.fxp
  3. Unzip amazonAIR.zip into your Web Root folder (For example: /work/www).
  4. Edit amazonAIR/amazon-fps/src/Amazon/FPS/Samples/.config.inc.php and replace
  5. define('AWS_ACCESS_KEY_ID', 'YOUR ACCESS KEY');
    define('AWS_SECRET_ACCESS_KEY', 'YOUR SECRET ACCESS KEY');
    

    with your own Amazon ACCESS key and SECRET_ACCESS_KEY.

  6. In Flash Builder click File->Import … and choose Flash Builder Project.
  7. Choose amazonAIRReturn.fxp
  8. Fill the Output Folder Location (this one should point to where you have unzipped amazonAIR.zip, in your web root), Web Root and Root URL with your values. It should look something like this:

Categories: air, flex, payment gateways, tutorials Tags:

The infamous Error #2044: Unhandled StatusEvent:. level=error, code= on LocalConnection

July 24th, 2009 1 comment

This is a blog post to all that was almost to throw their computers out of the window because they got "Error #2044: Unhandled StatusEvent:. level=error, code=" trying to communicate through LocalConnection.

So I am trying to send a message from a Flex application running in Flash Player to an AIR application. In the AIR application (called testAIR) I have something like:

private function initApp():void {
	var inbound:LocalConnection = new LocalConnection();
	//only allow connections from localhost
	inbound.allowDomain("localhost");
	inbound.client = new Object();
	//this is the function that will be called by the Browser App
	inbound.client.notifyPayment = function test():void {
		Alert.show("HERE");
	};
	inbound.connect("paymentSample");
}

pretty straightforward, right from the book.

In the Flex app I just do:

outbound.connect("paymentSample");
outbound.send("app#testAIR:paymentSample","notifyPayment");
outbound.close();

You might think that this should work. Well … NOT.  This is because in the AIR app the inbound LocalConnection is a variable that is declared in the local scope of a method. Now I was expecting that when I call  the connect method the inbound object will be referenced by another object (some LocalConnection manager, or event handler) and it will not get garbage collected after the method ends. Well, apparently is not the case. Either there is a bug in AIR, either this reference is a weak reference so it gets garbage collected. This means that by the time you try to send the message from Flash Player your inbound object is long gone!

The resolution is quite simple. You just need to reference the inbound object somewhere else, making him a member of class or something. In my case I just declare it as a private variable inside my MXML component:

private var inbound:LocalConnection = new LocalConnection();

private function initApp():void {
	//only allow connections from localhost
	inbound.allowDomain("localhost");
       ....

Hope this will help someone :)

Categories: Flash Player 10, flex, tips & tricks Tags:

Integrating PayPal Express Checkout with Flex

July 19th, 2009 11 comments

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:

Using Amazon Flexible Payment System with Flex

July 11th, 2009 7 comments

Amazon FPS is a popular and powerful payment service and in this paper I will discuss how you can integrate Amazon FPS into a RIA while preserving the high level of security required for these type of integrations. Amazon FPS is designed to integrate with standard, request-based web applications. While this request-based paradigm is successfully used by a lot of current web applications, Rich Internet Applications with the Single Page paradigm have proved to be better suited for many e-commerce workflows and use cases.

To better illustrate let’s consider the following scenario:

John visits onDemand.tv, a new on demand video site. He chooses 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 onDemand.tv. John, being already trapped in the action, decides to pay the amount using Amazon Payments. After the transaction is completed 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. Amazon FPS uses several security elements to make sure that all the payment processed through the service are as secure as possible:

  • Usage of https for communicating with Amazon FPS Web Services ensures that the communication is protected from third party access.
  • A signature mechanism based on Access Keys and Secret Keys ensures that each Seller is uniquely identified.
  • A co-branded page hosted on Amazon servers ensures that the users enter their credentials and pre-approve all the amounts only on the Amazon domain.

Looking at these security elements of Amazon FPS we can make a very important observation regarding protecting the Amazon Secret Key: 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 signature related computation should NOT be made in Flex and the Amazon Secret Key should NOT under any circumstance be put into a Flex App.

Architectural Approach and UI solutions

Summing this up, our architectural solution has to comply with two 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 Amazon Security Key plus the need to go to the Amazon Co-Branded page to authenticate the users

In order to address these we propose the following approach:

  • all payment related processing should be done on the server side so that the Amazon Secret Key will be protected
  • the access to the Co-Branded page should be done in a pop-up page so that the Flex Application will stay in the Single Page Paradigm

Thus the buyer’s experience of Amazon FPS Basic Quick Start using Flex will be like this:

1 John visits onDemand.tv, chooses to watch The Matrix and when Neo has to choose between the Red Pill and the Blue Pill the movie stops and asks for $1. John decides to pay, selects Amazon Payments as the payment method, and clicks Pay Nowclip_image002[1]

Security Note:

Starting from this point it is mandatory that all requests are done through https.

2 After John clicks Pay Now a Pop Up window is opened to the Amazon Co-Branded User Interface (CBUI). This is a standard HTML based Web Application and it’s hosted on the Amazon servers. He signs into his Amazon Payments account using his e-mail ID and password.

clip_image004[1]

3 After he signs in, John views the Payment Method page. This page enables him to select a personal payment instrument, such as his credit card, for the transaction.John selects his Amazon Payments account balance (ABT) as the payment instrument and clicks Continue.

clip_image006[1]

4 After he clicks Continue, John views the Payment Summary page. He reviews the payment details and clicks Confirm.

clip_image008[1]

5 After clicking Confirm, John is redirected to the onDemand.tc company’s web site. The web page he’s redirected to is specified in the returnURL parameter in the co-branded service request. The Return Page contains a “Return to Movie” button.The URL contains additional information including the status of the authorization, and a reference, called the TokenId, to the token stored on Amazon servers. You use that token in Amazon FPS transaction actions (such as Pay) to actually initiate the transfer of money.

Important:

The payment transaction is not initiated by Amazon FPS. The onDemand.tv company must make a Pay web service request with the TokenId that the co-branded service returned earlier.

6 After John clicks “Return to Movie” the Pop Up window closes and the Flex App is notified that the authorization process has ended. Now it can call the Server logic to perform the actual payment and resume the movie so that John will finally enter The Matrix.

Calling the Amazon Co-Branded User Interface

As we said above the Amazon Secret Key needs to stay on the server, so signature processing will be done on the server as well. For these examples we will use PHP as a server language and also the Amazon FPS PHP SDK. Of course you can use any server language, the principles and techniques highlighted here remain the same.

So in order to call the Amazon Co-Branded UI we’ll do the following:

Open a popup 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','amazonWindow','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("https://miti.pricope.com/testAmazon/startPaymentFlex.php");
url.data = new URLVariables();
var obj:URLVariables = new URLVariables();
url.data.movieId = moviePick.selectedItem.value;
url.data.paymentReason = 'Enter The Matrix';
url.method = "GET";
navigateToURL(url, "amazonWindow");

By using navigateToURL we also assure that if the window.open call doesn’t work (because of a drastic pop-up blocker) we still manage to continue the workflow.

In the server page we generate the Amazon Co-Branded UI Request and redirect the browser to that request (startPaymentFlex.php)

session_start();

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

$obj = new Amazon_FPS_CBUIUtils(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY);
$obj->setMandatoryParams("SingleUse", "https://" . $_SERVER['HTTP_HOST'] . "/testAmazon/return.php");
//The refernce ID is unique to your business
//You can replace the standard UID php function with more suitable function
$ref = uniqid("amazon");
$obj->setCallerReference($ref);
$obj->setTransactionAmount(getMovieAmount($_GET['movieId']));
$obj->setPaymentReason($_GET['paymentReason']);
$qs = $obj->getURL() ;
//We use session data to store the state of the application between requests
//The amount will be used later on (in return.php) to invoke the FPS Pay method
//We also hold the status of the transaction. This will be requested
//by the Flex App
$_SESSION['status'] = 'START';
$_SESSION['transaction_amount'] = getMovieAmount($_GET['movieId']);
$_SESSION['movieId'] = $_GET['movieId'];

header("Location:$qs")

Note we also store some data in the session (status, transaction amount and movieId). These variables will be used in the return page to actually invoke the Amazon FPS Pay method.

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

Returning from Amazon and making the payment

After the user completes the Amazon Co-Branded page workflow and authorizes the transaction he is redirected to the return page specified in the returnURL parameter in the Co-Branded service request, in our case the return.php page. In this page, after verifying that the returning request is valid I’ve chosen to actually call the Pay method in the Amazon FPS and initiate the money transfer.

For this I used again the Amazon FPS PHP SDK.

function validateQueryString()
{
    echo "validing the query string now\n";
    $querystring = $_SERVER['QUERY_STRING'];
    echo $_GET['signature'];
    $obj = new Amazon_FPS_CBUIUtils(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY);
    //Original signature received in response from Amazon FPS should be specified.
    $signatureMatched = $obj->validateQueryString($querystring,$_GET['signature']);

    if ($signatureMatched) {
        echo "signature matched \n";
        $request =  new Amazon_FPS_Model_PayRequest();
        //set the proper senderToken here.
        $request->setSenderTokenId($_GET['tokenID']);
        $amount = new Amazon_FPS_Model_Amount();
        $amount->setCurrencyCode("USD");
        //set the transaction amount here;
        $amount->setValue($_SESSION['transaction_amount']);
        $request->setTransactionAmount($amount);
        //set the unique caller reference here.
        $request->setCallerReference($_GET['callerReference']);
        $service = new Amazon_FPS_Client(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY);
        invokePay($service, $request);
    }
    else
        echo "Signature did not match \n";
}

validateQueryString();

I have used the same invokePay function that can be found in the Amazon FPS PHP SDK, although in the case of a successful transaction I have modified the session variable that stores the status:

function invokePay(Amazon_FPS_Interface $service, $request)
{
     try {
             $response = $service->pay($request);

             echo ("Service Response\n");
             echo ("=======================================================\n");

             echo("        PayResponse\n");
             if ($response->isSetPayResult()) {
                 echo("            PayResult\n");
                 $payResult = $response->getPayResult();
                 if ($payResult->isSetTransactionId())
                 {
                     echo("                TransactionId\n");
                     echo("                    " . $payResult->getTransactionId() . "\n");
                 }
                 if ($payResult->isSetTransactionStatus())
                 {
                     echo("                TransactionStatus\n");
                     echo("                    " . $payResult->getTransactionStatus() . "\n");
                     //CHECK Transaction Status is Success
                     $_SESSION['status'] = 'OK';
                 }
             }
             if ($response->isSetResponseMetadata()) {
                 echo("            ResponseMetadata\n");
                 $responseMetadata = $response->getResponseMetadata();
                 if ($responseMetadata->isSetRequestId())
                 {
                     echo("                RequestId\n");
                     echo("                    " . $responseMetadata->getRequestId() . "\n");
                 }
             }

    } catch (Amazon_FPS_Exception $ex) {
        echo("Caught Exception: " . $ex->getMessage() . "\n");
        echo("Response Status Code: " . $ex->getStatusCode() . "\n");
        echo("Error Code: " . $ex->getErrorCode() . "\n");
        echo("Error Type: " . $ex->getErrorType() . "\n");
        echo("Request ID: " . $ex->getRequestId() . "\n");
        echo("XML: " . $ex->getXML() . "\n");
    }
}

Using ExternalInterface to notify the Flex App

The only thing left now is to notify the Flex application and close the pop-up window.

First we need to prepare the Flex App. We create a payment notification function to be called by the pop-up window. This function is called through ExternalInterace. Because the JavaScript call can be overwritten (using FireBug for instance) the ExternalInterface call is not secure. So we use the call only to notify that the Amazon workflow has ended.

The Status is then retrieved from the server through HTTPS.

private function paymentNotification():void {
	var srv:HTTPService = new HTTPService();
	srv.url = "https://miti.pricope.com/testAmazon/paymentStatus.php";
	srv.addEventListener(ResultEvent.RESULT,function (event:ResultEvent):void {
		Alert.show("Status: " + event.result.status);
	});
	srv.send();
}

In this case paymentStatus.php is a simple php that will only retrieve the status packed in a simple XML format:

session_start();
echo '<status>' . $_SESSION['status'] . '</status>'

This function needs to be explicitly exposed through the ExternalInterface of Flash Player in order to be available to JavaScript calls. This call should be executed when the Flex application finishes initializing. The applicationComplete event is a good candidate for this.

//This will be used by return.php to notify Flex App that the payment has been made
ExternalInterface.addCallback('paymentNotification',paymentNotification);

Back to return.php, the only thing that remains is to close the pop-up window and notify the Flex App.

<script type="text/javascript">
	function gotoflex() {
		window.opener.window.document.getElementById('testAmazon').paymentNotification();
		window.close();
	}
</script>
<form>
<input type="button" value="Close This Window and Return to Flex APP" onclick="gotoflex()"/>
</form>

Installing the sample files

1. Unzip amazonFlexPHP.zip into your Web Root folder (For example: /work/www).

2. Edit amazonFlex/amazon-fps/src/Amazon/FPS/Samples/.config.inc.php and replace

define('AWS_ACCESS_KEY_ID', 'YOUR KEY');
define('AWS_SECRET_ACCESS_KEY', 'YOUR SECREY KEY');

with your own Amazon ACCESS key and SECRET_ACCESS_KEY.

3. In Flash Builder click File->Import … and choose Flash Builder Project.

4. Choose amazonFlex.fxp

5. Fill the the Output Folder Location, Web Root and Root URL with your values. It should look something like this:

image

Categories: flex, payment gateways, tutorials Tags:

Playing with Custom Layout in Flex 4

May 29th, 2009 9 comments

gumboListAs Flex 4 SDK is almost in it’s Beta state I took a look at his features and what impressed me the most was how the presentation is decoupled from the behavior. I remember a presentation around Max 2007 when Ely Greenfield, the principal scientist for Flex SDK, showed a sneak peek on how this will make a lot of skinning things a lot simpler. For example, it’s simple to make a list look … let’s say to make it look like the Fan effect that Mac users love so much :)

I found this quite easy to implement using Flex 4. Because the list can be skinned in MXML it’s so easy to program the skin and stay in MXML for the most part. The only thing that I actually needed to program was how the elements are laid out.

The basic List skin looks like this:

<s:states>
    <s:State name="normal"/>
    <s:State name="hover"/>
    <s:State name="disabled"/>
</s:states>

<fx:Metadata>[HostComponent("spark.components.List")]</fx:Metadata>
<s:DataGroup itemRenderer="components.RepeatedItem1"
        clipAndEnableScrolling="true"  id="dataGroup"
        rollOver="currentState='hover'">
    <s:layout>
        <components:LargeCircleLayout id="myLayout" radius="1400"
            stepAngle="0" stepAngle.hover="3.5"/>
    </s:layout>
</s:DataGroup> 

Notice that it’s nothing but a DataGroup that has a layout. I’ve also added the Hover state to be able to open the list when you hover over it.

To add the nice effect it’s just a matter of animating one layout property:

<s:transitions>
    <s:Transition autoReverse="true">
        <s:Animate target="{myLayout}" duration="200">
            <s:SimpleMotionPath property="stepAngle"/>
        </s:Animate>
    </s:Transition>
</s:transitions>

You can take a look at the source code here and watch the list here.

Categories: flex, ria, tips & tricks Tags:

ODE (Open Dynamic Engine) for Flash

February 23rd, 2009 7 comments

I’ve took Alchemy for a test and decided to compile ODE (Open Dynamic Engine). Just to add yet another physics engine to the Flash World. It was a hell of a ride but I finally got to produce some bouncing balls :) . For a still unknown reason some as 3d libraries have been very slow to render 6 translucent walls and 2 balls. Papervision3D seems to move quite decent.

You can download the ode sources from here. To recompile them do (you need to have the Alchemy  environment turned on):

./configure

make clean

cd OPCODE

make

cd ../ode/src

make

cd ../swc

make

And here are the bouncing balls:

Update:

The Source view for the bouncing balls seems to be broken. So if you want to see the source for my little test project here it is.

Categories: alchemy, flex Tags:

Flex and Ajax

January 14th, 2009 3 comments

They made me a movie star. ADC had the guts to release some of my videos. If you can get along with my spectacular stammering and pass the feeling of pity or convulsive laughing this might be a good starting tutorial for using Flex and Ajax together.

 

Update:

Sorry for taking me so long. Here is a link to the archived project file. To import this project you should right click in the Flex Navigator, choose Import… -> Flex Project and then choose the zip file and follow the import wizard steps.

Categories: ajax, flex Tags:

Playing with Pixel Bender

November 10th, 2008 7 comments

As you probably know by now, Flash Player 10 has a new feature for image processing that allows you to perform some really cool effects and blends. Well actually this new feature is a little language for parallel computing. In this post I present some samples that show you how to integrate Pixel Bender with your Flex project from start to finish.

First of all you need the Pixel Bender Toolkit. You can get it from here. Second you will need to compile your Flex Project against Flash Player 10. There’s some documentation here. The whole idea behind my samples is that it took a while for me to put all things together and apply the effects on my Flex elements, and I want to make it easier for you.

In the first project I just made a simple Pixel Bender filter, which replaces the red channel with the blue one, and added it to an image.

Click here to see the demo

On the second project I used a filter with some parameters. It doesn’t do much, just clips a circle from the original image.

Click here to see the demo

The next one is a slightly more complex filter that has two input images. I use it to apply an image over a video.

Click here to see the demo

Finally, because Pixel Bender is basically a number cruncher, I use it to mix two ByteArrays. By chance :) these two ByteArrays are extracted from two sounds so this is also an example on how you can use Pixel Bender to mix two sounds.

Click here to see the demo (it might take a while before it starts playing because I have to load the sounds first)

UPDATE: The sound sample demo has two mixing methods. One is using PixelBender (onSampleData) and the other is using a pure AS3 code to mix. You can switch between the two (by changing the event handler at line 32) and and monitor the CPU to see if any performance improvements are detectable (on my computer is around 30%). I updated the demo to use the PixelBender method by default (thanks Chuck!)

You may want to take a look at the source code or download it.

Categories: Flash Player 10, flex Tags: