cancel
Showing results for 
Search instead for 
Did you mean: 

Create ARB Subscription via Opaque Data (from Accept.js)

So our application is a website that is built on ASP.NET.


The front end is JavaScript and the back end is C#.

 

We are using Accept.js on the front end to create two nonce tokens (1 for the ARB sub, 1 for the 1 time transaction).  I realize this might not be the best way to do this with two separate transactions but it is what we have for now.  This was actually working yesterday until after around 5pm.  Then we started getting the E00114 Invalid OTS Token error message every time we tried to create the ARB sub.  The 1 time transaction would work just fine.

 

So we tried flipping the nonce values in case the one we were trying to use for the ARB sub was wrong but even after swapping them to use the other one the 1 time transaction worked but the ARB sub did not.  This validated that the nonce values appear to be working fine.  We talked to Authorize.net support and they informed us that the error message E00114 could also be returned if the data sent to create the ARB sub was not valid even if the token was valid.

 

Can anyone help me diagnose or validate the ARB create transaction we are sending to Authorize.net?  I have read some people reference the ability to capture the XML being sent to Authorize.net via the SDK but since I am using the nuget package (v1.9.1) I'm not sure how to turn this option on.

 

Any help would be greatly appreciated.

pmgower
Member
27 REPLIES 27

Hi @pmgower,

 

Logging in the .NET SDK is done using the Microsoft's ETW system. More details in my reply on the other thread.

 

As far as troubleshooting the ARB request, hopefully you can get a log of exactly what's sent and we can see if there's a problem there. In the meantime, there's a couple of things to check.

  • Make absolutely sure that the same login ID is being used to make the ARB request as to get the nonce
  • Make sure that both places are going to the same environment (whether production or sandbox).
  • If you're seeing failures in production, what happens when you switch both the nonce generation and the ARB request to sandbox?

If you can get a log of the request, please post that here. In the meantime, if you want to post the section of your code that's doing the ARB request, maybe there's something to see there.

Aaron
All Star

Hello Aaron,

 

We are experiencing the same problem. Just started yesterday. We are using the Java SDK.

 

When we make our first charge, we set the duplicate window timeout to 0 seconds. The interesting thing is, we get the Invalid Token error when we execute our code in real time. However, if we step through the code in a debugger, enough time elapses between our 1 time charge and the ARB subscription set up that does not fail.

 

Again, this worked fine until yesterday. Also, it still works in the sandbox, but does not in production. We had been setting up subscriptions like this succesfully for several weeks now,  I think there is a problem on your end.

 

Thanks,

 

Tim Stevens, University of Minnesota Foundation.

Hi @steve074,

 

Ah, so the timing of the request is key for you. @pmgower, can you tell if yours is time-related? Like, can you induce a delay between retrieving the nonce and doing the ARB request?

 

If there's no one here currently investigating this internally, I'll make sure someone's on it.

Yes, it seems to be possibly ignoring the duplicate window time out. I opened support ticket 1-406091561, you can link back to that one if you want.

 

Thanks,

 

Tim

Hi Tim,

 

My hunch is that it's not related to the duplicate window, because if it wasn't respecting that timeout, you'd get a different error. However, there could be other checks employed that could prevent some sort of quick use, or other problems as well.

 

I'll try to escalate that ticket internally so they're not just asking the same things.

Thanks, we appreciate quick action on this as it is causing trouble for our donors.

 

One other observation that may help is that when we run in real time, we are often gettting the same nonce value on our second nonce call. Not always, and that doesn't seem to be related to the error, as it fails either way.

 

Tim

Thanks for the quick response @Aaron.  As of yesterday I couldn't even get the create ARB subscription to work.  However, this morning I tried it all from my local machine and it all works if I run it through the debugger to capture the trace/log information.  The moment I run it outside of the Visual Studio debugger it doesn't work and returns the same E00114 error message.  


I tried adding a 1 and then 5 second delay between when the front end sends the request to the backend to create the ARB subscription.  I suppose I could try to add a delay between getting the two differente nonce values on the frontend but I haven't done that yet because the create ARB subscription is the first one that is using a nonce so IF they are the same create ARB subscription should work.

 

I am now going to work on writing the necessary code to log the trace values.  Very discouraged at the fact that I can't easily turn on logging in your SDK and that I have to do it manually.

 

I will let you know once I get the XML from the trace information; however, when running it inside VS's debugger I didn't see where the request XML was being logged in the trace information.  Any guidenance into how I can get the request XML would be greatly appreciated.

 

Here is the code I use to send create the ARB Subscription:

 

const short AUTHORIZE_NET_NO_END_DATE_TOTAL_OCCURRANCES = 9999;

bool worked = false;
transactionResponse = null;

var monthlyInterval = new paymentScheduleTypeInterval()
{
    length = 1,
    unit = ARBSubscriptionUnitEnum.months
};
var monthlySchedule = new paymentScheduleType()
{
    interval = monthlyInterval,
    startDate = DateTime.Now.AddDays(1),
    totalOccurrences = AUTHORIZE_NET_NO_END_DATE_TOTAL_OCCURRANCES,
    trialOccurrences = 0
};
var paymentType = new paymentType() { Item = model.NonceToOpaque(model.SubscriptionNonce) };

string subscriptionName = $"ProxBox Subscription for {model.FullName}";
ARBSubscriptionType subscriptionType = new ARBSubscriptionType()
{
    amountSpecified = true,
    name = subscriptionName,
    amount = model.MonthlySubscriptionSubtotal,
    paymentSchedule = monthlySchedule,
    billTo = model.nameAndAddressType,
    shipTo = model.nameAndAddressType,
    payment = paymentType,
    trialAmountSpecified = false,
};

var request = new ARBCreateSubscriptionRequest { subscription = subscriptionType };
var controller = new ARBCreateSubscriptionController(request);
controller.Execute();

//get the response which will contain errors (if any)
var response = controller.GetApiResponse();

//validate respose
if (response != null)
{
    if (response.messages.resultCode == messageTypeEnum.Ok)
    {
        if (response.messages.message != null)
        {
            worked = true;
            transactionResponse = response.ToTransactionResponseModel();
        }
        else
        {
            var errorMessage = $"Subscription Error (Subscriber: {model.FullName} - {model.EmailAddress}): No message was set (refId: {response.refId})";
            logger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, errorMessage, exception: null);
        }
    }
    else
    {
        var errorMessage = $"Subscription Error (Subscriber: {model.FullName} - {model.EmailAddress}): {response.messages.message[0].code} {response.messages.message[0].text}";
        logger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, errorMessage, exception: null);
    }
}
else
{
    var results = string.Join(", ", controller.GetResults().ToArray());
    var errorMessage = $"Subscription Error (Subscriber: {model.FullName} - {model.EmailAddress}): Reponse was null, ResultCode: {controller.GetResultCode()}, Result Messages: {results}";
    logger.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, errorMessage, exception: null);
}

return worked;

Actually, @Aaron, after further review.  If I add a System.Threading.Thread.Sleep(5000) call before I try to create the request and send it to Authorize.net it in fact does allow it to succeed on my local machine. I will be testing this on the STAGE server very soon.

 

So back to your initial theory (which would explain how it stopped working with no code changes) is there seems to be a timing issue.  Did your team enable any extra checks or something that would require a delay between getting the Accept.js nonce values and using them in an api call this week?

 

Also should we be concerned about doing two nonce requests to accept.js one after the other in the front end?

 

 


@pmgower wrote:

Did your team enable any extra checks or something that would require a delay between getting the Accept.js nonce values and using them in an api call this week?  


I'm not aware of anything, but that's what we're trying to find out. We (Authorize.Net) haven't made any changes, but the bits that create the nonce are part of a larger Visa effort, so we can't rule out the possibility of a change being made somewhere outside of Authorize.Net that's inadvertantly affecting us.

 

It's complicated by the fact that the only reports of problems so far have been ARB related, which may be relevant or may be coincidental. We haven't seen any problems with just grabbing a nonce and immediately turning it around and doing a one-time charge, for example.

 


@pmgower wrote:

 

Also should we be concerned about doing two nonce requests to accept.js one after the other in the front end?


I don't know. It doesn't seem like there should be any problems, yet you're seeing some. Is that because of the nature of your setup where you're doing two nonce requests? Or could it possibly manifest itself on any nonce creation that's immediately followed by an ARB request using that nonce?

 

@steve074 reported that two quick nonce requests in a row can sometimes return the same nonce. In that scenario, I would expect that the second request would fail since the nonce has already been used.

 

So, there's no documented reason why you should expect the two nonce workflow to fail. However, given your current problems and the possibility of getting a duplicated nonce, I personally would want to steer clear of doing things that way.

 

The easiest smoothest way to do this would be this way:

 

1. Get a nonce

 

2. Send that nonce in to charge the card, with a flag set on the transaction to create a customer profile out of that transaction. There's not a great example of this in the API reference, but here's essentially what it would look like in the raw XML:

<?xml version="1.0" encoding="utf-8"?>
<createTransactionRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
  <merchantAuthentication>
    <name>login_id</name>
    <transactionKey>trans_key</transactionKey>
  </merchantAuthentication>
  <refId>123456</refId>
  <transactionRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="AnetApi/xml/v1/schema/AnetApiSchema.xsd">
    <transactionType>authCaptureTransaction</transactionType>
    <amount>18.95</amount>
    <payment>
      <opaqueData>
        <dataDescriptor>COMMON.ACCEPT.INAPP.PAYMENT</dataDescriptor>
        <dataValue>eyJjb2RlIjoiNTBfMl8wNjAwMDUyRDg0N0NGOUQxQUEyNkZGRTJBQkMyM0VEQkE3OTRFRjk3QUYwMTU1OERFNEQ0M0JFQkY5QzJGMjZDQzc2RjQyRUI2NDk3QTc4QURENjFGOUI2MThERTI5RjQ5MTMxMEM1IiwidG9rZW4iOiI5NDkwMjEzNTE2MTQzOTY2OTA0NjAzIiwidiI6IjEuMSJ9</dataValue>
      </opaqueData>
    </payment>
    <profile>
      <createProfile>true</createProfile>
    </profile>
    <customer>
      <id>99999456654</id>
      <email>customer@example.com</email>
    </customer>
  </transactionRequest>
</createTransactionRequest>

Basically, the same as a regular charge with a nonce, just adding the createProfile=true, and adding either a customer id or an email to act as a key in the profile creation.

 

3. Send the profile ID and payment profile ID returned in step 2 in a request to create a subscription.