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

16 Comments

Comments have been disabled for this content.