Showing ideas with status Accepted.
Show all ideas
When a webhook notification is recieved there is no way to trace it back to a customer/event/action. In the case of hosted forms (i.e. Accept Hosted), none of the values (e.g. invoice number) submitted in the request for a form validation token appear in the webhook notification, so there is no way to immediately know what the webhook notification is in regards to. This forces us to always query authorize.net for the transaction details to see what the transaction applies to (e.g. invoice number) and confirm the transaction is completed. I imagine that a webhook notification alone is not especially useful unless it provides access to a correlation token and status. Because these values are small in size and almost definitely required by any merchant software, I feel the very small increase in payload could greatly reduce the need for subsequent queries - saving merchants as well as Authorize.net a lot of extra processing and network traffic.
... View more
Our company was having trouble with our connection to Authnet in the sandbox environment due to the recent upgrade requiring TLS 1.2. Our company's app is running with Java 1.7. We tried setting our project's http protocols to force TLS 1.2 but this didnt seem to be working. Eventually we discovered that the anet-java-sdk:1.9.3 is usign a default HTTPClient. We had to override the HttpClient and HttpCallTask classes in the util directory. Anywhere that the class set up a defaultHttpClient, we replaced that code with this: SSLContext sslContext = SSLContexts.custom() .useTLS() .build(); SSLConnectionSocketFactory f = new SSLConnectionSocketFactory( sslContext, new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(f) .build(); The entire HttpClient and HttpCallTask classes are below. If we could get these changes added to a new SDK from Authnet, that may help other customers avoid this same problem. Also, it would be helpful for us as then we can continue just importing the entire file library rather than including all the anet files in our own code structure. HttpClient: package net.authorize.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URLDecoder; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.params.ConnRoutePNames; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpConnectionParams; import org.apache.http.protocol.HTTP; import net.authorize.Environment; import net.authorize.ResponseField; import net.authorize.Transaction; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.CloseableHttpClient; import javax.net.ssl.SSLContext; import org.apache.http.conn.ssl.SSLContexts; import javax.net.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; /** * Transportation object used to facilitate the communication with the respective gateway. * */ public class HttpClient { private static Log logger = LogFactory.getLog(HttpClient.class); public static final String ENCODING = "UTF-8"; static boolean proxySet = false; static boolean UseProxy = Environment.getBooleanProperty(Constants.HTTPS_USE_PROXY); static String ProxyHost = Environment.getProperty(Constants.HTTPS_PROXY_HOST); static int ProxyPort = Environment.getIntProperty(Constants.HTTPS_PROXY_PORT); static int httpConnectionTimeout = Environment.getIntProperty(Constants.HTTP_CONNECTION_TIME_OUT); static int httpReadTimeout = Environment.getIntProperty(Constants.HTTP_READ_TIME_OUT); static { LogHelper.info(logger, "Use Proxy: '%s'", UseProxy); httpConnectionTimeout = (httpConnectionTimeout == 0 ? Constants.HTTP_CONNECTION_TIME_OUT_DEFAULT_VALUE : httpConnectionTimeout ); httpReadTimeout = (httpReadTimeout == 0 ? Constants.HTTP_READ_TIME_OUT_DEFAULT_VALUE : httpReadTimeout); } /** * Creates the http post object for an environment and transaction container. * * @param env * @param transaction * @return HttpPost object * * @throws Exception */ private static HttpPost createHttpPost(Environment env, Transaction transaction) throws Exception { URI postUrl; HttpPost httpPost = null; if(transaction instanceof net.authorize.aim.Transaction || transaction instanceof net.authorize.sim.Transaction) { if(transaction instanceof net.authorize.aim.Transaction && ((net.authorize.aim.Transaction)transaction).isCardPresent()) { postUrl = new URI(env.getCardPresentUrl() + "/gateway/transact.dll"); } else { postUrl = new URI(env.getBaseUrl() + "/gateway/transact.dll"); } httpPost = new HttpPost(postUrl); httpPost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false); //set the tcp connection timeout httpPost.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT, httpConnectionTimeout); //set the time out on read-data request httpPost.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT, httpReadTimeout); httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"); httpPost.setEntity(new StringEntity(transaction.toNVPString(), HTTP.UTF_8)); } else if (transaction instanceof net.authorize.arb.Transaction || transaction instanceof net.authorize.cim.Transaction || transaction instanceof net.authorize.reporting.Transaction) { postUrl = new URI(env.getXmlBaseUrl() + "/xml/v1/request.api"); httpPost = new HttpPost(postUrl); httpPost.getParams().setBooleanParameter(CoreProtocolPNames.USE_EXPECT_CONTINUE, false); //set the TCP connection timeout httpPost.getParams().setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT, httpConnectionTimeout); //set the time out on read-data request httpPost.getParams().setIntParameter(HttpConnectionParams.SO_TIMEOUT, httpReadTimeout); httpPost.setHeader("Content-Type", "text/xml; charset=utf-8"); httpPost.setEntity(new StringEntity(transaction.toXMLString(), HTTP.UTF_8)); } return httpPost; } /** * Creates a response map for a given response string and transaction container. * * @param transaction * @param responseString * @return container map containing semi-processed data after request was posted * @throws UnsupportedEncodingException */ private static Map<ResponseField, String> createResponseMap(Transaction transaction, String responseString) throws UnsupportedEncodingException { Map<ResponseField, String> responseMap = null; // aim/sim if(transaction instanceof net.authorize.aim.Transaction || transaction instanceof net.authorize.sim.Transaction) { String decodedResponseData = URLDecoder.decode(responseString, HTTP.UTF_8); responseMap = ResponseParser.parseResponseString(decodedResponseData); } return responseMap; } /** * Executes a Transaction against a given Environment. * * @param environment * @param transaction * @return container map containing semi-processed data after request was posted */ public static Map<ResponseField, String> execute(Environment environment, Transaction transaction) { Map<ResponseField, String> responseMap = new HashMap<ResponseField, String>(); if(environment != null && transaction != null) { try { SSLContext sslContext = SSLContexts.custom() .useTLS() .build(); SSLConnectionSocketFactory f = new SSLConnectionSocketFactory( sslContext, new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(f) .build(); setProxyIfRequested(httpClient); // create the HTTP POST object HttpPost httpPost = createHttpPost(environment, transaction); // execute the request HttpResponse httpResponse = httpClient.execute(httpPost); String rawResponseString; if(httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity entity = httpResponse.getEntity(); // get the raw data being received InputStream instream = entity.getContent(); rawResponseString = convertStreamToString(instream); } // handle HTTP errors else { StringBuilder responseBuilder = new StringBuilder(); responseBuilder.append(3).append(net.authorize.aim.Transaction.TRANSACTION_FIELD_DELIMITER); responseBuilder.append(3).append(net.authorize.aim.Transaction.TRANSACTION_FIELD_DELIMITER); responseBuilder.append(22).append(net.authorize.aim.Transaction.TRANSACTION_FIELD_DELIMITER); responseBuilder.append(httpResponse != null ? httpResponse.getStatusLine().getReasonPhrase() : " "); rawResponseString = responseBuilder.toString(); } httpClient.getConnectionManager().shutdown(); String cleanResponseString = XmlUtility.descapeStringForXml(rawResponseString); responseMap = HttpClient.createResponseMap(transaction, cleanResponseString); } catch (Exception e) { LogHelper.warn(logger, "Exception getting response: '%s': '%s', '%s'", e.getMessage(), e.getCause(), Arrays.toString(e.getStackTrace())); } } return responseMap; } /** * Converts a response inputstream into a string. * * @param is * @return String */ public static String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line; try { while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } catch (IOException e) { LogHelper.warn(logger, "Exception reading data from Stream: '%s'", e.getMessage()); } finally { if ( null != reader){ try { reader.close(); } catch (IOException e) { LogHelper.warn(logger, "Exception closing BufferedReader: '%s'", e.getMessage()); } } if ( null != is) { try { is.close(); } catch (IOException e) { LogHelper.warn(logger, "Exception closing InputStream: '%s'", e.getMessage()); } } } return sb.toString(); } /** * Executes a Transaction against a given Environment. * * @param environment * @param transaction * @return BasicXmlDocument containing semi-processed data after request was posted */ public static BasicXmlDocument executeXML(Environment environment, Transaction transaction) { BasicXmlDocument response = new BasicXmlDocument(); if(environment != null && transaction != null) { try { SSLContext sslContext = SSLContexts.custom() .useTLS() .build(); SSLConnectionSocketFactory f = new SSLConnectionSocketFactory( sslContext, new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(f) .build(); setProxyIfRequested(httpClient); // create the HTTP POST object HttpPost httpPost = createHttpPost(environment, transaction); // execute the request HttpResponse httpResponse = httpClient.execute(httpPost); String rawResponseString; if(httpResponse != null && httpResponse.getStatusLine().getStatusCode() == 200) { HttpEntity entity = httpResponse.getEntity(); // get the raw data being received InputStream instream = entity.getContent(); rawResponseString = convertStreamToString(instream); } else { StringBuilder responseBuilder = new StringBuilder(); if(transaction instanceof net.authorize.arb.Transaction || transaction instanceof net.authorize.cim.Transaction || transaction instanceof net.authorize.reporting.Transaction) { responseBuilder.append("<?xml version=\"1.0\" ?>"); responseBuilder.append("<messages><resultCode>Error</resultCode>"); responseBuilder.append("<message><code>E00001</code>"); responseBuilder.append("<text>"); responseBuilder.append(httpResponse != null?httpResponse.getStatusLine().getReasonPhrase():""); responseBuilder.append("</text></message></messages>"); } else { responseBuilder.append("<?xml version=\"1.0\" ?>"); responseBuilder.append("<response>"); responseBuilder.append("<ResponseCode>3</ResponseCode>"); responseBuilder.append("<Errors><Error><ErrorCode>22</ErrorCode><ErrorText><![CDATA["); responseBuilder.append(httpResponse != null?httpResponse.getStatusLine().getReasonPhrase():""); responseBuilder.append("]]></ErrorText></Error></Errors></response>"); } rawResponseString = responseBuilder.toString(); } httpClient.getConnectionManager().shutdown(); if(rawResponseString == null) return null; int mark = rawResponseString.indexOf("<?xml"); if(mark == -1){ return null; } response.parseString(rawResponseString.substring(mark,rawResponseString.length())); if(response.IsAccessible() == false){ return null; } } catch (Exception e) { LogHelper.warn(logger, "Exception getting response: '%s': '%s', '%s'", e.getMessage(), e.getCause(), Arrays.toString(e.getStackTrace())); } } return response; } /** * if proxy use is requested, set http-client appropriately * @param httpClient the client to add proxy values to */ public static void setProxyIfRequested(CloseableHttpClient httpClient) { if ( UseProxy) { if ( !proxySet) { LogHelper.info(logger, "Setting up proxy to URL: '%s://%s:%d'", Constants.PROXY_PROTOCOL, ProxyHost, ProxyPort); proxySet = true; } HttpHost proxyHttpHost = new HttpHost(ProxyHost, ProxyPort, Constants.PROXY_PROTOCOL); httpClient.getParams().setParameter( ConnRoutePNames.DEFAULT_PROXY, proxyHttpHost); } } } HttpCallTask: package net.authorize.util; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.concurrent.Callable; import javax.xml.bind.JAXBException; import javax.xml.bind.UnmarshalException; import net.authorize.Environment; import net.authorize.api.contract.v1.ANetApiRequest; import net.authorize.api.contract.v1.ANetApiResponse; import net.authorize.api.contract.v1.MessageTypeEnum; import net.authorize.api.contract.v1.MessagesType; import net.authorize.api.contract.v1.MessagesType.Message; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.methods.HttpPost; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.client.CloseableHttpClient; import javax.net.ssl.SSLContext; import org.apache.http.impl.client.HttpClients; import org.apache.http.conn.ssl.SSLContexts; import javax.net.ssl.SSLSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; //import net.authorize.api.controller.base.ErrorResponse; /** * Callable task to make http calls in future * @author ramittal * */ public class HttpCallTask implements Callable<ANetApiResponse> { private static Log logger = LogFactory.getLog(HttpCallTask.class); Environment env = null; ANetApiRequest request = null; @SuppressWarnings("rawtypes") Class classType = null; //private static ANetApiResponse errorResponse = null; private Message errorMessage = null; /** * Creates task to be called in future for making http call * @param env Env to point to * @param request Http request to send * @param classType Expected response type if successful */ public <T> HttpCallTask(Environment env, ANetApiRequest request, Class<T> classType) { this.env = env; this.request = request; this.classType = classType; this.errorMessage = new Message(); } @SuppressWarnings("unchecked") /** * Makes a http call, using the proxy if requested, and returns apiresponse * with error code set appropriately * @return ANetApiResponse successful or failed response */ public ANetApiResponse call() throws Exception { ANetApiResponse response = null; StringBuilder buffer = new StringBuilder(); CloseableHttpClient httpCaller = null; try { HttpPost httppost = HttpUtility.createPostRequest(this.env, this.request); SSLContext sslContext = SSLContexts.custom() .useTLS() .build(); SSLConnectionSocketFactory f = new SSLConnectionSocketFactory( sslContext, new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); httpCaller = HttpClients.custom() .setSSLSocketFactory(f) .build(); HttpClient.setProxyIfRequested(httpCaller); HttpResponse httpResponse = httpCaller.execute(httppost); if ( null != httpResponse) { if ( null != httpResponse.getStatusLine()) { if ( 200 == httpResponse.getStatusLine().getStatusCode()) { HttpEntity entity = httpResponse.getEntity(); // get the raw data being received InputStream instream = entity.getContent(); buffer.append(HttpUtility.convertStreamToString(instream)); } } } LogHelper.debug(logger, "Raw Response: '%s'", buffer.toString()); // handle HTTP errors if (0 == buffer.length()) { response = createErrorResponse(httpResponse, null); } else { // i.e. if ( StringUtils.isNotEmpty(buffer.toString())) Object localResponse = null; try { localResponse = XmlUtility.create(buffer.toString(), this.classType); } catch(UnmarshalException ume) { try { //try deserializing to error message localResponse = XmlUtility.create(buffer.toString(), net.authorize.api.contract.v1.ErrorResponse.class); } catch(JAXBException jabex) { response = createErrorResponse(httpResponse, jabex); } } catch(JAXBException jabex) { response = createErrorResponse(httpResponse, jabex); } //ObjectFactory factory = new ObjectFactory(); //JAXBElement<ANetApiResponse> error = factory.createErrorResponse(); //check if error if ( null == localResponse) { try { response = XmlUtility.create(buffer.toString(), ANetApiResponse.class); } catch(JAXBException jabex) { response = createErrorResponse(httpResponse, jabex); } } else { if (localResponse instanceof ANetApiResponse) { response = (ANetApiResponse) localResponse; } else { LogHelper.warn( logger, "Unknown ResponseType: '%s'", localResponse); } } } } catch (ClientProtocolException cpe) { response = createErrorResponse(null, cpe); } catch (IOException ioe) { response = createErrorResponse(null, ioe); } finally { if ( null != httpCaller) { httpCaller.getConnectionManager().shutdown(); } } return response; } private ANetApiResponse createErrorResponse(HttpResponse httpResponse, Exception exception) { ANetApiResponse response = new ANetApiResponse(); MessagesType aMessage = new MessagesType(); aMessage.setResultCode(MessageTypeEnum.ERROR); response.setMessages(aMessage); List<Message> messages = response.getMessages().getMessage(); //clear all messages messages.clear(); setErrorResponse(messages, httpResponse); setErrorResponse(messages, exception); return response; } private void setErrorResponse(List<Message> messages, HttpResponse httpResponse) { if ( null != httpResponse) { messages.add(errorMessage); String code = "Error"; String text = "Unknown Error"; if (null != httpResponse.getStatusLine()) { LogHelper.warn( logger, "Error deserializing response to '%s'", this.classType); code = String.format("%d", httpResponse.getStatusLine().getStatusCode()); if (null != httpResponse.getStatusLine().getReasonPhrase()) { text = httpResponse.getStatusLine().getReasonPhrase();} } setErrorMessageValues(code, text); } } private void setErrorResponse(List<Message> messages, Exception exception) { if ( null != exception) { messages.add(errorMessage); String code = "Error"; String text = "Unknown Error"; LogHelper.error( logger, "Http request execute failed: '%s'", exception.getMessage()); code = exception.getClass().getCanonicalName(); //code = exception.getClass().getTypeName();// requires java1.8 text = exception.getMessage(); setErrorMessageValues(code, text); } } private void setErrorMessageValues(String code, String text) { errorMessage.setCode(code); errorMessage.setText(text); LogHelper.warn(logger, "Adding ErrorMessage: Code: '%s', Text: '%s'", code, text); } } Hopefully this is helpful for anyone else struggling to connect to the Sandbox environment. -Tony
... View more
We are using the AuthorizeNet Nuget package in our code base to communicate with Authorize.Net. After the TLS1.2 upgrade at Authorize.Net in the sandbox environment, we have been using System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12; So that the communication does not fail. It would be great if the fix was applied on the Nuget Package. Thanks, Reji
... View more
A customer on my site just attempted to place an order with a valid Discover card number that is 19 digits long. Apparently, Discover and Visa have begun rolling out valid cards with 19 digits. The card passed my Luhn algorithm validation and was passed to Authorize.NET for authorization. The XML request was sent succefully; however, I received the following error response from Authorize.NET:
The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardNumber' element is invalid - The value XXXXXXXXXXXXXXXXXXXXX is invalid according to its datatype 'String' - The actual length is greater than the MaxLength value.
I checked on the Authorize.NET documentation, and it appears that only card numbers between 13 and 16 characters long are supported. When will this be changed to accommodate 19 digit card numbers?
... View more
I'm currently working on a solution where our customers have requested a migration-tool, to tie existing CIM entries to their business partners in their ERP system. In this case a method to retrieve all CIM profiles along with their corresponding payment profiles would be helpful. Currently the only option is to query the API for all CIM profile IDs and then iterate them and call the API for each one. In the sandbox environment this takes roughly 20 minutes for 4000 entries, using multi-threaded requesting. This performance is obviously pretty poor, and I imagine the method I described above would allviate this problem.
... View more
It seems so stupid that this is not already available. If you have an ARB subscriber for a service you are offering on a monthly basis, you would of course want to know, often and simply, if that subscriber has paid his last bill before you continue to service him. But instead of a simple API function, I have to parse through mountains of data and, if I dont want to have to do this everytime someone logs in ( to check if they should be able to), i also now have to create a database table to track this status and when it was last checked. CRAZY! Please Authorize.net, create a simple API to do this simple check!!!
... View more
Created from previous thread: https://community.developer.authorize.net/t5/Integration-and-Testing/How-to-set-billing-info-in-CIM-hostedForm/m-p/54627 Add ability to pre-load billing information into CIM hosted form. Our customer's billing information is already stored in our system, and we do not want to force them to enter it a second time when adding a payment profile. We would prefer instead to show the current billing information as the default values and allow them to modify the displayed information if the billing infomration is different for the credit card than what is already on file. ================================ carlosdanielmou wrote: In our system the user complete billing information, and when we show the form of the CIM hosted API, we need such data are loaded in the form, as we do that? First we call to createCustomerProfileRequest, with merchantCustomerId and email. Then I call createCustomerShippingAddressRequest with customer billing address and then, I call getHostedProfilePageRequest.
... View more
Status:
Accepted
Submitted on
05-02-2016
05:11 PM
Submitted by
RocklinSoftware
on
05-02-2016
05:11 PM
Hi AuthorizeNet, With the complexities of SAQ A, EF, D and the opportunities of globalization (i.e. en-CA, fr-CA, en-US, es-US, es-MX; North America + Mexico) it would be great to have localizable capabilities offered in your HostedForm and DirectPostMethod implementations. This would simplify product integration (Redirect, IFRAME, DirectPost, and JavaScript) and allow a SAQ A or SAQ EF implementation. My thought is to add hidden text fields i.e.; For fields like; - input type="hidden" name="x_invoice_num" value="dpm3-inv3-123" Add a new tag like; - input type="hidden" name="x_invoice_num_label" value="Invoice Number:" . This would go a long way to improving/solving localization and keeping PCI DSS to a minimum for the companies building solution with AuthorizeNet's SDK. Regards, Rocklin Software
... View more
Right now, connection details logged from HttpUtility at the debug level include a great deal of useful information along with - the api login and transaction key - full dump of the xml request including unmasked credit card number, expiration date, etc. Can we move the logging of these two items to a separately-configurable logger like "HttpUtility-sensitive"? I'd like to see the api login and transaction key logging go away completely from the HttpUtility output. ideally, I'd like to see the xml request filtered to not show any <payment> information beyond a generic <creditCard> output. (I suppose masked credit card number would be acceptable). I think it would also be wise to not output <billTo> information nor <customer> information with the non-sensitive-data logger other than <customer><id> even though this is not strictly required by PCI DSS. We want to log when transactions occur with enough context to know what those transactions are without making our logs a security risk.
... View more
Idea: A read-only key that can be generated specifically for the Transaction Details API. Background: We are developing an app that only uses the Transaction Details API. Which means we are only reading information. From a liability standpoint, we want to avoid saving a write-capable transaction key. Ideally a separate "read-only" transaction key could be created when a user turns on the Transaction Details API.
... View more
As we build out our integration we noticed it would nice to have some additonal search types added to the getCustomerPaymentProfileListRequest endpoint. The most useful for us would be to search by customerProfileID. Also an expiration date range would be nice along with a paymentType (credit card or bank account) A future request i could see is having the ability to have multiple searchTypes like customerProfileID and and an expiration month/year or range, or customerProfileID and paymentType. Thanks, -Nick
... View more
I have just recently wrapped up an integration with Auth.net to our website and erp system using CIM and the Payment Transaction API. Our system is passing the Level 3 data to Auth.net, but Auth.net doesn't pass this information to the processor. I was curious about the decision for Auth to hold onto the data and not deliver it to the processors and if this feature is on the roadmap? I would love to have the L3 data passed around, we could realize an incredible amount of savings from this (fees can be cut by up to half with this information, That's huge!). If this isn't on the roadmap, please consider adding support for this.
... View more
There needs to be a way to verify if a transaction has already been posted or not in order to help eliminate possible payment duplication. This could work by searching for an invoice number, date, and possibly even a payment amount; and get a list of all transactions where there is a match. This way I can make sure my application isnt trying to charge a second time when it should not.
... View more
Created from previous thread: https://community.developer.authorize.net/t5/Integration-and-Testing/refundTransaction-requires-expiration-date-in-XML-but-never-did/m-p/53579#M28687 Currently, to refund a transaction, you must provide both the masked credit card number and expiration date. Yet this information adds nothing to the request -- in fact, if you no longer have this information, you must issue a separate getTransactionDetail transaction to fetch this information. Rather than requiring two separate transactions to perform a single task, only require the original transaction id.
... View more
The CIM "Add New Payment Method" hosted form does not show an asterix before billing zip and street even though they are required fields. Card Number expiration date, and Card code are clearly indicated as required via an asterix. This will be confusing to our customers as the credit card number and expiration date fields are clearly marked with an asterix while street and zip appear optional, yet when customers hit save, they are told that zip and street are required. Ideally whether or not zip and street are required fields and trigger an error message should be determined from the merchant account AVS settings, or be determined by a setting indicated when requesting the hosted form token.
... View more
Hi, It's great that now we finally can retrieve card expiration dates via API call. Nevertheless, on https://test.authorize.net/profile/editPayment form expiration date is still displayed as masked. Our clients find this inconvenient. The idea is to show unmasked date on hosted form.
... View more
Status:
Accepted
Submitted on
07-15-2015
06:31 AM
Submitted by
messageagency1
on
07-15-2015
06:31 AM
The current minimum 7 day interval for ARB makes testing impossible. Developers need a shorter interval, for example 1 minute, to be able to test their applications.
... View more
Despite using best security practices to protect passwords, we consider the single form authentication to the Authorize.net portal to be a critical security concern. The concern is especially high with regard to CIM. When CIM is enabled, anybody breaking into the Authorize.net account can do a lot of damage (like creating transactions). We are in 2015 and two form factor authentication is widespread and easy to implement. It does not have to be a full blown 2-factor with MFA devices. A simple solution - for example using a mobile phone access code - would already be a huge improvement over the current system.
... View more
There should be a way to retrieve transaction details by their invoice number. If there is a network failure the only identifying information we have is the invoice number (not the Authorize.net generated transaction id). Using the getUnsettledTransactionListRequest call is a bad choose since it only returns the last 1000 records.
... View more
There needs to be a feature that allows you to get subscription information like when was the last valid payment, all attempt of card processing and whether it failed or went through, etc etc etc. ARB really is tiny with no usefull functions other than create and cancel subscriptions. Even the update is useless with the amount of things u can update about a transaction. So please add some features that gives users some idea of what is going on with their subscription. Is there a better payment processor than authorize.net that does this?
... View more