-
-
Save jakobt/b7400463e90e16928f57 to your computer and use it in GitHub Desktop.
| //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; | |
| } | |
| } |
@Groot90, I did what you suggested, but occours the error 403. Can you help me?
@diegoaraujolima
That error is probably related to your server's configuration. Maybe this thread could help: woocommerce/woocommerce#6529
Resolved. Add Header wc.Headers.Add("Content-Type", "application/json");. Works! Thankz!
@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.
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?
@diegoaraujolima:
You can use WebClient's UploadData method (instead of DownloadString).
Something like this (VB.NET):
'uploadData is for the body of http PUT request (for example, JSON data )
Dim dataArr() As Byte = Encoding.UTF8.GetBytes(uploadData)
wc.UploadData(url, "PUT", dataArr)
@Rey68:
Are you sure the error is exactly at line 71? It looks like your parameters[] array is empty.