Skip to content

Instantly share code, notes, and snippets.

@jakobt
Created January 19, 2015 20:06
Show Gist options
  • Save jakobt/b7400463e90e16928f57 to your computer and use it in GitHub Desktop.
Save jakobt/b7400463e90e16928f57 to your computer and use it in GitHub Desktop.
Consuming WooCommerce REST API from C#
//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
Copy link

Groot90 commented Dec 4, 2015

@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.

@putuyoga
Copy link

putuyoga commented Jan 5, 2016

For anyone who want to simplify the things, just use WoocommerceSharp

@danielgamajpa
Copy link

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;
        }

@shahshyam
Copy link

Hi
I have Create Product , Customer and many other item in woocommerce . Please contact me https://www.upwork.com/users/~01b266b20bfa60411d

@kapildesai
Copy link

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.

@shahshyam
Copy link

@kapildesai I will help you

@mbrn01
Copy link

mbrn01 commented Sep 7, 2017

@shahshyam can you help?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment