Search code examples
node.jspayment-gatewaypaymentauthorize.net

Node.js E00007 Authorize.net error - User authentication failed due to invalid authentication values


I've been stuck with this issue for a while, looks like generating a token getMerchantDetails is working. However, the second function, createAnAcceptPaymentTransaction, when making a payment doesn't work

E00007 User authentication failed due to invalid authentication values.

I've looked at numerous guides but they all are usually in Java or PHP. A lot of the guides point to ctrl.setEnvironment(SDKConstants.endpoint.production); needing to be set.

The payment works when running the Node API locally, but when running it on the production site it just throws error E00007.

I am using https://sandbox.authorize.net/ - do I have to use a production account to test in production? Even though my sandbox account is set to live mode?

Any suggestions welcome

enter image description here

const ApiContracts = require('authorizenet').APIContracts;
const ApiControllers = require('authorizenet').APIControllers;
const SDKConstants = require('authorizenet').Constants;

    async getMerchantDetails() {
        const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
        merchantAuthenticationType.setName(config.authorizeNet.apiLoginKey);
        merchantAuthenticationType.setTransactionKey(config.authorizeNet.transactionKey);

        const getRequest = new ApiContracts.GetMerchantDetailsRequest();
        getRequest.setMerchantAuthentication(merchantAuthenticationType);

        console.log(JSON.stringify(getRequest.getJSON(), null, 2));

        const ctrl = new ApiControllers.GetMerchantDetailsController(getRequest.getJSON());
        ctrl.setEnvironment(SDKConstants.endpoint.production);

        return new Promise(function (resolve, reject) {
            ctrl.execute(async () => {
                const apiResponse = ctrl.getResponse();
                const response = new ApiContracts.GetMerchantDetailsResponse(apiResponse);

                console.log(JSON.stringify(response, null, 2));
           })
       })
   }
    createAnAcceptPaymentTransaction(setDataValue, checkout) {
        const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
        merchantAuthenticationType.setName(config.authorizeNet.apiLoginKey);
        merchantAuthenticationType.setTransactionKey(config.authorizeNet.transactionKey);

        const opaqueData = new ApiContracts.OpaqueDataType();
        opaqueData.setDataDescriptor('COMMON.ACCEPT.INAPP.PAYMENT');
        opaqueData.setDataValue(setDataValue);

        const paymentType = new ApiContracts.PaymentType();
        paymentType.setOpaqueData(opaqueData);

        const orderDetails = new ApiContracts.OrderType();
        orderDetails.setInvoiceNumber(`${checkout?.id?.slice(checkout?.id?.length - 16)}`);
        orderDetails.setDescription('Generated by API');

        const tax = new ApiContracts.ExtendedAmountType();
        tax.setAmount('0');
        tax.setName('Base tax');
        tax.setDescription('Base tax is set to 0');

        const duty = new ApiContracts.ExtendedAmountType();
        duty.setAmount('0');
        duty.setName('Duty');
        duty.setDescription('Duty is set to 0');

        let shipping;
        if (checkout?.meta?.shippingPrice) {
            shipping = new ApiContracts.ExtendedAmountType();
            shipping.setAmount(checkout?.meta?.shippingPrice / 100);
            shipping.setName(checkout?.meta?.shippingName);
            shipping.setDescription(`ShipStation - ${checkout?.meta?.shippingCode}`);
        }

        const billTo = new ApiContracts.CustomerAddressType();

        const name = checkout.billing.fullName.split(' ');
        billTo.setFirstName(name.slice(0, name.length - 1).join(' '));
        billTo.setLastName(name[name.length]);
        // billTo.setCompany()
        billTo.setAddress(`${checkout.shipping.streetOne} ${checkout.shipping.streetTwo}`);
        billTo.setCity(checkout.shipping.city);
        billTo.setState(checkout.shipping.county);
        billTo.setZip(checkout.shipping.postcode);
        billTo.setCountry(checkout.shipping.country);

        const shipTo = new ApiContracts.CustomerAddressType();
        const billName = checkout.shipping.fullName.split(' ');
        shipTo.setFirstName(billName.slice(0, billName.length - 1).join(' '));
        shipTo.setLastName(billName[billName.length]);
        shipTo.setAddress(`${checkout.shipping.streetOne} ${checkout.shipping.streetTwo}`);
        shipTo.setCity(checkout.shipping.city);
        shipTo.setState(checkout.shipping.county);
        shipTo.setZip(checkout.shipping.postcode);
        shipTo.setCountry(checkout.shipping.country);

        const lineItemList = [];

        checkout.products.map(product => {
            const productLine = new ApiContracts.LineItemType();

            productLine.setItemId(product._id);
            productLine.setName(AuthorizeNetClass.cutString(product.data.name));
            productLine.setDescription(AuthorizeNetClass.cutString(product.data.description));
            productLine.setQuantity(product.quantity);
            productLine.setUnitPrice(product.data.price / 100);
            lineItemList.push(productLine);
        });

        const lineItems = new ApiContracts.ArrayOfLineItem();
        lineItems.setLineItem(lineItemList);

        const transactionSetting1 = new ApiContracts.SettingType();
        transactionSetting1.setSettingName('duplicateWindow');
        transactionSetting1.setSettingValue('120');

        const transactionSetting2 = new ApiContracts.SettingType();
        transactionSetting2.setSettingName('recurringBilling');
        transactionSetting2.setSettingValue('false');

        const transactionSettingList = [];
        transactionSettingList.push(transactionSetting1);
        transactionSettingList.push(transactionSetting2);

        const transactionSettings = new ApiContracts.ArrayOfSetting();
        transactionSettings.setSetting(transactionSettingList);

        const transactionRequestType = new ApiContracts.TransactionRequestType();
        transactionRequestType.setTransactionType(
            ApiContracts.TransactionTypeEnum.AUTHCAPTURETRANSACTION
        );
        transactionRequestType.setPayment(paymentType);
        transactionRequestType.setAmount(checkout.meta.total / 100);
        transactionRequestType.setLineItems(lineItems);
        // transactionRequestType.setUserFields(userFields);
        transactionRequestType.setOrder(orderDetails);
        transactionRequestType.setTax(tax);
        transactionRequestType.setDuty(duty);
        if (checkout?.meta?.shippingPrice) {
            transactionRequestType.setShipping(shipping);
        }
        transactionRequestType.setBillTo(billTo);
        transactionRequestType.setShipTo(shipTo);
        transactionRequestType.setTransactionSettings(transactionSettings);

        const createRequest = new ApiContracts.CreateTransactionRequest();
        createRequest.setMerchantAuthentication(merchantAuthenticationType);
        createRequest.setTransactionRequest(transactionRequestType);

        //pretty print request
        console.log(JSON.stringify(createRequest.getJSON(), null, 2));

        const ctrl = new ApiControllers.CreateTransactionController(createRequest.getJSON());
        //Defaults to sandbox
        ctrl.setEnvironment(SDKConstants.endpoint.production);

        return new Promise(function (resolve, reject) {
            ctrl.execute(async () => {
                const apiResponse = ctrl.getResponse();

                const response = new ApiContracts.CreateTransactionResponse(apiResponse);
                console.log(JSON.stringify(response, null, 2));
            })
       })

Solution

  • Your sandbox account and production account are separate and not related in any way. The https://sandbox.authorize.net/ URL is the sandbox environment and you must use your sandbox credentials here. If your code works in the sandbox it won't work in production until you update your credentials to your production credentials and set your code to point to the production URLs.

    You can test in production but you need to make sure you are not in live mode or else you will incur fees for any transactions that require connecting to your merchant account (i.e. payments, voids, refunds). Generally speaking it is simpler to test in the sandbox environment and just update your configuration to use the production environment, with the correct credentials, when you are ready to accept transactions.