cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

Card present transactions returning $0 amount in test mode

We are using the AIM SDK with .Net and C# to submit both card present (CP) and card not present (CNP) transactions via the CardPresentGateway class.

 

In test mode, the response always contains amount=$0, even if the transaction was approved.  Using the standard Gateway class, the actual transaction amount is returned.

 

1.  Is this expected behavior for the CP gateway in test mode?

 

2.  Are there currently any plans to make the two gateway classes behave the same?

 

3.  Can we expect that live transactions submitted via the CP gateway will behave correctly, returning the actual transaction amount?

 

Thanks for your help.

 

Bill

wcjensen
Member
7 REPLIES 7

can you post your code?

RaynorC1emen7
Expert

Here's the build-up and submission of the request.  In Execute(), the returned response always contains $0 in the amount field.

        public override TransactionResult ProcessCreditCardTransaction(CreditCardTransactionInfo transactionInfo)
        {
            var cardPresent = (Parameters.ContainsKey("UseCardPresentGateway") && Parameters["UseCardPresentGateway"].ToLower().Trim() == "true");
            
            var request = CreateCCRequest(transactionInfo, cardPresent);
            AddBasicInfo(request, transactionInfo);
            AddCreditCardInfo(request, transactionInfo);
            AddPayingMemberInfo(request, transactionInfo);
            AddMemberInfo(request, transactionInfo);

            var response = Execute(request, cardPresent);

            var result = CaptureResults(request, response);

            return result;
        }

        #region Implementation methods using Authorize.net SDK

        private GatewayRequest CreateCCRequest(CreditCardTransactionInfo transactionInfo, bool cardPresent)
        {
            if (cardPresent)
            {
                if (!string.IsNullOrEmpty(transactionInfo.Track1) || !string.IsNullOrEmpty(transactionInfo.Track2))
                {
                    return new CardPresentAuthorizationRequest(transactionInfo.Amount, transactionInfo.Track1, transactionInfo.Track2);
                }
                else
                {
                    var expirationMonth = transactionInfo.ExpirationDate.Substring(0, 2);
                    var expirationYear = transactionInfo.ExpirationDate.Substring(2, 2);
                    return new CardPresentAuthorizationRequest(transactionInfo.Amount, transactionInfo.CardNumber, expirationMonth, expirationYear);
                }
            }
            else
            {
                return new AuthorizationRequest(transactionInfo.CardNumber, transactionInfo.ExpirationDate, transactionInfo.Amount, string.Empty);
            }
        }

        private GatewayRequest AddBasicInfo(GatewayRequest request, Mass.EFT.Lib.TransactionInfo info)
        {
            string description = FormatDescription(info.MemberNumber, info.PayingMemberFirstName, info.PayingMemberLastName);
            request.Description = description;
            request.AddInvoice(info.InvoiceNumber);
            return request;
        }

        private string FormatDescription(string memberNumber, string payingMemberFirstName, string payingMemberLastName)
        {
            return string.Format("{0} {1} {2} - Tap {3}",
                memberNumber,
                payingMemberFirstName,
                payingMemberLastName,
                DateTime.Now.ToString("yyyy-MM-dd"));
        }

        private GatewayRequest AddCreditCardInfo(GatewayRequest request, CreditCardTransactionInfo info)
        {
            request.CardCode = info.CardCode;
            request.TransId = info.TransactionId;
            request.Type = CreditTransactionTypeConverter.ConvertToXType(info.TransactionType);
            request.AuthCode = info.AuthorizationCode;
            return request;
        }

        private GatewayRequest AddPayingMemberInfo(GatewayRequest request, Mass.EFT.Lib.TransactionInfo transactionInfo)
        {
            string billingAddress = null;
            string billingState = null;
            string billingZip = null;

            if (transactionInfo is CreditCardTransactionInfo)
            {
                CreditCardTransactionInfo info = (CreditCardTransactionInfo)transactionInfo;

                billingAddress = info.PayingMemberBillingAddress + " " + info.PayingMemberBillingCity;
                billingState = info.PayingMemberBillingState;
                billingZip = info.PayingMemberBillingZip;
            }

            request.AddCustomer(transactionInfo.PayingMemberNumber,
                                transactionInfo.PayingMemberFirstName,
                                transactionInfo.PayingMemberLastName,
                                billingAddress,
                                billingState,
                                billingZip);
            return request;
        }

        private GatewayRequest AddMemberInfo(GatewayRequest request, Mass.EFT.Lib.TransactionInfo transactionInfo)
        {
            request.AddShipping(transactionInfo.MemberNumber, transactionInfo.MemberFirstName, transactionInfo.MemberLastName, null, null, null);
            return request;
        }

        private IGatewayResponse Execute(GatewayRequest request, bool cardPresent)
        {
            request.TestRequest = (TestMode == true) ? "TRUE" : "FALSE";
            var gate = (cardPresent) ? new CardPresentGateway(AuthToken, AccessToken, TestMode) : new Gateway(AuthToken, AccessToken, TestMode);

            var response = gate.Send(request);
            return response;
        }

 

Which field are you getting the amount in CaptureResults()?

response.Amount.  I view it in the debugger on return from gate.Send().

 

Here's the CaptureResults() code:

        private TransactionResult CaptureResults(GatewayRequest request, IGatewayResponse response)
        {
            var result = new TransactionResult
            {
                Amount                  = Convert.ToDecimal(response.Amount),
                AuthorizationCode       = response.AuthorizationCode,
                ResponseCode            = Convert.ToInt32(response.ResponseCode),
                Status                  = ResponseCodeConverter.ToTransactionStatus(response.ResponseCode),
                TransactionId           = response.TransactionID,
                Reason                  = response.Message,         // Message supplies Response Reason Text

                PaymentMethod           = (request is EcheckRequest) ? PaymentMethods.ECheck : PaymentMethods.CreditCard,
            };

            var baseResponse = response as GatewayResponse;     // Cast to concrete type
            if (baseResponse != null)
            {
                // Pick up stuff not accessible through interface
                result.TransactionType          = baseResponse.TransactionType;
                result.Description              = baseResponse.Description;
                result.AvsResponse              = baseResponse.AVSResponse;
                result.CardCodeResponse         = baseResponse.CCVResponse;
                result.ReasonCode               = ExtractReasonCode(baseResponse.GetValueByIndex(2));
            };

            var cpResponse = response as CardPresentResponse;
            if (cpResponse != null)
            {
                result.AvsResponse = cpResponse.AVSResponse;
                result.CardCodeResponse = cpResponse.CardCodeResponse;

                // Not present in CardPresentResponse
                
                //result.TransactionType = cpResponse.TransactionType;
                //result.Description = cpResponse.Description;
                //result.ReasonCode = ExtractReasonCode(cpResponse.GetValueByIndex(2));
            }

            return result;
        }

        private int ExtractReasonCode(string stringVal)
        {
            int reasonCode;
            int.TryParse(stringVal, out reasonCode);
            return reasonCode;
        }

 

That the approved amount. I think it only use for split tender(Partial Authorization Transactions).

We do not do partial authorization transactions at this time.

 

Apparently there was a similar problem when partial authorization transactions were first introduced as mentioned several years ago here:

http://community.developer.authorize.net/t5/News-and-Announcements/Amount-field-returning-0-in-test-...

 

That problem seems to have been fixed in the standard NCP gateway.

 

So will a live (non-test-mode) CP transaction also return 0 in the response.Amount field, or would you recommend that we simply ASSUME that the approved amount was equal to the requested amount if the transaction was approved?

If you are not using partial auth. then yes "we simply ASSUME that the approved amount was equal to the requested amount if the transaction was approved?"