From 97be0054dfc10031f16a93fcc4e0ee61a4d00d58 Mon Sep 17 00:00:00 2001 From: Jim Wang Date: Tue, 15 Nov 2022 23:23:24 -0600 Subject: [PATCH 1/4] Add multiple frameworks support, .Net framework 4.5, .Net Standard 2.0, .Net 6.0 --- .gitignore | 1 + Authorize.NET/AuthorizeNET.csproj | 98 ++++++++--------- Authorize.NET/AuthorizeNetExtension.cs | 137 +++++++++++++++++++++++ Authorize.NET/AuthorizeNetOptions.cs | 39 +++++++ Authorize.NET/Environment.cs | 33 +++++- Authorize.NET/LogHelper.cs | 143 +++++++++++++++++++++++++ Authorize.NET/Util/LogHelper.cs | 82 ++++++++++++-- AuthorizeNET.sln | 14 ++- MIGRATING.md | 2 +- README.md | 59 +++++++++- 10 files changed, 540 insertions(+), 68 deletions(-) create mode 100644 Authorize.NET/AuthorizeNetExtension.cs create mode 100644 Authorize.NET/AuthorizeNetOptions.cs create mode 100644 Authorize.NET/LogHelper.cs diff --git a/.gitignore b/.gitignore index fd5204b5..10016f08 100644 --- a/.gitignore +++ b/.gitignore @@ -181,3 +181,4 @@ UpgradeLog*.htm # Microsoft Fakes FakesAssemblies/ +/.vs diff --git a/Authorize.NET/AuthorizeNET.csproj b/Authorize.NET/AuthorizeNET.csproj index 809a0741..8c8cff99 100644 --- a/Authorize.NET/AuthorizeNET.csproj +++ b/Authorize.NET/AuthorizeNET.csproj @@ -1,49 +1,27 @@  - + - Debug - AnyCPU - 9.0.30729 - 2.0 - {5D52EAEC-42FB-4313-83B8-69E2F55EBF14} - Library - Properties - AuthorizeNet - AuthorizeNet - v4.5 - 512 - - - - - - 3.5 + net45;netstandard2.0;net6.0 + 2.0.3 + AuthorizeNet + AuthorizeNet + false + AuthorizeNet + Use this SDK to integrate with the Authorize.Net APIs for Payment Transactions, Recurring Billing, Customer Payment Profiles and Reporting. + https://github.com/AuthorizeNet/sdk-dotnet/blob/master/LICENSE.txt + https://github.com/wjmirror/AuthorizeNet-sdk-dotnet + git + https://github.com/wjmirror/AuthorizeNet-sdk-dotnet + Payments API Authorize.Net + True + True + AuthorizeNet.MultiFrameworks + http://developer.authorize.net/resources/images/favicon.ico + https://github.com/AuthorizeNet/sdk-dotnet/blob/master/LICENSE.txt + Build with multiple frameworks, .Net framework 4.5, .Net Standard 2.0 and .Net 6.0 - - AnyCPU - true - full - false - bin/Debug/ - DEBUG;TRACE - prompt - 4 - bin/Debug/AuthorizeNet.XML - 0219,1591,1635 - false - - - AnyCPU - pdbonly - true - bin/Release - TRACE - prompt - 4 - bin/Release/AuthorizeNet.XML - false - - + + @@ -54,7 +32,10 @@ + + + @@ -121,13 +102,26 @@ - - - + + + 3.1.0 + + + 3.1.0 + + + 3.1.0 + + + + + 6.0.0 + + + 6.0.0 + + + 6.0.0 + + \ No newline at end of file diff --git a/Authorize.NET/AuthorizeNetExtension.cs b/Authorize.NET/AuthorizeNetExtension.cs new file mode 100644 index 00000000..acdaa8a5 --- /dev/null +++ b/Authorize.NET/AuthorizeNetExtension.cs @@ -0,0 +1,137 @@ +#if NETSTANDARD || NET6_0 +using AuthorizeNet.Api.Contracts.V1; +using AuthorizeNet.Api.Controllers.Bases; +using AuthorizeNet.Util; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using System; + +namespace AuthorizeNet +{ + /// + /// AuthorizeNet ServiceProvider Extension. + /// + public static class AuthorizeNetExtension + { + /// + /// Setup client library options. Call this extension function to setup Authorize.Net client library. + /// It set the ILoggerFactory for logging, + /// set ApiOperationBase<ANetApiRequest, ANetApiResponse>.RunEnvironment according to AuthorizeNetOptions.Environment + /// set ApiOperationBase<ANetApiRequest, ANetApiResponse>.MerchantAuthentication according to AuthorizeNetOptions.ApiLoginId and AuthorizeNetOptions.TransactionKey. + /// + /// Service Provider. + /// The AuthorizeNetOptions builder delegation. + /// The default merchant authentication builder delegation. + /// + /// The AuthorizeNetOptions can be configured either in ConfigureService with IServiceCollection.Configure<AuthorizeNetOptions> or use optionsBuilder. Exception is thrown when neither of them is set. + /// The merchantAuenticationBuilder is called to setup the default marchant authentication. + /// ILoggerFactory is required in .Net Core, exception is thrown when the ILoggerFactory is not configured in DI container. + /// + public static void SetupAuthorizeNet(this IServiceProvider services, Action optionsBuilder = null, Action merchantAuenticationBuilder = null) + { + AuthorizeNetOptions options = null; + IOptions optionsMonitor = services.GetService>(); + + if (optionsMonitor == null && optionsBuilder == null) + throw new Exception($"The AuthorizeNetOptions is not configured and optionsBuilder Action is not set."); + + if (optionsMonitor != null) + options = optionsMonitor.Value; + + optionsBuilder?.Invoke(options); + + //setup ILoggerFactory + ILoggerFactory loggerFactory = services.GetService(); + if (loggerFactory == null) + throw new Exception($"Can't Get the ILoggerFactory service."); + + LogFactory.LoggerFactory = loggerFactory; + LogFactory.LoggingSensitiveData = options.LoggingSensitiveData; + + //setup environment + AuthorizeNet.Environment.GetConfigurationPropertyValue = (propName) => + { + string propValue = null; + if (propName == Constants.HttpConnectionTimeout) + { + if (options.ConnectionTimeout != null) + propValue = options.ConnectionTimeout.ToString(); + } + else if (propName == Constants.HttpReadWriteTimeout) + { + if (options.ReadWriteTimeout != null) + propValue = options.ReadWriteTimeout.ToString(); + } + else if (propName == Constants.HttpsUseProxy) + { + if (options.UseProxy != null) + propValue = options.UseProxy.ToString(); + } + else if (propName == Constants.HttpsProxyHost) + { + propValue = options.ProxyHost; + } + else if (propName == Constants.HttpsProxyPort) + { + if (options.ProxyPort != null) + propValue = options.ProxyPort.ToString(); + } + else + { + throw new Exception($"The property {propName} is not configured in AuthorizeNetOptions "); + } + + return propValue; + }; + + + AuthorizeNet.Environment runningEnvironment = AuthorizeNet.Environment.LOCAL_VM; + + if (0 == string.Compare(options.Environment, "PRODUCTION", true)) + { + runningEnvironment = AuthorizeNet.Environment.PRODUCTION; + } + else if (0 == string.Compare(options.Environment, "SANDBOX", true)) + { + runningEnvironment = AuthorizeNet.Environment.SANDBOX; + } + else if (0 == string.Compare(options.Environment, "LOCAL_VM", true)) + { + runningEnvironment = AuthorizeNet.Environment.LOCAL_VM; + } + else if (0 == string.Compare(options.Environment, "HOSTED_VM", true)) + { + runningEnvironment = AuthorizeNet.Environment.HOSTED_VM; + } + else if (0 == string.Compare(options.Environment, "CUSTOM", true)) + { + if (string.IsNullOrWhiteSpace(options.BaseUrl)) + throw new Exception("The AuthorizeNetOptions.BaseUrl can not be empty in Custom environment."); + + if (string.IsNullOrWhiteSpace(options.XmlBaseUrl)) + throw new Exception("The AuthorizeNetOptions.XmlBaseUrl can not be empty in Custom environment."); + + runningEnvironment = AuthorizeNet.Environment.createEnvironment(options.BaseUrl, options.XmlBaseUrl, options.CardPresentUrl); + } + else + { + throw new Exception($"Invalid environment name: {options.Environment}, it must be Production, SandBox, Local_VM, Hosted_VM or Custom"); + } + + ApiOperationBase.RunEnvironment = runningEnvironment; + + //setup merchant authentication + merchantAuthenticationType merchantAuthentication = new merchantAuthenticationType + { + name = options.ApiLoginId, + ItemElementName = ItemChoiceType.transactionKey, + Item = options.TransactionKey + }; + merchantAuenticationBuilder?.Invoke(merchantAuthentication); + ApiOperationBase.MerchantAuthentication = merchantAuthentication; + } + + } +} +#endif \ No newline at end of file diff --git a/Authorize.NET/AuthorizeNetOptions.cs b/Authorize.NET/AuthorizeNetOptions.cs new file mode 100644 index 00000000..baddbab7 --- /dev/null +++ b/Authorize.NET/AuthorizeNetOptions.cs @@ -0,0 +1,39 @@ +#if NETSTANDARD || NET6_0 +using AuthorizeNet.APICore; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AuthorizeNet +{ + /// + /// Authorize.Net connection options, the Environment, ApiLoginId and TransactionKey are required. + /// When Environment is CUSTOM, the BaseUrl, XmlBaseUrl are required. + /// + public class AuthorizeNetOptions + { + /// + /// Environment Name, can be SandBox, Production or Custom. The BaseUrl and XmlBaseUrl are required when Environment is Custom. + /// + public string Environment { get; set; } = "SANDBOX"; + public string ApiLoginId { get; set; } + public string TransactionKey { get; set; } + + public bool? UseProxy { get; set; } + public string ProxyHost { get; set; } + public int? ProxyPort { get; set; } + + public int? ConnectionTimeout { get; set; } + public int? ReadWriteTimeout { get; set; } + + public string BaseUrl { get; set; } + public string XmlBaseUrl { get; set; } + public string CardPresentUrl { get; set; } + + public bool LoggingSensitiveData { get; set; } + + } +} +#endif \ No newline at end of file diff --git a/Authorize.NET/Environment.cs b/Authorize.NET/Environment.cs index 9eacd4ab..53a8af6f 100644 --- a/Authorize.NET/Environment.cs +++ b/Authorize.NET/Environment.cs @@ -117,7 +117,7 @@ public static bool getBooleanProperty( String propertyName) return value; } - +#if NET45 private static object mutex = new object(); /// @@ -148,5 +148,36 @@ public static String GetProperty(String propertyName) { } return stringValue; } +#else + + public static Func GetConfigurationPropertyValue; + + /// + /// Reads the value from property file and/or the environment + /// Values in property file supersede the values set in environmen + /// + /// propertyName name of the property to read + /// String property value + public static String GetProperty(String propertyName) + { + String stringValue = null; + String propValue = null; + + if (GetConfigurationPropertyValue != null) + { + propValue = GetConfigurationPropertyValue(propertyName); + } + var envValue = System.Environment.GetEnvironmentVariable(propertyName); + if (null != propValue && propValue.Trim().Length > 0) + { + stringValue = propValue; + } + else if (null != envValue && envValue.Trim().Length > 0) + { + stringValue = envValue; + } + return stringValue; + } +#endif } } \ No newline at end of file diff --git a/Authorize.NET/LogHelper.cs b/Authorize.NET/LogHelper.cs new file mode 100644 index 00000000..f6dc9d3d --- /dev/null +++ b/Authorize.NET/LogHelper.cs @@ -0,0 +1,143 @@ +namespace AuthorizeNet.Util +{ + using System; + using System.Diagnostics; + using System.Globalization; +#if NET45 + using System.Diagnostics; +#endif +#if NETSTANDARD || NET6_0 + using Microsoft.Extensions.Logging; +#endif + /// + /// + /// + /// + public static class LogHelper { + + static LogHelper() { + } + + public static void debug(Log logger, string format, params object[] arguments) { + string logMessage = getMessage(logger, format, arguments); + if ( null != logMessage) { logger.debug(logMessage); } + } + + public static void error(Log logger, string format, params object[] arguments) { + string logMessage = getMessage(logger, format, arguments); + if ( null != logMessage) { logger.error(logMessage); } + } + + public static void info(Log logger, string format, params object[] arguments) { + string logMessage = getMessage(logger, format, arguments); + if ( null != logMessage) { logger.info(logMessage); } + } + + public static void warn(Log logger, string format, params object[] arguments) { + string logMessage = getMessage(logger, format, arguments); + if ( null != logMessage) { logger.warn(logMessage); } + } + + private static string getMessage(Log logger, string format, params object[] arguments) { + string logMessage = null; + + if ( null != logger && null != format && 0 < format.Trim().Length) { + logMessage = string.Format(CultureInfo.InvariantCulture, format, arguments); + //do encoding etc here or output neutralization as necessary + } + return logMessage; + } + } + + public class Log + { +#if NET45 + private static TraceSource traceSource = new TraceSource("AnetDotNetSdkTrace"); + + public void error(string logMessage) { Trace(TraceEventType.Error, logMessage); } + public void info(string logMessage) { Trace(TraceEventType.Information, logMessage); } + public void debug(string logMessage) { Trace(TraceEventType.Verbose, logMessage); } + public void warn(string logMessage) { Trace(TraceEventType.Warning, logMessage); } + public void trace(string logMessage) + { + Trace(TraceEventType.Verbose, logMessage); + } + public static void Trace(TraceEventType eventType, string message) + { + try + { + if (traceSource.Switch.ShouldTrace(eventType)) + { + string tracemessage = string.Format("{0}\t[{1}]\t{2}", DateTime.Now.ToString("MM/dd/yy HH:mm:ss"), eventType, message); + foreach (TraceListener listener in traceSource.Listeners) + { + listener.WriteLine(tracemessage); + listener.Flush(); + } + } + } + catch (Exception) + { + + } + } +#endif +#if NETSTANDARD || NET6_0 + private readonly ILogger _logger; + public Log( ILogger logger ) + { + this._logger = logger; + } + public void error(string logMessage) + { + this._logger.LogError(logMessage); + } + public void info(string logMessage) + { + this._logger.LogInformation(logMessage); + } + public void debug(string logMessage) + { + this._logger.LogDebug(logMessage); + } + public void warn(string logMessage) + { + this._logger.LogWarning(logMessage); + } + public void trace(string logMessage) + { + this._logger.LogTrace(logMessage); + } +#endif + public void error(object logMessage) { error(logMessage.ToString()); } + public void info(object logMessage) { info(logMessage.ToString()); } + public void debug(object logMessage) { debug(logMessage.ToString()); } + public void warn(object logMessage) { warn(logMessage.ToString()); } + public void trace(object logMessage) { trace(logMessage.ToString()); } + } + + public class LogFactory + { +#if NET45 + private static readonly Log Logger = new Log(); + public static Log getLog(Type classType) + { + return Logger; + } +#endif +#if NETSTANDARD || NET6_0 + public static ILoggerFactory LoggerFactory { get; set; } + public static Log getLog(Type classType) + { + if (null == LoggerFactory) + throw new Exception($"The static property LogFactory.LoggerFactory is not set."); + + var logger=LoggerFactory.CreateLogger(classType); + + return new Log(logger); + + } +#endif + } + +} \ No newline at end of file diff --git a/Authorize.NET/Util/LogHelper.cs b/Authorize.NET/Util/LogHelper.cs index 1c9407d9..f16047ce 100644 --- a/Authorize.NET/Util/LogHelper.cs +++ b/Authorize.NET/Util/LogHelper.cs @@ -3,7 +3,13 @@ namespace AuthorizeNet.Util using System; using System.Diagnostics; using System.Globalization; - + using System.Text.RegularExpressions; +#if NET45 + using System.Diagnostics; +#endif +#if NETSTANDARD || NET6_0 + using Microsoft.Extensions.Logging; +#endif /// /// /// @@ -46,18 +52,17 @@ private static string getMessage(Log logger, string format, params object[] arg public class Log { +#if NET45 private static TraceSource traceSource = new TraceSource("AnetDotNetSdkTrace"); public void error(string logMessage) { Trace(TraceEventType.Error, logMessage); } public void info(string logMessage) { Trace(TraceEventType.Information, logMessage); } public void debug(string logMessage) { Trace(TraceEventType.Verbose, logMessage); } public void warn(string logMessage) { Trace(TraceEventType.Warning, logMessage); } - - public void error(object logMessage) { error(logMessage.ToString()); } - public void info(object logMessage) { info(logMessage.ToString()); } - public void debug(object logMessage) { debug(logMessage.ToString()); } - public void warn(object logMessage) { warn(logMessage.ToString()); } - + public void trace(string logMessage) + { + Trace(TraceEventType.Verbose, logMessage); + } public static void Trace(TraceEventType eventType, string message) { try @@ -77,15 +82,78 @@ public static void Trace(TraceEventType eventType, string message) } } +#endif +#if NETSTANDARD || NET6_0 + private readonly ILogger _logger; + private bool _loggingSensitiveData = false; + public Log(ILogger logger, bool loggingSensitiveData) + { + this._logger = logger; + this._loggingSensitiveData = loggingSensitiveData; + } + public void error(string logMessage) + { + this._logger.LogError(maskSensitiveMessage(logMessage)); + } + public void info(string logMessage) + { + this._logger.LogInformation(maskSensitiveMessage(logMessage)); + } + public void debug(string logMessage) + { + this._logger.LogDebug(maskSensitiveMessage(logMessage)); + } + public void warn(string logMessage) + { + this._logger.LogWarning(maskSensitiveMessage(logMessage)); + } + public void trace(string logMessage) + { + this._logger.LogTrace(maskSensitiveMessage(logMessage)); + } + private string maskSensitiveMessage(string message) + { + if (string.IsNullOrWhiteSpace(message)) + return message; + + if (this._loggingSensitiveData) + return message; + + string maskedXmlMessage = SensitiveDataTextLogger.maskSensitiveXmlString(message); + string maskedMessage = SensitiveDataTextLogger.maskCreditCards(maskedXmlMessage); + return maskedMessage; + } +#endif + public void error(object logMessage) { error(logMessage.ToString()); } + public void info(object logMessage) { info(logMessage.ToString()); } + public void debug(object logMessage) { debug(logMessage.ToString()); } + public void warn(object logMessage) { warn(logMessage.ToString()); } + public void trace(object logMessage) { trace(logMessage.ToString()); } } public class LogFactory { +#if NET45 private static readonly Log Logger = new Log(); public static Log getLog(Type classType) { return Logger; } +#endif +#if NETSTANDARD || NET6_0 + public static ILoggerFactory LoggerFactory { get; set; } + public static bool LoggingSensitiveData { get; set; } + public static Log getLog(Type classType) + { + if (null == LoggerFactory) + throw new Exception($"The static property LogFactory.LoggerFactory is not set."); + + var logger = LoggerFactory.CreateLogger(classType); + + return new Log(logger, LogFactory.LoggingSensitiveData); + + } +#endif } } \ No newline at end of file diff --git a/AuthorizeNET.sln b/AuthorizeNET.sln index f2173b30..878f32b7 100644 --- a/AuthorizeNET.sln +++ b/AuthorizeNET.sln @@ -1,15 +1,20 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33103.184 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuthorizeNET", "Authorize.NET\AuthorizeNET.csproj", "{5D52EAEC-42FB-4313-83B8-69E2F55EBF14}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AuthorizeNET", "Authorize.NET\AuthorizeNET.csproj", "{5D52EAEC-42FB-4313-83B8-69E2F55EBF14}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AuthorizeNETtest", "AuthorizeNETtest\AuthorizeNETtest.csproj", "{CDA0D4D8-E4AA-4BEA-8839-04D69607D914}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7EBF48A1-8AC1-4E84-BDCC-E0984183D098}" ProjectSection(SolutionItems) = preProject + .travis.yml = .travis.yml AuthorizeNET.vsmdi = AuthorizeNET.vsmdi + CONTRIBUTING.md = CONTRIBUTING.md + LICENSE.txt = LICENSE.txt + MIGRATING.md = MIGRATING.md + README.md = README.md EndProjectSection EndProject Global @@ -35,6 +40,9 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {3A695E68-E010-4370-BA32-C6CCB737541D} + EndGlobalSection GlobalSection(TestCaseManagementSettings) = postSolution CategoryFile = AuthorizeNET.vsmdi EndGlobalSection diff --git a/MIGRATING.md b/MIGRATING.md index b5a1c7d5..fac1c6c8 100644 --- a/MIGRATING.md +++ b/MIGRATING.md @@ -17,7 +17,7 @@ Authorize.Net no longer supports several legacy classes, including AIM, ARB and ## Example #### Sample new model code for (charge-credit-card) - ```Dotnet + ```csharp using System; using AuthorizeNet.Api.Controllers; using AuthorizeNet.Api.Contracts.V1; diff --git a/README.md b/README.md index 157f28e1..021857ff 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,8 @@ ## Requirements -* .NET 3.5 or later -* Microsoft® Visual Studio 2008 or later +* .NET 4.5 or later, .Net Standard 2.0 and .Net 6.0 +* Microsoft® Visual Studio 2022 or later * Nunit 2.6.3; * An Authorize.Net account (see _Registration & Configuration_ section below) @@ -25,7 +25,7 @@ The Authorize.Net APIs only support connections using the TLS 1.2 security proto ## Installation To install the AuthorizeNet .NET SDK, run the following command in the Package Manager Console: -`PM> Install-Package AuthorizeNet` +`PM> Install-Package AuthorizeNet.MultiFrameworks` ## Registration & Configuration Use of this SDK and the Authorize.Net APIs requires having an account on the Authorize.Net system. You can find these details in the Settings section. @@ -37,6 +37,7 @@ To authenticate with the Authorize.Net API, use your account's API Login ID and After you have obtained your credentials, load them into the appropriate variables in your code. The below sample code shows how to set the credentials as part of the API request. #### To set your API credentials for an API request: +* .Net Framework 4.5 and above ```csharp ApiOperationBase.MerchantAuthentication = new merchantAuthenticationType() { @@ -45,16 +46,52 @@ ApiOperationBase.MerchantAuthentication = new m Item = "YOUR_TRANSACTION_KEY", }; ``` +* .Net Core 3.1, .Net 6.0 and above +1. Configure AuthorizeNetOptions appsettings.json +```json +{ + "AuthorizeNetOptions": { + "Environment": "SANDBOX", + "ApiLoginId": "YOUR_API_LOGIN_ID", + "TransactionKey": "YOUR_TRANSACTION_KEY" + } +} +``` + +2. Configure AuthorizeNetOptions in ConfigureServices, and setup AuthorizeNet with IServiceProvider extension function SetupAuthorizeNet. +```csharp +public void ConfigureServices(IServiceCollection services) +{ + services.AddOptions(); + services.Configure(options => Configuration.GetSection(nameof(AuthorizeNetOptions)).Bind(options)); +} +public void Configure(IApplicationBuilder app) +{ + app.ApplicationServices.SetupAuthorizeNet(); +} +``` + Never include your API Login ID and Transaction Key directly in a file in a publically accessible portion of your website. As a best practice, define the API Login ID and Transaction Key in a constants file, and reference those constants in your code. ### Switching between the sandbox environment and the production environment Authorize.Net maintains a complete sandbox environment for testing and development purposes. The sandbox environment is an exact replica of our production environment, with simulated transaction authorization and settlement. By default, this SDK is configured to use the sandbox environment. To switch to the production environment, set the appropriate environment constant using ApiOperationBase `RunEnvironment` method. For example: +* .Net Framework 4.5 and above ```csharp // For PRODUCTION use ApiOperationBase.RunEnvironment = AuthorizeNet.Environment.PRODUCTION; ``` - +* .Net Core 3.1, .Net 6.0 and above + Change appsettings.json +```json +{ + "AuthorizeNetOptions": { + "Environment": "PRODUCTION", + "ApiLoginId": "YOUR_API_LOGIN_ID", + "TransactionKey": "YOUR_TRANSACTION_KEY" + } +} +``` API credentials are different for each environment, so be sure to switch to the appropriate credentials when switching environments. @@ -100,6 +137,7 @@ For additional help in testing your code, Authorize.Net maintains a [comprehensi ## Logging Sensitive Data A new sensitive data logger has been introduced with the Authorize.Net .NET SDK, which is an enhancement on the existing logging framework. +### .Net Framework 4.5 and above The logger uses `System.Diagnostics` namespace in .NET Framework. No external libraries need to be installed along with the application to use the logger. Enable the logger by providing the following configuration in the `app.config/web.config` files of your application. The log levels supported are `'Verbose','Information','Warning'` and `'Error'`. @@ -172,6 +210,19 @@ To unmask sensitive data, use the default `TextWriterTraceListener` and `Console ``` `AnetDotNetSdkTrace` should be used as the source name, as it is being used by the TraceSource inside logger framework code. +### .Net Core 3.1 , .Net 6.0 and above +As Defaut, the sensitive data is marked, change the appsettings.json to enable the sensitive data logging. +```json +{ + "AuthorizeNetOptions": { + "Environment": "PRODUCTION", + "ApiLoginId": "YOUR_API_LOGIN_ID", + "TransactionKey": "YOUR_TRANSACTION_KEY", + "LoggingSensitiveData": true + } +} +``` + ### Transaction Hash Upgrade Authorize.Net is phasing out the MD5 based `transHash` element in favor of the SHA-512 based `transHashSHA2`. The setting in the Merchant Interface which controlled the MD5 Hash option is no longer available, and the `transHash` element will stop returning values at a later date to be determined. For information on how to use `transHashSHA2`, see the [Transaction Hash Upgrade Guide](https://developer.authorize.net/support/hash_upgrade/). From 6cd6d64a555a96ee85a43a4d29844e5c13409906 Mon Sep 17 00:00:00 2001 From: Jim Wang Date: Tue, 15 Nov 2022 23:54:22 -0600 Subject: [PATCH 2/4] clean up --- Authorize.NET/LogHelper.cs | 143 ------------------------------------- 1 file changed, 143 deletions(-) delete mode 100644 Authorize.NET/LogHelper.cs diff --git a/Authorize.NET/LogHelper.cs b/Authorize.NET/LogHelper.cs deleted file mode 100644 index f6dc9d3d..00000000 --- a/Authorize.NET/LogHelper.cs +++ /dev/null @@ -1,143 +0,0 @@ -namespace AuthorizeNet.Util -{ - using System; - using System.Diagnostics; - using System.Globalization; -#if NET45 - using System.Diagnostics; -#endif -#if NETSTANDARD || NET6_0 - using Microsoft.Extensions.Logging; -#endif - /// - /// - /// - /// - public static class LogHelper { - - static LogHelper() { - } - - public static void debug(Log logger, string format, params object[] arguments) { - string logMessage = getMessage(logger, format, arguments); - if ( null != logMessage) { logger.debug(logMessage); } - } - - public static void error(Log logger, string format, params object[] arguments) { - string logMessage = getMessage(logger, format, arguments); - if ( null != logMessage) { logger.error(logMessage); } - } - - public static void info(Log logger, string format, params object[] arguments) { - string logMessage = getMessage(logger, format, arguments); - if ( null != logMessage) { logger.info(logMessage); } - } - - public static void warn(Log logger, string format, params object[] arguments) { - string logMessage = getMessage(logger, format, arguments); - if ( null != logMessage) { logger.warn(logMessage); } - } - - private static string getMessage(Log logger, string format, params object[] arguments) { - string logMessage = null; - - if ( null != logger && null != format && 0 < format.Trim().Length) { - logMessage = string.Format(CultureInfo.InvariantCulture, format, arguments); - //do encoding etc here or output neutralization as necessary - } - return logMessage; - } - } - - public class Log - { -#if NET45 - private static TraceSource traceSource = new TraceSource("AnetDotNetSdkTrace"); - - public void error(string logMessage) { Trace(TraceEventType.Error, logMessage); } - public void info(string logMessage) { Trace(TraceEventType.Information, logMessage); } - public void debug(string logMessage) { Trace(TraceEventType.Verbose, logMessage); } - public void warn(string logMessage) { Trace(TraceEventType.Warning, logMessage); } - public void trace(string logMessage) - { - Trace(TraceEventType.Verbose, logMessage); - } - public static void Trace(TraceEventType eventType, string message) - { - try - { - if (traceSource.Switch.ShouldTrace(eventType)) - { - string tracemessage = string.Format("{0}\t[{1}]\t{2}", DateTime.Now.ToString("MM/dd/yy HH:mm:ss"), eventType, message); - foreach (TraceListener listener in traceSource.Listeners) - { - listener.WriteLine(tracemessage); - listener.Flush(); - } - } - } - catch (Exception) - { - - } - } -#endif -#if NETSTANDARD || NET6_0 - private readonly ILogger _logger; - public Log( ILogger logger ) - { - this._logger = logger; - } - public void error(string logMessage) - { - this._logger.LogError(logMessage); - } - public void info(string logMessage) - { - this._logger.LogInformation(logMessage); - } - public void debug(string logMessage) - { - this._logger.LogDebug(logMessage); - } - public void warn(string logMessage) - { - this._logger.LogWarning(logMessage); - } - public void trace(string logMessage) - { - this._logger.LogTrace(logMessage); - } -#endif - public void error(object logMessage) { error(logMessage.ToString()); } - public void info(object logMessage) { info(logMessage.ToString()); } - public void debug(object logMessage) { debug(logMessage.ToString()); } - public void warn(object logMessage) { warn(logMessage.ToString()); } - public void trace(object logMessage) { trace(logMessage.ToString()); } - } - - public class LogFactory - { -#if NET45 - private static readonly Log Logger = new Log(); - public static Log getLog(Type classType) - { - return Logger; - } -#endif -#if NETSTANDARD || NET6_0 - public static ILoggerFactory LoggerFactory { get; set; } - public static Log getLog(Type classType) - { - if (null == LoggerFactory) - throw new Exception($"The static property LogFactory.LoggerFactory is not set."); - - var logger=LoggerFactory.CreateLogger(classType); - - return new Log(logger); - - } -#endif - } - -} \ No newline at end of file From 0041fc807bdf3a1ddb9e5d483f8c05ff1b1d719d Mon Sep 17 00:00:00 2001 From: Jim Wang Date: Wed, 16 Nov 2022 00:15:26 -0600 Subject: [PATCH 3/4] Update nuget package metadata --- Authorize.NET/AuthorizeNET.csproj | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Authorize.NET/AuthorizeNET.csproj b/Authorize.NET/AuthorizeNET.csproj index 8c8cff99..65e87270 100644 --- a/Authorize.NET/AuthorizeNET.csproj +++ b/Authorize.NET/AuthorizeNET.csproj @@ -2,23 +2,24 @@ net45;netstandard2.0;net6.0 - 2.0.3 + 2.0.3.1 AuthorizeNet AuthorizeNet false AuthorizeNet Use this SDK to integrate with the Authorize.Net APIs for Payment Transactions, Recurring Billing, Customer Payment Profiles and Reporting. https://github.com/AuthorizeNet/sdk-dotnet/blob/master/LICENSE.txt - https://github.com/wjmirror/AuthorizeNet-sdk-dotnet + https://github.com/wjmirror/AuthorizeNet-sdk-dotnet/tree/feature/multi-frameworks git - https://github.com/wjmirror/AuthorizeNet-sdk-dotnet - Payments API Authorize.Net + https://github.com/wjmirror/AuthorizeNet-sdk-dotnet/tree/feature/multi-frameworks + Payments API; Authorize.Net True True AuthorizeNet.MultiFrameworks http://developer.authorize.net/resources/images/favicon.ico https://github.com/AuthorizeNet/sdk-dotnet/blob/master/LICENSE.txt Build with multiple frameworks, .Net framework 4.5, .Net Standard 2.0 and .Net 6.0 + AuthorizeNet, jimwang1014 From c58fd17815ad5624035d82b51a7756817cf379be Mon Sep 17 00:00:00 2001 From: Jim Wang Date: Wed, 16 Nov 2022 00:19:48 -0600 Subject: [PATCH 4/4] add license info in package. --- Authorize.NET/AuthorizeNET.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Authorize.NET/AuthorizeNET.csproj b/Authorize.NET/AuthorizeNET.csproj index 65e87270..1a9ec3cd 100644 --- a/Authorize.NET/AuthorizeNET.csproj +++ b/Authorize.NET/AuthorizeNET.csproj @@ -20,6 +20,7 @@ https://github.com/AuthorizeNet/sdk-dotnet/blob/master/LICENSE.txt Build with multiple frameworks, .Net framework 4.5, .Net Standard 2.0 and .Net 6.0 AuthorizeNet, jimwang1014 + LICENSE.txt @@ -101,6 +102,10 @@ + + True + \ +