Created
January 19, 2015 20:06
-
-
Save jakobt/b7400463e90e16928f57 to your computer and use it in GitHub Desktop.
Consuming WooCommerce REST API from C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//C# port of the https://github.com/kloon/WooCommerce-REST-API-Client-Library | |
//Including handling of woocommerce insisting on uppercase UrlEncoded entities | |
public class WoocommerceApiClient | |
{ | |
private static byte[] HashHMAC(byte[] key, byte[] message) | |
{ | |
var hash = new HMACSHA256(key); | |
return hash.ComputeHash(message); | |
} | |
private string Hash(string input) | |
{ | |
using (SHA1Managed sha1 = new SHA1Managed()) | |
{ | |
var hash = sha1.ComputeHash(Encoding.UTF8.GetBytes(input)); | |
var sb = new StringBuilder(hash.Length*2); | |
foreach (byte b in hash) | |
{ | |
// can be "x2" if you want lowercase | |
sb.Append(b.ToString("X2")); | |
} | |
return sb.ToString(); | |
} | |
} | |
public const string API_ENDPOINT = "wc-api/v1/"; | |
public string ApiUrl { get; set; } | |
public string ConsumerSecret { get; set; } | |
public string ConsumerKey { get; set; } | |
public bool IsSsl { get; set; } | |
public WoocommerceApiClient(string consumerKey, string consumerSecret, string storeUrl, bool isSsl = false) | |
{ | |
if (string.IsNullOrEmpty(consumerKey) || string.IsNullOrEmpty(consumerSecret) || | |
string.IsNullOrEmpty(storeUrl)) | |
{ | |
throw new ArgumentException("ConsumerKey, consumerSecret and storeUrl are required"); | |
} | |
this.ConsumerKey = consumerKey; | |
this.ConsumerSecret = consumerSecret; | |
this.ApiUrl = storeUrl.TrimEnd('/') + "/" + API_ENDPOINT; | |
this.IsSsl = isSsl; | |
} | |
public string GetAllProducts() | |
{ | |
return MakeApiCall("products", new Dictionary<string, string>() {{"filter[limit]", "2000"}}); | |
} | |
public string GetProducts() | |
{ | |
return MakeApiCall("products"); | |
} | |
private string MakeApiCall(string endpoint, Dictionary<string, string> parameters = null, string method = "GET") | |
{ | |
if (parameters == null) | |
{ | |
parameters = new Dictionary<string, string>(); | |
} | |
parameters["oauth_consumer_key"] = this.ConsumerKey; | |
parameters["oauth_timestamp"] = | |
DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds.ToString(); | |
parameters["oauth_timestamp"] = parameters["oauth_timestamp"].Substring(0, | |
parameters["oauth_timestamp"].IndexOf(".")); | |
parameters["oauth_nonce"] = Hash(parameters["oauth_timestamp"]); | |
parameters["oauth_signature_method"] = "HMAC-SHA256"; | |
parameters["oauth_signature"] = GenerateSignature(parameters, method, endpoint); | |
WebClient wc = new WebClient(); | |
StringBuilder sb = new StringBuilder(); | |
foreach (var pair in parameters) | |
{ | |
sb.AppendFormat("&{0}={1}", HttpUtility.UrlEncode(pair.Key), HttpUtility.UrlEncode(pair.Value)); | |
} | |
var url = this.ApiUrl + endpoint + "?" + sb.ToString().Substring(1).Replace("%5b","%5B").Replace("%5d","%5D"); | |
var result = wc.DownloadString(url); | |
return result; | |
} | |
private string GenerateSignature(Dictionary<string, string> parameters, string method, string endpoint) | |
{ | |
var baserequesturi = Regex.Replace(HttpUtility.UrlEncode(this.ApiUrl + endpoint), "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper()); | |
var normalized = NormalizeParameters(parameters); | |
var signingstring = string.Format("{0}&{1}&{2}", method, baserequesturi, | |
string.Join("%26", normalized.OrderBy(x => x.Key).ToList().ConvertAll(x => x.Key + "%3D" + x.Value))); | |
var signature = | |
Convert.ToBase64String(HashHMAC(Encoding.UTF8.GetBytes(this.ConsumerSecret), | |
Encoding.UTF8.GetBytes(signingstring))); | |
Console.WriteLine(signature); | |
return signature; | |
} | |
private Dictionary<string, string> NormalizeParameters(Dictionary<string, string> parameters) | |
{ | |
var result = new Dictionary<string, string>(); | |
foreach (var pair in parameters) | |
{ | |
var key = HttpUtility.UrlEncode(HttpUtility.UrlDecode(pair.Key)); | |
key = Regex.Replace(key, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper()).Replace("%", "%25"); | |
var value = HttpUtility.UrlEncode(HttpUtility.UrlDecode(pair.Value)); | |
value = Regex.Replace(value, "(%[0-9a-f][0-9a-f])", c => c.Value.ToUpper()).Replace("%", "%25"); | |
result.Add(key, value); | |
} | |
return result; | |
} | |
} |
For anyone who want to simplify the things, just use WoocommerceSharp
To use the PUT / POST I created a new method (named for MakeApiCallPUT ()) and function equivalent to line 77
var result = wc.DownloadString (url);
I put:
var result = wc.UploadString (url, "PUT", dadosJSON);
where dadosJSON is JSON content that will be sent to update.
Full function was as follows:
private string MakeApiCallPUT(string endpoint, string dadosJSON = null, string method = "PUT")
{
Dictionary<string, string> parameters = null;
if (parameters == null)
{
parameters = new Dictionary<string, string>();
}
parameters["oauth_consumer_key"] = this.ConsumerKey;
//parameters["oauth_timestamp"] = DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds.ToString();
//parameters["oauth_timestamp"] = parameters["oauth_timestamp"].Substring(0, parameters["oauth_timestamp"].IndexOf(","));
parameters["oauth_timestamp"] = ((DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1).Ticks) / (1000 * 10000)).ToString();
parameters["oauth_nonce"] = Hash(parameters["oauth_timestamp"]);
parameters["oauth_signature_method"] = "HMAC-SHA256";
parameters["oauth_signature"] = GenerateSignature(parameters, method, endpoint);
WebClient wc = new WebClient();
StringBuilder sb = new StringBuilder();
foreach (var pair in parameters)
{
sb.AppendFormat("&{0}={1}", HttpUtility.UrlEncode(pair.Key), HttpUtility.UrlEncode(pair.Value));
}
var url = this.ApiUrl + endpoint + "?" + sb.ToString().Substring(1).Replace("%5b", "%5B").Replace("%5d", "%5D").Replace("%7b", "%7B").Replace("%7d", "%7D").Replace("%3a", "%3A").Replace("%2c", "%2C");
//var result = wc.DownloadString(url);
var result = wc.UploadString(url, "PUT", dadosJSON);
return result;
}
Hi
I have Create Product , Customer and many other item in woocommerce . Please contact me https://www.upwork.com/users/~01b266b20bfa60411d
Can any body provide a solution for PUT or POST errors....Not able to solve the same......I can Fetch the products but cannot Update a product.
@kapildesai I will help you
@shahshyam can you help?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@diegoaraujolima
Great! Glad to hear you've fixed it.
To everyone:
Be sure that line #65 is using the proper time delimiter for your time zone. It can be a dot, but it also can be a comma character.