I have built a Wordpress plugin that among other things, creates several Woocommerce Webhooks upon activation. This is done using internal API classes and functions, as per below:
function createWebhook($userID,$topic,$secret,$deliveryURL,$status)
{
$webhook = new WC_Webhook();
$webhook->set_user_id($userID); // User ID used while generating the webhook payload.
$webhook->set_topic( $topic ); // Event used to trigger a webhook.
$webhook->set_secret( $secret ); // Secret to validate webhook when received.
$webhook->set_delivery_url( $deliveryURL ); // URL where webhook should be sent.
$webhook->set_status( $status ); // Webhook status.
$save = $webhook->save();
return $save;
}
This works well.
What I want to be able to do is remove these Webhooks upon deactivation of the plugin. Is there any way to fetch the Woocommerce Webhooks via the internal Wordpress or Woocommerce API, so I can loop through and remove the relevant ones?
I would just remove all Webhooks where the delivery URL has a domain of xyz.com. This part is straight-forward, I just don't know how to fetch the Webhooks.
I don't want to use the external Woocommerce API, which requires an API key and HTTP requests.
Thanks
I ended up querying the database to get the webhooks, which looks to be working well. I'm not sure there's any other way. Please let me know if there is!
global $wpdb;
$results = $wpdb->get_results( "SELECT webhook_id, delivery_url FROM {$wpdb->prefix}wc_webhooks" );
foreach($results as $result)
{
if(strpos($result->delivery_url, 'domain.com') !== false)
{
$wh = new WC_Webhook();
$wh->set_id($result->webhook_id);
$wh->delete();
}
}
#greg's answer points you in the right direction, but the returned data is just an array of ID's for each webhook, to get more data you need to parse those ID's into webhook objects - which has protected props, but public getter methods, like so:
$data_store = \WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks([ 'status' => 'active', 'paginate' => true ] );
$_items = array_map( 'wc_get_webhook', $webhooks->webhooks );
$_array = [];
foreach( $_items as $_item ){
$_array[] = [
'id' => $_item->get_id(),
'name' => $_item->get_name(),
'topic' => $_item->get_topic(),
'delivery_url' => $_item->get_delivery_url(),
'secret' => $_item->get_secret(),
];
}
You can get an array of all webhook IDs with the following:
$data_store = WC_Data_Store::load( 'webhook' );
$webhooks = $data_store->search_webhooks();
That's what WooCommerce does when building the table list:
https://github.com/woocommerce/woocommerce/blob/master/includes/admin/class-wc-admin-webhooks-table-list.php
Related
Very odd issue. I have built a plugin (for a client, not a public one) that creates a couple of REST endpoints that a shipping service (Shippo) passes data to (all this is fine and working). The plugin takes the data, gets an Order Number, and attempts to set a Completed status.
The code only works perfectly if the Order is from the Admin account. But any other custom account and the status will not save. An order note is generated claiming the status was changed, and I can set meta data on the order. But the status will not change.
In the code, I have attempted to use update_status() and set_status() both with and without .save();
add_action('rest_api_init', function () {
register_rest_route('lab/v1', '/shipment_label_created_shippo', ['methods' => 'POST', 'callback' => 'rest_shipment_label_created_shippo', 'permission_callback' => '__return_true', ]);
register_rest_route('lab/v1', '/shipment_label_updated_shippo', ['methods' => 'POST', 'callback' => 'rest_shipment_label_updated_shippo', 'permission_callback' => '__return_true', ]);
register_rest_route('lab/v1', '/shipment_tracking_updated_shippo', ['methods' => 'POST', 'callback' => 'rest_shipment_tracking_updated_shippo', 'permission_callback' => '__return_true', ]);});
// Label Created in Shippo (transaction_created)
function rest_shipment_label_created_shippo($data){
$log = new WC_Logger();
$response = new WP_REST_Response("Failed");
$response->set_status(200);
$meta_order_number = $data['data']['metadata'];
$woo_order_number = explode(" ", $meta_order_number);
$order_number = intval($woo_order_number[1]);
if ($shippo_status == "SUCCESS" && !is_null($shippo_order_id)) {
if( class_exists('WC_Order') && $order_number > 0 ) {
$order = wc_get_order($order_number);
if ($order) {
$payment_method = $order->get_payment_method();
$payment_method_title = $order->get_payment_method_title();
$date_paid = $order->get_date_paid();
// Update the Order Meta as well for tracking
$update_order_was_shipped = update_post_meta($order_number, '_order_was_shipped', $date_shipped);
// Add the Shippo Transaction ID
$update_transactionid = update_post_meta($order_number, '_shippo_transaction_id', $shippo_transaction_id);
if ($payment_method == "invoice" && !is_null($date_paid))
{
$order->update_status('shipped-invoiced');
$saved_order_id = $order->save();
}
else
{
$order->update_status('completed');
$saved_order_id = $order->save();
}
}
Thanks in advance for any thoughts you might have!
Just in case someone else stumbles onto this I wanted to answer the question.
The reason it appears as though only Admin orders (orders I placed) are working is because I never had the order tab up. Our client, always had the Order open that they were updating via a 3rd party. When the Rest API was hit by the 3rd party, order details were not saved because the order was locked.
This makes sense of course, but was not top of mind for me.
I want to be able to add meta to a media post type by using WP REST API.
I want to use Postman because, for now, I just want to test how the API is working. The docs seems to be somewhat confusing. I would be grateful if you have any working examples.
Basically, I want to add copyright meta field to the media using this API.
for creating API you need to add route first. you can add route using below code:
function custom_meta_api() {
register_rest_route('wp/v1', '/update_meta/(?P<id>[\d]+)', array(
array(
'methods' => 'POST',
'callback' => 'saveMeta',
),
));
}|
add_action('rest_api_init', 'custom_meta_api');
you can pass your image id in (?P<id>[\d]+)
now in postman write url
http://your-url/wp-json/wp/v1/update_meta/5 with POST request
in body you can write below code
{"data":
{
"copyright":"xyz"
}
}
and to save in postmeta table create function saveMeta(which you have written in callback). Code for the function is below:
function saveMeta(WP_REST_Request $data) {
$bookingID = $data['id'];
$request = $data->get_json_params();
extract($request['data']);
update_post_meta($bookingID, 'copyright', $copyright);
$response = array();
$response["code"] = "success";
$response["message"] = "";
$response["data"] = array();
$response["data"][] = 'meta added';
return $response;
}
is it possible to get post data/type from the wordpress rest api using url as parameter?
I knowing this function already from soundcloud. There is an resolve function with an url parameter (see https://developers.soundcloud.com/docs/api/reference#resolve). When you call this rest api endpoint, you get detailed information if the url is for example a track or playlist.
Unfortunately i couldn't find a function at the wordpress rest api documentation for doing this. What i exactly want is to get the post data/type by only knowing the url
https://demo.wp-api.org/2017/05/23/hello-world/ => post
https://demo.wp-api.org/example => page
https://demo.wp-api.org/category/example => category
With a function like this
https://demo.wp-api.org/wp-json/wp/v2/resolve?url=https://demo.wp-api.org/2017/05/23/hello-world/
Is there a way to do this? Or do i need to write my own rest api endpoint with a wordpress plugin?
this solved the problem
function route_handler($request)
{
global $wp;
global $wp_query;
$parameters = $request->get_json_params();
$url = $parameters["url"];
$_SERVER['REQUEST_URI'] = $url;
$wp->parse_request();
$wp->query_posts();
//Insert queries for more specific information
//Modify or simplify the query results
//Here I'm just returning the query results.
return json_encode($wp_query);
}
add_action('rest_api_init', function () {
register_rest_route('custom-theme/v1', '/route', array(
'methods' => 'POST',
'callback' => 'route_handler',
));
});
see: https://medium.com/#harryhorton/query-wp-rest-api-using-any-permalink-url-f5e4e4dd36b7
You could just get all the posts https://demo.wp-api.org/wp-json/wp/v2/posts and then do some thing like:
$.each(data, function(index, post){
if(post.link == yourUrl){
//yourcode
}
});
If you don't want to write your own endpoint
I want to hide the definition of endpoints in a WordPress rest api... in the case of https://www.wpwhitesecurity.com/wp-json I want to return a 404 or an empty array, but not the list of endpoints of the site.
Some idea?
Thanks!
From version 4.4.0 exists the hook rest_index, the documentation in https://developer.wordpress.org/reference/hooks/rest_index/ describes :
This contains the data describing the API. This includes information
about supported authentication schemes, supported namespaces, routes
available on the API, and a small amount of data about the site.
The next code is working perfectly as I needed :
function my_site_rest_index( $response ){
return array();
}
add_filter('rest_index', 'my_site_rest_index');
function chuck_disable_rest_endpoints( $access ) {
if( ! is_user_logged_in() ) {
return new WP_Error( 'rest_cannot_access', __( 'Only logged users are able to call REST API.', 'disable-json-api' ), array( 'status' => rest_authorization_required_code() ) );
}return $access;
}
add_filter( 'rest_authentication_errors', 'chuck_disable_rest_endpoints' );
This will return that only logged users can access to API
So I'm trying to work with the WP REST API. Using latest version of WP. I am using this in an external application and testing with Postman.
This is what I want to do:
display custom meta fields in the GET posts request
GET all posts (no limit)
create / update / delete (multiple) meta fields in one API request
Are these things possible with WP REST API? If so, can anyone share some examples?
I know all these work very well with WooCommerce REST API.
The better way is to use a custom endpoint to achieve this. You must create your own plugin for this...
//register different functions for different methods, use parameters in url for GET calls
register_rest_route('plugin_name', 'your_endpoint', array(
array('methods' => 'POST',
'callback' => 'magic_function',
))
);
function magic_function( $request ) {
//You can filter the query to get all posts (rest_{$this->post_type}_query)
add_filter('rest_post_query','my_custom_query', 10, 3);
$custom_request = new WP_REST_Request( 'GET', '/wp/v2/post');
$response= rest_do_request( $custom_request );
$response->data['meta_field'] = get_post_meta($response->data['id'], 'meta_field',true);
return new WP_REST_Response($response->data);
}
function my_custom_query($args, $request){
//returns all posts in request...
$args['numberposts'] = -1;
return $args;
}