/** * Setup payload for subscription webhook delivery. * * @since 2.0 */ public static function create_payload($payload, $resource, $resource_id, $id) { if ('subscription' == $resource && empty($payload) && wcs_is_subscription($resource_id)) { $webhook = new WC_Webhook($id); $event = $webhook->get_event(); $current_user = get_current_user_id(); wp_set_current_user($webhook->get_user_id()); WC()->api->WC_API_Subscriptions->register_routes(array()); $payload = WC()->api->WC_API_Subscriptions->get_subscription($resource_id); wp_set_current_user($current_user); } return $payload; }
/** * Updated the Webhook topic. * * @param WC_Webhook $webhook */ private function update_topic($webhook) { if (!empty($_POST['webhook_topic'])) { $resource = ''; $event = ''; switch ($_POST['webhook_topic']) { case 'custom': if (!empty($_POST['webhook_custom_topic'])) { list($resource, $event) = explode('.', wc_clean($_POST['webhook_custom_topic'])); } break; case 'action': $resource = 'action'; $event = !empty($_POST['webhook_action_event']) ? wc_clean($_POST['webhook_action_event']) : ''; break; default: list($resource, $event) = explode('.', wc_clean($_POST['webhook_topic'])); break; } $topic = $resource . '.' . $event; if (wc_is_webhook_valid_topic($topic)) { $webhook->set_topic($topic); } } }
} // Delete old user keys from usermeta foreach ($api_users as $_user) { $user_id = intval($_user->user_id); delete_user_meta($user_id, 'woocommerce_api_consumer_key'); delete_user_meta($user_id, 'woocommerce_api_consumer_secret'); delete_user_meta($user_id, 'woocommerce_api_key_permissions'); } } /** * Webhooks * Make sure order.update webhooks get the woocommerce_order_edit_status hook */ $order_update_webhooks = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'order.updated')); foreach ($order_update_webhooks as $order_update_webhook) { $webhook = new WC_Webhook($order_update_webhook->ID); $webhook->set_topic('order.updated'); } /** * Refunds for full refunded orders. * Update fully refunded orders to ensure they have a refund line item so reports add up. */ $refunded_orders = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_order', 'post_status' => array('wc-refunded'))); foreach ($refunded_orders as $refunded_order) { $order_total = get_post_meta($refunded_order->ID, '_order_total', true); $refunded_total = $wpdb->get_var($wpdb->prepare("\n\t\tSELECT SUM( postmeta.meta_value )\n\t\tFROM {$wpdb->postmeta} AS postmeta\n\t\tINNER JOIN {$wpdb->posts} AS posts ON ( posts.post_type = 'shop_order_refund' AND posts.post_parent = %d )\n\t\tWHERE postmeta.meta_key = '_refund_amount'\n\t\tAND postmeta.post_id = posts.ID\n\t", $refunded_order->ID)); if ($order_total > $refunded_total) { $refund = wc_create_refund(array('amount' => $order_total - $refunded_total, 'reason' => __('Order Fully Refunded', 'woocommerce'), 'order_id' => $refunded_order->ID, 'line_items' => array(), 'date' => $refunded_order->post_modified)); } } wc_delete_shop_order_transients();
/** * Load & enqueue active webhooks * * @since 2.2 */ private function load_webhooks() { if (false === ($webhooks = get_transient('woocommerce_webhook_ids'))) { $webhooks = get_posts(array('fields' => 'ids', 'post_type' => 'shop_webhook', 'post_status' => 'publish', 'posts_per_page' => -1)); set_transient('woocommerce_webhook_ids', $webhooks); } foreach ($webhooks as $webhook_id) { $webhook = new WC_Webhook($webhook_id); $webhook->enqueue(); } }
/** * Ensure valid webhook data response. * * @since 2.2 * @param array $response * @param WC_Webhook $webhook */ protected function check_get_webhook_response($response, $webhook) { $this->assertEquals($webhook->id, $response['id']); $this->assertEquals($webhook->get_name(), $response['name']); $this->assertEquals($webhook->get_status(), $response['status']); $this->assertEquals($webhook->get_topic(), $response['topic']); $this->assertEquals($webhook->get_resource(), $response['resource']); $this->assertEquals($webhook->get_event(), $response['event']); $this->assertEquals($webhook->get_hooks(), $response['hooks']); $this->assertEquals($webhook->get_delivery_url(), $response['delivery_url']); $this->assertArrayHasKey('created_at', $response); $this->assertArrayHasKey('updated_at', $response); }
/** * Get the delivery log for the given webhook ID and delivery ID * * @since 2.2 * @param string $webhook_id webhook ID * @param string $id delivery log ID * @param string|null $fields fields to limit response to * @return array */ public function get_webhook_delivery($webhook_id, $id, $fields = null) { try { // Validate webhook ID $webhook_id = $this->validate_request($webhook_id, 'shop_webhook', 'read'); if (is_wp_error($webhook_id)) { return $webhook_id; } $id = absint($id); if (empty($id)) { throw new WC_API_Exception('woocommerce_api_invalid_webhook_delivery_id', __('Invalid webhook delivery ID', 'woocommerce'), 404); } $webhook = new WC_Webhook($webhook_id); $log = $webhook->get_delivery_log($id); if (!$log) { throw new WC_API_Exception('woocommerce_api_invalid_webhook_delivery_id', __('Invalid webhook delivery', 'woocommerce'), 400); } $delivery_log = $log; // Add timestamp $delivery_log['created_at'] = $this->server->format_datetime($log['comment']->comment_date_gmt); // Remove comment object unset($delivery_log['comment']); return array('webhook_delivery' => apply_filters('woocommerce_api_webhook_delivery_response', $delivery_log, $id, $fields, $log, $webhook_id, $this)); } catch (WC_API_Exception $e) { return new WP_Error($e->getErrorCode(), $e->getMessage(), array('status' => $e->getCode())); } }
/** * Prepare a single webhook output for response. * * @param WP_REST_Request $request Request object. * @return WP_REST_Response $response Response data. */ public function prepare_item_for_response($post, $request) { $id = (int) $post->ID; $webhook = new WC_Webhook($id); $data = array('id' => $webhook->id, 'name' => $webhook->get_name(), 'status' => $webhook->get_status(), 'topic' => $webhook->get_topic(), 'resource' => $webhook->get_resource(), 'event' => $webhook->get_event(), 'hooks' => $webhook->get_hooks(), 'delivery_url' => $webhook->get_delivery_url(), 'date_created' => wc_rest_prepare_date_response($webhook->get_post_data()->post_date_gmt), 'date_modified' => wc_rest_prepare_date_response($webhook->get_post_data()->post_modified_gmt)); $context = !empty($request['context']) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object($data, $request); $data = $this->filter_response_by_context($data, $context); // Wrap the data in a response object. $response = rest_ensure_response($data); $response->add_links($this->prepare_links($post)); /** * Filter webhook object returned from the REST API. * * @param WP_REST_Response $response The response object. * @param WC_Webhook $webhook Webhook object used to create response. * @param WP_REST_Request $request Request object. */ return apply_filters("woocommerce_rest_prepare_{$this->post_type}", $response, $webhook, $request); }
/** * Load & enqueue active webhooks * * @since 2.2 */ public function load_webhooks() { $args = array('fields' => 'ids', 'post_type' => 'shop_webhook', 'post_status' => 'publish'); $query = new WP_Query($args); if (!empty($query->posts)) { foreach ($query->posts as $id) { $webhook = new WC_Webhook($id); $webhook->enqueue(); } } }
function wc_update_270_webhooks() { /** * Make sure product.update webhooks get the woocommerce_product_quick_edit_save * and woocommerce_product_bulk_edit_save hooks. */ $product_update_webhooks = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'product.updated')); foreach ($product_update_webhooks as $product_update_webhook) { $webhook = new WC_Webhook($product_update_webhook->ID); $webhook->set_topic('product.updated'); } }
function wc_update_240_webhooks() { global $wpdb; /** * Webhooks. * Make sure order.update webhooks get the woocommerce_order_edit_status hook. */ $order_update_webhooks = get_posts(array('posts_per_page' => -1, 'post_type' => 'shop_webhook', 'meta_key' => '_topic', 'meta_value' => 'order.updated')); foreach ($order_update_webhooks as $order_update_webhook) { $webhook = new WC_Webhook($order_update_webhook->ID); $webhook->set_topic('order.updated'); } }
/** * Create Webhook. */ private function create() { if (empty($_REQUEST['_wpnonce']) || !wp_verify_nonce($_REQUEST['_wpnonce'], 'create-webhook')) { wp_die(__('Action failed. Please refresh the page and retry.', 'woocommerce')); } if (!current_user_can('publish_shop_webhooks')) { wp_die(__('You don\'t have permissions to create Webhooks!', 'woocommerce')); } $webhook_id = wp_insert_post(array('post_type' => 'shop_webhook', 'post_status' => 'pending', 'ping_status' => 'closed', 'post_author' => get_current_user_id(), 'post_password' => strlen($password = uniqid('webhook_')) > 20 ? substr($password, 0, 20) : $password, 'post_title' => sprintf(__('Webhook created on %s', 'woocommerce'), strftime(_x('%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce'))), 'comment_status' => 'open')); if (is_wp_error($webhook_id)) { wp_die($webhook_id->get_error_messages()); } update_post_meta($webhook_id, '_webhook_pending_delivery', true); $webhook = new WC_Webhook($webhook_id); $webhook->set_api_version('wp_api_v1'); delete_transient('woocommerce_webhook_ids'); // Redirect to edit page wp_redirect(admin_url('admin.php?page=wc-settings&tab=api§ion=webhooks&edit-webhook=' . $webhook_id . '&created=1')); exit; }
/** * Get a single webhook delivery. * * @param WP_REST_Request $request Full details about the request. * @return WP_Error|WP_REST_Response */ public function get_item($request) { $id = (int) $request['id']; $webhook = new WC_Webhook((int) $request['webhook_id']); if (empty($webhook->post_data->post_type) || 'shop_webhook' !== $webhook->post_data->post_type) { return new WP_Error('woocommerce_rest_webhook_invalid_id', __('Invalid webhook id.', 'woocommerce'), array('status' => 404)); } $log = $webhook->get_delivery_log($id); if (empty($id) || empty($log)) { return new WP_Error('woocommerce_rest_invalid_id', __('Invalid resource id.', 'woocommerce'), array('status' => 404)); } $delivery = $this->prepare_item_for_response((object) $log, $request); $response = rest_ensure_response($delivery); return $response; }
/** * Wrapper function to execute the `woocommerce_deliver_webhook_async` cron * hook, see WC_Webhook::process() * * @since 2.2 * @param int $webhook_id webhook ID to deliver * @param mixed $arg hook argument */ function wc_deliver_webhook_async($webhook_id, $arg) { $webhook = new WC_Webhook($webhook_id); $webhook->deliver($arg); }