betfairng icon indicating copy to clipboard operation
betfairng copied to clipboard

Converted AuthClient to work with .net core

Open MarkOates71 opened this issue 5 years ago • 2 comments

I've rewritten the AuthClient class to work with .net core but run into an issue with the cert, the problem I have is I'm seeing a betfair response of CERT_AUTH_REQUIRED

I'm newish to c#/ .net core so any help would be appreciated, and once working i'll post the code here

thanks Mark

MarkOates71 avatar Aug 06 '19 21:08 MarkOates71

I have just done the same thing, where did you get stuck? The below returns a session id so from there you should be good.

Make sure you've uploaded your .pfx to betfair and allowed cert auth.

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Authentication;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using Betting.Models.Betfair;
using Newtonsoft.Json;

namespace Betting
{
    public class BaseBetfairClient
    {
        public const string APPKEY_HEADER = "X-Application";
        public const string SESSION_TOKEN_HEADER = "X-Authentication";

        private static readonly string LIST_EVENT_TYPES_METHOD = "SportsAPING/v1.0/listEventTypes";
        private static readonly string LIST_MARKET_TYPES_METHOD = "SportsAPING/v1.0/listMarketTypes";
        private static readonly string LIST_MARKET_CATALOGUE_METHOD = "SportsAPING/v1.0/listMarketCatalogue";
        private static readonly string LIST_MARKET_BOOK_METHOD = "SportsAPING/v1.0/listMarketBook";
        private static readonly string PLACE_ORDERS_METHOD = "SportsAPING/v1.0/placeOrders";
        private static readonly string LIST_MARKET_PROFIT_AND_LOST_METHOD = "SportsAPING/v1.0/listMarketProfitAndLoss";
        private static readonly string LIST_CURRENT_ORDERS_METHOD = "SportsAPING/v1.0/listCurrentOrders";
        private static readonly string LIST_CLEARED_ORDERS_METHOD = "SportsAPING/v1.0/listClearedOrders";
        private static readonly string CANCEL_ORDERS_METHOD = "SportsAPING/v1.0/cancelOrders";
        private static readonly string REPLACE_ORDERS_METHOD = "SportsAPING/v1.0/replaceOrders";
        private static readonly string UPDATE_ORDERS_METHOD = "SportsAPING/v1.0/updateOrders";
        private static readonly String FILTER = "filter";
        private static readonly String LOCALE = "locale";
        private static readonly String CURRENCY_CODE = "currencyCode";
        private static readonly String MARKET_PROJECTION = "marketProjection";
        private static readonly String MATCH_PROJECTION = "matchProjection";
        private static readonly String ORDER_PROJECTION = "orderProjection";
        private static readonly String PRICE_PROJECTION = "priceProjection";
        private static readonly String SORT = "sort";
        private static readonly String MAX_RESULTS = "maxResults";
        private static readonly String MARKET_IDS = "marketIds";
        private static readonly String MARKET_ID = "marketId";
        private static readonly String INSTRUCTIONS = "instructions";
        private static readonly String CUSTOMER_REFERENCE = "customerRef";
        private static readonly String INCLUDE_SETTLED_BETS = "includeSettledBets";
        private static readonly String INCLUDE_BSP_BETS = "includeBspBets";
        private static readonly String NET_OF_COMMISSION = "netOfCommission";
        private static readonly String BET_IDS = "betIds";
        private static readonly String PLACED_DATE_RANGE = "placedDateRange";
        private static readonly String ORDER_BY = "orderBy";
        private static readonly String SORT_DIR = "sortDir";
        private static readonly String FROM_RECORD = "fromRecord";
        private static readonly String RECORD_COUNT = "recordCount";
        private static readonly string BET_STATUS = "betStatus";
        private static readonly string EVENT_TYPE_IDS = "eventTypeIds";
        private static readonly string EVENT_IDS = "eventIds";
        private static readonly string RUNNER_IDS = "runnerIds";
        private static readonly string SIDE = "side";
        private static readonly string SETTLED_DATE_RANGE = "settledDateRange";
        private static readonly string GROUP_BY = "groupBy";
        private static readonly string INCLUDE_ITEM_DESCRIPTION = "includeItemDescription";

        private string appKey = "xxx";

        private string sessionToken;

        private const string DEFAULT_COM_BASEURL = "https://identitysso-cert.betfair.com";

        public async Task<LoginResponse> doLogin(string username, string password, string certFilename)
        {
            if (File.Exists(certFilename))
            {
                var client = initHttpClientInstance(appKey);
                var content = getLoginBodyAsContent(username, password);
                var result = await client.PostAsync(DEFAULT_COM_BASEURL + "/api/certlogin", content);
                result.EnsureSuccessStatusCode();

                string _content = await result.Content.ReadAsStringAsync();

                LoginResponse loginResponse = JsonConvert.DeserializeObject<LoginResponse>(_content);
                return loginResponse;
            }
            else
            {
                throw new FileNotFoundException(certFilename);
            }
        }

        public HttpClient initHttpClientInstance(string appKey, string baseUrl = DEFAULT_COM_BASEURL)
        {
            var cert = new X509Certificate2("xxx.pfx", "xxx");
            var clientHandler = new HttpClientHandler();
            clientHandler.ClientCertificates.Add(cert);
            
            var client = new HttpClient(clientHandler);
            client.BaseAddress = new Uri(baseUrl);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Add("X-Application", appKey);
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            return client;
        }

        private FormUrlEncodedContent getLoginBodyAsContent(string username, string password)
        {
            var postData = new List<KeyValuePair<string, string>>();
            postData.Add(new KeyValuePair<string, string>("username", username));
            postData.Add(new KeyValuePair<string, string>("password", password));
            return new FormUrlEncodedContent(postData);
        }
    }
}

bitcoinbrisbane avatar Aug 13 '19 05:08 bitcoinbrisbane

I fixed this the day after posting but didn't get chance to post my solution which is more aligned to the original code, see below, I did already have cert uploaded to Betfair. I ended up replacing the method getWebRequestHandlerWithCert with one of my own (which references HttpClientHandler instead of WebRequestHandler) called GetHttpClient

Original Code private WebRequestHandler getWebRequestHandlerWithCert (string certFilename) { var cert = new X509Certificate2(certFilename, "");

        var clientHandler = new WebRequestHandler();
        clientHandler.ClientCertificates.Add(cert);
        return clientHandler;
    }

Changed to.....

private HttpClientHandler GetHttpClient(X509Certificate2 certData) {

        //specify to use TLS 1.2 as default connection
        System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

        var clientHandler = new HttpClientHandler();

        clientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
        clientHandler.SslProtocols = SslProtocols.Tls12;

        X509Certificate2 newCert = new X509Certificate2(certData);
        clientHandler.ClientCertificates.Add(newCert);
        return clientHandler;

    }

Let me know if you try this out Mark

MarkOates71 avatar Aug 13 '19 06:08 MarkOates71