/// <summary> /// A convenience function that tries to ensure that a given URL is a valid tictail domain. It does this by making a /// HEAD request to the given domain, and returns true if the response contains an X-ShopId header. /// **Warning**: a domain could fake the response header, which would cause this method to return true. /// **Warning**: this method of validation is not officially supported by tictail and could break at any time. /// </summary> /// <param name="url">The URL of the shop to check.</param> /// <returns>A boolean indicating whether the URL is valid.</returns> public static async Task <bool> IsValidShopDomainAsync(string url) { var uri = TictailService.BuildShopUri(url, true); using (var client = new HttpClient()) { using (var msg = new HttpRequestMessage(HttpMethod.Head, uri)) { try { var response = await client.SendAsync(msg); return(response.Headers.Any(h => h.Key == "X-ShopId")); } catch (HttpRequestException) { return(false); } } } }
/// <summary> /// Builds an authorization URL for tictail OAuth integration. /// </summary> /// <param name="scopes"></param> /// <param name="myTictailUrl">The shop's *.mytictail.com URL.</param> /// <param name="tictailApiKey">Your app's public API key.</param> /// <param name="redirectUrl"></param> /// <param name="state"></param> /// <returns>The authorization url.</returns> public static Uri BuildAuthorizationUrl(IEnumerable <string> scopes, string myTictailUrl, string tictailApiKey, string redirectUrl, string state = null) { //Prepare a uri builder for the shop URL var builder = new UriBuilder(TictailService.BuildShopUri(myTictailUrl, false)); var scopeFormateed = $"{string.Join(",", scopes)}"; //Build the querystring var qs = new List <KeyValuePair <string, string> > { new KeyValuePair <string, string>("response_type", "code"), new KeyValuePair <string, string>("client_id", tictailApiKey), new KeyValuePair <string, string>("scope", scopeFormateed), new KeyValuePair <string, string>("state", state), new KeyValuePair <string, string>("redirect_uri", HttpUtility.UrlEncode(redirectUrl)), }; builder.Path = "oauth/authorize"; builder.Query = string.Join("&", qs.Select(s => $"{s.Key}={s.Value}")); return(builder.Uri); }
/// <summary> /// Authorizes an application installation, generating an access token for the given shop. /// </summary> /// <param name="authCode"></param> /// <param name="myTictailUrl"> /// The store's *.tictail.com URL, which should be a paramter named 'shop' on the request /// querystring. /// </param> /// <param name="tictailApiKey">Your app's public API key.</param> /// <param name="tictailSecretKey">Your app's secret key.</param> /// <param name="scopes"></param> /// <returns>The authorization result.</returns> public static async Task <Root> AuthorizeWithResult(string authCode, string myTictailUrl, string tictailApiKey, string tictailSecretKey, IEnumerable <string> scopes) { var ub = new UriBuilder(TictailService.BuildShopUri(myTictailUrl, false)) { Path = "oauth/token" }; var values = new Dictionary <string, string> { { "client_id", $"{tictailApiKey}" }, { "client_secret", $"{tictailSecretKey}" }, { "code", $"{authCode}" }, { "grant_type", "authorization_code" }, { "scope", $"[{string.Join(",", scopes)}]" }, }; var content = new FormUrlEncodedContent(values); using (var client = new HttpClient()) using (var msg = new CloneableRequestMessage(ub.Uri, HttpMethod.Post, content)) { var request = client.SendAsync(msg); var response = await request; var rawDataString = await response.Content.ReadAsStringAsync(); TictailService.CheckResponseExceptions(response, rawDataString); //var json = JToken.Parse(rawDataString); //var a = new AuthorizationResult(json.Value<string>("access_token"), // json.Value<string>("scope").Split(','), json.Value<TictailStore>("store")); var json = JsonConvert.DeserializeObject <Root>(rawDataString); //return new AuthorizationResult(json.Value<string>("access_token"), // json.Value<string>("scope").Split(','), json.Value<TictailStore>("store")); return(json); } }