Epicor Credit Card Processing (EPX) Questions

Does anyone know if EPX the new Epicor Credit Card Processing Gateway stuff if it has integration points API? REST? anything like that?
We want to be able to integrate it with our website for credit card processing as well as Epicor ERP Proper

1 Like

Curious, have you done this yet? We just went live with Epicor on-premise, EPX and use Authorize.net for our website sales. The idea is that auth.net will interface with EPX and our webstore orders go over REST API and store credit card info in the credit card order entry screen on the sales order. Looking for validation on our setup but am not finding anyone else who’s integrated their website with EPX.

Hi Melissa,

I’m pretty sure that EPX uses their own gateway and not Auth.net. Meaning the EPX gateway would need to be connected to your webstore in order for the CC token to be generated and passed into Epicor. Hope this helps.

Matt

EPX issued us 2 EPX MIDs. One that’s configured within Epicor and one with an association to Auth.net for our Website transactions. We had to call Auth.net for them to connect the new MIDs to EPX. We were told by the EPX sales guy 2 MIDs were necessary if we wanted to process payments for sales on our website and run the pre-authorization through Auth.net. The implementation of EPX has been a mess. They basically helped us configure it on our server then we were on our own to figure out the rest…

I believe what we were / are going to use is a MID through Payeezy not sure if that’s the same as Auth.net or not but that’s what they offered us.

1 Like

She probably meant https://www.authorize.net/ which actually has been around forever doing payments. They may be a reliable partner.

That’s correct. authorize.net

In order for the credit card to come from your website and be useable in epicor the same gateway must be used on both sides. For example if you want someone to check out on your website and “preauth” the credit card and then later capture that credit card authorization inside of epicor you will need to have the payment gateway be the same on both sides meaning you can not have Authorize.net be the gateway on the webstore and payeazy be the gateway in epicor. You will also need some kind of a bridge that maps the CC token from your ecomm store into the appropriate customer record in epicor so it can be used approproately. Also you shouldn’t need to have multiple merchant accounts unless you are selling different products on your website than you are in normal business.

1 Like

That’s super helpful info. There’s no way this will work with the 2 merchant accounts. Our old website to ERP integration passed over the Authorize.net transaction ID/approval code in the sales order to the ERP system which used the same Authorize.net merchant account when the card was ready to be charged at shipping. Epicor EPX doesn’t have a WordPress plugin to my knowledge so I don’t know how we would run the preauthorization without Authorize.net

Best option would be for EPX to integrate Payeasy to your wordpress site but it will require development if they dont have one out of the box which it sounds like they do not. Another option would be to just run straight sales on the website instead of doing the Pre-auth and capture later option. That may be difficult though if you dont know things like shipping costs or lead times on delivery.

1 Like

There isn’t an API per se, but you can invoke the credit card entry window from a web page with a little bit of JS. I have reverse-engineered how Epicor Web Access did it here:

With the script above you build a CCResponse containing the card token, send it back to the server, and save it to your credit card order, invoice, or cash deposit, something like this:

if (ccInfo != null)
{
    tsOrder = boSO.GetByID(orderNum);
    orderHed = tsOrder.OrderHed.FirstOrDefault();
    if (orderHed != null)
    {
        orderHed.CreditCardOrder = true;
        orderHed.CardMemberName = ccInfo.CardMemberName;
        orderHed.CardmemberReference = ccInfo.CardmemberReference;
        orderHed.ExpirationMonth = ccInfo.ExpirationMonth;
        orderHed.ExpirationYear = ccInfo.ExpirationYear + 2000;
        orderHed.CCStreetAddr = ccInfo.CCStreetAddr;
        orderHed.CCZip = ccInfo.CCZip;
        orderHed.CCCity = ccInfo.CCCity;
        orderHed.CCState = ccInfo.CCState;
        orderHed.CCResponse = ccInfo.CCResponse;
        orderHed.RowMod = "U";

        boSO.ProcessPayGateMessage(ref tsOrder);

        boSO.MasterUpdate(false, true, "OrderHed", orderHed.CustNum, orderHed.OrderNum, false, ref tsOrder, out _, out _, out _, out _, out _, out _);
    }
}

Once you have a way of saving a credit card token to your order, invoice, or cash deposit, you use the respective Epicor BOs through REST to run authorizations or deposits. I have had this working in a production web app for a little over a year without issue.

They key irritant is that Epicor doesn’t have a special place to save credit card information, it’s saved directly into the CreditTran trable, with links to OrderHed, InvcHead, or CashHead tables, so basically if you want to “remember” credit card info in your app, you have to get the last sales order, invoice, or cash deposit that is a credit card transaction that succeeded for your customer, and load the token and other card info from there. This is how I do it:

public CreditCardInfo GetCreditCardInfo(int custNum)
{
    CreditCardInfo retVal = null;

    try
    {
        using (var Db = new Models.EpicorDataContext(_epicorConnStr))
        {
            var company = _company;
            var ccProc = Db.CreditCardProcs.FirstOrDefault(ccp => ccp.Company == company);
            var customer = Db.Customers.FirstOrDefault(c => c.Company == company
                                                            && c.CustNum == custNum);

            if (ccProc != null && customer != null)
            {
                var part1 = Db.OrderHeds.Where(oh => oh.Company == company
                                                    && oh.CustNum == custNum
                                                    && oh.CreditCardOrder)
                                        .Join(Db.CreditTrans,
                                                oh => new { oh.Company, oh.CustNum, oh.OrderNum, k1 = true, k2 = true },
                                                ct => new { ct.Company, ct.CustNum, ct.OrderNum, k1 = ct.CardType.StartsWith("ERP"), k2 = (ct.Result == "0") },
                                                (oh, ct) => new CreditCardInfo()
                                                {
                                                    TranNum = ct.TranNum,
                                                    CardNumber = ct.CardNumber,
                                                    CardType = ct.CardType,
                                                    CardMemberName = ct.CardMemberName,
                                                    ExpirationMonth = ct.ExpMonth,
                                                    ExpirationYear = ct.ExpYear,
                                                    CCToken = ct.CardStore,
                                                    CardmemberReference = ct.CardmemberReference,
                                                    CCZip = customer.Zip,
                                                    CCStreetAddr = customer.Address1,
                                                    CCCity = customer.City,
                                                    CCState = customer.State,
                                                    IsTraining = ccProc.IsTraining,
                                                    CreditCardOrder = customer.CreditCardOrder
                                                });

                var part2 = Db.InvcHeads.Where(ih => ih.Company == company
                                                    && ih.CustNum == custNum)
                                        .Join(Db.CreditTrans,
                                                ih => new { ih.Company, ih.CustNum, ih.InvoiceNum, k1 = true, k2 = true },
                                                ct => new { ct.Company, ct.CustNum, ct.InvoiceNum, k1 = ct.CardType.StartsWith("ERP"), k2 = (ct.Result == "0") },
                                                (ih, ct) => new CreditCardInfo()
                                                {
                                                    TranNum = ct.TranNum,
                                                    CardNumber = ct.CardNumber,
                                                    CardType = ct.CardType,
                                                    CardMemberName = ct.CardMemberName,
                                                    ExpirationMonth = ct.ExpMonth,
                                                    ExpirationYear = ct.ExpYear,
                                                    CCToken = ct.CardStore,
                                                    CardmemberReference = ct.CardmemberReference,
                                                    CCZip = customer.Zip,
                                                    CCStreetAddr = customer.Address1,
                                                    CCCity = customer.City,
                                                    CCState = customer.State,
                                                    IsTraining = ccProc.IsTraining,
                                                    CreditCardOrder = customer.CreditCardOrder
                                                });

                var part3 = Db.CashHeads.Where(ch => ch.Company == company
                                                    && ch.CustNum == custNum
                                                    && ch.CreditCard)
                                        .Join(Db.CreditTrans,
                                                ch => new { ch.Company, ch.CustNum, ch.HeadNum, k1 = true, k2 = true },
                                                ct => new { ct.Company, ct.CustNum, ct.HeadNum, k1 = ct.CardType.StartsWith("ERP"), k2 = (ct.Result == "0") },
                                                (ch, ct) => new CreditCardInfo()
                                                {
                                                    TranNum = ct.TranNum,
                                                    CardNumber = ct.CardNumber,
                                                    CardType = ct.CardType,
                                                    CardMemberName = ct.CardMemberName,
                                                    ExpirationMonth = ct.ExpMonth,
                                                    ExpirationYear = ct.ExpYear,
                                                    CCToken = ct.CardStore,
                                                    CardmemberReference = ct.CardmemberReference,
                                                    CCZip = customer.Zip,
                                                    CCStreetAddr = customer.Address1,
                                                    CCCity = customer.City,
                                                    CCState = customer.State,
                                                    IsTraining = ccProc.IsTraining,
                                                    CreditCardOrder = customer.CreditCardOrder
                                                });

                retVal = part1.Union(part2).Union(part3).OrderByDescending(ct => ct.TranNum).FirstOrDefault();

                if (retVal == null)
                {
                    retVal = new CreditCardInfo()
                    {
                        CardNumber = "",
                        CardType = "",
                        CardMemberName = "",
                        CCResponse = "",
                        CCToken = "",
                        CardmemberReference = "",
                        CCZip = customer.Zip,
                        CCStreetAddr = customer.Address1,
                        CCCity = customer.City,
                        CCState = customer.State,
                        IsTraining = ccProc.IsTraining,
                        CreditCardOrder = customer.CreditCardOrder
                    };
                }

            }


        }
    }
    catch { }

    return retVal;
}
2 Likes

Thanks Hugo!

1 Like

Hi Melissa,

Were you ever able to figure out a way to process payments with your website? I’m in a similar situation as you were a year ago, any tips?

Thanks in advance!

We implemented eBizCharge to resolve the integration issues. I highly recommend using them if you need to integrate an ecommerce site to Epicor.

2 Likes

Thanks for the response!

Do you transact in CAD or only USD?

EBizCharge works in both USD and CAD

@MRog but can you use your own gateway as mentioned in this article of authorize.net and not use the eBizCharge gateway? That is the solution I believe was trying to be resolved.

In order for proper integration to be had between ecomm and ERP the payment gateway must be the same on both sides, so for EBizCharge to work properly between both systems and have the CC token transfer from one platform to another and be usable the EBiz gateway has to be used on both sides. This is the route that Melissa went with us to accomplish her goal. You can use auth.net with whomever you want but it just will break the integration cycle for cc processing. Am I answering your question?