Similar to the enhancement thas was made for getCustomerProfileRequest (https://community.developer.authorize.net/t5/Ideas/UnMasked-Expiration-Date-in-Hosted-CIM-s/idi-p/49457), there should be an option to obtain the unmasked expiration date from getTransactionDetails. This is important, for example in the case when a refund needs to be issued. The refund API expects the expiration date.
... View more
Account Updater deletes Payment Profiles stored in CIM due to the fact that they are marked as "closed" by the issuing bank. However, some customers continue to re-enter the same card details month after month showing that this is fact a false positive. When attempting to process a payment against these cards, they are succesful, and don't return a closed status. There is a flaw in the data passed by the banks to account updater, or in updater itself. In my limited testing, I discovered this was happening to several % of my cards every single month costing me thousands in revenu in a pretty short amount of time. Several other Authorize.net users have noticed the same problem Read the support forum thread My guess is that if everyone who used CIM and account updater looked at their monthly updater report, and checked the last 4 of cards deleted, they would find that it's deleting some of the same customers credit cards every single month! The account updater sales page states that, "It costs 7 times more to get a new customer than to keep a current one." yet account updater is deleting active card data every single month. Three potential solutions: Don't delete any payment profiles ever - only update. If we must delete, only delete payment profiles that have been marked as closed by account updater, and also have a declined authorization. Allow users to choose which cards to run the account updater on. I for example would choose to only run the account updater on accounts that had failed billing attempts. Since I've been told by customer support that this can't be fixed, I would like to point out that Stripe does not have this same problem with their account updater, and in my testing, my card churn rate was much lower with Stripe.
... View more
When a customer does not enter the correct credit card details, there is a warning sign added next to the credit card as well as the field's underline becomes red. This is fine but when customers are on smaller displays, they need to know to scroll back up the form to find the error. The suggestion here is to add an error message just above the "Pay" and "Cancel" buttons (just like some of the system errors like the "declined" messages) which describes to the customer what the problem is so they know to scroll back up to fix the issue. We are seeing significant problems with our customers and they wind up canceling the transaction!
... View more
I need to add something like this is a secure payment or something like that within accept hosted payment page. can any one have idea or any suggestion?
... View more
Hello, We would like to implement the following use case for an online information source (such as an online magazine): A visitor buys a subscription for a period of time (say 6 months) Once the subscription ends, is cancelled or a payment fails, we would like to suspend automatically the customer's access to the magazine We would need to see additional events for payment failure and the end of subscription (final payment made). At the moment, there is an event for "last but one" payment, but that is not sufficient. Thanks
... View more
I'm trying to find out if there is an API call that will return whether or not CIM has been enabled on an account or not. Right now we have the occassional customer who has initial issues with our payment implementation, and it often is a result of them (our customer) not having CIM enabled in their Authorize.net account. I would very much like to be able to programatically do a check for whether or not CIM is enabled. Oh, and it would be ideal if the call didn't return a response that "implied" the anwser of whether or not CIM was enabled, but rather explicitly stated it.
... View more
Not everyone programms in C#. There are still a few of us VB programmers out here and it would be great if you had some VB Samples. You used to have them...I don't know what changed.
... View more
Status:
Under Review
Submitted on
04-23-2018
04:04 PM
Submitted by
eventespresso
on
04-23-2018
04:04 PM
When using Authorize.Net Accept Hosted in an iFrame, the "Description" and "Invoice Number" areas are too narrow to read easily. For example, see this screenshot: https://monosnap.com/file/HFdx6i4XhyZhoflYF9iE5i6rOkUZPD# We are working around this by forcing the iFrame's container to have a minimum width of 400px, which is sufficiently wide for the Description and Invoice number to look better, but it's not the ideal solution because then mobile users need to scroll left and right to read everything. Ideally, if the iFrame's area is more narrow than 300 px or something, the contents of description should fall BELOW the title "Description", and likewise the invoice number would fall under the title "Invoice Number". Eg, instead of ============================ Description {contents-of-description} Invoice Number {invoice-number} ============================ on narrow screens, it should become ============================ Description {contents-of-description} Invoice Number {invoice-number} ============================ This would make better use of the limited horizontal space. And yes I realize you can customize the form however you like if you use Accept.js, but I think this is a pretty general issue (experienced by anyone who actually tests their payment form on a mobile device) so it would make sense to fix it on the hosted solution. Besides, the fix should only require a few CSS tweaks.
... View more
Status:
Under Review
Submitted on
03-05-2018
02:28 PM
Submitted by
knightcode
on
03-05-2018
02:28 PM
We just started using the in-person iOS SDK. Holy Hell, the UI is bad. Can you make the signature box transparent, so that it matches whatever we set the background color to. Then just give it a border that's the same color as the text font color (if you don't want to add another setting). And can we set the font? Or can you pick a better one, please.
... 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
In createTransactionRequest we are able to create a new customer profile from data which was sent in this API call by setting <createProfile>true</createProfile> flag: <profile>
<createProfile>true</createProfile>
</profile> Since customer is only being created after transaction is set, and not assosiated with it, any of GetTransactionList, GetUnsettledTransactionList and GetTransactionDetails API calls will respond with empty customer profile field. Flag <createProfile> only declares that profile will be created, so this is an expected behavior. But also it might be usefull to associate customer profile with transaction where it was created. A new flag might be added to avoid changing <createProfile> strict behavior, and at the same time add more flexibility to this call: <profile>
<createProfile>true</createProfile>
<associateWithTransaction>true</associateWithTransaction>
</profile> , or something similar.
... View more
A credit card payment can only be refunded for up to 120 days without having to resort to using ECC. ECC is cumbersome and creates PCI compliance hassles. Competitor gateways can often refund transactions up to a year after they happen. Please extend the non-ECC refund window to 365 days.
... View more
We would like to be able to bill our clients in one currency, and have the funds settled into our account in another. As an example, we would like to charge our UK clients in GBP, and then have the funds converted, and deposited into our Australian bank account in AUD. I think it's important that our clients always know exactly how much will be deducted from their credit cards, as opposed to having it fluctuate each month based on that days exchange rate. I contacted Authorize.net to see if they offer this service, and they suggested that I post the suggestion here. If this option was available, we would be happy to have multiple Authorize.net accounts - one for each country/currency that we have clients Thanks
... 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
There are many solutions providers that are trying to integrate with a payment processors to give their clients a robust system - not only for people paying them, but for paying their employees as well - via direct Deposit. For example non profits (and many for profits) need to accept money via online (donations or payments for products and services). Authorize.net has this portion down - Hooray!!! The part we need in a full CRM - Enterprise system is the ability to make payroll direct deposits to our employees. Churches and other companies use software like what we offer to keep all their systems running but we need a processor in the back end that can handle any type of money movement ie - one bank to many banks (direct deposit), receiving money from multiple banks to one bank (paying for something online from multiple clients), making payments to vendors, and so on. Thanks for listening. Jay
... View more
Status:
Under Review
Submitted on
09-06-2016
08:07 AM
Submitted by
mkienenb
on
09-06-2016
08:07 AM
One of the problems with using CIM hosted forms is that it's difficult to determine what profile information has changed (payment profiles added or edited). Another issue is that it's difficult to provide an audit trail which identifies who initiated the changes. One possibility that could address these issues is specifying some kind of reference id (not the per-transaction refid field) in the getHostedProfilePageRequest which would be assigned to each payment profile (or shipping address, although this is not something I use) which the end user created or edited using this token. Or it could be the token itself. Then return that identifier for each payment profile (or shipping address) returned by getCustomerPaymentProfileListRequest. End-developers can easily identify which payment profiles were modified by a specific token consumer. We can also provide an audit trail of which token consumer modified a record most recently.Comments?
... View more
Status:
Under Review
Submitted on
09-01-2016
01:50 PM
Submitted by
ToddOliver
on
09-01-2016
01:50 PM
Currently, there is no method via the API to validate and reconcile ACH payments from echeck transactions made to our bank account. Payments received into our bank account do not contain any tracking numbers or relation to which batch(s) are included in the payment. Therefore, we cannot finilize the confirmation of payment per person based on teh ACH deposit. According to Authorize.net support, the only way to determine which batches are included in a given payment is to manually review the Funding Calculation immediately prior to the ACH transaction. We find this cumbersome and unrealistic in a production environment. Instead, we propose additions to the API. List ACH deposits: to provide a full listing of ACH deposits to the merchant account with deposited amount by date range List ACH deposit batches: Per ACH deposit, list batches included in the ACH deposit with $ amount per batch Currently, there is a 9 digit number provided in the ACH deposit info from Authorize.net. We assume that number is an ACT payment id. The API should provide a method to query by that number to retrieve included batch id numbers, transaction amounts, and deposit amounts. Without at lease 1 & 2 above, there is no API (a.k.a. automated) method to validate receipt of funds per batch and transaction which leaves the merchant exposed to missing failed deposits or other ACH issues.
... 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