You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ofbiz.apache.org by "BJ Freeman (JIRA)" <ji...@apache.org> on 2007/12/19 21:43:43 UTC

[jira] Updated: (OFBIZ-274) Authorize.NET Payment Gateway Implementation

     [ https://issues.apache.org/jira/browse/OFBIZ-274?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

BJ Freeman updated OFBIZ-274:
-----------------------------

    Attachment: AIMProperites.patch

did not want to open a new jira so put it here.
this is what I think is the best solution.
I also included all the properties for AIM.



> Authorize.NET Payment Gateway Implementation
> --------------------------------------------
>
>                 Key: OFBIZ-274
>                 URL: https://issues.apache.org/jira/browse/OFBIZ-274
>             Project: OFBiz
>          Issue Type: New Feature
>          Components: accounting
>    Affects Versions: SVN trunk
>            Reporter: Marco Risaliti
>             Fix For: SVN trunk
>
>         Attachments: AIM_guide.pdf, aimdoc.txt, AIMPaymentServices.java.txt, AIMProperites.patch, authnet_20060614.tgz, authnetcredit.patch, AuthorizeResponse.java.txt, Dev.pdf, java_aim.zip
>
>
> Copy of http://jira.undersunconsulting.com/browse/OFBIZ-385 from Si Chen
> ====================================================
> A lot of people over the years have requested and implemented Authorize.NET payment gateway for OFBiz. This issue is for an official implementation that's part of the standard OFBiz distribution. 
> I'm going to start by posting some suggestions from Andy on how to implement it and also some documentation and samples. If you have code that you can share, please use this issue tracker. 
>  
>  
>  All    Comments    Work Log    Change History       Sort Order:   
> Comment by Si Chen [26/Jul/05 01:52 PM] [ Permlink ] 
> Andy's suggestions (from email): 
> > Looks like this will be very simple to implement. It does not appear that any external libraries will be needed so this integration will be able to come working with OFBiz out of the box. 
> > 
> > Just follow the examples included in OFBiz for CyberSource or any of the other currently implemented gateways this should give you a good start. 
> > 
> > You'll want to add the necessary configuration fields to the payment properties file. The transaction key, etc. 
> > 
> > -Andy 
> Comment by Si Chen [26/Jul/05 01:53 PM] [ Permlink ] 
> Sample Java code for Authorize.NET. 
> Comment by Si Chen [26/Jul/05 01:56 PM] [ Permlink ] 
> Official API guide 
> Comment by Si Chen [26/Jul/05 01:57 PM] [ Permlink ] 
> More developer's guide. 
> Comment by David E. Jones [30/Nov/05 11:06 PM] [ Permlink ] 
> BTW, this last comment was from Brett Palmer, not from me. It is a re-post with some small changes of what Brett sent before. 
> Comment by David E. Jones [30/Nov/05 11:22 PM] [ Permlink ] 
> Here is our implementation of the Authorize.net interface. We use a simple service to invoke the Authorize.net credit card processor. The service calls the processCard method and returns the response from Authorize.net. Authorize uses a simple HTTP protocol so it is pretty easy to work with. You will also notice that we Authorize's test credit whenever we process a credit card that starts with "7777". This is helpful when you want to test your implementation and if you want to verify if Authorize is working. 
> We wrote this service before we started using common ofbiz credit card processors like Verisign. We would like to see a common Authorize.net implementation to follows the ofbiz standards. 
> /*********************************************/ 
> public class AuthorizeNet { 
>     public static final String module = AuthorizeNet.class.getName(); 
>     public static HashMap validateCCard(Map params) { 
> HashMap results = new HashMap(); 
> if ("7777".equals(params.get("ccNumber"))) { 
> String number = "4111111111111111"; 
> String monthExp = "01"; 
> String yearExp = "01"; 
> String type = "VISA"; 
> String orderId = "1234"; 
> String testReq = "TRUE"; 
> String transAmt = "100"; 
> String description = "test authorization"; 
> Map testParams = new HashMap(); 
> testParams.put("ccType",type); 
> testParams.put("ccNumber",number); 
> testParams.put("ccMonth",monthExp); 
> testParams.put("ccYear",yearExp); 
> testParams.put("orderId",orderId); 
> testParams.put("testReq",testReq); 
> testParams.put("ccTransDescription",description); 
> testParams.put("ccTransAmount",transAmt); 
> results = processCard(testParams); 
> } else { 
> params.put("testReq","FALSE"); 
> params.put("ccTransDescription","authorization transaction"); 
> results = processCard(params); 
> } 
> return results; 
> } 
> private static String getUrl() { 
> Properties props = UtilProperties.getProperties("authorize.properties"); 
> String url = (String) props.get("authorize.net.url"); 
> Debug.logInfo("Authorize url: " + url ,module); 
> //return "https://transact.authorize.net/gateway/transact.dll"; 
> return url; 
> } 
> private static HashMap processCard(Map params) { 
> HashMap result = new HashMap(); 
> String type = (String) UtilFormatOut.checkNull((String)params.get("ccType")); 
> String number = (String) UtilFormatOut.checkNull((String)params.get("ccNumber")); 
> String monthExp = (String) UtilFormatOut.checkNull((String)params.get("ccMonth")); 
> String yearExp = (String) UtilFormatOut.checkNull((String)params.get("ccYear")); 
> String orderId = (String) UtilFormatOut.checkNull((String)params.get("orderId")); 
> String testReq = (String) UtilFormatOut.checkNull((String)params.get("testReq")); 
> String amount = (String) UtilFormatOut.checkNull((String)params.get("ccTransAmount")); 
> String description = (String) UtilFormatOut.checkNull((String)params.get("ccTransDescription")); 
> String url = getUrl(); 
> String expDate = monthExp + yearExp; 
> Debug.logInfo("type = " + type,module); 
> Debug.logInfo("number = " + number,module); 
> Debug.logInfo("amount = " + amount,module); 
> Debug.logInfo("monthExp = " + monthExp,module); 
> Debug.logInfo("yearExp = " + yearExp,module); 
> Debug.logInfo("orderId = " + orderId,module); 
> Debug.logInfo("testReq = " + testReq,module); 
> Debug.logInfo("amount = " + amount,module); 
> Debug.logInfo("description = " + description,module); 
> // check minimum required values 
> if ((amount.length() == 0) || (number.length() == 0) || 
> (testReq.length() == 0)||(expDate.length() == 0) || 
> (type.length() == 0) || (orderId.length() == 0) || 
> (amount.length() == 0) || (description.length() == 0)) { 
> result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_ERROR); 
> result.put(ModelService.ERROR_MESSAGE, "Minimum required - invalid values"); 
> return result; 
> } 
> Map data = new HashMap(); 
> String phone1 = (String)UtilFormatOut.checkNull((String)params.get("contactPhone1")); 
> String phone2 = (String)UtilFormatOut.checkNull((String)params.get("contactPhone2")); 
> String phone3 = (String)UtilFormatOut.checkNull((String)params.get("contactPhone3")); 
> String phone = phone1 + "-" + phone2 + "-" + phone3; // not sure of the format here 
> // contact information 
> data.put("x_first_name",UtilFormatOut.checkNull((String)params.get("billingFirstName"))); 
> data.put("x_last_name",UtilFormatOut.checkNull((String)params.get("billinglastName"))); 
> data.put("x_phone",phone); 
> data.put("x_address",UtilFormatOut.checkNull((String)params.get("billingAddress1"))); 
> data.put("x_city",UtilFormatOut.checkNull((String)params.get("billingCity"))); 
> data.put("x_state",UtilFormatOut.checkNull((String)params.get("billingState"))); 
> data.put("x_zip",UtilFormatOut.checkNull((String)params.get("billingZip"))); 
> data.put("x_country",UtilFormatOut.checkNull((String)params.get("billingCountry"))); 
> data.put("x_email",UtilFormatOut.checkNull((String)params.get("email"))); 
> // order information 
> data.put("x_card_num",number); 
> data.put("x_exp_date",expDate); 
> data.put("x_amount",amount); 
> data.put("x_cust_id","in2m-" + orderId); 
> data.put("x_invoice_num","in2m-" + orderId); 
> data.put("x_description",description); 
> // shipping information 
> if( "true".equals(params.get(UserEnroll.SETUP_SHIPPING))) { 
> data.put("x_ship_to_first_name",UtilFormatOut.checkNull((String)params.get("shippingFirstName"))); 
> data.put("x_ship_to_last_name",UtilFormatOut.checkNull((String)params.get("shippingLastName"))); 
> data.put("x_ship_to_address",UtilFormatOut.checkNull((String)params.get("shippingAddress"))); 
> data.put("x_ship_to_city",UtilFormatOut.checkNull((String)params.get("shippingCity"))); 
> data.put("x_ship_to_state",UtilFormatOut.checkNull((String)params.get("shippingState"))); 
> data.put("x_ship_to_zip",UtilFormatOut.checkNull((String)params.get("shippingZip"))); 
> data.put("x_ship_to_country",UtilFormatOut.checkNull((String)params.get("shippingCountry"))); 
> }else{ 
> data.put("x_ship_to_first_name",UtilFormatOut.checkNull((String)params.get("billingFirstName"))); 
> data.put("x_ship_to_last_name",UtilFormatOut.checkNull((String)params.get("billingLastName"))); 
> data.put("x_ship_to_address",UtilFormatOut.checkNull((String)params.get("billingAddress"))); 
> data.put("x_ship_to_city",UtilFormatOut.checkNull((String)params.get("billingCity"))); 
> data.put("x_ship_to_state",UtilFormatOut.checkNull((String)params.get("billingState"))); 
> data.put("x_ship_to_zip",UtilFormatOut.checkNull((String)params.get("billingZip"))); 
> data.put("x_ship_to_country",UtilFormatOut.checkNull((String)params.get("billingCountry"))); 
> } 
> // authorize configuration defaults 
> data.put("x_version","3.1"); 
> data.put("x_delim_data","TRUE"); 
> data.put("x_method","CC"); 
> data.put("x_type","AUTH_ONLY"); 
> data.put("x_email_customer","FALSE"); 
> data.put("x_email_merchant","TRUE"); 
> data.put("x_Test_Request",testReq); 
> data.put("x_relay_reponse","FALSE"); 
> data.put("x_login","XXXXX"); 
> data.put("x_tran_key","XXXXX"); 
> Debug.logInfo("Authorize.net data string " + data.toString(),module); 
> String respCode = EcommerceServices.VALID; 
> try { 
> HttpClient httpClient = new HttpClient(url,data); 
> httpClient.setClientCertificateAlias("AUTHORIZE_NET"); 
> String httpResponse = httpClient.post(); 
> AuthorizeResponse authorizeResponse = new AuthorizeResponse(httpResponse); 
> String authRespCode = authorizeResponse.get("x_response_code"); 
> if (!authRespCode.equals("1")) { 
> respCode = EcommerceServices.DECLINED; 
> } 
> result.put("httpResponse",httpResponse); 
> result.put("authorizeResponse",authorizeResponse); 
> } catch (HttpClientException e) { 
> respCode = EcommerceServices.PENDING; 
> } 
> result.put("respCode",respCode); 
> result.put(ModelService.RESPONSE_MESSAGE, ModelService.RESPOND_SUCCESS); 
> return result; 
> } 
> } 
> Comment by Kyle Tippetts [17/Jan/06 06:59 PM] [ Permlink ] 
> Skeletal Authorize.Net implementation 
> Comment by Kyle Tippetts [17/Jan/06 07:04 PM] [ Permlink ] 
> Here's a skeletal implementation based on what David posted here earlier, and designed (to the best of my knowledge/ability) to work with the OFBiz credit card processing system. (See the attached AIMPaymentServices and AuthorizeResponse classes above). I only implemented the AUTH_CAPTURE process, since that's what my client wanted (and didn't want OFBiz to handle the capture -- go figure). Anyway, it's a start, I suppose. Any suggestions would be *greatly* appreciated. 
> Here is a snippet of the authorizedotnet payment configuration from payment.properties and below it the service definition. I'm sure the service def could be cleaned up, but there it is: 
> ############################################ 
> # Authorize.Net Configuration 
> ############################################ 
> # Transaction Url 
> payment.authorizedotnet.url=https://secure.authorize.net/gateway/transact.dll 
> # Version 
> payment.authorizedotnet.version=3.1 
> # Delimited data 
> payment.authorizedotnet.delimited=TRUE 
> # Delimited Character 
> payment.authorizedotnet.delimiter=| 
> # Method 
> payment.authorizedotnet.method=CC 
> # Transaction Type 
> payment.authorizedotnet.type=AUTH_CAPTURE 
> # Email Customer? 
> payment.authorizedotnet.emailcustomer=FALSE 
> # Email Merchant? 
> payment.authorizedotnet.emailmerchant=TRUE 
> # Test Mode 
> payment.authorizedotnet.test=TRUE 
> # Relay Response? 
> payment.authorizedotnet.relay=FALSE 
> # Username 
> payment.authorizedotnet.login= 
> # Password 
> payment.authorizedotnet.password= 
> # Default Transaction Description 
> payment.authorizedotnet.transdescription= 
> -------------------------------------------------------- 
> ### Service Definition ### 
> <service name="aimAuthCapture" engine="java" 
> location="org.ofbiz.accounting.thirdparty.authorizedotnet.AIMPaymentServices" invoke="ccAuthCapture"> 
> <attribute name="billingAddress" type="GenericValue" mode="IN" optional="true"/> 
> <attribute name="cardSecurityCode" type="Object" mode="IN" optional="true"/> 
> <attribute name="contactEmail" type="Object" mode="IN" optional="true"/> 
> <attribute name="contactPerson" type="Object" mode="IN" optional="true"/> 
> <attribute name="creditCard" type="GenericValue" mode="IN" optional="true"/> 
> <attribute name="currency" type="Object" mode="IN" optional="true"/> 
> <attribute name="orderId" type="String" mode="IN" optional="true"/> 
> <attribute name="orderItems" type="Object" mode="IN" optional="true"/> 
> <attribute name="orderPaymentPreference" type="Object" mode="IN" optional="true"/> 
> <attribute name="paymentConfig" type="Object" mode="IN" optional="true"/> 
> <attribute name="processAmount" type="Double" mode="INOUT" optional="true"/> 
> <attribute name="shippingAddress" type="GenericValue" mode="IN" optional="true"/> 
> <attribute name="authResult" type="Boolean" mode="OUT" optional="true"/> 
> <attribute name="captureResult" type="Boolean" mode="OUT" optional="true"/> 
> <attribute name="captureAmount" type="Double" mode="OUT" optional="true"/> 
> <attribute name="captureFlag" type="String" mode="OUT" optional="true"/> 
> <attribute name="captureMessage" type="String" mode="OUT" optional="true"/> 
> <attribute name="authCode" type="String" mode="OUT" optional="true"/> 
> <attribute name="authRefNum" type="String" mode="OUT" optional="false"/> 
> <attribute name="authFlag" type="String" mode="OUT" optional="true"/> 
> <attribute name="authMessage" type="String" mode="OUT" optional="true"/> 
> <attribute name="cvCode" type="String" mode="OUT" optional="true"/> 
> <attribute name="avsCode" type="String" mode="OUT" optional="true"/> 
> <attribute name="scoreCode" type="String" mode="OUT" optional="true"/> 
> <attribute name="captureCode" type="String" mode="OUT" optional="true"/> 
> <attribute name="captureRefNum" type="String" mode="OUT" optional="true"/> 
> <attribute name="internalRespMsgs" type="List" mode="OUT" optional="true"/> 
> <attribute name="customerRespMsgs" type="List" mode="OUT" optional="true"/> 
> </service> 
> Comment by Si Chen [20/Jan/06 06:00 PM] [ Permlink ] 
> Kyle, 
> I'll help you with this. Would you mind sending in one patch file including the config, the service definitions, and the .java files you made? In general that is a good thing to do--copying and pasting can lead to errors. 
> Thanks, 
> Si 
> Comment by Kyle Tippetts [21/Jan/06 11:02 PM] [ Permlink ] 
> Si, 
> Thanks for helping me out -- I'm new to all of this. To that end, can you direct me to some instructions on how to create a patch file? I can't seem to find anything online that provides that information. I think I need to use diff and patch, but I want to make sure I do it right.... 
> Thanks, 
> --Kyle 
> Comment by Si Chen [25/Jan/06 09:11 AM] [ Permlink ] 
> Go to your ofbiz/ directory and from the command line 
> $ svn diff > ofbiz385.patch 
> Then upload that file ofbiz385.patch 
> If you don't have the command line svn, go download it from here: http://subversion.tigris.org/project_packages.html 
> There may also be plugins for eclipse, etc., but the idea is the same. 
> Comment by Fred Forester [10/Jun/06 01:10 PM] [ Permlink ] 
> Si, 
> have you done any work on this? If not I may run with it if that's ok. 
> Thanx 
> Fred 
> Comment by Si Chen [13/Jun/06 11:59 AM] [ Permlink ] 
> If you could that'd be great! 
> Comment by Fred Forester [14/Jun/06 10:05 AM] [ Permlink ] 
> Si, 
> I have something that works with version 3.0 of the certification gateway. 
> before I submit it I wanted to know the proper license info I should add if any. 
> Thanx 
> Fred 
> Comment by Jacopo Cappellato [14/Jun/06 10:08 AM] [ Permlink ] 
> Hi Fred, 
> you'll find the license header in the file "APACHE2_HEADER" in the OFBiz folder. 
> Thanks for asking this. 
> Comment by Fred Forester [14/Jun/06 10:48 AM] [ Permlink ] 
> Si, 
> version 3.0 only allows Auth,Capture,AuthCapture. there was some paranoia in setting up a transkey on our account so I couldn't use 3.1. 
> The test property will log more data but testing is done via the certification url. you can use live cards or test card #s. I havent tried the live url but everything passes on the certification url. 
> thanx 
> Fred 
> Comment by Fred Forester [22/Jun/06 01:23 PM] [ Permlink ] 
> I recently founnd that it is possible to handle a credit transaction with AIM 3.0. 
> I'll try to get to it in a few weeks. 
> Fred 
> Comment by Si Chen [23/Jun/06 01:00 PM] [ Permlink ] 
> Ok, that'd be great! 
> Comment by Fred Forester [26/Jun/06 12:48 PM] [ Permlink ] 
> si, 
> this should add support for the CREDIT transaction. I was not able to do much testing on this since the test gateway doesn't return a transid. according to authdotnet you have to "test" these "live" :). 
> Comment by Si Chen [26/Jun/06 04:25 PM] [ Permlink ] 
> So should I wait for your AIM 3.0 implementation or look at these as they are? 
> Comment by Fred Forester [26/Jun/06 04:33 PM] [ Permlink ] 
> Si, 
> these should do it. 
> authnet_20060614.tgz, authnetcredit.patch 
> and this is the 3.0 implementation. 
> Thanx. 
> Fred 
>   
> Comment by Leon Torres [27/Jun/06 05:38 PM] [ Permlink ] 
> Hi Fred, 
> The authnet_20060614.tgz, authnetcredit.patch have been committed into ofbiz accounting as of r 7883. It would be nice if you could add some documentation too, like how the test is triggered. Some of the comments and logging could also be improved or cleaned up, otherwise it's looking good. Just send a patch against 7883. 
> Leon 
> Comment by Fred Forester [27/Jun/06 05:47 PM] [ Permlink ] 
> Hi Leon 
> Sure, I can put something together for doc. 
> thanx for getting this in. 
> Fred 
> Comment by Fred Forester [28/Jun/06 05:07 PM] [ Permlink ] 
> Hi Leon, 
> Here is a text file with a short writeup. 
> Thanx 
> Fred 

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.