betfairng
betfairng copied to clipboard
Converted AuthClient to work with .net core
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
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);
}
}
}
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