Straight Capture (Do we need doauthorize?)
Straight Capture (Do we need doauthorize?)
Hello,
I'm trying to implement a gateway for Braintree Payment Solutions. There API is very simple in that it has you simply pass a direct post the server that includes your username and pass as the parameters. In a test transaction I would simply pass this to the gateway
username=demoapi&password=password1&ccnumber=4111111111111111&ccexp=1010&type=sale&amount=10.00&customer_vault=add_customer
and it would return a query string with the response items. I have the source code for the authorize.net implementation and it seems like it is way more than I need. I have been using this link
http://wiki.ablecommerce.com/index.php/ ... nt_Gateway
As a guide but it doesn't really explain the order in which ablecommerce executes these items. I'm probably overlooking something, but if someone can possibly break the process down for me perhaps I can understand what's going on in the code sample a bit better.
Another question I have is, if my gateway supports recurring billing and someone buys a subscription item does abelcommerce automatically fire the DoAuthorizeRecurring method?
Thanks,
I'm trying to implement a gateway for Braintree Payment Solutions. There API is very simple in that it has you simply pass a direct post the server that includes your username and pass as the parameters. In a test transaction I would simply pass this to the gateway
username=demoapi&password=password1&ccnumber=4111111111111111&ccexp=1010&type=sale&amount=10.00&customer_vault=add_customer
and it would return a query string with the response items. I have the source code for the authorize.net implementation and it seems like it is way more than I need. I have been using this link
http://wiki.ablecommerce.com/index.php/ ... nt_Gateway
As a guide but it doesn't really explain the order in which ablecommerce executes these items. I'm probably overlooking something, but if someone can possibly break the process down for me perhaps I can understand what's going on in the code sample a bit better.
Another question I have is, if my gateway supports recurring billing and someone buys a subscription item does abelcommerce automatically fire the DoAuthorizeRecurring method?
Thanks,
Re: Straight Capture (Do we need doauthorize?)
In sample gateway code you will see three major function types. 1)- Required for gateway interaction with application via UI for example configuration 2)- Method that are required to work against different commands to perform payment actions.
So UI methods will be called by application when some one try to configure it via merchant where it prompts merchant to add/edit required data about gateway for example gateway request URL etc.
When someone places order and try to process the payment AbleCommerce looks for associated payment gateway for customer picked payment method. Then ablecommerce creates an instance of correct gateway and determine what transaction it supports. Then if merchant is set the gateway to Authorize and Capture mode it will first call DoAuthorize method and then DoCapture.
So UI methods will be called by application when some one try to configure it via merchant where it prompts merchant to add/edit required data about gateway for example gateway request URL etc.
When someone places order and try to process the payment AbleCommerce looks for associated payment gateway for customer picked payment method. Then ablecommerce creates an instance of correct gateway and determine what transaction it supports. Then if merchant is set the gateway to Authorize and Capture mode it will first call DoAuthorize method and then DoCapture.
Re: Straight Capture (Do we need doauthorize?)
Hi mazhar, thank you for the reply. So in the doauthorize and docapture methods is it performing two seperate calls to the gateway? Or if authorize and capture is enabled is it merely building he authorization part of the direct post, then passing it along to the docapture method?
Also on the recurring billing, is the DoAuthorizeRecurring called automatically on subscription items when recurring billing is enabled for a gateway?
Thanks for all of your help.
Also on the recurring billing, is the DoAuthorizeRecurring called automatically on subscription items when recurring billing is enabled for a gateway?
Thanks for all of your help.
Re: Straight Capture (Do we need doauthorize?)
anyone on the recurring billing question?
Re: Straight Capture (Do we need doauthorize?)
Both are separate calls made by ablecommerce depending upon the mode of gateway. Some merchants only want to authorize payments and want to capture manually. In this case only authorize will be called. But if you set you gateway mode to Authorize & Capture then it will first call authorize and then it will capture the authorized amount.
Re: Straight Capture (Do we need doauthorize?)
so if i get what you're saying, it does not run the doauthorizereccuring method on subscription items automatically. That would have to be done within docapture?
Re: Straight Capture (Do we need doauthorize?)
Okay, so I have my custom gateway implemented and I'm trying to do a test purchase on a subscription item... I've adjusted doauthorize and docapture to use this information. Nothing is happening, transactions are not pending. I put some debugging that writes to a text file at the beginning of docapture and doauthorize. The debugging code never fires, so doauthorize and docapture are never getting called. I put debugging code in the "initialize" event and it is getting called.
I suspect it has to do with subscription items (which I asked about above twice with no answer) and I hope I can get a helpful reply.
On check out I noticed this message on the receipt page
Order #28 has a balance due but it includes one or more subscription payments. Please contact us in order to complete your order.
Is this why authorize/capture is not happening? Can someone please help me out with this. I am literally days away from purchasing ablecommerce for our solution if I can get this working as advertised. Thanks in advance.
I suspect it has to do with subscription items (which I asked about above twice with no answer) and I hope I can get a helpful reply.
On check out I noticed this message on the receipt page
Order #28 has a balance due but it includes one or more subscription payments. Please contact us in order to complete your order.
Is this why authorize/capture is not happening? Can someone please help me out with this. I am literally days away from purchasing ablecommerce for our solution if I can get this working as advertised. Thanks in advance.
Re: Straight Capture (Do we need doauthorize?)
Okay, I just did a test with a non-subscription item and it worked like a charm... Now I'm convinced that it's the subscription items. Can someone please give me some help with how the gateway implementation handles subscriptions? Thanks!
- Logan Rhodehamel
- Developer
- Posts: 4116
- Joined: Wed Dec 10, 2003 5:26 pm
Re: Straight Capture (Do we need doauthorize?)
Hello mezojeff-
I am familiar with Braintree although I haven't worked with it in a while. From this thread I assume your goal is to implement a recurring charge system through this gateway?
One thing to understand about our subscription / recurring billing implementation is that the gateways we support all have a similar approach. We tell the gateway up front about the payment schedule, how much is the first payment, how much are repeat payments, how often do payments get made, etc. Once we pass this information to the gateway, the gateway handles all of the recurring billing events.
Braintree is a little different. You request a payment and get a token. You can subsequently charge a customer with this token. In this scenario, it's the client software that has responsibility for initiating future events.
You could make this work, but you need to build in some way of identifying future events and then requesting the payments. You would not need to use the recurring billing portions of the gateway - instead you'd be working with the plain DoAuthorize / DoCapture methods. Subsequent capures wuld be made using the token rather than the credit card info.
Am I in the right direction or is my memory of Braintree too faded?
I am familiar with Braintree although I haven't worked with it in a while. From this thread I assume your goal is to implement a recurring charge system through this gateway?
One thing to understand about our subscription / recurring billing implementation is that the gateways we support all have a similar approach. We tell the gateway up front about the payment schedule, how much is the first payment, how much are repeat payments, how often do payments get made, etc. Once we pass this information to the gateway, the gateway handles all of the recurring billing events.
Braintree is a little different. You request a payment and get a token. You can subsequently charge a customer with this token. In this scenario, it's the client software that has responsibility for initiating future events.
You could make this work, but you need to build in some way of identifying future events and then requesting the payments. You would not need to use the recurring billing portions of the gateway - instead you'd be working with the plain DoAuthorize / DoCapture methods. Subsequent capures wuld be made using the token rather than the credit card info.
Am I in the right direction or is my memory of Braintree too faded?
Cheers,
Logan
.com
If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.
Logan
.com
If I do not respond to an unsolicited private message, it's not because I'm ignoring you. It's because the answer to your question is valuable to others. Try the new topic button.
Re: Straight Capture (Do we need doauthorize?)
your memory is fine on braintree. As I posted above I can get it to do a authorize and capture fine on regular products. However those methods get fired when buying subscription product. That's where my problem now lies.
Re: Straight Capture (Do we need doauthorize?)
this is from the gateway debug, the top is an attempt to purchase a subscription item, the bottom two is just buying a normal non-subscription product.
Send: <?xml version="1.0" encoding="utf-8"?><ARBCreateSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><merchantAuthentication><name>demoapi</name><transactionKey>password1</transactionKey></merchantAuthentication><subscription><name>MezoVault Basic - Monthly</name><paymentSchedule><interval><length>1</length><unit>months</unit></interval><startDate>2010-02-09</startDate><totalOccurrences>32767</totalOccurrences></paymentSchedule><amount>9.99</amount><payment><creditCard><cardNumber>xxxxxxxxxxxx1111</cardNumber><expirationDate>2010-10</expirationDate></creditCard></payment><order><invoiceNumber>28:27</invoiceNumber><description>Order #28, Sub #27</description></order><customer><type>individual</type><id>1</id><email>jeff@mezolink.com</email><phoneNumber>2175555555</phoneNumber></customer><billTo><firstName>Jeff</firstName><lastName>Turner</lastName><company>Mezolink</company><address>400 Neil</address><city>Champaign</city><state>IL</state><zip>61820</zip><country>US</country></billTo></subscription></ARBCreateSubscriptionRequest>
Receive: <?xml version="1.0" encoding="utf-8"?><ErrorResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><messages><resultCode>Error</resultCode><message><code>E00003</code><text>The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:totalOccurrences' element is invalid - The value '32767' is invalid according to its datatype 'Short' - The MaxInclusive constraint failed.</text></message></messages></ErrorResponse>
Send: username=xxxxxxxx&password=xxxxxxxx&firstname=Jeff&lastname=Turner&company=Mezolink&address1=400+Neil&city=Champaign&state=IL&zip=61820&country=US&phone=2175555555&fax=&ipaddress=127.0.0.1&email=&shipping_firstname=DEMO&shipping_lastname=DEMO&shipping_company=&shipping_address1=DEMO&shipping_city=DEMO&shipping_state=DEMO&shipping_zip=DEMO&shipping_country=US&amount=22.74&payment=creditcard&type=auth&ccnumber=xxxxxxxxxxxx1111&ccexp=102010&cvv=xxx
Receive: response=1&responsetext=SUCCESS&authcode=123456&transactionid=1185463424&avsresponse=N&cvvresponse=M&orderid=&type=auth&response_code=100&customer_vault_id=
Send: username=xxxxxxxx&password=xxxxxxxx&firstname=Jeff&lastname=Turner&company=Mezolink&address1=400+Neil&city=Champaign&state=IL&zip=61820&country=US&phone=2175555555&fax=&customer_vault=add_customer&ipaddress=127.0.0.1&email=&shipping_firstname=DEMO&shipping_lastname=DEMO&shipping_company=&shipping_address1=DEMO&shipping_city=DEMO&shipping_state=DEMO&shipping_zip=DEMO&shipping_country=US&amount=43.19&payment=creditcard&type=auth&ccnumber=xxxxxxxxxxxx1111&ccexp=102010&cvv=xxx
Receive: response=1&responsetext=SUCCESS&authcode=123456&transactionid=1185465071&avsresponse=N&cvvresponse=M&orderid=&type=auth&response_code=100&customer_vault_id=1387509031
Send: <?xml version="1.0" encoding="utf-8"?><ARBCreateSubscriptionRequest xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><merchantAuthentication><name>demoapi</name><transactionKey>password1</transactionKey></merchantAuthentication><subscription><name>MezoVault Basic - Monthly</name><paymentSchedule><interval><length>1</length><unit>months</unit></interval><startDate>2010-02-09</startDate><totalOccurrences>32767</totalOccurrences></paymentSchedule><amount>9.99</amount><payment><creditCard><cardNumber>xxxxxxxxxxxx1111</cardNumber><expirationDate>2010-10</expirationDate></creditCard></payment><order><invoiceNumber>28:27</invoiceNumber><description>Order #28, Sub #27</description></order><customer><type>individual</type><id>1</id><email>jeff@mezolink.com</email><phoneNumber>2175555555</phoneNumber></customer><billTo><firstName>Jeff</firstName><lastName>Turner</lastName><company>Mezolink</company><address>400 Neil</address><city>Champaign</city><state>IL</state><zip>61820</zip><country>US</country></billTo></subscription></ARBCreateSubscriptionRequest>
Receive: <?xml version="1.0" encoding="utf-8"?><ErrorResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd"><messages><resultCode>Error</resultCode><message><code>E00003</code><text>The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:totalOccurrences' element is invalid - The value '32767' is invalid according to its datatype 'Short' - The MaxInclusive constraint failed.</text></message></messages></ErrorResponse>
Send: username=xxxxxxxx&password=xxxxxxxx&firstname=Jeff&lastname=Turner&company=Mezolink&address1=400+Neil&city=Champaign&state=IL&zip=61820&country=US&phone=2175555555&fax=&ipaddress=127.0.0.1&email=&shipping_firstname=DEMO&shipping_lastname=DEMO&shipping_company=&shipping_address1=DEMO&shipping_city=DEMO&shipping_state=DEMO&shipping_zip=DEMO&shipping_country=US&amount=22.74&payment=creditcard&type=auth&ccnumber=xxxxxxxxxxxx1111&ccexp=102010&cvv=xxx
Receive: response=1&responsetext=SUCCESS&authcode=123456&transactionid=1185463424&avsresponse=N&cvvresponse=M&orderid=&type=auth&response_code=100&customer_vault_id=
Send: username=xxxxxxxx&password=xxxxxxxx&firstname=Jeff&lastname=Turner&company=Mezolink&address1=400+Neil&city=Champaign&state=IL&zip=61820&country=US&phone=2175555555&fax=&customer_vault=add_customer&ipaddress=127.0.0.1&email=&shipping_firstname=DEMO&shipping_lastname=DEMO&shipping_company=&shipping_address1=DEMO&shipping_city=DEMO&shipping_state=DEMO&shipping_zip=DEMO&shipping_country=US&amount=43.19&payment=creditcard&type=auth&ccnumber=xxxxxxxxxxxx1111&ccexp=102010&cvv=xxx
Receive: response=1&responsetext=SUCCESS&authcode=123456&transactionid=1185465071&avsresponse=N&cvvresponse=M&orderid=&type=auth&response_code=100&customer_vault_id=1387509031
Re: Straight Capture (Do we need doauthorize?)
after further experimentation I see that ablecommerce automatically goes straight to the DoAuthorizeRecurring method when purchasing a subscription item... So, I will most likely need to run the doauthorize and docapture events inside of that method, then append the extra code to setup a recurring billing... So it would look something like this.
DoAuthorizeRecurring()
{
DoAuthorize()
DoCapture()
SetupRecurringBilling()
return transaction?
}
Does this look like it will work?
DoAuthorizeRecurring()
{
DoAuthorize()
DoCapture()
SetupRecurringBilling()
return transaction?
}
Does this look like it will work?
Re: Straight Capture (Do we need doauthorize?)
I've played with this for a little while longer this morning. I have a question, I've deduced that the DoAuthorizeRecurring gets called first for subscription items. I've also realized that I do not need to run the doauthorize and docapture inside of that method. Does anything get called upon success of the DoAuthorizeRecurring? In other words if you have Authorize and Capture enabled, will it run the DoCapture method after DoAuthorizeRecurring?
Thanks,
Thanks,
Re: Straight Capture (Do we need doauthorize?)
Still at the same spot as yesterday. I'll break down my inquiry into simpler terms.
On subscription items, with recurring billing set as an option on the gateway, what methods are fired when AuthorizeAndCapture are set to true.
I know that DoAuthorizeRecurring is called first, where I'm stuck is do I do the code for the authorize and the capture within that method, or is the DoCapture method called after a successful authorization inside of the DoAuthorizeRecurring method.
Thank you
On subscription items, with recurring billing set as an option on the gateway, what methods are fired when AuthorizeAndCapture are set to true.
I know that DoAuthorizeRecurring is called first, where I'm stuck is do I do the code for the authorize and the capture within that method, or is the DoCapture method called after a successful authorization inside of the DoAuthorizeRecurring method.
Thank you
Re: Straight Capture (Do we need doauthorize?)
Okay, finally figured this out (on my own). and I'm posting it here for the benefit of future users.
If you have recurring billing set as a supported transaction for your gateway, when a person purchases a subscription item it does all of the work inside of this method.
DoAuthorizeRecurring
It does not touch DoAuthorize or DoCapture during this process, those are used for non-subscription transactions. So what you will need to do inside of DoAuthorizeRecurring is this.
Create your payment,order,and user objects from the AuthorizeRecurringTransactionRequest
Build your gatewayrequest
Send Request to Gateway
Parse the response into a transaction object
return the transaction object
Inside of my gatewayrequest I put all of the code to both setup the recurring billing, and do an initial capture for the monthly rate.
If you have recurring billing set as a supported transaction for your gateway, when a person purchases a subscription item it does all of the work inside of this method.
DoAuthorizeRecurring
It does not touch DoAuthorize or DoCapture during this process, those are used for non-subscription transactions. So what you will need to do inside of DoAuthorizeRecurring is this.
Create your payment,order,and user objects from the AuthorizeRecurringTransactionRequest
Build your gatewayrequest
Send Request to Gateway
Parse the response into a transaction object
return the transaction object
Inside of my gatewayrequest I put all of the code to both setup the recurring billing, and do an initial capture for the monthly rate.
Re: Straight Capture (Do we need doauthorize?)
Implementation of payment gateways has been discussed at http://wiki.ablecommerce.com/index.php/ ... nt_Gateway. The source of the Authorize.net gateway implementation is also available for reference. ftp://ftp.ablecommerce.com/evals/AuthorizeNet.zip
You can have a look at it to see how recurring payments are handled.
Here is the relevant code from Authorize.Net implementation
You can have a look at it to see how recurring payments are handled.
Here is the relevant code from Authorize.Net implementation
Code: Select all
public override AuthorizeRecurringTransactionResponse DoAuthorizeRecurring(AuthorizeRecurringTransactionRequest authorizeRequest)
{
//ACCESS REQUIRED DATA FOR BUILDING REQUEST
Payment payment = authorizeRequest.Payment;
if (payment == null) throw new ArgumentNullException("request.Payment");
Order order = payment.Order;
if (order == null) throw new ArgumentNullException("request.Payment.Order");
Transaction errTrans;
//KEEP TRACK OF SENSITIVE DATA THAT SHOULD NOT BE RECORDED
Dictionary<string, string> debugReplacements = new Dictionary<string, string>();
//GENERATE REQUEST
XmlDocument arbRequest = new XmlDocument();
arbRequest.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><ARBCreateSubscriptionRequest />");
XmlUtility.SetElementValue(arbRequest.DocumentElement, "merchantAuthentication/name", this.MerchantLogin);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "merchantAuthentication/transactionKey", this.TransactionKey);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/name", authorizeRequest.SubscriptionName);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/paymentSchedule/interval/length", authorizeRequest.PaymentFrequency.ToString());
switch (authorizeRequest.PaymentFrequencyUnit)
{
case PaymentFrequencyUnit.Day:
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/paymentSchedule/interval/unit", "days");
break;
case PaymentFrequencyUnit.Month:
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/paymentSchedule/interval/unit", "months");
break;
default:
errTrans = Transaction.CreateErrorTransaction(this.PaymentGatewayId, authorizeRequest, "U", "Unsupported payment frequency unit: " + authorizeRequest.PaymentFrequencyUnit.ToString());
return new AuthorizeRecurringTransactionResponse(errTrans);
}
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/paymentSchedule/startDate", LocaleHelper.LocalNow.ToString("yyyy-MM-dd"));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/paymentSchedule/totalOccurrences", authorizeRequest.NumberOfPayments.ToString());
//DETERMINE IF THERE IS A DIFFERENT INITIAL AND RECURRING AMOUNT
if (authorizeRequest.RecurringChargeSpecified)
{
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/paymentSchedule/trialOccurrences", "1");
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/amount", authorizeRequest.RecurringCharge.ToString("F2"));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/trialAmount", authorizeRequest.Amount.ToString("F2"));
}
else
{
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/amount", authorizeRequest.Amount.ToString("F2"));
}
//DETERMINE METHOD AND TYPE
AccountDataDictionary accountData = new AccountDataDictionary(payment.AccountData);
PaymentInstrument instrument = payment.PaymentMethod.PaymentInstrument;
switch (instrument)
{
case PaymentInstrument.AmericanExpress:
case PaymentInstrument.Discover:
case PaymentInstrument.MasterCard:
case PaymentInstrument.Visa:
string accountNumber = accountData.GetValue("AccountNumber");
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/payment/creditCard/cardNumber", accountNumber);
if (this.UseDebugMode) debugReplacements.Add(accountNumber, MakeReferenceNumber(accountNumber));
string expirationMonth = accountData.GetValue("ExpirationMonth");
if (expirationMonth.Length == 1) expirationMonth.Insert(0, "0");
string expirationYear = accountData.GetValue("ExpirationYear");
if (expirationYear.Length == 2) expirationYear = "20" + expirationYear;
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/payment/creditCard/expirationDate", expirationYear + "-" + expirationMonth);
break;
case PaymentInstrument.Check:
errTrans = Transaction.CreateErrorTransaction(this.PaymentGatewayId, authorizeRequest, "E", "Check is not yet implemented!");
return new AuthorizeRecurringTransactionResponse(errTrans);
default:
errTrans = Transaction.CreateErrorTransaction(this.PaymentGatewayId, authorizeRequest, "E", "The requested payment instrument is not supported: " + instrument.ToString());
return new AuthorizeRecurringTransactionResponse(errTrans);
}
//COMBINE ORDER AND PAYMENT ID TO PREVENT DUPLICATE ERRORS
//WHEN MORE THAN ONE SUBSCRIPTION EXISTS FOR A SINGLE ORDER
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/order/invoiceNumber", string.Format("{0}:{1}", order.OrderNumber, payment.SubscriptionId));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/order/description", string.Format("Order #{0}, Sub #{1}", order.OrderNumber, payment.SubscriptionId));
//CUSTOMER TYPE SHOULD BE 'I' FOR INDIVIDUAL OR 'B' FOR BUSINESS
string customerType = accountData.GetValue("CustomerType");
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/type", ((customerType == "B") ? "business" : "individual"));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/id", order.UserId.ToString());
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/email", order.BillToEmail);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/phoneNumber", order.BillToPhone);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/faxNumber", order.BillToFax, true, false);
//look for drivers license data
if (accountData.ContainsKey("LicenseNumber") && accountData.ContainsKey("LicenseState") && accountData.ContainsKey("BirthDate"))
{
string licenseNumber = HttpUtility.UrlEncode(accountData.GetValue("LicenseNumber"));
string licenseState = HttpUtility.UrlEncode(accountData.GetValue("LicenseState"));
DateTime birthDate = DateTime.Parse(accountData.GetValue("BirthDate"));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/driversLicense/number", licenseNumber);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/driversLicense/state", licenseState);
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/customer/driversLicense/dateOfBirth", birthDate.ToString("yyyy-MM-dd"));
if (this.UseDebugMode)
{
//need to replace license number with truncated version
debugReplacements.Add(licenseNumber, MakeReferenceNumber(licenseNumber));
}
}
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/firstName", StringHelper.Truncate(order.BillToFirstName, 50));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/lastName", StringHelper.Truncate(order.BillToLastName, 50));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/company", StringHelper.Truncate(order.BillToCompany, 50));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/address", StringHelper.Truncate(order.BillToAddress1, 60));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/city", StringHelper.Truncate(order.BillToCity, 40));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/state", StringHelper.Truncate(order.BillToProvince, 40));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/zip", StringHelper.Truncate(order.BillToPostalCode, 20));
XmlUtility.SetElementValue(arbRequest.DocumentElement, "subscription/billTo/country", order.BillToCountryCode);
string requestDocument = arbRequest.OuterXml;
//INSERT THE NAMESPACE FOR THE DOCUMENT ELEMENT
requestDocument = requestDocument.Replace("<ARBCreateSubscriptionRequest", "<ARBCreateSubscriptionRequest xmlns=\"AnetApi/xml/v1/schema/AnetApiSchema.xsd\"");
//RECORD REQUEST
if (this.UseDebugMode)
{
//ALWAYS MASK THE CREDENTIALS
string credentials = String.Format("x_login={0}&x_tran_key={1}", this.MerchantLogin, this.TransactionKey);
string debugCredentials = "x_login=xxxxxxxx&x_tran_key=xxxxxxxx";
debugReplacements[credentials] = debugCredentials;
this.RecordCommunication(this.Name, CommunicationDirection.Send, requestDocument, debugReplacements);
}
//SEND REQUEST
arbRequest = new XmlDocument();
arbRequest.LoadXml(requestDocument);
XmlDocument arbResponse = this.SendXmlRequestToGateway(arbRequest);
//RECORD RESPONSE
if (this.UseDebugMode) this.RecordCommunication(this.Name, CommunicationDirection.Receive, arbResponse.OuterXml, null);
//PROCESS RESPONSE AND RETURN RESULT
XmlNamespaceManager nsmgr = new XmlNamespaceManager(arbResponse.NameTable);
nsmgr.AddNamespace("ns1", "AnetApi/xml/v1/schema/AnetApiSchema.xsd");
string responseCode = XmlUtility.GetElementValue(arbResponse.DocumentElement, "ns1:messages/ns1:message/ns1:code", nsmgr);
string responseMessage = XmlUtility.GetElementValue(arbResponse.DocumentElement, "ns1:messages/ns1:message/ns1:text", nsmgr);
if (XmlUtility.GetElementValue(arbResponse.DocumentElement, "ns1:messages/ns1:resultCode", nsmgr).ToLowerInvariant() == "ok")
{
//SUCCESS RESPONSE
Transaction transaction = new Transaction();
transaction.PaymentGatewayId = this.PaymentGatewayId;
transaction.TransactionType = TransactionType.AuthorizeRecurring;
transaction.TransactionStatus = TransactionStatus.Successful;
transaction.Amount = authorizeRequest.Amount;
transaction.RemoteIP = authorizeRequest.RemoteIP;
transaction.ResponseCode = responseCode;
transaction.ResponseMessage = responseMessage;
transaction.TransactionDate = LocaleHelper.LocalNow;
transaction.AuthorizationCode = XmlUtility.GetElementValue(arbResponse.DocumentElement, "ns1:subscriptionId", nsmgr);
return new AuthorizeRecurringTransactionResponse(transaction);
}
//ERROR RESPONSE
errTrans = Transaction.CreateErrorTransaction(this.PaymentGatewayId, TransactionType.AuthorizeRecurring, authorizeRequest.Amount, responseCode, responseMessage, authorizeRequest.RemoteIP);
return new AuthorizeRecurringTransactionResponse(errTrans);
}
Re: Straight Capture (Do we need doauthorize?)
right... but what isn't discussed in that wiki article is what methods are touched for each type of transaction. Trust me I read through that article about a dozen times while going through the process of setting up this custom gateway for Braintree. It was very helpful, but could have been more so. See below.
If something like this were added into the wiki it could have saved me alot of time.
::Implemented methods on custom gateways based off of authorize.net example::
Authorize - DoAuthorize() is the only method that is implemented
AuthorizeAndCapture - DoAuthorize() and DoCapture() are implemented in that order.
RecurringBilling - DoAuthorizeRecurring() is the only method that is implemented when this is a supported transaction for your gateway.
I definitely appreciate the resources that are out there, and they've been very helpful. I now have a very granular understanding of how the custom gateway is implemented and have ablecommerce doing everything that I need it to do. I feel like I can create a library for pretty much any gateway out there now thanks to going through this process. Thanks for your suggestions.
If something like this were added into the wiki it could have saved me alot of time.
::Implemented methods on custom gateways based off of authorize.net example::
Authorize - DoAuthorize() is the only method that is implemented
AuthorizeAndCapture - DoAuthorize() and DoCapture() are implemented in that order.
RecurringBilling - DoAuthorizeRecurring() is the only method that is implemented when this is a supported transaction for your gateway.
I definitely appreciate the resources that are out there, and they've been very helpful. I now have a very granular understanding of how the custom gateway is implemented and have ablecommerce doing everything that I need it to do. I feel like I can create a library for pretty much any gateway out there now thanks to going through this process. Thanks for your suggestions.