WooCommerce REST API Custom Fields - api

Is it possible to access custom fields for orders, products, customers via WooCommerce REST API? If not natively, then what plugins or workarounds or hacks are out there that work? Thanks!

Answering my own question:
It is possible using the following: (using v3 legacy API)
To send custom fields back to the server:
(For Orders)
{
"order_meta": {
"key": "value"
}
}
To retrieve custom fields from server use this filter with your end point:
http://www.example.com/wc-api/v3/orders?filter[meta]=true
This works for Products as well.

As mentioned in the comment after WooCommerce creates an order via the API it will fire woocommerce_api_create_order hook, you can make use of it.
Add the following code to your theme's functions.php file
add_action( 'woocommerce_api_create_order', 'my_woocommerce_api_create_order', 10, 2);
function my_woocommerce_api_create_order( $order_id, $data ) {
// $data contains the data was posted, add code to extract the required
// fields and process it as required
}
Similarly look at the code in plugins/woocommerce/includes/api/*.php files, find the suitable action or filter hook for the end point and use it.

SIMPLE SOLUTION THAT WORKED FOR ME (using REST API REQUEST):
URL: https:///wp-json/wc/v3/orders/1234
METHOD: PUT
BODY:
{
"status": "completed",
"meta_data": [{
"key": "is_web_server_handled",
"value": "1"
}]
}

Related

HubSpot API — Automatically bulk delete tasks/contacts/deals (or anything) using Make

I would like to automatically bulk delete all tasks older than a month in HubSpot (we have more than 10,000 tasks!), instead of doing it one by one. I tried looking on the internet but it doesn’t seem that HubSpot has any functionalities like it. Thus, I tried to implement such scenario using Make (formerly Integromat) unsuccessfully.
Answering to my question for knowledge purposes.
I managed to create a scenario allowing me to automatically bulk delete tasks (or anything) based on a certain set of criteria using Make (formerly Integromat). I had to use HubSpot’s API and Flow Control tools to achieve such result.
The scenario looks like the following:
Module 1: API Call
Search for all tasks based on a certain set of criteria (here, all tasks created before the last 30 days).
If you wish to search for another object (such as contacts or deals), you can take a look at the CRM Search API for all available search requests. You can also browse through the Properties API to get a comprehensive list of available properties.
URL: /crm/v3/objects/tasks/search
Method: POST
Body:
{
"limit": "5",
"properties": [
"hs_task_subject",
"hs_task_type",
"hs_timestamp"
],
"filterGroups": [
{
"filters": [
{
"propertyName": "hs_task_status",
"operator": "EQ",
"value": "NOT_STARTED"
},
{
"propertyName": "hs_createdate",
"operator": "LT",
"value": "{{formatDate(addDays(now; -30); "x")}}"
}
]
}
]
}
Module 2: Repeater
Initial Value: 0
Repeats: {{if(module1.body.total = null; 1; module1.body.total / 100)}} (if total is less than 100, do not repeat)
Step: {{ifempty(module1.body.paging.next.after; 100)}} (automatically sets it to the first module’s after value, otherwise to 100 if after` value is empty)
You can find out more about properties and search limitations here and here. Basically, the repeater allows you to loop over all HubSpot pages.
Module 3: Sleep
Sleep module to prevent RateLimitError
Module 4: API Call
Same as Module 1, except that you must add an after parameter to include the repeater’s value.
+ "after": "{{module2.i}}"
Module 5: Iterator
Iterate over Module 4’s results array: {{module4.body.results}}.
Module 6: API Call
Delete tasks using the ID returned by the iterator.
{
"inputs":[
{
"id":"{{module5.id}}"
}
]
}
Voilà !

Trello REST API: Delete Custom Field item from a Card

How do I delete a Custom Field item from a card, using Trello REST API?
The documentation only mentions updating, not removing an already set value.
The closest I'll get, is setting an empty value, like this:
{
"value": {
"text": ""
}
}
When I'll then fetch the card in JSON format (card url + .json at the end), it's still shows up among other customFieldItems, with an empty value.
If I manually clear the value using Trello in the browser, the custom field item is removed from the card, and no longer shows up in the json format.
How can I achieve the same thing, but using the REST API ?
According to the documentation, this can be done by setting an empty string for value.
i.e. instead of
{
"value": {
"text": ""
}
}
you want to send a request with
{
"value": ""
}
It took me a while to figure this out because the documentation is kind of confusing and has empty strings for everything else as well, but this one particular empty string is useful.

error generating storefront id in shopify buy js sdk

I am super confused with the documentation on Shopify. I wanted to use their Javascript Buy SDK. To follow their simple product fetch example, in the docs, it says that "Before you can retrieve a product or collection, you need to query for a Storefront ID. After you've obtained either a product ID or collection ID, you can fetch the product or collection using the SDK."
So using the Shopify Graphiql app and from the example to get a storefront ID, the request looks like this.
{
shop {
productByHandle(handle: "my-own-product-handle") {
id
}
}
}
the expected return id is somewhat like
"id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzczNDE0OTkzOTk=" in some sort of encoded value. But however the ID I am getting is like a URL. Here is what I got in return.
{
"data": {
"shop": {
"productByHandle": {
"id": "gid://shopify/Product/1349634097238"
}
}
},
"extensions": {
"cost": {
"requestedQueryCost": 2,
"actualQueryCost": 2,
"throttleStatus": {
"maximumAvailable": 1000,
"currentlyAvailable": 998,
"restoreRate": 50
}
}
}
}
When I use this URL to do a request as shown in JS SDK example
// Fetch a single product by ID
const productId = 'gid://shopify/Product/13496340972223';
client.product.fetch(productId).then((product) => {
// Do something with the product
console.log(product);
});
I get the error in the console that Variable id of type ID! was provided invalid value.
I am not able to figure out where I am missing the dots.
Please help!
Thanks.
Think I have cracked it.... or at least found a work around. This should be clearer I feel, which makes me think I'm wrong.... anyway, here's what I found out.
When using the Shopify graphiQl app you can ask for the id. (just as you have shown above). Take the result and encode it into base64 here..
https://www.base64encode.org/
That will give you the result - 'Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzEzNDk2MzQwOTcyMjIz'.
Stick that in your productId variable and you should get a response.

How to change keys lable of yii2 advanced API response

I have created API module in my yii2 advanced application and also added HttpBearerAuth in controller file and it is working.
On Unauthorized I'm getting below response :
{"name":"Unauthorized","message":"Your request was made with invalid credentials.","code":0,"status":401,"type":"yii\\web\\UnauthorizedHttpException"}
I want to change key label of this response like below :
{"error":"Unauthorized","errorMessage":"Your request was made with invalid credentials.","code":0,"status":401}
How do I update these keys?
Attach an event handler to yii\web\Response::EVENT_BEFORE_SEND and examine the $data attribute of the yii\web\Response class. Not sure, but guess you'll find an array where the keys are exactly those that you want to change.
You just need to filter out the responses you want to handle (eg everything except status codes 200 & 201).
Maybe something like this... probably bugs included :-)
Event::on(yii\web\Response::className(), yii\web\Response::EVENT_BEFORE_SEND, function ($event) {
if (Yii::$app->response->getStatusCode() > 201) {
if (isset(Yii::$app->response->data['name']) {
Yii::$app->response->data['error'] = Yii::$app->response->data['name'];
unset(Yii::$app->response->data['name']);
}
}
});

EmberJS Route to 'single' getting JSONP

I'm having trouble with EmberJS to create a single view to posts based on the ID, but not the ID of the array, I actually have a ID that comes with the json I got from Tumblr API.
So the ID is something like '54930292'.
Next I try to use this ID to do another jsonp to get the post for this id, it works if you open the api and put the id, and actually if you open the single url with the ID on it, works too, the problem is:
When, on the front page for example, I click on a link to go to the single, it returns me nothing and raise a error.
But if you refresh the page you get the content.
Don't know how to fix and appreciate some help :(
I put online the code: http://tkrp.net/tumblr_test/
The error you were getting was because the SingleRoute was being generated as an ArrayController but the json response was not an Array.
App.SingleController = Ember.ObjectController.extend({
});
Further note that the model hook is not fired when using linkTo and other helpers. This because Ember assumes that if you linked to a model, the model is assumed to be as specified, and it directly calls setupController with that model. In your case, you need to still load the individual post. I added the setupController to the route to do this.
App.SingleRoute = Ember.Route.extend({
model: function(params) {
return App.TKRPTumblr.find(params.id);
},
setupController: function(controller, id) {
App.TKRPTumblr.find(id)
.then(function(data) {
controller.set('content', data.response);
});
}
});
I changed the single post template a bit to reflect how the json response. One final change I made was to directly return the $.ajax. Ember understands jQuery promises directly, so you don't need to do any parsing.
Here is the updated jsbin.
I modified: http://jsbin.com/okezum/6/edit
Did this to "fix" the refresh single page error:
setupController: function(controller, id) {
if(typeof id === 'object'){
controller.set('content', id.response);
}else{
App.TKRPTumblr.find(id)
.then(function(data) {
controller.set('content', data.response);
});
}
}
modified the setupController, since I was getting a object when refreshing the page and a number when clicking the linkTo
Dont know if it's the best way to do that :s