Amazon Simple Pay in ASP.NET

During the past few weeks, I had a chance to work with various payment systems for some project requirements. It’s interesting to mention that I was lucky to work on multiple projects dealing with payment systems, which gave me very great experience in this area. So, I already had experience with PayPal implementation in various platforms, including ASP.NET. Maybe, I will get back to PayPal, Moneybookers, AlertPay and other payment methods later, but in this post I’m going to show you how easy is to implement Amazon Simple Pay in your ASP.NET website.

I would have to mention that it is easy especially if you know what you should do next when implementing payment methods in your asp.net website. This is important because even though all payment systems work pretty much the same, still the backend implementation differs.

Here are the key steps you will do when working with payment systems or making a payment:

  1. You Buy something on the merchant website
  2. Chose the payment method and Checkout with that
    (you are redirected to payment operator website e.g. Amazon/PayPal etc.)
  3. Log in with your payment operator credentials (Authenticate)
  4. Finish the process and Confirm the payment
  5. Then, you get redirected back to the merchant’s site

For Amazon Payments, the complete workflow is shown with the following drawing

Amazon CBUI

Before you start with doing any implementation

Before you start with implementing Amazon Simple Pay, it is very recommended to pass through (and read) the following pages:

Is Amazon Simple Pay right for you? Check the following page: HERE


Getting Set Up

  1. Create Developer Account
    1. Go to http://payments.amazon.com and click the Developer tab.
    2. Click on Sign up for this Service
    3. Then, on the next page shown up, click Sign Up
  2. Create Sandbox Account (for testing while in development phase)
    1. Go to https://payments-sandbox.amazon.com
    2. Click Create account on the top-right corner and continue with the procedure

In order to be able to work with Amazon Payments out of the Sandbox, you will have to create an Amazon Payments Business Account in the Business tab on the payments.amazon.com website.

 

Implementation with ASP.NET

The first thing you need to do is to go http://docs.amazonwebservices.com/AmazonSimplePay/latest/ASPAdvancedUserGuide/ and get the sample code.

Standard

ASP Standard -CS-2.0 .zip

Donations

ASP Donation -CS-2.0 .zip

Marketplace

ASP MarketPlace -CS-2.0 .zip

Subscription

ASP Subscription -CS-2.0 .zip

The Standard code is enough. But if you make either Donations, Marketplace or Subscription, then you can use the corresponding sample code zips.

As you have seen in the drawing above, the first thing you need to do is to create Amazon Button that will be used for Checkout and Process the Order Payment.

Since you can’t just really put a form inside form if you use WebForms (you can if you use ASP.NET MVC) you can first read my other blog here.

So, lets first create our own class that will help us make HTTP(S) POST to another URL and wrap the code from my other blog there.

public class PaymentGatewayPost
{
    public System.Collections.Specialized.NameValueCollection ListParams = new System.Collections.Specialized.NameValueCollection();
    public string Url = "";
    public string Method = "post";
    public string FormName = "form1";

    public void Add(string name, string value)
    {
        ListParams.Add(name, value);
    }

    public void Post()
    {
        System.Web.HttpContext.Current.Response.Clear();
        System.Web.HttpContext.Current.Response.Write("<html><head>");
        System.Web.HttpContext.Current.Response.Write(string.Format("</head><body onload=\"document.{0}.submit()\">",
            FormName));
        System.Web.HttpContext.Current.Response.Write(string.Format("<form name=\"{0}\" method=\"{1}\" action=\"{2}\" >",
            FormName, Method, Url));
        int i = 0;

        while (i < ListParams.Keys.Count)
        {
            System.Web.HttpContext.Current.Response.Write(string.Format("<input name=\"{0}\" type=\"hidden\" value=\"{1}\">",
                ListParams.Keys[i], ListParams[ListParams.Keys[i]]));
            i += 1;
        }

        System.Web.HttpContext.Current.Response.Write("</form>");
        System.Web.HttpContext.Current.Response.Write("</body></html>");
        System.Web.HttpContext.Current.Response.End();
    }
}

So, you may have seen similar implementation somewhere else, since this is one of the standard ways to make HTTP POSTS to another URL using ASP.NET Webforms.

Now, since we have the class to make the post, let’s collect the required parameters to make payment with Amazon.

It is very good approach to keep all the global Amazon configuration settings in Web.config, so for that purpose I have created my own ConfigReader static wrapper class that will be used to read the corresponding values from Web.Config. The implementation of ConfigReader class is:

public static class ConfigReader
{
    /// <summary>
    /// Our website return url set in Web.cofnig App Settings
    /// </summary>
    public static string ReturnURL
    {
        get { return WebConfigurationManager.AppSettings["ReturnURL"]; }
    }

    /// <summary>
    /// Instant Payment Notification URL
    /// </summary>
    public static string IpnURL
    {
        get { return WebConfigurationManager.AppSettings["IpnURL"]; }
    }

    /// <summary>
    /// Amazon Payment url in Web.config - We can switch from Sandbox to Real anytime
    /// </summary>
    public static string AmazonPaymentUrl
    {
        get { return WebConfigurationManager.AppSettings["AmazonPaymentUrl"]; }
    }

    /// <summary>
    /// Amazon AccessKeyID
    /// Get it on: https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key
    /// </summary>

    public static string AccessKeyID
    {
        get { return WebConfigurationManager.AppSettings["AccessKeyID"]; }
    }

    /// <summary>
    /// Amazon SecretKey
    /// Get it on: https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key
    /// </summary>

    public static string SecretKey
    {
        get { return WebConfigurationManager.AppSettings["SecretKey"]; }
    }

    /// <summary>
    /// Account ID
    /// </summary>
    public static string AccountID
    {
        get { return WebConfigurationManager.AppSettings["AccountID"]; }
    }
}

You can add some additional parameters, but mainly these are enough so that your payment system will be configurable and you won’t need to change your code once it runs well.

Now, let’s create DoPayment method that will accept parameter of type Order and will supply all needed parameters before making HTTP POST to Amazon.

public void DoPayment(Order order)
{
    Uri gatewayUrl = new Uri(ConfigReader.AmazonPaymentUrl);
    
    PaymentGatewayPost post = new PaymentGatewayPost();
    post.FormName = "SimplePay";
    post.Url = gatewayUrl.ToString();
    post.Method = "POST";
    post.Add("immediateReturn", "1");
    post.Add(AmazonPaymentsHelper.SIGNATURE_VERSION_KEYNAME, AmazonPaymentsHelper.SIGNATURE_VERSION_2);
    post.Add(AmazonPaymentsHelper.SIGNATURE_METHOD_KEYNAME, AmazonPaymentsHelper.HMAC_SHA256_ALGORITHM);
    post.Add("accessKey", ConfigReader.AccessKeyID);
    post.Add("amount", String.Format(CultureInfo.InvariantCulture, "USD {0:0.00}", order.Amount));
    post.Add("description", string.Format("{0} - {1}", "ORDERED SOME ITEM", order.OrderID));

    /*
    * Your Amazon Payments account ID. This parameter is not used
    * and should not be present if you sign the button using your secret key.
    * For more information, see Using Access Identifiers on Amazon User Guide Website).
    * */
    post.Add("amazonPaymentsAccountId", ConfigReader.AccountID);

    post.Add("returnUrl", ConfigReader.ReturnURL); //where to return after finishing with transaction

    //Amazon can send additional posts to this url in our website
    //to notify us about particular transaction state
    //we should handle it and update our records in database accordingly
    post.Add("ipnUrl", ConfigReader.IpnURL);

    post.Add("processImmediate", "1"); //0 will reserve the payment, 1 will process it immediatelly
    post.Add("referenceId", order.OrderID);
    post.Add("abandonUrl", ConfigReader.ReturnURL); //same as return url
    string signature = GetParametersSignature(post, gatewayUrl);
    post.Add(AmazonPaymentsHelper.SIGNATURE_KEYNAME, signature);

    //make the post
    post.Post();
}

Oh right, we are almost there. For most of the parameters you have comment either inside DoPayment method or in the ConfigReader class for parameters that are added in Web.config

Parameters in Web.config should be inside <appSettings> … </appSettings> section in format <add key=”keyName” value=”value” />

Example:

<add key="ReturnURL" value="http://localhost/mywebsite/AmazonReturnURL.aspx" />
<add key="IpnURL" value="http://localhost/mywebsite/AmazonIPNUrl.aspx" />

The value for AmazonPaymentUrl key should be https://authorize.payments-sandbox.amazon.com/pba/paypipeline or without -sandbox when you will start using real accounts (remember, sandbox accounts are for testing purpose only!). Since you can also call some of the FPS (Flexible Payment Service) methods even when using ASP (Amazon Simple Pay), you can use the FPS URL is https://fps.sandbox.amazonaws.com or without .sandbox when you will start using real accounts.

Two more things you may see strange in the previous code, these are:

· AmazonPaymentsHelper class – which is my own class created for various stuff. You have the same class in the samples (available above) named SignatureUtils inside ASPStandard-CS-2.0\ASPStandard-CS-2.0\ButtonGenerationWithSignature\src folder.

· GetParametersSignature method, which is static method in my class and uses the SignParameters method from AmazonPaymentsHelper

public static string GetParametersSignature(PaymentGatewayPost post, Uri gatewayUrl)
{
    return AmazonPaymentsHelper.SignParameters
    (
    post.ListParams,
    ConfigReader.SecretKey,
    post.Method,
    gatewayUrl.Host,
    gatewayUrl.AbsolutePath
    );
}

With this method we sign parameters using our SecretKey, which we have in Web.config.

And last, we have an Order class which is used to provide info for the current order.

public class Order
{
    public string OrderID { get; set; }
    public string CustomerId { get; set; }
    public decimal Amount { get; set; }
    public int Quantity { get; set; }
}

At the end, you need to add Button or get an Image Button from Amazon Payments website and bind a method that will fire on button click and will call DoPayment(Order order) function. There you can fill the Order info also. Once you click the button, you will be redirected to Amazon CBUI Payments website where user should log in with his email and confirm the payment. There you will see other information sent as a parameter using the http post values.

Once the payment is confirmed, you will be automatically redirected to the Return URL with some parameters that shows the transaction status and some other details.

For now, this is all. In the next blog, I will write more about handling and validating return url query string parameters and handling and validating IPN url posted form parameters, where Amazon sends post to the IPN (Instant Payment Notification) url once the payment is processed with status either completed, failed or other.

I hope this was helpful blog for you.

Please do let me know your feedback.

Regards,
Hajan

Published Wednesday, April 20, 2011 12:27 AM by hajan

Comments

# re: Amazon Simple Pay in ASP.NET

Wednesday, April 20, 2011 2:50 AM by Vasja

Now this is can make your life easier :)

# re: Amazon Simple Pay in ASP.NET

Good Article, Keep it up....

# re: Amazon Simple Pay in ASP.NET

Thursday, April 21, 2011 4:48 AM by Walter

Thank you for an excellent article. Keep up the good work. I would like to see a similar article on PayPal integration. I'll keep watching your blog and hopefully you'll get a chance to post soon. Kind Regards. Walter.

# re: Amazon Simple Pay in ASP.NET

Thursday, April 21, 2011 10:07 AM by hajan

Thanks guys for your comments!

@Walter, I have in plan to write about integrating with PayPal and Moneybookers too! Stay tuned! ;)

# re: Amazon Simple Pay in ASP.NET

Monday, June 20, 2011 3:29 PM by Matt

How do you implement the signing function using namevaluecollection rather than IDictionary? This code is useless on the signature end, but perfect for unsigned buttons.

# re: Amazon Simple Pay in ASP.NET

Monday, June 20, 2011 3:51 PM by hajan

Matt, please check the Amazon Sample code. I think there is something for what you ask. Otherwise, I have some more blogs planned related Amazon Payments for publishing soon.

# re: Amazon Simple Pay in ASP.NET

Monday, June 20, 2011 5:09 PM by Matt

Thanks Hajan. The sample code uses a very complicated method to generate the form (without the javascript function to post). I really like the way you do this, its clean. I look forward to seeing your code above implemented with signed buttons.

# re: Amazon Simple Pay in ASP.NET

Tuesday, July 26, 2011 3:00 PM by Corey

Thank you for the great example Hajan!  Do you have any details about the IPN implmentation?

# re: Amazon Simple Pay in ASP.NET

Wednesday, July 27, 2011 3:46 AM by hajan

@Matt... thanks for the comment...

@Corey, yep... being too much busy in the last few weeks, but I am definitely going to write more about that ;) - stay tuned.

# re: Amazon Simple Pay in ASP.NET

Saturday, December 10, 2011 8:50 AM by sxnshr

Given help was more helpfull. but If you send  tips for how to Implement amazon gateway when Client used American Experss/other credit cards...that will be more helpful for me...(Actually I am Not more Exp... Developer)

# re: Amazon Simple Pay in ASP.NET

Monday, February 13, 2012 9:47 AM by Bret

Could you put the code on Github or somewhere?  Dropbox is blocked at my work and when trying to download from home it says that access was denied to the files.  

# re: Amazon Simple Pay in ASP.NET

Friday, February 17, 2012 1:42 PM by hajan

Bret, the files are not hosted in DropBox... so you have the whole code within the blog post including some reference links to Amazon Payments website where you can find more info and docs...

# re: Amazon Simple Pay in ASP.NET

Thursday, June 28, 2012 5:00 PM by jbonavita

Great Article. Did you ever do the IPN article? I could really use an example :)

# re: Amazon Simple Pay in ASP.NET

Sunday, March 24, 2013 11:31 AM by Gary Petersen

Great article here.  I am also looking for the IPN and / or Return Url article.  Did you ever post that?

# re: Amazon Simple Pay in ASP.NET

Monday, March 25, 2013 7:07 PM by petersga

Very nice article.  Have you ever written anything yet regarding the returnUrl or ipnUrl yet?  I too could use an example if you have it.

# re: Amazon Simple Pay in ASP.NET

Wednesday, September 4, 2013 8:06 AM by Nitin

Thanks for such good article.

Could you help me regarding, How to configure NopCommerce (or any website applications) products to Amazon.com.Also how to handle payment system in Amazon

Leave a Comment

(required) 
(required) 
(optional)
(required)