authorizenet / sdk-dotnet Goto Github PK
View Code? Open in Web Editor NEW.Net SDK for Authorize.Net API
License: Other
.Net SDK for Authorize.Net API
License: Other
Allow passing of merchantCustomerId. This works and I have implemented it in one of my projects.
public Customer CreateCustomer(string email, string description, string merchantCustomerId)
{
//use the XSD class to create the profile
var newCustomer = new customerProfileType();
newCustomer.description = description;
newCustomer.email = email;
newCustomer.merchantCustomerId = merchantCustomerId;
var req = new createCustomerProfileRequest();
req.profile = newCustomer;
//serialize and send
var response = (createCustomerProfileResponse)_gateway.Send(req);
//set the profile ID
return new Customer {
Email = email,
Description = description,
ProfileID = response.customerProfileId,
ID = merchantCustomerId
};
}
Get list of subscription info with similar info to web interface.
The updateSubscription Request makes use of a function called "ToUpdateableAPI" to apparently remove elements that would conflict with the update request. This function procludes some updatedable fields such as description and invoice. It also includes some elements that can't be changed such as schedule, occurences, and amount.
The date function for CIM (reportedly) uses a parse function that will only work on computers localized to EN-US.
for example in CardPresentPriorAuthCapture.cs file (and in many other places) there is a code line:
this.Queue(ApiFields.Amount, amount.ToString());
So, if in your environment decimal separator is ",", then decimal 5.5M is converted to string "5,5".
it should be:
this.Queue(ApiFields.Amount, amount.ToString(CultureInfo.InvariantCulture));
Because in AIM_guide.pdf documentation field x_amount description says:
Value: Amount of the transaction.
Format: 15 digit-maximum, with a decimal point (no dollar symbol). For
example, 8.95.
Notes: This is the total amount and must include tax, shipping, and any
other charges.
In test mode (and could be production), the AuthorizeAndCapture method of CIM returns null/0 for all properties. I would assume that it isn't parsing the returned data correctly. A valid transaction returns Approved = false and AuthorizationCode/Amount to null.
var response = gateway.AuthorizeAndCapture(order);
if (!response.Approved){
throw new AuthorizeNetException("The transaction was not approved.");
}
var payment = new Payment{
DateTime = DateTime.Now,
Type = PaymentType.CreditCard,
AuthorizationCode = response.AuthorizationCode,
Amount = response.Amount
};
response.ResponseCode = "OkI00001Successful."
response.Approved = false
response.CAVResponse = "Blank or not present = CAVV not validated"
The "creditRequest" is specific to Credit Cards and there is no equivalent method for eCheck transactions.
The new Environment (Environment.cs) class causes collisions with the System.Environment class, with the result that references to either class must be fully defined.
Change class name to something that does not cause collisions.
Using ARB there is no way to get the response codes when using CreateSubscription() method. In other areas of the SDK this functionality is built in.
Am I missing a method?
This works well, except that when the profile is created the original transaction is not associated to the new profile. Also the system creates the billing address as a new shipto address which is not something I would personally desire as it may be a billing address only.
There are quite a few class definitions in this SDK that do not use proper Pascal casing.
Examples:
These definitions violate the standard C# conventions defined by Microsoft:
https://msdn.microsoft.com/en-us/library/vstudio/ms229040(v=vs.100).aspx
The closing slash is pointing the wrong direction.
Also be nice if the x_customer_ip field was included by default.
Because we do not want to validate by charging the customer to create a payment profile, it would be beneficial to be able to set this.
I changed it on my local as below:
public string AddCreditCard(string profileID, string cardNumber, int expirationMonth, int expirationYear, string cardCode, Address billToAddress,validationModeEnum validationMode) {
// Get the expiration date.
DateTime dt; // = DateTime.Parse(expirationMonth.ToString() + "-1-" + expirationYear.ToString());
if (!CommonFunctions.ParseDateTime(expirationYear, expirationMonth, 1, out dt))
{ throw new Exception("Invalid credit card expiration date"); }
DateTime expDate = new DateTime(dt.Year, dt.Month, 1).AddMonths(1).AddDays(-1);
string sExpDate = expDate.ToString("yyyy-MM");
// Make sure the card has not expired.
if (expDate <= DateTime.Now)
throw new Exception("The credit card expiration date \"" + sExpDate + "\" is expired.");
var req = new createCustomerPaymentProfileRequest();
req.customerProfileId = profileID;
req.paymentProfile = new customerPaymentProfileType();
req.paymentProfile.payment = new paymentType();
req.validationMode=validationMode;
req.validationModeSpecified=true;
var card = new creditCardType();
if (!String.IsNullOrEmpty(cardCode)) card.cardCode = cardCode;
card.cardNumber = cardNumber;
card.expirationDate = sExpDate;
req.paymentProfile.payment.Item = card;
if (billToAddress != null)
req.paymentProfile.billTo = billToAddress.ToAPIType();
req.validationModeSpecified = true;
req.validationMode = this._mode;
var response = (createCustomerPaymentProfileResponse)_gateway.Send(req);
return response.customerPaymentProfileId;
}
We have been relying on the silent-postback process data to check our ARB transactions for quite a while as that was the only place we could get the subscription information, but once in a while we have come up with some missing record from the postback process.
To handle this we started looking for the missing transaction with the reporting API (now that you have the subscriptionid in there its MUCH easier, THANK YOU).
One piece that is still missing is the x_response_reason_code, and we use that to detect if the card expired or its just a failed transaction, so we can send a appropriate response to the card holder.
We have tried using the x_response_reason_text, but the postback version and the reporting version don't seem to be coming from the same place. See example below:
REPORTING: "Approval"
POSTBACK: "This transaction has been approved."
Is there any chance you could add x_response_reason_code to the API and in the mean time post a list of the response_reason_text returned returned form the reporting API so we can make a look up on that for now? I looked through the API SDK and could only find table for:
CAVVResponse, CardResponse, AVSResponse, TransactionStatus
Just as an FYI while your in there, these fields are also missing ;)
x_subscription_paynum
x_cvv2_resp_code
x_md5_hash
x_freight
Thanks again for your help!
GBY.
-R
Anytime we have an AVS mismatch (where zip/street is a no match) the system simply returns an e0027 and nothing else. There are no errors in the transactions nor anywhere else.
E0027 is not very specific and does not help.
This is specific to CIM.
Hi
When I try to use ARB payment and when I call PopulateSubscription, its throwing a error as first value i am set in that function.
Method not found: 'Void AuthorizeNet.APICore.ARBSubscriptionType.set_name(System.String)'.
Method not found: 'Void AuthorizeNet.APICore.creditCardSimpleType.set_cardNumber(System.String)'.
Please help.
Thanks,
Jaffer
see docs here
http://developer.authorize.net/api/reference/index.html#recurring-billing-get-a-list-of-subscriptions
Have some code that implements the functionality, let me know if you want it. Dont seem to have the permissions to update a branch here
Because _xmlDoc is a class-level variable, HttpXmlUtility.Send() is not thread-safe. As an example, if I attempt to call ReportingGateway.GetTransactionDetails in parallel for multiple transaction Ids, I get strange behavior like null reference exceptions because multiple threads are using the same XmlDocument instance. Would suggest moving _xmlDoc inside the 'Send' method.
GatewayResponse.cs
public string ResponseCode {
get {
return ParseResponse(0);
}
}
Should be
public string ResponseCode {
get {
return ParseResponse(2); // <-- Bug Fix
}
}
Yesterday received the announcement from Authorize.NET that they are changing the Url to use Akamai based urls as mentioned below.
Can you update the Environment file to point to new url or create a switch so that we can use the new url?
STR:
var gateway = new CustomerGateway(_apiLogin, _transactionKey, _serviceMode);
var order = new Order(_customerProfileId, _paymentProfileId, null)
{
Amount = amount,
Description = placeholder
};
IGatewayResponse response = null;
switch (_authType)
{
case "AUTH_CAPTURE":
response = gateway.AuthorizeAndCapture(order);
break;
default:
throw new NotImplementedException("derp.");
}
Result:
"exceptionMessage": "Error processing request: E00003 - The element 'profileTransAuthCapture' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd' has invalid child element 'customerPaymentProfileId' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'. List of possible elements expected: 'tax, shipping, duty, lineItems, customerProfileId' in namespace 'AnetApi/xml/v1/schema/AnetApiSchema.xsd'.",
I am testing code to perform a refund transaction, and it is failing with this same E0027 error as described here: #73.
I am using a sandbox account and the "Controller" method for accessing the API. I am able to submit test AuthorizeAndCapture charges and Void them, getting correct responses. However, when I go to a refundTransaction against an existing unsettled charge, I am getting this E0027 error with absolutely no additional detail: all fields of transactionResponse are null, and there is no text description on the message.
In the issue I linked to, the suspected cause of the problem is an AVS validation error. However, for testing purposes I tried disabling both AVS and CCV filtering entirely on my sandbox account, and the error persists.
Here is a version of the code I am using, edited for clarity:
var request = new createTransactionRequest {
transactionRequest = new transactionRequestType {
transactionType = transactionTypeEnum.refundTransaction.ToString(),
refTransId = transaction.TransactionID,
amount = amount.Value,
profile = new customerProfilePaymentType {
customerProfileId = transaction.CreditCardProfile.Profile.AuthNetCustomerID,
paymentProfile = new paymentProfile {
paymentProfileId = transaction.CreditCardProfile.AuthNetPaymentID,
cardCode = transaction.CreditCardProfile.CCV,
}
},
}
};
var response = MakeRequest( request );
The MakeRequest() method shown ultimately does something like this:
var controller = new transactionRequestController( request );
var response = controller.ExecuteWithApiResponse( Environment );
Then the following statements hold true for the returned response:
response.transactionResponse.* == null
response.messages.resultCode == messageTypeEnum.Error
response.messages.message[0].code == "E0027"
response.messages.message[0].text == null
GatewayRequest.cs maps capture to prior_auth_Capture. There are multiple places in the SDK where Capture_Only is confused with Prior_Auth_Capture, so these should probably all be reviewed.
I've been working with the .Net SDK for Authorize.Net API from GitHub (version 1.8.3) and it seems that the CheckForErrors method in HttpXMLUtility is returning the incorrect response. It seemed as if the response was being altered and the response parameters like AuthCode and ResponseCode are missing.
This is being called from HttpXMLUtility.Send whether I do an Auth or a Capture. Both cases don't return an AuthCode.
In debugging it looks like the XML Response has 2 Child.Child level nodes. One is "messages" and the other is "directReponse". The way it is coded messages is the first Child.Child node, so it sets thingy.directReponse to the message and it never grabs the directReponse. (See current code below)
void CheckForErrors(ANetApiResponse response) {
if (response.GetType() == typeof(createCustomerProfileTransactionResponse)) {
//there's a directResponse we need to find...
var thingy = (createCustomerProfileTransactionResponse)response;
thingy.directResponse = null;
for (var i = 0; i <= 1; i++)
{
if (null != _xmlDoc && null != _xmlDoc.ChildNodes[i])
{
for (var j = 0; j <= 1; j++)
{
if (null != _xmlDoc.ChildNodes[i].ChildNodes[j])
{
thingy.directResponse = _xmlDoc.ChildNodes[i].ChildNodes[j].InnerText;
}
if (null != thingy.directResponse) { break; }
}
}
if (null != thingy.directResponse) { break; }
}
response = thingy;
} else {
if (response.messages.message.Length > 0) {
if (response.messages.resultCode == messageTypeEnum.Error) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < response.messages.message.Length; i++) {
sb.AppendFormat("Error processing request: {0} - {1}", response.messages.message[i].code, response.messages.message[i].text);
}
throw new InvalidOperationException(sb.ToString());
}
}
}
}
Should this inner look not be checking specifically for the directReponse node if there are more than one Child.Child node?
Perhaps it should be modified as so:
void CheckForErrors(ANetApiResponse response) {
if (response.GetType() == typeof(createCustomerProfileTransactionResponse)) {
//there's a directResponse we need to find...
var thingy = (createCustomerProfileTransactionResponse)response;
thingy.directResponse = null;
for (var i = 0; i <= 1; i++)
{
if (null != _xmlDoc && null != _xmlDoc.ChildNodes[i])
{
for (var j = 0; j <= 1; j++)
{
if (null != _xmlDoc.ChildNodes[i].ChildNodes[j])
{
if (_xmlDoc.ChildNodes[i].ChildNodes[j].Name == "directResponse")
{
thingy.directResponse = _xmlDoc.ChildNodes[i].ChildNodes[j].InnerText;
}
}
if (null != thingy.directResponse) { break; }
}
}
if (null != thingy.directResponse) { break; }
}
response = thingy;
} else {
if (response.messages.message.Length > 0) {
if (response.messages.resultCode == messageTypeEnum.Error) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < response.messages.message.Length; i++) {
sb.AppendFormat("Error processing request: {0} - {1}", response.messages.message[i].code, response.messages.message[i].text);
}
throw new InvalidOperationException(sb.ToString());
}
}
}
}
Looking to get some feedback in case I'm not on the right track.
Is there anyway that you can give a strong name to the AuthorizeNet.dll assembly that is officially released? I pull it down from NuGet as new versions are released and I cannot give any assemblies that use it a strong name.
AuthorizeNet.HttpXmlUtility.CheckForErrors has a serious issue. It's looking for a directResponse in _xmlDoc.ChildNodes[1].ChildNodes[1].InnerText, but that node does not exist when there is an error in the response.
In the method signature for CustomerGateway.Void() & CustomerGateway.Refund(), transactionId comes before approvalCode. However, in the interface ICustomerGateway, these two parameters are flipped. Anyone writing code against the interface, instead of the concrete implementation, is in for a surprise. Also, approvalCode is never used in the implementation. Can/Should it be removed?
Using the Authorize.net SDK C# System.xml 4.5 on VS 2012 from nuget, attempts at sending a request to add a credit card to an existing customer profile fails with following error:
The assembly with display name 'AuthorizeNet.XmlSerializers' failed to load in the 'LoadFrom' binding context of the AppDomain with ID 17. The cause of the failure was: System.IO.FileNotFoundException: Could not load file or assembly 'AuthorizeNet.XmlSerializers, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
After adding the HttpXMLUtility.cs to my project, I was able to determine it was failing at line 65 "var serializer = new XmlSerializer(type);" in ANetApiResponse.Send. I figured that I was missing the AuthorizeNet.XmlSerializer, but after searching no such library exists.
This library is exactly what I need to add a paymentprofile to an existing customerprofile. To no avail, I have been unable to find a substitute.
All the transactions performed using Gateway and AuthorizationRequest are performing authorization and capture and my assumption is based on two reasons.
I was looking for Auth_Only request and AuthorizationRequest is not doing it. Please assist me.
Thanks,
Kashyap
In the AIM IGatewayRequest AddCustomer method, there is not way to enter the customers city. This is also the case for the AddShipping method.
Here's my specific use case:
decimal amount = 159m;
orderDesc = "Some text, with a comma";
AuthorizeNet.Order order = new AuthorizeNet.Order(profileId, paymentProfileId, shippingAddress)
{
Amount = amount,
Description = orderDesc
};
IGatewayResponse authorizeNetResp = customerGateway.AuthorizeAndCapture(order);
// authorizeNetResp.Amount is 0 but should be 159
This is probably happening in a lot of scenarios (if address or shipping fields contain commas) because the response contains those fields, and just does a .Split(",")
to parse out all the values. If the request has a description (or address or shipping field) that contains a comma, all the values after that in the response are messed up.
As a workaround for now, I am just removing commas from the description.
Modern ASP.NET applications should use Async programming for better scalability. So I think it would be very useful if you add an async version of the methods making network calls.
What happened to this assembly? I was using it from version 1.7.1 of the nuget package and after upgrading to 1.8.2 it is no longer part of the nuget package. I need it to construct the response in my Payment Relay Endpoint in a Direct Post configuration. Please advise.
When trying to AuthorizeAndCapture using CIM, I am receiving a successful ResponseCode, but Approved is false. I tried the Unit Test from github and received the same message.
Someone else is also experiencing this posted on the forums: https://community.developer.authorize.net/t5/Integration-and-Testing/CIM-AuthorizeAndCapture-Approved-flag-set-to-false/m-p/49633#M25180
There are no error messages and am at a loss right now as to solve the problem.
This was probably mistakenly entered due to confusion between x_cust_id and x_customer_ip. But the IP address is not being sent correctly because of it.
The error is in ApiFields.cs
Every call into this using an existing customer profile returns an e0027 error in production. Using older SDK, things are fine and in sandbox everything is fine. The message says test transaction failed. I am setting the environment to product and all other calls work fine. The customer is created, the payment profile is created as well. It seems to be only when I try to charge a profile using the API as documented.
IT seems that in most of this SDK that charging a CIM customer is failing at some point. The old methods do not work an longer and new methods fail in production. I would greatly appreciate some feed back as this will cause us business loss.
This method is available in the CIM ASMX endpoint:
https://apitest.authorize.net/soap/v1/service.asmx?op=CreateCustomerProfileFromTransaction
But so far as I can tell - let me know if I'm wrong - it doesn't seem to be exposed anywhere in the .NET SDK. It would be handy to have that added.
Hello,
trying to create a free trial using ISubscriptionRequest.SetTrialPeriod method
subscription.SetTrialPeriod(1, 0); // the trial amount is zero dollars
but I am getting this error
Error processing request: E00026 - Both Trial Amount and Trial Occurrences are required.
The code checks if the TrialAmount is greater than Zero and only then sets ".hasTrialAmount". To workaround this I am doing something like this:
subscription.SetTrialPeriod(1, new Decimal(0.0001))
and I am not sure if that is a "Free Trial" anyway.
So, my current plan is to set StartDate to the date after the trial period ends and not use TrialAmount and TrialOccurencies properties at all.
Please advise.
Hey guys! Thanks for the great work.
I am a high volume authorize.net customer and do not want to validate a customer payment profile each time a new one is added. It basically doubles my costs if the system automatically submits two transactions per order. Having the ability to set the parameter to validationMode.none, would save me a ton of money.
I appreciate your consideration.
Reported in detail in the developer community here: https://community.developer.authorize.net/t5/Integration-and-Testing/CIM-AuthorizeAndCapture-Invalid-Response-on-Sandbox/td-p/49201/highlight/false
I have been using AuthorizeNet.dll for last 6 months, it is working great! Recently I am getting following error for few transactions :
"A duplicate transaction has been submitted"
I do research online and found the following link that explain nicely
https://support.authorize.net/authkb/index?page=content&id=A425&actp=LIST
My question is: How can I pass value for the parameter 'x_duplicate_window' once I call the following method, CustomerGateway.cs -> public IGatewayResponse AuthorizeAndCapture(Order order)?
Or do I need to modify something inside the AuthorizeAndCapture method?
Or do I need to modify something inside the HttpXmlUtility.cs->ANetApiResponse Send(ANetApiRequest apiRequest)
I appreciate any help. Thanks
Currently, if there is an error, an Invalid Operation Exception is being thrown, with message like: Error processing request: E00013 - Credit Card Number is invalid.
The error codes are not available in a strongly typed manner. The above message is not really user friendly and I would have to parse it to get the error code, which is error prone.
Can you add a strongly typed response for Subscription request instead of throwing an Exception? Our web site is multilanguage, so we need to translate the error codes.
Thanks!
This issue occurs completely random. I pass a valid transaction id string to GetTransactionDetails and CheckForErrors throws a NullReferenceException.
Stack Trace:
at AuthorizeNet.HttpXmlUtility.CheckForErrors(ANetApiResponse response) in c:\Users\dwoodfor\Downloads\sdk-dotnet-master\sdk-dotnet-master\Authorize.NET\Utility\HttpXmlUtility.cs:line 99
at AuthorizeNet.HttpXmlUtility.Send(ANetApiRequest apiRequest) in c:\Users\dwoodfor\Downloads\sdk-dotnet-master\sdk-dotnet-master\Authorize.NET\Utility\HttpXmlUtility.cs:line 80
at AuthorizeNet.ReportingGateway.GetTransactionDetails(String transactionID) in c:\Users\dwoodfor\Downloads\sdk-dotnet-master\sdk-dotnet-master\Authorize.NET\Reporting\ReportingGateway.cs:line 121
at NutraCardWeb.Controllers.TransactionController.Get(String id) in c:\Users\dwoodfor\Documents\Visual Studio 2012\Projects\NutraCardWeb\NutraCardWeb\Controllers\TransactionController.cs:line 30
at lambda_method(Closure , Object , Object[] )
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.b__9(Object instance, Object[] methodParameters)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
I have tried multiple times and each time I do an authorize/Capture using a customer profile and Authorize.order object, the response comes back as approved=false although in the sandbox I show a transaction approval. When I charge the card through AIM, it works fine.
This seems specific to CIM
The authorizeAndCapture method of the CIM customerGateway copies only specific data from the order. It ignores invoice, description, and probably other fields as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.