How to properly send JSON metadata value to Woocommerce API - c#

My c# application creates products using the Woocommerce.NET NuGet package.
I'm sending metadata with the key: woodmart_variation_gallery_data and value: {"5543":"5519"}
But the plugin that uses this metadata can't use the value, however, when checking the metadata in the database, it's exactly the same as I sent it.
But WordPress should serialize it unless I'm sending the JSON the wrong way.
For example, I need to send this JSON to Woocommerce:
{"5543":"5519"}
Here's how I would to this using code:
Product product = new Product();
//add some stuff like price
product.meta_data = new List<ProductMeta>()
{
new ProductMeta()
{
key = "woodmart_variation_gallery_data",
value = "{\"5543\":\"5519\"}"
}
}
await wcObject.Products.Add(product);
When this run, what I'm expecting to see in the database postmeta is serialized code:
a:1:{i:5543;s:4:"5519";}
But what I see is {"5543":"5519"} It's supposed to be serialized by wordpress/woocommerce, but it's not?

You can use Sharp Serialization Library

Related

CDKTF C# Get value from JSON object result of Terraform resource (TFToken)

TLDR Using CDKTF for C#, how do I use the outputContent of the ResourceGroupTemplateDeployment resource in downstream resources? The JSON structure is
{
apiKey: {
value: <the value>
},
queryKey: {
value: <the query key value>
}
}
So I would like to be able to pass this value to say, a Function App's config, but any attempts to get apiKey in C# lead to an error because C# sees the value as a Token and not the JSON object.
I am currently using CDKTF with C# to build out infrastructure. I am using a resource ResourceGroupTemplateDeployment which returns an Output object which is a string that is actually a JSON object. I would like to retrieve two values from this to use in downstream resources. In HCL this is trivial to do, I would just do something like sensitive(jsondecode(azurerm_resource_group_template_deployment.service.output_content).myKey.value) and that would get me what I need. In CDKTF though this is not so straightforward.
While running the initial synth (building and converting C# into json) the Output value is actually a TFToken. This means that it's essentially a placeholder for the real value which is currently unknown because Terraform hasn't actually run the plan/apply. more info on that here.
So it returns a string when the code is first run, but when terraform plan/apply runs it has the real values. I need the values from the JSON object to assign them to the downstream resources, how can I possibly do this if they're undefined when the code is building? Here is my code:
ResourceGroupTemplateDeployment searchService = new ResourceGroupTemplateDeployment(this, "search-service", new ResourceGroupTemplateDeploymentConfig
{
Name = $"{searchName}-{suffix.Result}",
ResourceGroupName = rg.Name,
DeploymentMode = "Incremental",
ParametersContent = JsonSerializer.Serialize(new Dictionary<string, Dictionary<string,string>>{
{"searchServices_dev_request_search_name", new Dictionary<string, string>{
{ "value", $"{searchName}-{suffix.Result}" }
}
}
}),
TemplateContent = template,
});
SearchTemplateOutput resultObj = JsonSerializer.Deserialize<SearchTemplateOutput>((searchService.OutputContent));
apiKey = resultObj.apiKey;
class SearchTemplateOutput {
public string apiKey {get; set;}
public string queryKey {get; set;}
}
The above code does not work and gets an error Unhandled exception. System.Text.Json.JsonException: '$' is an invalid start of a value. because the value is a Token, it's not an actual JSON object yet... but it will be :/
I also tried adding Token.AsString
SearchTemplateOutput resultObj = JsonSerializer.Deserialize<SearchTemplateOutput>(Token.AsString(searchService.OutputContent));
but the result is the same. It blows up trying to deserialize the result because it's a Token, not the actual values that I need to reference later.
I'm not sure how to handle this, the documentation just gives incredibly simple examples where you're getting something simple returned to you and you use the entire object that's returned, but in this situation it's a JSON object with multiple values that gets returned, so I am at a loss for how to access those values.
The answer to my question was found in the AWS documentation which was linked to from the TF documentation. Essentially it said that you can't manipulate JSON lists/strings, and so the solution was to just create the object using the resource group template (since there is an outstanding bug > 1 year in Azure where their API doesn't conform to their own standard which breaks the search service through terraform if using the free tier) and then after it is created, use the associated data object to get the values.
For what it's worth, here is the final setup I have done to be able to get the values safely using C#
DataAzurermSearchService searchSvcData = new DataAzurermSearchService(this, "search-service-data", new DataAzurermSearchServiceConfig
{
Name = searchService.Name,
ResourceGroupName = rg.Name
});
apiKey = searchSvcData.PrimaryKey;
queryKey = searchSvcData.QueryKeys.Get(0).GetStringAttribute("key");
This solution might be obvious to someone more well versed with C#, but it took me some time to figure it out. Hopefully it helps someone else someday

Dynamics CRM C# Plugin - First time with API

While I've been developing in Dynamics for awhile, I have never had to do an external call to an API before.
I'm not sure where to start. Any help in pointing me in the right direction would be very helpful.
The Api in question is located here:
http://apidocs.assess.com/
There are examples within there that show what needs to get passed to the url (https://app.fasttestweb.com/FastTest/api/swagger.json)
But in all honesty, this is my first attempt at this and I'm overwhelmed with the information I've been finding, and having trouble parsing through what needs to be done for this.
Step 1, of course is to generate an auth token from the site.
This needs to be passed in this formation (I assume that is JSON).
But I'm having trouble figuring out how to even do that part, or what the code should even look like. If anyone has an example of something they've done, or can point me to a link/video that walks through this, that would be awesome.
Note, I do have Newtonsoft.Json installed in Visual Studio, but I'm having trouble finding good examples on how to actually pass the information back and forth.
Thank you in advance.
How to call an API in rest is a really common practice as a developer since this is common practice to expose data, i highly recommend that you read up on the subject, there are alot of good resources out there, this site is one and youtube is another, did a quick search and found alot about it: https://www.youtube.com/results?search_query=intro+to+rest+c%23
To the problem at hand:
The swagger documentation tells you all you need to know to call the service your after,
Take the auth service for example, first of we need to know which method the service uses, in this case it is post.
Now we need to know which address we can call the service. Specified in the docs as: https://app.fasttestweb.com/FastTest/api/auth/simple
What are we sending:
{
"username": "string",
"pwd": "string",
"apiKey": "string",
"timeSent": 0,
"tokenTTL": 0
}
if you switch to model you can see the description of the parameters. You can even test this out directly in the page by editing the editable box with the values you were given and pressing "try it out!" in the bottom of the endpoint specification.
What response are we getting:
{
"apiToken": "string",
"timeGenerated": 0,
"ttl": 0
}
To call it, there are many ways to do this, i like to make separate objects/dto's of what im sending and recieving and then serialize/deserialize them from and to that object. Since you already have json.net here is how you do serialize.
You can specify the specific json names so it matches with the schema with an attribute
or define a strategy.
When you get the json back from the service you will have to deserialize it.
So your body obj would look like this for example
public class AuthBody
{
[JsonProperty("username")]
public string UserName { get; set; }
[JsonProperty("pwd")]
public string Password { get; set; }
[JsonProperty("apiKey")]
public string ApiKey { get; set; }
[JsonProperty("timeSent")]
public int TimeSent { get; set; }
[JsonProperty("tokenTTL")]
public int TokenTimeToLive { get; set; }
}
Just setup the response in similar fashion.
I like to use a lib called RestSharp to call rest services, its available on nuget.
Here is a very basic code example (not tested):
var body = new AuthBody()
{
UserName = "value",
Password = "value",
ApiKey = "value",
TimeSent = 123,
TokenTimeToLive = 10000
};
var json = JsonConvert.SerializeObject(body);
var client = new RestClient("https://app.fasttestweb.com/FastTest/api");
var request = new RestRequest("auth/simple", Method.POST, DataFormat.Json);
request.AddParameter("application/json", json, ParameterType.RequestBody);
var jsonResponse = client.Execute(request);
AuthResponse authResponse = JsonConvert.DeserializeObject<AuthResponse>(jsonResponse.Content);
You can also set the default serializer of restsharp to json.net if you want, then you can set the body with addJsonBody instead of the parameter and you dont have to serialize your object yourself, more info is available on RestSharp.
if you dont want to use RestSharp, the normal client is called HttpClient instead of RestClient, if you want to google it.
Hope it helps.

DocuSign - The "Custom Document Fields" are not being returned by the "ListDocuments" API of the "EnvelopesApi" provided by the C# SDK

Currently we are having an use-case in which a few custom data needs to be stored for each document of an DocuSign Envelope.
We are using the DocumentFields property of the Document class for the same while creating the EnvelopeDefinition instance being sent to the CreateEnvelope API provided by the DocuSign C# SDK as below.
var envelope = new EnvelopeDefinition {
Documents = new List<Document> {
new Document {
DocumentFields = new List<NameValue> {
new NameValue {
Name = "CustomField",
Value = "123"
}
}
}
}
};
But these fields are not being returned by the ListDocuments API though there is a DocumentFields property in the EnvelopeDocument model class being returned.
The same fields are being returned by the ListDocumentFields API.
Could anyone please let me know if this is the expected behavior or is there anyway these fields can be retrieved using the ListDocuments API to avoid the additional API call.
This is intended behavior of the DocuSign platform. The ListDocuments API is used to list the high-level meta data around each document in the envelope - for example the document's name and documentId. For the more detailed information such as custom field values etc you need to call the ListDocumentFields API.

Stripe .net "The signature for the webhook is not present in the Stripe-Signature header."

I am using Stripe.net SDK from NuGet. I always get the
The signature for the webhook is not present in the Stripe-Signature header.
exception from the StripeEventUtility.ConstructEvent method.
[HttpPost]
public void Test([FromBody] JObject incoming)
{
var stripeEvent = StripeEventUtility.ConstructEvent(incoming.ToString(), Request.Headers["Stripe-Signature"], Constants.STRIPE_LISTENER_KEY);
}
The WebHook key is correct, the Request Header contains "Stripe-Signature" keys.
I correctly receive incoming data from the Webhook tester utility (using nGrok with Visual Studio).
the secureCompare method seems to be the culprit => StripeEventUtility.cs
I tried to manipulate the incoming data from Stripe (Jobject, string, serializing...). The payload signature may cause some problem.
Has anybody had the same problem?
As per #Josh's comment, I received this same error
The signature for the webhook is not present in the Stripe-Signature header.
This was because I had incorrectly used the API secret (starting with sk_) to verify the HMAC on EventUtility.ConstructEvent.
Instead, Stripe WebHook payloads are signs with the Web Hook Signing Secret (starting with whsec_) as per the docs
The Web Hook Signing Secret can be obtained from the Developers -> WebHooks page:
The error can also occur because you are using the secret from the Stripe dashboard. You need to use the temporary one generated by the stripe cli if you are using the CLI for testing.
To obtain it run this:
stripe listen --print-secret
Im not sure about reason of this, but Json readed from Request.Body has a little bit different structure than parsed with [FromBody] and Serialized to string.
Also, you need to remove [FromBody] JObject incoming because then Request.Body will be empty.
The solution you need is:
[HttpPost]
public void Test()
{
string bodyStr = "";
using (var rd = new System.IO.StreamReader(Request.Body))
{
bodyStr = await rd.ReadToEndAsync();
}
var stripeEvent = StripeEventUtility.ConstructEvent(bodyStr, Request.Headers["Stripe-Signature"], Constants.STRIPE_LISTENER_KEY);
}
I was also receiving the same exception message when I looked at it in the debugger but when I Console.WriteLine(e.Message); I received a different exception message.
Received event with API version 2020-08-27, but Stripe.net 40.5.0 expects API version 2022-08-01. We recommend that you create a WebhookEndpoint with this API version. Otherwise, you can disable this exception by passing throwOnApiVersionMismatch: false to Stripe.EventUtility.ParseEvent or Stripe.EventUtility.ConstructEvent, but be wary that objects may be incorrectly deserialized.
I guess your best bet is to set throwOnApiVersionMismatch to false;
EventUtility.ParseEvent(json, header, secret, throwOnApiVersionMismatch: false)

C# library for Amazon Product Advertising API

I'm trying to retrieve data from 'Amazon Product Advertising API', and I see that I need to sign my request, and then the response is an XML document which should be parsed.
I wonder if there is any library which I can send my requests throught, and recieve the response back as an object.
If not, what should I do to convert those XML reponses to an object ? I've read about schemas, but where do I get those schemas from and where do I get from the defention for the response objects so I could define them my self.
Thanks alot!
You can use the following nuget package
PM> Install-Package Nager.AmazonProductAdvertising
Example:
var authentication = new AmazonAuthentication();
authentication.AccessKey = "accesskey";
authentication.SecretKey = "secretkey";
var client = new AmazonProductAdvertisingClient(authentication, AmazonEndpoint.DE);
//Search
var result = await client.SearchItemsAsync("canon eos");
//Lookup
var result = await client.GetItemsAsync("B00BYPW00I");
There is a library that helps you sign requests AND process the responses by converting the XML into a relatively easy-to-use object. I've been using it for a few weeks now and wrote my own helper classes to really make querying the API fast and easy.
I wrote a demo console C# app where you can just plug in your Amazon credentials and start playing around here:
https://github.com/zoenberger/AmazonProductAdvertising
I also answered a similar question here:
https://stackoverflow.com/a/33617604/5543992

Categories

Resources