Calling an Epicor Function via C# in an external program

I’ve got that somewhere, let me think.

I had to redo it:

namespace RCExample;

using RestSharp;
class Program
{
    static void Main(string[] args)
    {

        var options = new RestClientOptions("https://icanhazip.com")
        {
            RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
            {
                string certHash = "";
                certHash = certificate.GetCertHashString(System.Security.Cryptography.HashAlgorithmName.SHA512);
                Console.WriteLine(certHash);
                return true;
            }
        };            

        var client = new RestClient(options);

        var request = new RestRequest();
        
        request.AddHeader("Accept", "*/*");
        request.Method = Method.Get;
        
        var response = client.Execute(request);

    }
}

Response:
8E7F0961D277F9BC0625FB4CA3F67420B97A257A2F25417BDDF15DC900D176F43FA3C5B8AE9F75FAA1E229DE20CED5F18A81B376DA9A91D2352F42C04FC73956

Kevin, I still can’t get the string to display in the console window. The REST still isn’t working either. What do I need to do to put the hash where it’s needed, or to bypass it if I’m checking it myself? I’m not getting any kind of exception in the call. I did find there is a self-signed certificate in the IIS bindings that doesn’t expire until 2031. What am I doing wrong if I can call the function from the REST V2 help page?

What url are you passing it? Try passing the main url you use to get to kinetic, that
way it won’t need to try to auth.

I’m passing the URL https://usaz1app007p.am.dir.grpleg.com/EpicorERPPilot/api/v2/efx/KEN/PostAPInvoice/PostAPGroup. Same one I’m using in the Swagger call. What would I pass in instead?

Kevin, would you have time sometime today to chat about this by phone or Teams?

Normally I would, but after I finish my coffee, I’m packing up my office and moving 200 yards
away lol.

Pass it this: Let’s see what happens

https://usaz1app007p.am.dir.grpleg.com/EpicorERPPilot/apps/erp/home/

If I use that URL, how will the system know to call the function?

I meant just to get the cert hash.

OK, got it…

Kevin, I just tried the code above in a new project, will not return a certificate hash from the lambda expression. What next? Also wanted to ask if I need to have the certificate from the server installed on my system as well for the call to work…

No, that probably means that cert does not have a sha512 hash.

Go to the page in Chrome. Accept any security popups. Click the lock thingy in the left side of the address bar, should say not secure. Click on Certificate is not valid.

It should list the fingerprints and their types at the bottom.

Then we can check for that in code.

YAY! I’m getting the hash back now, it’s SHA-256. Says it’s SHA-512 in the certificate on the server, though… OK, how do I get the code to make the call properly if I validate the hash myself?

Change the System.Security.Cryptography.HashAlgorithmName to the proper one that applies.

OK, this is my code now:

        private static void CallPostFunction()
        {
            try
            {
                string remoteCertificateHash = "3541208100360DA080792701B6378B578AB6FB102562C54877F51BAF7CDA709A";

                HttpBasicAuthenticator httpBasicAuthenticator = new HttpBasicAuthenticator(Properties.Settings.Default.BatchEntryPerson, Properties.Settings.Default.BatchEntryPass);
                var options = new RestClientOptions(Properties.Settings.Default.AppServerURL)
                {
                    Authenticator = httpBasicAuthenticator
                    ,
                    RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                    {
                        bool success = false;
                        string certHash = "";
                        certHash = certificate.GetCertHashString(System.Security.Cryptography.HashAlgorithmName.SHA256);
                        if (certHash == remoteCertificateHash)
                        {
                            success = true;
                        }
                        return success;
                    }
                };
                //System.Net.ServicePointManager.ServerCertificateValidationCallback = (s, ce, ca, p) => true;
                var client = new RestClient(options);
                var request = new RestRequest();
                request.AddHeader("Accept", "application/json");
                request.AddHeader("X-API-Key", Properties.Settings.Default.APIKey);
                request.Method = Method.Post;
                var requestContentObj = new
                {
                    GroupID = $@"{BatchGroupID}"
                };
                string requestContent = JsonConvert.SerializeObject(requestContentObj);
                request.AddParameter("application/json", requestContent, ParameterType.RequestBody);
                var response = client.Execute(request);

This should work now with the original URI, which is returning the same hash, correct?

The “<language>” stuff around the code doesn’t work.
You need to use

```
code here
```

I fixed it for you.

Looks good at a glance. Give it a go !

Kevin, I STILL can’t get the REST call to work! Below is a screenshot of the Certificate Viewer for the certificate the site is using:

The certificate says the algorithm being used is PKCS #1 SHA-512 With RSA Encryption, but I’m using the SHA-256 hash in the screenshot. I can still run a successfull test from the REST Help page on the server. Any ideas?

Are you checking the correct hash type?

let’s see your code

private static void CallPostFunction()
        {
            try
            {
                //string remoteCertificateHash = "3541208100360DA080792701B6378B578AB6FB102562C54877F51BAF7CDA709A";
                string remoteCertificateHash = "F1E33102A19D2C8EDF43D9115F61574201686D1C177CC99AD30BEB7CB9C5F996";

                HttpBasicAuthenticator httpBasicAuthenticator = new HttpBasicAuthenticator(Properties.Settings.Default.BatchEntryPerson, Properties.Settings.Default.BatchEntryPass);
                var options = new RestClientOptions(Properties.Settings.Default.AppServerURL)
                {
                    Authenticator = httpBasicAuthenticator
                    ,
                    RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
                    {
                        bool success = false;
                        string certHash = "";
                        certHash = certificate.GetCertHashString(System.Security.Cryptography.HashAlgorithmName.SHA256);
                        if (certHash == remoteCertificateHash)
                        {
                            success = true;
                        }
                        return success;
                    }
                };
                //System.Net.ServicePointManager.ServerCertificateValidationCallback = (s, ce, ca, p) => true;
                var client = new RestClient(options);
                var request = new RestRequest();
                request.AddHeader("Accept", "application/json");
                request.AddHeader("X-API-Key", Properties.Settings.Default.APIKey);
                request.Method = Method.Post;
                var requestContentObj = new
                {
                    GroupID = $@"{BatchGroupID}"
                };
                string requestContent = JsonConvert.SerializeObject(requestContentObj);
                request.AddParameter("application/json", requestContent, ParameterType.RequestBody);
                var response = client.Execute(request);
                Console.WriteLine(response.ToString());
            }
            catch (Exception e)
            {
                throw new Exception("REST Call", e);
            }
        }

backticks my man … → ```