AmazonHelper.cs :  » Web-Frameworks » nopCommerce » NopSolutions » NopCommerce » Payment » Methods » Amazon » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Web Frameworks » nopCommerce 
nopCommerce » NopSolutions » NopCommerce » Payment » Methods » Amazon » AmazonHelper.cs
//------------------------------------------------------------------------------
// The contents of this file are subject to the nopCommerce Public License Version 1.0 ("License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at  http://www.nopCommerce.com/License.aspx. 
// 
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
// See the License for the specific language governing rights and limitations under the License.
// 
// The Original Code is nopCommerce.
// The Initial Developer of the Original Code is NopSolutions.
// All Rights Reserved.
// 
// Contributor(s): 
//------------------------------------------------------------------------------

using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using NopSolutions.NopCommerce.Common;
using System.Web;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Collections.Specialized;

namespace NopSolutions.NopCommerce.Payment.Methods.Amazon{
    public class AmazonHelper
    {
        public static readonly String SIGNATURE_KEYNAME = "signature";
        public static readonly String SIGNATURE_METHOD_KEYNAME = "signatureMethod";
        public static readonly String SIGNATURE_VERSION_KEYNAME = "signatureVersion";
        public static readonly String SIGNATURE_VERSION_1 = "1";
        public static readonly String SIGNATURE_VERSION_2 = "2";
        public static readonly String HMAC_SHA1_ALGORITHM = "HmacSHA1";
        public static readonly String HMAC_SHA256_ALGORITHM = "HmacSHA256";
        public static readonly String RSA_SHA1_ALGORITHM = "SHA1withRSA";
        public static readonly String CERTIFICATE_URL_KEYNAME = "certificateUrl";
        public static readonly String EMPTY_STRING = String.Empty;

        // Constants used when constructing the string to sign for v2
        public static readonly String AppName = "ASP";
        public static readonly String NewLine = "\n";
        public static readonly String EmptyUriPath = "/";
        public static String equals = "=";
        public static readonly String And = "&";
        public static readonly String UTF_8_Encoding = "UTF-8";

        /**
        * Calculate String to Sign for SignatureVersion 1
        * @param parameters request parameters
        * @return String to Sign
        */
        public static string SignParameters(NameValueCollection parameters, String key, 
            String HttpMethod, String Host, String RequestURI) //throws Exception
        {
            String signatureVersion = parameters[SIGNATURE_VERSION_KEYNAME];
            String algorithm = HMAC_SHA1_ALGORITHM;
            String stringToSign = null;
            if (signatureVersion == null && String.Compare(AppName, "FPS", true) != 0)
            {
                stringToSign = CalculateSignV1(parameters);
            }
            else if (String.Compare("1", signatureVersion, true) == 0)
            {
                stringToSign = CalculateSignV1(parameters);
            }
            else if (String.Compare("2", signatureVersion, true) == 0)
            {
                algorithm = parameters[SIGNATURE_METHOD_KEYNAME];
                stringToSign = CalculateSignV2(parameters, HttpMethod, Host, RequestURI);
            }
            else
            {
                throw new NopException("Invalid Signature Version specified");
            }
            return Sign(stringToSign, key, algorithm);
        }

        /**
      * Calculate String to Sign for SignatureVersion 1
      * @param parameters request parameters
      * @return String to Sign
      */
        private static string CalculateSignV1(NameValueCollection parameters)
        {
            StringBuilder data = new StringBuilder();
            IDictionary<String, String> sorted = new SortedDictionary<String, String>(StringComparer.OrdinalIgnoreCase);
            foreach(string paramKey in parameters.AllKeys)
            {
                sorted.Add(paramKey, parameters[paramKey]);
            }
            foreach (KeyValuePair<String, String> pair in sorted)
            {
                if (pair.Value != null)
                {
                    if (String.Compare(pair.Key, SIGNATURE_KEYNAME, true) == 0) continue;
                    data.Append(pair.Key);
                    data.Append(pair.Value);
                }
            }
            return data.ToString();
        }

        /**
       * Calculate String to Sign for SignatureVersion 2
       * @param parameters
       * @param httpMethod - POST or GET
       * @param hostHeader - Service end point
       * @param requestURI - Path
       * @return
       */
        private static string CalculateSignV2(NameValueCollection parameters, String httpMethod, String hostHeader, String requestURI)// throws SignatureException
        {
            StringBuilder stringToSign = new StringBuilder();
            if (httpMethod == null) throw new Exception("HttpMethod cannot be null");
            stringToSign.Append(httpMethod);
            stringToSign.Append(NewLine);

            // The host header - must eventually convert to lower case
            // Host header should not be null, but in Http 1.0, it can be, in that
            // case just append empty string ""
            if (hostHeader == null)
                stringToSign.Append("");
            else
                stringToSign.Append(hostHeader.ToLower());
            stringToSign.Append(NewLine);

            if (requestURI == null || requestURI.Length == 0)
                stringToSign.Append(EmptyUriPath);
            else
                stringToSign.Append(UrlEncode(requestURI, true));
            stringToSign.Append(NewLine);

            IDictionary<String, String> sortedParamMap = new SortedDictionary<String, String>(StringComparer.Ordinal);
            foreach(string paramKey in parameters.AllKeys)
            {
                sortedParamMap.Add(paramKey, parameters[paramKey]);
            }
            foreach (String key in sortedParamMap.Keys)
            {
                if (String.Compare(key, SIGNATURE_KEYNAME, true) == 0) continue;
                stringToSign.Append(UrlEncode(key, false));
                stringToSign.Append(equals);
                stringToSign.Append(UrlEncode(sortedParamMap[key], false));
                stringToSign.Append(And);
            }

            String result = stringToSign.ToString();
            return result.Remove(result.Length - 1);
        }

        public static String UrlEncode(String data, bool path)
        {
            StringBuilder encoded = new StringBuilder();
            String unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" + (path ? "/" : "");

            foreach (char symbol in System.Text.Encoding.UTF8.GetBytes(data))
            {
                if (unreservedChars.IndexOf(symbol) != -1)
                {
                    encoded.Append(symbol);
                }
                else
                {
                    encoded.Append("%" + String.Format("{0:X2}", (int)symbol));
                }
            }

            return encoded.ToString();

        }

        /**
         * Computes RFC 2104-compliant HMAC signature.
         */
        public static String Sign(String data, String key, String signatureMethod)// throws SignatureException
      {
            try
            {
                ASCIIEncoding encoding = new ASCIIEncoding();
                HMAC Hmac = HMAC.Create(signatureMethod);
                Hmac.Key = encoding.GetBytes(key);
                Hmac.Initialize();
                CryptoStream cs = new CryptoStream(Stream.Null, Hmac, CryptoStreamMode.Write);
                cs.Write(encoding.GetBytes(data), 0, encoding.GetBytes(data).Length);
                cs.Close();
                byte[] rawResult = Hmac.Hash;
                String sig = Convert.ToBase64String(rawResult, 0, rawResult.Length);
                return sig;
            }
            catch (Exception e)
            {
                throw new NopException("Failed to generate signature: " + e.Message);
            }
      }

            /**
         * Validates the request by checking the integrity of its parameters.
         * @param parameters - all the http parameters sent in IPNs or return urls. 
         * @param urlEndPoint should be the url which recieved this request. 
         * @param httpMethod should be either POST (IPNs) or GET (returnUrl redirections)
         */
        public static Boolean ValidateRequest(NameValueCollection parameters,
               String urlEndPoint, String httpMethod) 
        {
            String signatureVersion = null;
            //This is present only in case of signature version 2. If this is not present we assume this is signature version 1.
            try
            {
                signatureVersion = parameters[SIGNATURE_VERSION_KEYNAME];
            }
            catch (KeyNotFoundException)
            {
                signatureVersion = null;
            }

            if(SIGNATURE_VERSION_2.Equals(signatureVersion))
                return ValidateSignatureV2(parameters, urlEndPoint, httpMethod);
            else
                return ValidateSignatureV1(parameters);
         }

        /**
          * Verifies the signature using PKI.
          */
        private static  Boolean ValidateSignatureV2(NameValueCollection parameters,
            String urlEndPoint, String httpMethod)
        {
            //1. input validation.
            String signature = parameters[SIGNATURE_KEYNAME];
            if (signature == null)
            {
                throw new Exception("'signature' is missing from the parameters.");
            }

            String signatureMethod = parameters[SIGNATURE_METHOD_KEYNAME];
            if (signatureMethod == null)
            {
                throw new Exception("'signatureMethod' is missing from the parameters.");
            }

            String signatureAlgorithm = GetSignatureAlgorithm(signatureMethod);
            if (signatureAlgorithm == null)
            {
                throw new Exception("'signatureMethod' present in parameters is invalid. " +
                        "Valid signatureMethods are : 'RSA-SHA1'");
            }

            String certificateUrl = parameters[CERTIFICATE_URL_KEYNAME];
            if (certificateUrl == null)
            {
                throw new Exception("'certificateUrl' is missing from the parameters.");
            }

            String certificate = GetPublicKeyCertificateAsString(certificateUrl);
            if (certificate == null)
            {
                throw new Exception("public key certificate could not fetched from url: " + certificateUrl);
            }

            //2. calculating the string to sign
            String stringToSign = EMPTY_STRING;
            try
            {
                Uri uri = new Uri(urlEndPoint);
                String hostHeader = getHostHeader(uri);
                String requestURI = GetRequestURI(uri);
                stringToSign = CalculateSignV2(parameters, httpMethod, hostHeader, requestURI);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
            //3. verify signature 
            try
            {
                byte[] signatureBytes = Base64DecodeToBytes(signature);
                X509Certificate2 x509Cert = new X509Certificate2(StrToByteArray(certificate));
                RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)x509Cert.PublicKey.Key;
                return RSA.VerifyData(StrToByteArray(stringToSign), new SHA1Managed(), signatureBytes);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }
        }

        private static bool ValidateSignatureV1(NameValueCollection parameters)
        {
            String stringToSign = CalculateSignV1(parameters);
            String signature = parameters[SIGNATURE_KEYNAME];
            String sig;
            try
            {
                ASCIIEncoding encoding = new ASCIIEncoding();
                HMAC Hmac = HMAC.Create("HmacSHA1");
                Hmac.Key = encoding.GetBytes(SimplePaySettings.SecretKey);
                Hmac.Initialize();
                CryptoStream cs = new CryptoStream(Stream.Null, Hmac, CryptoStreamMode.Write);
                cs.Write(encoding.GetBytes(stringToSign), 0, encoding.GetBytes(stringToSign).Length);
                cs.Close();
                byte[] rawResult = Hmac.Hash;
                sig = Convert.ToBase64String(rawResult, 0, rawResult.Length);

            }
            catch (Exception e)
            {
                throw new Exception("Failed to generate HMAC : " + e.Message);
            }
            return sig.Equals(signature);
        }


        public static string V2UrlEncode(String data, bool path)
        {
            StringBuilder encoded = new StringBuilder();
            String unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~" + (path ? "/" : "");

            foreach (char symbol in System.Text.Encoding.UTF8.GetBytes(data))
            {
                if (unreservedChars.IndexOf(symbol) != -1)
                {
                    encoded.Append(symbol);
                }
                else
                {
                    encoded.Append("%" + String.Format("{0:X2}", (int)symbol));
                }
            }
            return encoded.ToString();
        }



        public static string UrlDecode(String value)
        {
            return HttpUtility.UrlDecode(value, Encoding.UTF8);
        }

        private static string getHostHeader(Uri uri)
        {
            int port = uri.Port;
            if (port != -1)
            {
                if(uri.Scheme.Equals(Uri.UriSchemeHttps) && port ==443
                    || uri.Scheme.Equals(Uri.UriSchemeHttp) && port == 80)
                    port = -1;
            }
            return uri.Host.ToLower() + (port != -1 ? ":" + port : "");
        }

        private static string GetRequestURI(Uri uri)
        {
            String requestURI = uri.LocalPath;
            if (requestURI == null || requestURI.Equals(EMPTY_STRING)) {
                requestURI = "/";
            } else {
                requestURI = UrlDecode(requestURI);
            }
            return requestURI;
        }

        private static string GetSignatureAlgorithm(string signatureMethod)
        {
            if ("RSA-SHA1".Equals(signatureMethod)) {
                return RSA_SHA1_ALGORITHM;
            }
            return null;
        }

        private static string GetPublicKeyCertificateAsString(string certificateUrl)
        {
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(certificateUrl);
            request.AllowAutoRedirect = false;
            HttpWebResponse resp = (HttpWebResponse)request.GetResponse();
            Stream stream = resp.GetResponseStream();
            StreamReader read = new StreamReader(stream);
            String data = read.ReadToEnd();
            return data;
        }

        /// <summary>
        /// Base64 decode a string
        /// </summary>
        /// <param name="data">Data</param>
        /// <returns>Data</returns>
        public static byte[] Base64DecodeToBytes(string data)
        {
            return Convert.FromBase64String(data);
        }

        /// <summary>
        /// Convert a string to a byte array
        /// </summary>
        /// <param name="str">String</param>
        /// <returns>Byte array</returns>
        public static byte[] StrToByteArray(string str)
        {
            return new UTF8Encoding().GetBytes(str);
        }

    }
}
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.