Have your own great idea for a new API feature?

or maybe a suggested improvement to an existing one? Share it and become a god of the developer world.

New Idea
0 Votes

Email a simple checkout link

Status: Delivered
by on ‎10-24-2017 05:41 AM

A way to email a simple checkout link would be great.  I give custom quotes and it is very difficult to create a simple checkout button, then create a new page on my website then email the link to my customer, have the customer browse to my website, click the checkout  button and enter their information. 

 

It would be much easier if I could email them the simple checkout link, then have them click the link from directly in their email and checkout.

Status: Delivered

Hello @tammycline @jdubs

 

We now support sending Invoices from within the Merchant Interface and your customers can pay on their mobile phones or desktops.  It's also available in the Sandbox to try. 

0 Votes

I suggest its good if we can send parameters and enable/disable payment options (credit card/bank account) in "Get an Accept Payment Page" API request. Adding to that it would be nice if we can control credit card types (VISA/MASTER/AMEX/etc.) as well.  Then user can only pay using allowed credit card type if it is a credit card payment.

Status: Delivered

Hi @Sandun

 

While we haven't yet updated the Accept Hosted documentation to reflect this, we've just barely updated Accept Hosted to support exactly what you're describing.

 

In the hostedPaymentPaymentOptions setting, you now can pass two additional Boolean parameters. showBankAccount and showCreditCard can be sent to direct which payment types to make available on the form. The default parameters for both if they are not sent is "true".

 

The documentation should be updated to reflect this within the next couple of weeks.

0 Votes

For Accept Hosted, when specifying hostedPaymentReturnOptions, there needs to be a way we can construct the url for the GET that includes values returned after successful authcapture in the receipt page.

 

When specifying name value pairs, we should be allowed to refer to DOM element values as variables and then substituted to construct the URL (and urlencoded) for the Continue button since the elements are present in that same receipt page as the button.

 

A suggested syntax is as follows:

"settingValue": "{\"url\":\"https://www.mysite.com/continue?invoiceID=[$receiptInvoiceNumber]&receiptID=[$receiptTransactionId]\......"}"

 

The concept of variables could be generalized for use in other name value pairs as needed.

 

Thanks for considering.

 

Jayaram

0 Votes

Add webhook from profile.js to the hosting web page when saving an added/edited payment profile. Notifying the hosting web page of saving an added / edited payment profile would allow emailing our company when a client adds/edits a payment profile.

 

Send communication to hosting web page from profile.js function btnSave_onclick when added/edited payment profile saved.  Currently communications are only sent to hosting web page when saving a single edited payment profile.  I'd like to send communication to hosting web page when adding/editing multiple payment profiles.

 

I'd also like the IFrameCommunicator to pass paymentProfileID to the IFrames containing webpage so we know which credit cards were added or edited.

Rewrote idea to be clearer.

0 Votes

Accept Hosted Form formatting

Status: New
by on ‎09-13-2017 10:16 AM

AN wants us to drop SIM and move to Accept Hosted.  Well, then give us the tools to format the AH form in the same way that we could in SIM.  This should have been obvious when the decision was made to introduce the new method.  Where's the carrot other than the threat of terminating SIM?  This isn't the way to "Win Friends!"

0 Votes

Hello all, 

 

 

Any one knows about getting Transaction details by passing Subscription ids? Is there any apis or anyother way to get transaction information by using subscriptions ids?

 

Please let me know if there is any quick solution for this. i need to develop it in my project.

 

Thanks in advance.

0 Votes

Webhook for a Settled Transaction

Status: New
by on ‎08-26-2017 06:59 AM

Right now there is a webhook for when an authorization is captured, but not for the transaction when it is settled. There is a hook for the refund and void states, so it would be nice to include a settled one as well.

0 Votes

Increase 31 character limit for product names

Status: New
by on ‎08-10-2017 08:33 AM

I see there is a 31 character limit for product names. However, the nature of the product that is being sold makes this very inconvenient. I've noticed that any products with over 31 characters in the name (and possibly short description as well) will trigger the "Line item 1 is invalid" error.

 

Please see this thread.

0 Votes

Provide a way or any best practice to ensure initial session is same as return confirmation from iFrame session. Just calling getTranasctionDetails and matching transaction ID and timestamp does not ensure same session.

0 Votes

Authnet Java SDK doesnt support TLS 1.2. Need to update util classes.

Status: Accepted
by ‎06-13-2017 11:45 AM - edited ‎06-13-2017 11:53 AM

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

Status: Accepted
0 Votes

Hi all,

 

I want to be able when a user requests a service on my system to:

1. authorize only a transaction

2. capture previously authorized amount (from step 1) for a certain date in the future (within 30 days, how long the authorization code is active)

 

I don't think clients should be implementing some sort of scheduler for when a "capture previously authorized transaction" should occure.

 

A use case would be car rental:

Online I book a car and provide my credit card info.

The rental company authorizes my credit card and does the capture on the date when the rental date is set.

 

 

Status: Comments Requested

This is an interesting suggestion.  Did you have a specific timeframe to delay, say 7-15 days?  Do any other developers have a similar need?

0 Votes

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.

 

Status: Under Review
0 Votes

I am sending a createTransactionRequest with <createProfile>true</createProfile>.

 

If there is already a profile associated with the credit card the following error is included in the response:

 

<profileResponse>

<messages>
<resultCode>Error</resultCode>
<message>
<code>E00039</code>
<text>A duplicate record with ID 1812052420 already exists.</text>
</message>

</messages>

</profileResponse>

 

Then I have to send a getCustomerProfileRequest to get the customerPaymentProfileId which is required in order to use the profile in the future.

 

Is it possible to include the default customerPaymentProfileId in the error message so I would not have to send another request to your server?

 

In our system we want to use tokenization but we can't always precreate the profiles.

 

Thank You

 

Lynn Millard, Software Engineer

The Hudson Group

360 Merrimack Street

Lawrence, MA 01843

 

0 Votes

Add a getPaymentProfile method to Accept.js

Status: New
by on ‎04-05-2017 11:59 AM

Hi there,

 

It seems like almost a no-brainer to have a method, using Accept.js, to get a payment profile, so that a self-hosted payment form could be populated without from the client machine, rather than having to go through our server using the API. It seems like all it would need is the customerProfileID and the customerPaymentProfileID to pull that info, just like the existing getCustomerPaymentProfile() method found in the AuthorizeNetCIM class.

0 Votes

extend refund window past 120 days

Status: Under Review
by on ‎01-24-2017 08:22 PM

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.

Status: Under Review
0 Votes

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

Status: Under Review
0 Votes

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.

Status: Accepted
0 Votes

Direct Deposit

Status: Under Review
by on ‎10-10-2016 02:24 PM

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 

Status: Under Review
0 Votes

Many stores need an automatic return to register the conversion for Google eCommerce.  By limiting the SIM method to a manual click by the customer causes a high degree of abandonment at the payment completion stage and therefore, no conversion registered with Google eCommerce.  It does work as it should if authorize.net's domain is excluded in the Google eCommerce settings AND the customer clicks on the authorize.net receipt page button.  HOWEVER, many times, they don't.

This is aggravated by the fact that the receipt page proclaims "Thank you for your order!" in bold text that is hard-coded and cannot be changed by the merchant.  This reinforces the impression to the customer that he is done and exacerbates the abandonment issue.

The Relay Response method DOES NOT WORK correctly when using SIM, and Silent Post URL does not send the information needed to clear the customer's cart in the store. 

 

DPM is out of the question due to issues regarding that approach not actually lessening scope of PCI compliance.  Officers at companies like Trustwave state that it puts the store completely in-scope and is no different than AIM, regardless of claims that by Authorize.net that DPM lessens scope.

There are 2 things that need to be addressed and modified in the SIM receipt page:

1. There should be an option for the post back to the merchant store using SIM be automatic and not wait for user input on a receipt page. (Again Relay Response does NOT work!)

2. The field that states success on the receipt page ("Thank you for your order!") should be editable text by the merchant for situations where the receipt page IS displayed but a different message is desired.

Please consider these two minor modifications to the SIM platform.  They would be a great benefit to many, many merchants, especially those using conversion tracking systems.

Thank you.

Status: Declined

The SIM and DPM are now deprecated in favor of using Accept.js or Accept Hosted.