add custom metadata to woocommerce webhook hook - woocommerce

I have a webhook set up to trigger when there is a new order and it works just fine, I use it in a custom app to notify when there is a new order. But now i need to be able to add custom meta data to the webhook, is this possible?
the current output
{
"id": 1,
"name": "alert new order",
"status": "active",
"topic": "order.created",
"resource": "order",
"event": "created",
"hooks": [
"woocommerce_new_order"
],
is there a way to add meta data in this hooks array or in the same json like
{
"id": 1,
"name": "alert new order",
"status": "active",
"topic": "order.created",
"resource": "order",
"event": "created",
"metdadata": "mata data value"
"hooks": [
"woocommerce_new_order"
],
The php (found it searching around)so far i had tried but simple does not work or do anything
add_action( 'woocommerce_webhook_payload', 'sendsikkert_woocommerce_webhook_payload' );
function sendsikkert_woocommerce_webhook_payload( $payload, $resource, $resource_id, $id ) {
$order = wc_get_order( $resource_id );
$ssmail = get_post_meta( $order->get_order_number(), '_token', true );
$cvrnr = get_post_meta( $order->get_order_number(), 'restaurante', true );
$payload['order']['Sendsikkert_email'] = $ssmail;
$payload['order']['CVRNR'] = $cvrnr;
return $payload;
}

Related

WordPress rest api custom endpoint not getting all meta data, getting some fields meta data only

In the WordPress website, I have added one custom post type "inventory".To post data to that inventory created one end rest API endpoint. the created endpoint is not getting all the metadata from the inventory post type. In that inventory post type, I have an input field to enter date but while getting the data using endpoint I am not getting that date field data. I have tried register_rest_field() to get metadata using API endpoint, but in postman, I am getting only some fields.
My HTML Code looks like below
<div class="from_date inventory-form-to-input">
<input type="text" style="border: 1px solid #ddd;" class="pac-date-picker hasDatepicker"
name="nets_availability_pickup_datetime[]" value="0000-00-00 00:00:00" autocomplete="off"
id="dp1605714040849">
</div>
<div class="to_date inventory-form-to-input">
<input type="text" style="border: 1px solid #ddd;" class="pac-date-picker hasDatepicker"
name="nets_availability_dropoff_datetime[]" value="0000-00-00 00:00:00" autocomplete="off"
id="dp1605714040850">
</div>
And response in postman:
{
"id": 197794,
"date": "2020-11-03T04:33:35",
"date_gmt": "2020-11-03T10:33:35",
"guid": {
"rendered": "https://mywebsite.com.com/?post_type=inventory&p=197794"
},
"modified": "2020-11-17T10:11:24",
"modified_gmt": "2020-11-17T16:11:24",
"slug": "000-030-065x-001",
"status": "publish",
"type": "inventory",
"link": "https://mywebsite.com.com/inventory/000-030-065x-001/",
"title": {
"rendered": "000-030-065x-001"
},
"featured_media": 0,
"parent": 0,
"template": "",
"meta": {
"nets_hourly_ranges_cost": [
"a:0:{}"
],
"nets_daily_pricing": [
"a:0:{}"
],
"nets_monthly_pricing": [
"a:0:{}"
],
"nets_day_ranges_cost": [
"a:0:{}"
],
"_edit_lock": [
"1605629551:619"
],
"_edit_last": [
"619"
],
"quantity": [
"1"
],
"pricing_type": [
"general_pricing"
],
"general_price": [
"100"
],
"_yoast_wpseo_focuskeywords": [
"[]"
],
"_yoast_wpseo_keywordsynonyms": [
"[\"\"]"
]
},
"quantity": "1",
"pricing_type": "general_pricing",
"general_price": "100",
"nets_availability_block_by": [],
"nets_availability_pickup_datetime": "",
"_links": {
"self": [
{
"href": "https://mywebsite.com.com/wp-json/wp/v2/inventory/197794"
}
],
"collection": [
{
"href": "https://mywebsite.com/wp-json/wp/v2/inventory"
}
],
"about": [
{
"href": "https://mywebsite.com/wp-json/wp/v2/types/inventory"
}
],
"wp:attachment": [
{
"href": "https://mywebsite.com/wp-json/wp/v2/media?parent=197794"
}
],
"curies": [
{
"name": "wp",
"href": "https://api.w.org/{rel}",
"templated": true
}
]
}
},
tried below code to create a custom endpoint and to get metadata:
function my_plugin_rest_route_for_post( $route, $post ) {
if ( $post->post_type === 'inventory' ) {
$route = '/wp/v2/inventory/' . $post->ID;
}
return $route;
}
add_action( 'rest_api_init', function () {
register_rest_field( 'inventory', 'quantity', array(
'get_callback' => function( $post_arr ) {
return get_post_meta( $post_arr['id'], 'quantity', true );
},
) );
register_rest_field( 'inventory', 'pricing_type', array(
'get_callback' => function( $post_arr ) {
return get_post_meta( $post_arr['id'], 'pricing_type', true );
},
) );
register_rest_field( 'inventory', 'general_price', array(
'get_callback' => function( $post_arr ) {
return get_post_meta( $post_arr['id'], 'general_price', true );
},
) );
register_rest_field( 'inventory', 'nets_availability_block_by', array(
'get_callback' => function( $post_arr ) {
return get_post_meta( $post_arr['id'], 'nets_availability_block_by',false);
},
) );
register_rest_field( 'inventory', 'nets_availability_pickup_datetime', array(
'get_callback' => function( $post_arr ) {
return get_post_meta( $post_arr['id'], 'nets_availability_pickup_datetime', true );
},
) );
/*used to get all metadata*/
register_rest_field( 'inventory', 'meta', array(
'get_callback' => function( $post_arr ) {
return get_post_meta( $post_arr['id'], '', true );
},
) );
} );
please anyone suggest me how to get those datefields 'nets_availability_pickup_datetime' & 'nets_availability_dropoff_datetime'.
Thanks in advance.
You can get inspiration from one of my old code. Permission callback is used to add a security layer to your API, but is usually optional. The parameter args is also optional.
register_rest_route('v2/boutique', '/order/status', array(
'methods' => 'POST',
'permission_callback' => array($this, 'check_access'),
'callback' => array($this, "api_check_order"),
'args' => [
'transaction_id', 'order_id'
],
));
public function check_access(WP_REST_Request $request)
{
// Check credential
// if(in_array($_SERVER['REMOTE_ADDR'], self::$available_ip)){
$creds = $request->get_header('token');
if (!empty($creds)) {
if (self::verify_token(self::$creds_pass, $creds)) {
return true;
} else {
return new WP_Error(
'rest_forbidden',
__('Error'),
array('status' => 404)
);
}
} else {
return new WP_Error(
'rest_forbidden',
__('Error'),
array('status' => 404)
);
}
}

How do I change the output of the serialization from my entity?

$normalizer = new ObjectNormalizer();
// $normalizer->setCircularReferenceLimit(2);
$normalizer->setCircularReferenceHandler(function ($object) {
return $object->getId();
});
$normalizer->setIgnoredAttributes(array('users', '__initializer__', '__cloner__', 'authkey', '__isInitialized__', "products"));
$serializer = new Serializer(array($normalizer), array(new JsonEncoder()));
return new JsonResponse($serializer->serialize($product, 'json'));
Thats the result:
{
"id": 128,
"name": "product",
"price": 12,
"category": {
"id": 58,
"name": "category",
"company": {
"id": 1,
"name": "foo",
"tables": []
}
},
"description": "this is a product",
"company": {
"id": 1,
"name": "foo",
"tables": []
}
}
but how can i get the following result:
{
"id": 128,
"name": "product",
"price": 12,
"category": {
"name": "category"
},
"description": "this is a product",
"company": {
"id": 1,
"name": "foo",
"tables": []
}
}
How can I variate between the values?
for example I want here:
"category": {
"name": "category" },
later the id as well.
Take a look at the serializer component Attributes Groups. I believe this is what you are looking for.
You can select which entity properties should be included in each particular response.
Just simply set group in an entity
/**
* #Groups({"group1", "group2"})
*/
public $foo;
And then specify group or an array of groups for serialization
$serializer = new Serializer(array($normalizer));
$data = $serializer->normalize($obj, null, array('groups' => 'group1'));
Sometimes just groups is not enough, that is when you can use Doctrine hydrator. This is a bit more complex solution, but this gives you much more possibilities.
Normally you would use Attributes Groups when you need to make a simple selection - retrieve one particular entity or a collection of entities with some joined entities (use groups for joins as well). Doctrine hydrator is used when you need an aggregated selection, for example retrieve data from table that does not has specified relation, or add combined data along with regular data.

WooCommerce can't see product variations

I'm trying to manage WooCommerce entirely by its REST API but with no luck, i'm trying to insert a product with variations
I can succesfully create a product with a POST to {{url}}/wp-json/wc/v3/products/
After product creation, i have to create its variations with a POST to a separate endpoint to {{url}}/wp-json/wc/v3/products/{{product_id}}/variations, this works too
I can see the product variation created with a GET in {{url}}/wp-json/wc/v3/products/{{product_id}}/variations and its own GET {{url}}/wp-json/wc/v3/products/{{product_id}}/variations/{{variation_id}}
I can correctly see the rows created in the wordpress database
All calls are a 201 with the expected object as response
However, i'm not able to see any product variations on the woocommerce product page
What i found its that a product with variations that work have an array variations which contains the variations ids, but when i create a product with API the array of the product created is empty, this would explain why i'm not able to see any product variation on the product page.
This is a sample of product variation that I create:
{
"regular_price": "225",
"status": "publish",
"manage_stock": true,
"stock_quantity": 1,
"stock_status": "instock",
"image": {
"src": "https://via.placeholder.com/150"
},
"on_sale": true,
"shipping_class": "1",
"attributes": [
{
"id": 2,
"name": "Color",
"option": "Red"
},
{
"id": 3,
"name": "Size",
"option": "Xl"
}
]}
I was not able to found a similar issue, any thoughts?
The problem could be in the product creation process. I can't know for sure without looking at the data used for product creation, but I'll try anyway. I see that you use two different attributes for the variants. So, the products should be created to support those attributes correctly:
{
"name": "Sample Product",
"type": "Example",
"description": "A Demo Product",
"images": {
{
"src": "path/to/img",
"position": 1
}
},
"categories": {
{
"id": 12
}
},
"attributes": {
{
"id": 2,
"name": "Color",
"variation": true,
"visible": true,
"options": [ 'Red', 'Green', 'Blue' ]
},
{
"id": 3,
"name": "Size",
"variation": true,
"visible": true,
"options": [ 'M', 'L', 'XL' ]
}
}
}
If "variation": true is missing in the main product's attributes, then the variants created under attributes without that flag won't show up as variants. I know it's a shot in the dark, but maybe it'll help you.

Create product variations with python woocommerce api

I am attempting to create a product with variations in WooCommerce but I am getting this error:
{u'message': u'No route was found matching the URL and request method', u'code': u'rest_no_route', u'data': {u'status': 404}}
when I run the create_variation function from the API.
I ran a GET on the attributes for the product I created and it found no attributes even though the printed response when I created the product had the attributes listed.
Here is my code to create the variable product:
data = {
"name": row[3],
"type": "variable",
"description": row[4],
"images": [
{
"src": row[15],
"position": 0
}
],
"in_stock": True,
"sku": row[2],
'attributes': [
{
'name': 'Size',
'variation': True,
'visible': True,
'options': sizeList,
},
{
'name': 'Color',
'variation': True,
'visible': True,
'options': colorList,
}
],
}
print(wcapiNew.post("products", data).json())
Here is my code to create the variations:
result = wcapi.get("products/sku/"+row[2]).json()
product_id = result['product']['id']
variationData = {
"regular_price": row[17],
"image": {
"src": row[13]
},
"sku": row[19],
"attributes": [
{
"name": "Color",
"option": row[6]
},
{
"name": "Size",
"option": row[10]
}
]
}
print(wcapiNew.post("products/"+str(product_id)+"/variations", variationData).json())
I've been tearing my hair out trying to figure out what I'm doing wrong but I'm clueless right now.
Any help is appreciated. Thanks.
This is my variations data, and it work.
data_1 = {
"regular_price": "9.00",
"sku": "premium-quality-101-red",
"attributes": [
{
"id": 1,
"option": "Red"
}]
}
I figure out that you need to use id, and update one variation at a time.

How do you add custom fields defined in posts to the rest API responses in wordpress

I want to do this without using any sort of plugin since these are both core wordpress features (custom fields and the REST API). Here is the documentation for custom fields for reference:
https://codex.wordpress.org/Using_Custom_Fields
Here is a screenshot from my wordpress installation:
Here is what the API response for a post looks like currently:
{
"_links": {
"about": [
{
"href": "http://example.com/wp-json/wp/v2/types/post"
}
],
"author": [
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/users/1"
}
],
"collection": [
{
"href": "http://example.com/wp-json/wp/v2/posts"
}
],
"curies": [
{
"href": "https://api.w.org/{rel}",
"name": "wp",
"templated": true
}
],
"replies": [
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/comments?post=21"
}
],
"self": [
{
"href": "http://example.com/wp-json/wp/v2/posts/21"
}
],
"version-history": [
{
"href": "http://example.com/wp-json/wp/v2/posts/21/revisions"
}
],
"wp:attachment": [
{
"href": "http://example.com/wp-json/wp/v2/media?parent=21"
}
],
"wp:featuredmedia": [
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/media/23"
}
],
"wp:term": [
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/categories?post=21",
"taxonomy": "category"
},
{
"embeddable": true,
"href": "http://example.com/wp-json/wp/v2/tags?post=21",
"taxonomy": "post_tag"
}
]
},
"author": 1,
"categories": [
5,
4
],
"comment_status": "open",
"content": {
"protected": false,
"rendered": ""
},
"date": "2017-05-14T15:25:33",
"date_gmt": "2017-05-14T15:25:33",
"excerpt": {
"protected": false,
"rendered": ""
},
"featured_media": 23,
"format": "standard",
"guid": {
"rendered": "http://example.com/?p=21"
},
"id": 21,
"link": "http://example.com/2017/05/14/post/",
"meta": [],
"modified": "2017-05-15T18:17:34",
"modified_gmt": "2017-05-15T18:17:34",
"ping_status": "open",
"slug": "",
"sticky": false,
"tags": [],
"template": "",
"title": {
"rendered": ""
},
"type": "post"
}
In case it could be relevant, here are my active plugins:
First you need to register_rest_fields to adding custom endpoints in WP REST API JSON Response
add_action( 'rest_api_init', 'add_custom_fields' );
function add_custom_fields() {
register_rest_field(
'post',
'custom_fields', //New Field Name in JSON RESPONSEs
array(
'get_callback' => 'get_custom_fields', // custom function name
'update_callback' => null,
'schema' => null,
)
);
}
Then define your functions to get custom fields
function get_custom_fields( $object, $field_name, $request ) {
//your code goes here
return $customfieldvalue;
}
Tested on local site
For those using Advanced Custom Fields: this is now offered out of the box as of v5.11 on a per-field group basis. Steps:
Edit the field group you want added to the REST API
Under Settings, click Show in REST API
For fine-grain control over what exactly the REST API shows and when, see Documentation > Guides > WP REST API Integration on the ACF website. This includes examples of how to include/exclude individual fields within a field group.
Use this plugin for this solution:
https://wordpress.org/plugins/acf-to-rest-api/ as it allows you to expose the Advanced Custom Fields into their own JSON response via new endpoints listed here https://github.com/airesvsg/acf-to-rest-api#endpoints. You can then forkJoin the two observables (if using Angular) and utilize the combined response toward your purpose.
Suppose we want to add 'sku' and 'price' meta to the 'product' postType
and the rest_api url is :
site_addresses.com/wp-json/wp/v2/product
Put this code in the functions.php
function af_create_custom_meta_in_REST()
{
$post_types = ["product"]; //post types that will include custom fields
foreach ($post_types as $post_type) {
register_rest_field(
$post_type,
'custom_fields',
[
'get_callback' => 'expose_custom_fields',
'schema' => null,
]
);
}
}
function expose_custom_fields($object)
{
$fields = ["_sku", "_price"]; //custom fields name
$post_ID = $object['id'];
$return_value = [];
foreach ($fields as $field) {
$field = strval($field);
$meta = get_post_meta($post_ID, $field);
if (count($meta) > 1)
$return_value[$field] = $meta;
else if ($meta[0])
$return_value[$field] = $meta[0];
else
$return_value[$field] = ""; //if you set this to null result will be 'null'
}
if ($return_value)
return $return_value;
return []; //if you set this to null result will be 'null'
}
add_action('rest_api_init', 'af_create_custom_meta_in_REST');
you can change $post_types or $fields to anything you want
Result image :
image of rest_api reslut
Just add it in your CMS and then it should be available inside your WP REST API.

Resources