Initial project's source code check-in.
This commit is contained in:
commit
b03b0b373f
4573 changed files with 981205 additions and 0 deletions
|
@ -0,0 +1,324 @@
|
|||
// Copyright (c) 2011, Outercurve Foundation.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// - Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// - Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// - Neither the name of the Outercurve Foundation nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
using System;
|
||||
using System.Web;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace WebsitePanel.Ecommerce.EnterpriseServer
|
||||
{
|
||||
/// <summary>
|
||||
/// Payment provider for the Authorize.NET Gateway
|
||||
/// </summary>
|
||||
public class AuthorizeNetProvider : SystemPluginBase, IPaymentGatewayProvider
|
||||
{
|
||||
public const string DEMO_SERVICE_URL = "https://test.authorize.net/gateway/transact.dll";
|
||||
public const string LIVE_SERVICE_URL = "https://secure.authorize.net/gateway/transact.dll";
|
||||
public const char DELIMITER_CHAR = '|';
|
||||
public const string API_VERSION = "3.1";
|
||||
public const string TRANSACTION_TYPE = "AUTH_CAPTURE";
|
||||
public const string PAYMENT_METHOD = "CC";
|
||||
|
||||
public const string MD5_INVALID_MSG = "MD5 hash value received is either incorrect or modified.";
|
||||
|
||||
public override string[] SecureSettings
|
||||
{
|
||||
get
|
||||
{
|
||||
return new string[] { AuthNetSettings.MD5_HASH, AuthNetSettings.TRANSACTION_KEY };
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets Authorize.Net account is demo
|
||||
/// </summary>
|
||||
public bool DemoAccount
|
||||
{
|
||||
get
|
||||
{
|
||||
return Convert.ToBoolean(PluginSettings[AuthNetSettings.DEMO_ACCOUNT]);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets whether provider is running in live mode
|
||||
/// </summary>
|
||||
public bool LiveMode
|
||||
{
|
||||
get
|
||||
{
|
||||
return Convert.ToBoolean(PluginSettings[AuthNetSettings.LIVE_MODE]);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets whether email confirmations enabled
|
||||
/// </summary>
|
||||
public bool SendConfirmation
|
||||
{
|
||||
get
|
||||
{
|
||||
return Convert.ToBoolean(PluginSettings[AuthNetSettings.SEND_CONFIRMATION]);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Get MD5 hash value for the account
|
||||
/// </summary>
|
||||
public string MD5_Hash
|
||||
{
|
||||
get { return PluginSettings[AuthNetSettings.MD5_HASH]; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets transaction key for the account
|
||||
/// </summary>
|
||||
public string TransactionKey
|
||||
{
|
||||
get { return PluginSettings[AuthNetSettings.TRANSACTION_KEY]; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets Authorize.Net account username
|
||||
/// </summary>
|
||||
public string Username
|
||||
{
|
||||
get { return PluginSettings[AuthNetSettings.USERNAME]; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets merchant email to send confirmations by email
|
||||
/// </summary>
|
||||
public string MerchantEmail
|
||||
{
|
||||
get { return PluginSettings[AuthNetSettings.MERCHANT_EMAIL]; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets Authorize.Net service url
|
||||
/// </summary>
|
||||
public string ServiceUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (DemoAccount)
|
||||
return DEMO_SERVICE_URL;
|
||||
return LIVE_SERVICE_URL;
|
||||
}
|
||||
}
|
||||
|
||||
#region IPaymentGatewayProvider Members
|
||||
|
||||
public TransactionResult SubmitPaymentTransaction(CheckoutDetails details)
|
||||
{
|
||||
//init result structure
|
||||
TransactionResult ret = new TransactionResult();
|
||||
//create request content
|
||||
string data = GetRequestData(details);
|
||||
// create webrequest instance
|
||||
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(ServiceUrl);
|
||||
webRequest.Method = "POST";
|
||||
webRequest.ContentLength = data.Length;
|
||||
webRequest.ContentType = "application/x-www-form-urlencoded";
|
||||
// send service request
|
||||
StreamWriter sw = null;
|
||||
try
|
||||
{
|
||||
sw = new StreamWriter(webRequest.GetRequestStream());
|
||||
sw.Write(data);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (sw != null)
|
||||
sw.Close();
|
||||
}
|
||||
// read service response
|
||||
AIMResponse aimResponse = null;
|
||||
HttpWebResponse webResponse = null;
|
||||
try
|
||||
{
|
||||
// get response
|
||||
webResponse = (HttpWebResponse)webRequest.GetResponse();
|
||||
// emit new response
|
||||
aimResponse = new AIMResponse(webResponse.GetResponseStream(), DELIMITER_CHAR);
|
||||
}
|
||||
finally
|
||||
{
|
||||
webResponse.Close();
|
||||
webRequest.Abort();
|
||||
}
|
||||
// copy raw service response
|
||||
ret.RawResponse = aimResponse.RawResponse;
|
||||
// read service response status
|
||||
switch (aimResponse[AIMField.ResponseCode])
|
||||
{
|
||||
case "1": //This transaction has been approved.
|
||||
case "4": //This transaction is being held for review.
|
||||
// check MD5 signature
|
||||
if (!CheckResponseSignature(Username, MD5_Hash, aimResponse[AIMField.TransactionId], details[CheckoutKeys.Amount],
|
||||
aimResponse[AIMField.ResponseSignature]))
|
||||
{
|
||||
throw new Exception(MD5_INVALID_MSG);
|
||||
}
|
||||
//
|
||||
ret.Succeed = true;
|
||||
//
|
||||
ret.TransactionId = aimResponse[AIMField.TransactionId];
|
||||
// mark transaction as a completed
|
||||
ret.TransactionStatus = TransactionStatus.Approved;
|
||||
//
|
||||
break;
|
||||
case "2": // This transaction has been declined.
|
||||
case "3": // There has been an error processing this transaction.
|
||||
//
|
||||
ret.StatusCode = String.Concat(AuthorizeNetKeys.ErrorPrefix, aimResponse[AIMField.ResponseCode],
|
||||
aimResponse[AIMField.ResponseReasonCode]);
|
||||
//
|
||||
ret.Succeed = false;
|
||||
//
|
||||
ret.TransactionStatus = TransactionStatus.Declined;
|
||||
//
|
||||
break;
|
||||
}
|
||||
// return result
|
||||
return ret;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private bool CheckResponseSignature(string login, string md5hash,
|
||||
string transactId, string amount, string signature)
|
||||
{
|
||||
//input string = "MD5 Hash Value"+"API Login ID"+"Trans ID"+"Amount"
|
||||
byte[] data = Encoding.ASCII.GetBytes(md5hash + login + transactId + amount);
|
||||
MD5 md5 = new MD5CryptoServiceProvider();
|
||||
byte[] result = md5.ComputeHash(data);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach (byte b in result)
|
||||
{
|
||||
sb.Append(b.ToString("X2"));
|
||||
}
|
||||
// validate response signature
|
||||
return (sb.ToString() == signature);
|
||||
}
|
||||
|
||||
private string GetRequestData(CheckoutDetails details)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
AddRequestData(CheckoutKeys.CardNumber, AuthorizeNetKeys.CardNumber, sb, details);
|
||||
AddRequestData(CheckoutKeys.VerificationCode, AuthorizeNetKeys.VerificationCode, sb, details);
|
||||
|
||||
// expire date
|
||||
string expireDate = String.Concat(details[CheckoutKeys.ExpireMonth], details[CheckoutKeys.ExpireYear]);
|
||||
AddRequestData(AuthorizeNetKeys.ExpirationDate, expireDate, sb);
|
||||
|
||||
AddRequestData(CheckoutKeys.Amount, AuthorizeNetKeys.Amount, sb, details);
|
||||
|
||||
//TODO: Add currency support
|
||||
AddRequestData(CheckoutKeys.Currency, AuthorizeNetKeys.CurrencyCode, sb, details);
|
||||
|
||||
AddRequestData(CheckoutKeys.InvoiceNumber, AuthorizeNetKeys.InvoiceNumber, sb, details);
|
||||
AddRequestData(CheckoutKeys.ContractNumber, AuthorizeNetKeys.TransDescription, sb, details);
|
||||
|
||||
AddRequestData(CheckoutKeys.FirstName, AuthorizeNetKeys.FirstName, sb, details);
|
||||
AddRequestData(CheckoutKeys.LastName, AuthorizeNetKeys.LastName, sb, details);
|
||||
// email is shipping
|
||||
AddRequestData(CheckoutKeys.CustomerEmail, AuthorizeNetKeys.CustomerEmail, sb, details);
|
||||
AddRequestData(CheckoutKeys.Address, AuthorizeNetKeys.Address, sb, details);
|
||||
AddRequestData(CheckoutKeys.Zip, AuthorizeNetKeys.Zip, sb, details);
|
||||
AddRequestData(CheckoutKeys.City, AuthorizeNetKeys.City, sb, details);
|
||||
AddRequestData(CheckoutKeys.State, AuthorizeNetKeys.State, sb, details);
|
||||
AddRequestData(CheckoutKeys.Country, AuthorizeNetKeys.Country, sb, details);
|
||||
AddRequestData(CheckoutKeys.Phone, AuthorizeNetKeys.Phone, sb, details);
|
||||
AddRequestData(CheckoutKeys.Fax, AuthorizeNetKeys.Fax, sb, details);
|
||||
AddRequestData(CheckoutKeys.CustomerId, AuthorizeNetKeys.CustomerId, sb, details);
|
||||
AddRequestData(CheckoutKeys.IPAddress, AuthorizeNetKeys.IPAddress, sb, details);
|
||||
|
||||
// shipping information
|
||||
AddRequestData(CheckoutKeys.ShipToFirstName, AuthorizeNetKeys.ShipToFirstName, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToLastName, AuthorizeNetKeys.ShipToLastName, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToCompany, AuthorizeNetKeys.ShipToCompany, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToZip, AuthorizeNetKeys.ShipToZip, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToAddress, AuthorizeNetKeys.ShipToAddress, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToCity, AuthorizeNetKeys.ShipToCity, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToState, AuthorizeNetKeys.ShipToState, sb, details);
|
||||
AddRequestData(CheckoutKeys.ShipToCountry, AuthorizeNetKeys.ShipToCountry, sb, details);
|
||||
|
||||
// service settings
|
||||
// copy account username
|
||||
AddRequestData(AuthorizeNetKeys.Account, Username, sb);
|
||||
// copy response delimiter char
|
||||
AddRequestData(AuthorizeNetKeys.DelimiterChar, DELIMITER_CHAR.ToString(), sb);
|
||||
// copy transaction key
|
||||
AddRequestData(AuthorizeNetKeys.TransactionKey, TransactionKey, sb);
|
||||
// copy send confirmation flag & merchant email
|
||||
if (SendConfirmation)
|
||||
{
|
||||
AddRequestData(AuthorizeNetKeys.MerchantEmail, MerchantEmail, sb);
|
||||
AddRequestData(AuthorizeNetKeys.SendConfirmation, "TRUE", sb);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddRequestData(AuthorizeNetKeys.SendConfirmation, "FALSE", sb);
|
||||
}
|
||||
// copy API version
|
||||
AddRequestData(AuthorizeNetKeys.Version, API_VERSION, sb);
|
||||
// copy demo mode flag
|
||||
if (!LiveMode)
|
||||
AddRequestData(AuthorizeNetKeys.DemoMode, "TRUE", sb);
|
||||
// copy payment method
|
||||
AddRequestData(AuthorizeNetKeys.PaymentMethod, PAYMENT_METHOD, sb);
|
||||
// copy transaction type
|
||||
AddRequestData(AuthorizeNetKeys.TransactType, TRANSACTION_TYPE, sb);
|
||||
// copy delim data flag
|
||||
AddRequestData(AuthorizeNetKeys.DelimData, "TRUE", sb);
|
||||
// copy relay response flag
|
||||
AddRequestData(AuthorizeNetKeys.RelayResponse, "FALSE", sb);
|
||||
// return result
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private void AddRequestData(string key1, string key2, StringBuilder sb, CheckoutDetails details)
|
||||
{
|
||||
AddRequestData(key2, details[key1], sb);
|
||||
}
|
||||
|
||||
private void AddRequestData(string key, StringBuilder sb, CheckoutDetails details)
|
||||
{
|
||||
AddRequestData(key, details[key], sb);
|
||||
}
|
||||
|
||||
private void AddRequestData(string key, string value, StringBuilder sb)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(key) && !String.IsNullOrEmpty(value))
|
||||
{
|
||||
if (sb.Length == 0)
|
||||
sb.AppendFormat("{0}={1}", key, value);
|
||||
else
|
||||
sb.AppendFormat("&{0}={1}", key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue