[ http://issues.apache.org/jira/browse/OFBIZ-274?page=all ]
Marco Risaliti updated OFBIZ-274: --------------------------------- Attachment: Dev.pdf java_aim.zip > Authorize.NET Payment Gateway Implementation > -------------------------------------------- > > Key: OFBIZ-274 > URL: http://issues.apache.org/jira/browse/OFBIZ-274 > Project: OFBiz (The Open for Business Project) > Issue Type: New Feature > Components: accounting > Affects Versions: SVN trunk > Reporter: Marco Risaliti > Attachments: AIM_guide.pdf, aimdoc.txt, AIMPaymentServices.java.txt, > authnet_20060614.tgz, authnetcredit.patch, AuthorizeResponse.java.txt, > Dev.pdf, java_aim.zip > > > 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. - If you think it was sent incorrectly contact one of the administrators: http://issues.apache.org/jira/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira