using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; using System.Security.Cryptography; /// /// Helper class to handle the payment integration with PayGate /// /// public enum ProcessNowOptions { Yes, No }; public class PayGateSubscriptions { public string PayGate_ID { get; set; } public string PayGate_Key { get; set; } public string Reference { get; set; } public float Amount { get; set; } public string Currency { get; set; } public string Return_URL { get; set; } public string UserEmail { get; set; } public ProcessNowOptions ProcessNow { get; set; } public float ProcessNowAmount { get; set; } public DateTime SubsStartDate { get; set; } public DateTime SubsEndDate { get; set; } //private static string PayGate_Server = "https://www.paygate.co.za/paywebv2/process.trans"; private static string PayGate_Server = "SendRequestSubs.aspx"; private static string PayGate_Version = "21"; /****************************************************************************************************/ /// /// Initializes a new instance of the class. /// public PayGateSubscriptions() { PayGate_ID = System.Configuration.ConfigurationManager.AppSettings.Get("PayGate_ID"); PayGate_Key = System.Configuration.ConfigurationManager.AppSettings.Get("PayGate_Key"); Currency = System.Configuration.ConfigurationManager.AppSettings.Get("PayGate_Currency"); Return_URL = System.Configuration.ConfigurationManager.AppSettings.Get("PayGate_ReturnURL"); } /****************************************************************************************************/ /// /// Initializes a new instance of the class. /// /// The pay gate ID. /// The pay gate encryption key. /// The pay gate currency. /// The pay gate return URL. public PayGateSubscriptions(string PayGate_ID, string PayGate_Key, string PayGate_Currency, string PayGate_ReturnURL) { this.PayGate_ID = PayGate_ID; this.PayGate_Key = PayGate_Key; this.Currency = PayGate_Currency; this.Return_URL = PayGate_ReturnURL; } /****************************************************************************************************/ /// /// Generates the PayGate MD5 checksum. /// /// The data. /// private string GenerateChecksum(string Data) { ASCIIEncoding AE = new ASCIIEncoding(); byte[] ByteSource = AE.GetBytes(Data); MD5CryptoServiceProvider MD5 = new MD5CryptoServiceProvider(); byte[] Hash = MD5.ComputeHash(ByteSource); string Checksum = ""; for (int i = 0; i < Hash.Length; i++) { Checksum += Hash[i].ToString("x2").ToUpper(); } return Checksum; } /****************************************************************************************************/ /// /// Starts the payment process. /// public string StartPayment() { string TransDate = DateTime.Now.ToString("yyyy-MM-dd HH:mm"); string TransAmnt = (Amount * 100).ToString("G0"); string NowAmnt = (ProcessNowAmount * 100).ToString("G0"); string Frequency = "201"; //Subs Frequency - set to 1st day of the month. See below. string ChecksumSource = PayGate_Version + "|" + PayGate_ID + "|"; ChecksumSource += Reference + "|"; ChecksumSource += TransAmnt + "|"; ChecksumSource += Currency + "|"; ChecksumSource += Return_URL + "|"; ChecksumSource += TransDate + "|"; if (!string.IsNullOrEmpty(UserEmail)) ChecksumSource += UserEmail + "|"; ChecksumSource += SubsStartDate.ToString("yyyy-MM-dd") + "|"; ChecksumSource += SubsEndDate.ToString("yyyy-MM-dd") + "|"; ChecksumSource += Frequency + "|"; if (ProcessNow == ProcessNowOptions.Yes) { ChecksumSource += "YES|" + NowAmnt + "|"; } else { ChecksumSource += "NO||"; } ChecksumSource += PayGate_Key; string Checksum = GenerateChecksum(ChecksumSource); string PostUrl = PayGate_Server + "?"; PostUrl += "VERSION=" + PayGate_Version; PostUrl += "&PAYGATE_ID=" + PayGate_ID; PostUrl += "&REFERENCE=" + Reference; PostUrl += "&AMOUNT=" + TransAmnt; PostUrl += "&CURRENCY=" + Currency; PostUrl += "&TRANSACTION_DATE=" + TransDate; PostUrl += "&SUBS_START_DATE=" + SubsStartDate.ToString("yyyy-MM-dd"); PostUrl += "&SUBS_END_DATE=" + SubsEndDate.ToString("yyyy-MM-dd"); PostUrl += "&SUBS_FREQUENCY=" + Frequency; if (ProcessNow == ProcessNowOptions.Yes) { PostUrl += "&PROCESS_NOW=YES"; PostUrl += "&PROCESS_NOW_AMOUNT=" + NowAmnt; } else { PostUrl += "&PROCESS_NOW=NO"; PostUrl += "&PROCESS_NOW_AMOUNT="; } PostUrl += "&RETURN_URL=" + Return_URL; if (!string.IsNullOrEmpty(UserEmail)) PostUrl += "&EMAIL=" + UserEmail; PostUrl += "&CHECKSUM=" + Checksum; return PostUrl; } /****************************************************************************************************/ /// /// Confirms the checksum result. /// /// The rx amount. /// The transaction_ status. /// The result_ code. /// The result_ desc. /// The auth_ code. /// The transaction_ id. /// The risk_ indicator. /// The checksum. /// public bool ConfirmChecksumResult(string rxAmount, string Transaction_Status, string Result_Code, string Result_Desc, string Auth_Code, string Transaction_Id, string Subscription_Id, string Risk_Indicator, string rxChecksum) { bool result = false; string ChecksumSource = PayGate_ID + "|"; ChecksumSource += Reference + "|"; ChecksumSource += Transaction_Status + "|"; ChecksumSource += Result_Code + "|"; ChecksumSource += Auth_Code + "|"; ChecksumSource += rxAmount + "|"; ChecksumSource += Result_Desc + "|"; ChecksumSource += Transaction_Id + "|"; ChecksumSource += Subscription_Id + "|"; if (!string.IsNullOrEmpty(Risk_Indicator)) ChecksumSource += Risk_Indicator + "|"; ChecksumSource += PayGate_Key; result = rxChecksum.ToUpper().Equals(GenerateChecksum(ChecksumSource)); return result; } /****************************************************************************************************/ public string GetChecksumResult(string rxAmount, string Transaction_Status, string Result_Code, string Result_Desc, string Auth_Code, string Transaction_Id, string Subscription_Id, string Risk_Indicator, string rxChecksum) { string result = ""; string ChecksumSource = PayGate_ID + "|"; ChecksumSource += Reference + "|"; ChecksumSource += Transaction_Status + "|"; ChecksumSource += Result_Code + "|"; ChecksumSource += Auth_Code + "|"; ChecksumSource += rxAmount + "|"; ChecksumSource += Result_Desc + "|"; ChecksumSource += Transaction_Id + "|"; ChecksumSource += Subscription_Id + "|"; if (!string.IsNullOrEmpty(Risk_Indicator)) ChecksumSource += Risk_Indicator + "|"; ChecksumSource += PayGate_Key; result = GenerateChecksum(ChecksumSource); return result; } /****************************************************************************************************/ /// /// Gets the transaction status. /// /// The status. /// public string GetTransactionStatus(int Status) { string result = ""; switch (Status) { case 0: result = "Pending"; break; case 1: result = "Approved"; break; case 2: result = "Declined"; break; } return result; } /****************************************************************************************************/ /// /// Gets the result code. /// /// The code. /// public string GetResultCode(int Code) { string result = ""; switch (Code) { case 0: result = "N/A"; break; case 990017: result = "Approved Transaction"; break; case 900003: result = "Insufficient Funds"; break; case 900007: result = "Declined Transaction"; break; case 900004: result = "Invalid Card Number"; break; case 990022: result = "Unprocessed Transaction"; break; } return result; } /****************************************************************************************************/ /// /// Gets the risk indicator. /// /// The status. /// public string GetRiskIndicator(string Status) { string result = ""; switch (Status.ToUpper()) { case "AX": result = "Authenticated"; break; case "NX": result = "Not Authenticated"; break; default: result = "N/A"; break; } return result; } /****************************************************************************************************/ /// /// Return the results code as a status code. /// /// The code. /// public int ResultCodeAsStatus(int Code) { int result = 0; switch (Code) { case 0: result = (int)PaymentResults.Pending; break; case 990017: result = (int)PaymentResults.Approved; break; case 900003: result = (int)PaymentResults.InsufficientFunds; break; case 900007: result = (int)PaymentResults.Declined; break; case 900004: result = (int)PaymentResults.InvalidCard; break; case 990022: result = (int)PaymentResults.Pending; break; } return result; } /****************************************************************************************************/ /* Subscription Frequency Codes */ /* Code Description 111 Weekly on Sun 112 Weekly on Mon 113 Weekly on Tue 114 Weekly on Wed 115 Weekly on Thu 116 Weekly on Fri 117 Weekly on Sat 121 2nd Weekly on Sun 122 2nd Weekly on Mon 123 2nd Weekly on Tue 124 2nd Weekly on Wed 125 2nd Weekly on Thu 126 2nd Weekly on Fri 127 2nd Weekly on Sat 131 3rd Weekly on Sun 132 3rd Weekly on Mon 133 3rd Weekly on Tue 134 3rd Weekly on Wed 135 3rd Weekly on Thu 136 3rd Weekly on Fri 137 3rd Weekly on Sat 201 Monthly on 1st 202 Monthly on 2nd 203 Monthly on 3rd 204 Monthly on 4th 205 Monthly on 5th 206 – 227 as above 228 Monthly on 28th 229 Last day of the month 301 – 328 Every 2nd month on 1st to 28th respectively 329 Every 2nd month on last day of the month 401 – 428 Every 3rd month on 1st to 28th respectively 429 Every 3rd month on last day of the month */ /****************************************************************************************************/ /* Card Brand Card Number Risk Indicator Approved Transactions. RESULT_CODE = 990017; TRANSACTION_STATUS = 1. Visa 4000000000000002 Authenticated (AX) * MasterCard 5200000000000015 Authenticated (AX) American Express 378282246310005 Not Authenticated (NX) FNB Cell Pay Point N/A; enter MR PASS in Account Holder field. Authenticated (AX) Mobux 6397729999003950 Not Applicable (XX) Ukash Voucher (with new voucher issued as change) 9999991500000000012 Authenticated (AX) Ukash Voucher (with no change voucher issued) 9999991500000000020 Authenticated (AX) Ukash Card 9826160000000005 Authenticated (AX) Insufficient Funds Transactions. RESULT_CODE = 900003; TRANSACTION_STATUS = 2. MasterCard 5200000000000023 Not Authenticated (NX) * Visa 4000000000000028 Not Authenticated (NX) American Express 371449635398431 Not Authenticated (NX) Declined Transactions. RESULT_CODE = 900007; TRANSACTION_STATUS = 2. Visa 4000000000000036 Authenticated (AX) * MasterCard 5200000000000049 Authenticated (AX) * Diners Club 30569309025904 Not Applicable (XX) FNB Cell Pay Point N/A; enter MR FAIL in Account Holder field. Not Applicable (XX) Mobux 6397729999003550 Not Applicable (XX) Ukash Voucher 9999991500000000038 Not Applicable (XX) Ukash Card 9826160000000013 Not Applicable (XX) Invalid Card Number. RESULT_CODE = 900004; TRANSACTION_STATUS = 2. All other card numbers Not Applicable (XX) Unprocessed Transactions. RESUT_CODE = 990022; TRANSACTION_STATUS = 0. MasterCard 5200000000000064 Not Applicable (XX) Expiry Date must be in the future; Card Holder & CVV or Ukash PIN can be made up. * = Using these card numbers will allow you to test the MasterCard SecureCode / Verified-by-Visa authentication process. The default test account does not allow any customisation; all options are enabled and there is no logo. */ }