1

I am creating an ARB Subscription in Authorize.net using the customer profile. This is my flow :

  1. creating a customer and payment profile.
  2. create the first-month payment through auth capture.
  3. creating an ARB subscription using this customer profile.

Here 1 & 2 completes successfully but the 3rd step shows the error: E00040, The record cannot be found. This error occurs only when I am creating the subscription just after creating a new profile. If I use this same customer profile to create the ARB subscription after some time, it works fine. It will be very useful if anyone could help me out in this scenario. Thanks in Advance.

 const profile = await subscriptionHelper.createPaymentProfile(userData, body.CreditCardPayment, body.shippingAddress)

  if (profile.error) {
    const error = helper.createErrorResponse({
      status: 403,
      error: 'Supplier Authorize profile error',
      message: profile.error,
    });
    return res.send(error)
  }

  //charging the current customer profile

  subscriptionHelper.chargePaymentProfile(
    planDetail.amount,
    profile.authorizenet_profileId,
    profile.authorizenet_paymentProfileId,
    async (err, paymentDetails) => {
      console.log("error==>", err);
      if (err) {
        const error = helper.createErrorResponse({
          status: 403,
          error: 'Transaction Failed',
          message: err,
        });
        return res.send(error)
      }

      //creating subscription
      const subscription_details = {
        interval_length: planDetail.PlanType.dataValues.length,
        interval_unit: planDetail.PlanType.dataValues.name,
        name: planDetail.PlanType.dataValues.detail
      }
      const startDate = moment().add(subscription_details.interval_length, subscription_details.interval_unit).format("YYYY-MM-DD")

      subscription_details.start_date = startDate

      subscriptionHelper.createSubscription(
        profile.authorizenet_profileId,
        profile.authorizenet_paymentProfileId,
        planDetail.amount,
        subscription_details,
        async (err, subscriptionId) => {
          console.log("err===>", err);
          console.log("subscriptionId", subscriptionId);
          if (err) {
            const error =  helper.createErrorResponse({
              status: 403,
              error: 'Subscription Failed',
              message: err,
            });
            return res.send(error)
          }
         
          return res.send(helper.createSuccessResponse({subscriptionId}, {
            message: 'subscription created succesfully',
          })) ;
        }
      )
    }
  )
exports.createPaymentProfile = async (user, CreditCardPayment, address) => {
    try {
        const checkProfile = await subscriptionRepo.getAuthorizeProfile({ supplier_id: user.id })
        console.log("checkProfile==>",checkProfile);
        if (!checkProfile) {
            return await authorize.createCustomerProfile(user, CreditCardPayment, address).then(async res => {
                try {
                    let paymentProfileId = JSON.parse(res.authorizeCustomerPaymentProfileIdList.numericString[0])

                    let newProfile = await subscriptionRepo.createAuthorizenetProfile({
                        supplier_id: user.id,
                        authorizenet_profileId: res.authorizeCustomerProfileID,
                        authorizenet_paymentProfileId: paymentProfileId,
                        name_on_card: CreditCardPayment.NameOnCard,
                        last4: CreditCardPayment.CardNumber.substr(CreditCardPayment.CardNumber.length - 4),
                        expiry: `${CreditCardPayment.ExpiryMonth}${CreditCardPayment.ExpiryYear}`
                    })
                    return newProfile
                } catch (e) {
                    console.log("error==>", e.message)
                    return { error: e.message }
                }
            }).catch(err => {
                console.log("error==>", err.message)
                return { error: err.message }
            })
        } else {
            const AuthorizenetProfileData = await subscriptionRepo.getAuthorizeProfile({
                supplier_id: user.id,
                last4: CreditCardPayment.CardNumber.substr(CreditCardPayment.CardNumber.length - 4),
                expiry: `${CreditCardPayment.ExpiryMonth}${CreditCardPayment.ExpiryYear}`
            });

            if (!AuthorizenetProfileData) {
                return await authorize.createCustomerPaymentProfile(
                    checkProfile.authorizenet_profileId,
                    user,
                    CreditCardPayment,
                    address
                ).then(async res => {
                    try {
                        if (res.code == "I00001") {//success code
                            let newProfile = await subscriptionRepo.createAuthorizenetProfile({
                                supplier_id: user.id,
                                authorizenet_profileId: res.customerProfileID,
                                authorizenet_paymentProfileId: res.customerPaymentProfileID,
                                name_on_card: CreditCardPayment.NameOnCard,
                                last4: CreditCardPayment.CardNumber.substr(CreditCardPayment.CardNumber.length - 4),
                                expiry: `${CreditCardPayment.ExpiryMonth}${CreditCardPayment.ExpiryYear}`
                            })

                            return newProfile
                        } else if (res.code == "E00039") {
                            console.log("Card already exists for this profile")
                            return { error: res.error }
                        } else {
                            console.log("invalid card", res.error)
                            return { error: res.error }
                        }

                    } catch (e) {
                        console.log("error==>", e.message)
                        return { error: e.message }
                    }
                }).catch(err => {
                    console.log("error==>", err.message)
                    return { error: err.message }
                })
            } else {
                return AuthorizenetProfileData
            }
        }

    } catch (e) {
        console.log(e);
        return { error: e }
    }
}

exports.chargePaymentProfile = (amount, customerProfileId, customerPaymentProfileId, cb) => {
    authorize.chargeCustomerProfile(
        customerProfileId,
        customerPaymentProfileId,
        amount,
        (error, code, transactionData) =>{
            try{
                if (code == "I00001") { //success code
                    return cb(null,transactionData)

                } else {
                    return cb(error,null)
                }
            }catch(e){
                console.log("err==>",e);
                return callback(e,null)
            }
        }
    )
}
const createCustomerProfile = (user, CreditCardPayment, address) => {
  return new Promise((resolve, reject) => {
    const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
    merchantAuthenticationType.setName(settings.authorizenet.apiLoginId);
    merchantAuthenticationType.setTransactionKey(settings.authorizenet.transactionKey);

    const isCardValid = helper.validateCard(CreditCardPayment.CardNumber, CreditCardPayment.ExpiryMonth, CreditCardPayment.ExpiryYear)
    if (!isCardValid) {
      reject({ message: 'Invalid Card' })
    }
    const creditCard = new ApiContracts.CreditCardType();
    creditCard.setCardNumber(CreditCardPayment.CardNumber);
    creditCard.setExpirationDate(`${CreditCardPayment.ExpiryMonth}${CreditCardPayment.ExpiryYear.substring(2)}`);

    const paymentType = new ApiContracts.PaymentType();
    paymentType.setCreditCard(creditCard);

    const customerAddress = new ApiContracts.CustomerAddressType();
    customerAddress.setFirstName(address.firstname);
    customerAddress.setLastName(address.lastname);
    customerAddress.setAddress(address.line1);
    customerAddress.setCity(address.city);
    customerAddress.setState(address.state);
    customerAddress.setZip(address.pincode);
    customerAddress.setCountry(address.country);
    customerAddress.setPhoneNumber(address.phone);

    const customerPaymentProfileType = new ApiContracts.CustomerPaymentProfileType();
    customerPaymentProfileType.setCustomerType(
      ApiContracts.CustomerTypeEnum.INDIVIDUAL,
    );
    customerPaymentProfileType.setPayment(paymentType);
    customerPaymentProfileType.setBillTo(customerAddress);

    const paymentProfilesList = [];
    paymentProfilesList.push(customerPaymentProfileType);

    const customerProfileType = new ApiContracts.CustomerProfileType();
    customerProfileType.setDescription('Profile description here');
    customerProfileType.setEmail(user.email);
    customerProfileType.setPaymentProfiles(paymentProfilesList);

    const createRequest = new ApiContracts.CreateCustomerProfileRequest();
    createRequest.setProfile(customerProfileType);
    createRequest.setValidationMode(ApiContracts.ValidationModeEnum.TESTMODE);
    createRequest.setMerchantAuthentication(merchantAuthenticationType);

    const ctrl = new ApiControllers.CreateCustomerProfileController(
      createRequest.getJSON(),
    );

    ctrl.execute(function () {
      const apiResponse = ctrl.getResponse();

      const response = new ApiContracts.CreateCustomerProfileResponse(
        apiResponse,
      );

      if (response != null) {
        if (response.getMessages().getResultCode() === ApiContracts.MessageTypeEnum.OK) {
          resolve({
            authorizeCustomerProfileID: response.getCustomerProfileId(),
            authorizeCustomerPaymentProfileIdList: response.getCustomerPaymentProfileIdList()
          });
        } else {
          reject({
            message: `${response
              .getMessages()
              .getMessage()[0]
              .getText()}`
          })
        }
      } else {
        reject({ message: 'Null response received' })
      }
    })

  })
}

const createCustomerPaymentProfile = (authorizeCustomerProfileID, user, creditCardDetails, address) => {
  return new Promise((resolve, reject) => {
    const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
    merchantAuthenticationType.setName(settings.authorizenet.apiLoginId);
    merchantAuthenticationType.setTransactionKey(settings.authorizenet.transactionKey);

    const isCardValid = helper.validateCard(creditCardDetails.CardNumber, creditCardDetails.ExpiryMonth, creditCardDetails.ExpiryYear)
    if (!isCardValid) {
      reject({ message: 'Invalid Card' })
    }
    const creditCard = new ApiContracts.CreditCardType();
    creditCard.setCardNumber(creditCardDetails.CardNumber);
    creditCard.setExpirationDate(`${creditCardDetails.ExpiryMonth}${creditCardDetails.ExpiryYear.substring(2)}`);

    const paymentType = new ApiContracts.PaymentType();
    paymentType.setCreditCard(creditCard);

    const customerAddress = new ApiContracts.CustomerAddressType();
    customerAddress.setFirstName(address.firstname);
    customerAddress.setLastName(address.lastname);
    customerAddress.setAddress(address.line1);
    customerAddress.setCity(address.city);
    customerAddress.setState(address.state);
    customerAddress.setZip(address.pincode);
    customerAddress.setCountry(address.country);
    customerAddress.setPhoneNumber(address.phone);

    const profile = new ApiContracts.CustomerPaymentProfileType();
    profile.setBillTo(customerAddress);
    profile.setPayment(paymentType);

    const createRequest = new ApiContracts.CreateCustomerPaymentProfileRequest();

    createRequest.setMerchantAuthentication(merchantAuthenticationType);
    createRequest.setCustomerProfileId(authorizeCustomerProfileID);
    createRequest.setPaymentProfile(profile);
    const ctrl = new ApiControllers.CreateCustomerPaymentProfileController(
      createRequest.getJSON(),
    );

    ctrl.execute(function () {

      const apiResponse = ctrl.getResponse();

      const response = new ApiContracts.CreateCustomerPaymentProfileResponse(
        apiResponse,
      );

      if (response != null) {
        if (response.getMessages().getResultCode() === ApiContracts.MessageTypeEnum.OK) {
          resolve({
            code: response
              .getMessages()
              .getMessage()[0]
              .getCode(),
            customerPaymentProfileID: response.getCustomerPaymentProfileId(),
            customerProfileID: response.getCustomerProfileId(),
          });
        } else {
          reject({
            message: `${response
              .getMessages()
              .getMessage()[0]
              .getText()}`,
            code: response
              .getMessages()
              .getMessage()[0]
              .getCode(),
          })
        }
      } else {
        reject({ message: 'Null response received' })
      }
    })
  })
}

const chargeCustomerProfile = (
  customerProfileId,
  customerPaymentProfileId,
  amount,
  cb
) => {
  const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
  merchantAuthenticationType.setName(settings.authorizenet.apiLoginId);
  merchantAuthenticationType.setTransactionKey(settings.authorizenet.transactionKey);

  const profileToCharge = new ApiContracts.CustomerProfilePaymentType();
  profileToCharge.setCustomerProfileId(customerProfileId);

  const paymentProfile = new ApiContracts.PaymentProfile();
  paymentProfile.setPaymentProfileId(customerPaymentProfileId);
  profileToCharge.setPaymentProfile(paymentProfile);
  const transactionRequestType = new ApiContracts.TransactionRequestType();
  transactionRequestType.setTransactionType(
    ApiContracts.TransactionTypeEnum.AUTHCAPTURETRANSACTION,
  );
  transactionRequestType.setProfile(profileToCharge);
  transactionRequestType.setAmount(amount);

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

  const ctrl = new ApiControllers.CreateTransactionController(
    createRequest.getJSON(),
  );

  ctrl.execute(function () {
    const apiResponse = ctrl.getResponse();
    const response = new ApiContracts.CreateTransactionResponse(apiResponse);

    if (response != null) {
      if (response.getMessages().getResultCode() == ApiContracts.MessageTypeEnum.OK) {
        if (response.getTransactionResponse().getMessages() != null) {
          return cb(
            undefined,
            response.getMessages().getMessage()[0].getCode(),
            {
              transactionResp: response.getTransactionResponse(),
              customerProfileId: response.getTransactionResponse().getProfile()
                .customerProfileId,
              customerPaymentProfileId: response
                .getTransactionResponse()
                .getProfile().customerPaymentProfileId,
              transactionID: response.getTransactionResponse().getTransId(),
              Response_Code: response.getTransactionResponse().getResponseCode(),
              Message_Code: response
                .getTransactionResponse()
                .getMessages()
                .getMessage()[0]
                .getCode(),
              Description: response
                .getTransactionResponse()
                .getMessages()
                .getMessage()[0]
                .getDescription(),
            }
          );
        }
        let error = 'Failed Transaction';

        if (response.getTransactionResponse().getErrors() != null) {
          error = `${response
            .getTransactionResponse()
            .getErrors()
            .getError()[0]
            .getErrorText()}`;
        }
        return cb(error, undefined, undefined);
      }
      let error = 'Failed Transaction';
      if (
        response.getTransactionResponse() != null &&
        response.getTransactionResponse().getErrors() != null
      ) {
        error = ` ${response
          .getTransactionResponse()
          .getErrors()
          .getError()[0]
          .getErrorText()}`;
        return cb(error, undefined, undefined);
      } else {
        return cb(
          ` ${response
            .getMessages()
            .getMessage()[0]
            .getText()}`,
          response.getMessages().getMessage()[0].getCode(),
          undefined,
        );
      }

    } else {
      return cb('Null Response.', undefined, undefined);
    }
  })

}

const createSubscriptionFromCustomerProfile = (
  customerProfileId,
  customerPaymentProfileId,
  amount,
  subscription_details,
  cb
) => {
  const date = new Date()
  const merchantAuthenticationType = new ApiContracts.MerchantAuthenticationType();
  merchantAuthenticationType.setName(settings.authorizenet.apiLoginId);
  merchantAuthenticationType.setTransactionKey(settings.authorizenet.transactionKey);
  const interval = new ApiContracts.PaymentScheduleType.Interval();
  interval.setLength(subscription_details.interval_length);

  if(subscription_details.interval_unit == "months"){
        interval.setUnit(ApiContracts.ARBSubscriptionUnitEnum.MONTHS);
    }
    if(subscription_details.interval_unit == "days"){
        interval.setUnit(ApiContracts.ARBSubscriptionUnitEnum.DAYS);
    }
  const paymentScheduleType = new ApiContracts.PaymentScheduleType();
    paymentScheduleType.setInterval(interval);
    paymentScheduleType.setStartDate(subscription_details.start_date);
    paymentScheduleType.setTotalOccurrences(9999);

  const customerProfileIdType = new ApiContracts.CustomerProfileIdType();
    customerProfileIdType.setCustomerProfileId(customerProfileId);
    customerProfileIdType.setCustomerPaymentProfileId(customerPaymentProfileId);

  var orderType = new ApiContracts.OrderType();
  orderType.setInvoiceNumber(`${date.getFullYear()}${date.getMonth()+1}${date.getDate()}${date.getHours()}${date.getMinutes()}${date.getSeconds()}${date.getMilliseconds()}`);

  const arbSubscription = new ApiContracts.ARBSubscriptionType();
    arbSubscription.setName(subscription_details.name);
    arbSubscription.setPaymentSchedule(paymentScheduleType);
    arbSubscription.setAmount(amount);
    arbSubscription.setOrder(orderType) // for remove duplication
    arbSubscription.setProfile(customerProfileIdType);

  const createRequest = new ApiContracts.ARBCreateSubscriptionRequest();
    createRequest.setMerchantAuthentication(merchantAuthenticationType);
  createRequest.setSubscription(arbSubscription);
  createRequest.setRefId(`${date.getFullYear()}${date.getMonth()+1}${date.getDate()}${date.getHours()}${date.getMinutes()}${date.getSeconds()}${date.getMilliseconds()}`)

  const ctrl = new ApiControllers.ARBCreateSubscriptionController(
        createRequest.getJSON(),
    );

  ctrl.execute(function() {
    const apiResponse = ctrl.getResponse();

        const response = new ApiContracts.ARBCreateSubscriptionResponse(
            apiResponse,
        );

    if (response != null) {
            if (response.getMessages().getResultCode() == ApiContracts.MessageTypeEnum.OK) {
                console.log(`Subscription Id : ${response.getSubscriptionId()}`);
                return cb(
                    response.getMessages().getMessage()[0].getText(), 
                    response.getMessages().getMessage()[0].getCode(),
                    response.getSubscriptionId()
                );
            }
            return cb(
                response.getMessages().getMessage()[0].getText(),
                response.getMessages().getMessage()[0].getCode(),
                undefined
            );
        }
    return cb('Null Response', undefined, undefined);
  })
}
sarath raj
  • 13
  • 4

1 Answers1

1

This seems a replication issue, this may occur if request#1 & request#3 hits two different data centers, prior to full sync. across all data centers.

Possible solutions is to either (1) implement a retry mechanism whenever an E00040 error occurs, or (2) add a short delay between the two requests.

There is a better solution if you're able to rethink your integration flow. ARB is interoperable with CIM, meaning whenever you create an ARB subscription, the system checks if there is no related CIM profile, one will be created, thus, technically speaking you can eliminate request#1 from your flow, if your requirements allow it.

  • Thanks for the reply. I have scheduled a node cron, which will retry the failed subscriptions again. And step#1 will only be done for new users as I am checking whether they have a customer profile with Authorize. – sarath raj May 18 '21 at 08:54
  • We only did request #2 and #3 since we ask CIM profile to be created at the time of the transaction - but we still got the error as well. – TheStoryCoder Jun 29 '23 at 10:16
  • Issue seems to be only in production - couldn't reproduce in sandbox... – TheStoryCoder Jun 29 '23 at 10:17