WC_API_Webhooks

The WooCommerce WC API Webhooks class.

Defined (2)

The class is defined in the following location(s).

/includes/api/legacy/v2/class-wc-api-webhooks.php  
  1. class WC_API_Webhooks extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/webhooks'; 
  5.  
  6. /** 
  7. * Register the routes for this class 
  8. * @since 2.2 
  9. * @param array $routes 
  10. * @return array 
  11. */ 
  12. public function register_routes( $routes ) { 
  13.  
  14. # GET|POST /webhooks 
  15. $routes[ $this->base ] = array( 
  16. array( array( $this, 'get_webhooks' ), WC_API_Server::READABLE ),  
  17. array( array( $this, 'create_webhook' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),  
  18. ); 
  19.  
  20. # GET /webhooks/count 
  21. $routes[ $this->base . '/count' ] = array( 
  22. array( array( $this, 'get_webhooks_count' ), WC_API_Server::READABLE ),  
  23. ); 
  24.  
  25. # GET|PUT|DELETE /webhooks/<id> 
  26. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  27. array( array( $this, 'get_webhook' ), WC_API_Server::READABLE ),  
  28. array( array( $this, 'edit_webhook' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),  
  29. array( array( $this, 'delete_webhook' ), WC_API_Server::DELETABLE ),  
  30. ); 
  31.  
  32. # GET /webhooks/<id>/deliveries 
  33. $routes[ $this->base . '/(?P<webhook_id>\d+)/deliveries' ] = array( 
  34. array( array( $this, 'get_webhook_deliveries' ), WC_API_Server::READABLE ),  
  35. ); 
  36.  
  37. # GET /webhooks/<webhook_id>/deliveries/<id> 
  38. $routes[ $this->base . '/(?P<webhook_id>\d+)/deliveries/(?P<id>\d+)' ] = array( 
  39. array( array( $this, 'get_webhook_delivery' ), WC_API_Server::READABLE ),  
  40. ); 
  41.  
  42. return $routes; 
  43.  
  44. /** 
  45. * Get all webhooks 
  46. * @since 2.2 
  47. * @param array $fields 
  48. * @param array $filter 
  49. * @param int $page 
  50. * @return array 
  51. */ 
  52. public function get_webhooks( $fields = null, $filter = array(), $status = null, $page = 1 ) { 
  53.  
  54. if ( ! empty( $status ) ) { 
  55. $filter['status'] = $status; 
  56.  
  57. $filter['page'] = $page; 
  58.  
  59. $query = $this->query_webhooks( $filter ); 
  60.  
  61. $webhooks = array(); 
  62.  
  63. foreach ( $query->posts as $webhook_id ) { 
  64.  
  65. if ( ! $this->is_readable( $webhook_id ) ) { 
  66. continue; 
  67.  
  68. $webhooks[] = current( $this->get_webhook( $webhook_id, $fields ) ); 
  69.  
  70. $this->server->add_pagination_headers( $query ); 
  71.  
  72. return array( 'webhooks' => $webhooks ); 
  73.  
  74. /** 
  75. * Get the webhook for the given ID 
  76. * @since 2.2 
  77. * @param int $id webhook ID 
  78. * @param array $fields 
  79. * @return array 
  80. */ 
  81. public function get_webhook( $id, $fields = null ) { 
  82.  
  83. // ensure webhook ID is valid & user has permission to read 
  84. $id = $this->validate_request( $id, 'shop_webhook', 'read' ); 
  85.  
  86. if ( is_wp_error( $id ) ) { 
  87. return $id; 
  88.  
  89. $webhook = new WC_Webhook( $id ); 
  90.  
  91. $webhook_data = array( 
  92. 'id' => $webhook->id,  
  93. 'name' => $webhook->get_name(),  
  94. 'status' => $webhook->get_status(),  
  95. 'topic' => $webhook->get_topic(),  
  96. 'resource' => $webhook->get_resource(),  
  97. 'event' => $webhook->get_event(),  
  98. 'hooks' => $webhook->get_hooks(),  
  99. 'delivery_url' => $webhook->get_delivery_url(),  
  100. 'created_at' => $this->server->format_datetime( $webhook->get_post_data()->post_date_gmt ),  
  101. 'updated_at' => $this->server->format_datetime( $webhook->get_post_data()->post_modified_gmt ),  
  102. ); 
  103.  
  104. return array( 'webhook' => apply_filters( 'woocommerce_api_webhook_response', $webhook_data, $webhook, $fields, $this ) ); 
  105.  
  106. /** 
  107. * Get the total number of webhooks 
  108. * @since 2.2 
  109. * @param string $status 
  110. * @param array $filter 
  111. * @return array 
  112. */ 
  113. public function get_webhooks_count( $status = null, $filter = array() ) { 
  114. try { 
  115. if ( ! current_user_can( 'read_private_shop_webhooks' ) ) { 
  116. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_webhooks_count', __( 'You do not have permission to read the webhooks count', 'woocommerce' ), 401 ); 
  117.  
  118. if ( ! empty( $status ) ) { 
  119. $filter['status'] = $status; 
  120.  
  121. $query = $this->query_webhooks( $filter ); 
  122.  
  123. return array( 'count' => (int) $query->found_posts ); 
  124. } catch ( WC_API_Exception $e ) { 
  125. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  126.  
  127. /** 
  128. * Create an webhook 
  129. * @since 2.2 
  130. * @param array $data parsed webhook data 
  131. * @return array 
  132. */ 
  133. public function create_webhook( $data ) { 
  134.  
  135. try { 
  136. if ( ! isset( $data['webhook'] ) ) { 
  137. throw new WC_API_Exception( 'woocommerce_api_missing_webhook_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'webhook' ), 400 ); 
  138.  
  139. $data = $data['webhook']; 
  140.  
  141. // permission check 
  142. if ( ! current_user_can( 'publish_shop_webhooks' ) ) { 
  143. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_webhooks', __( 'You do not have permission to create webhooks.', 'woocommerce' ), 401 ); 
  144.  
  145. $data = apply_filters( 'woocommerce_api_create_webhook_data', $data, $this ); 
  146.  
  147. // validate topic 
  148. if ( empty( $data['topic'] ) || ! wc_is_webhook_valid_topic( strtolower( $data['topic'] ) ) ) { 
  149. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_topic', __( 'Webhook topic is required and must be valid.', 'woocommerce' ), 400 ); 
  150.  
  151. // validate delivery URL 
  152. if ( empty( $data['delivery_url'] ) || ! wc_is_valid_url( $data['delivery_url'] ) ) { 
  153. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_url', __( 'Webhook delivery URL must be a valid URL starting with http:// or https://', 'woocommerce' ), 400 ); 
  154.  
  155. $webhook_data = apply_filters( 'woocommerce_new_webhook_data', array( 
  156. 'post_type' => 'shop_webhook',  
  157. 'post_status' => 'publish',  
  158. 'ping_status' => 'closed',  
  159. 'post_author' => get_current_user_id(),  
  160. 'post_password' => strlen( ( $password = uniqid( 'webhook_' ) ) ) > 20 ? substr( $password, 0, 20 ) : $password,  
  161. // @codingStandardsIgnoreStart 
  162. 'post_title' => ! empty( $data['name'] ) ? $data['name'] : sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ),  
  163. // @codingStandardsIgnoreEnd 
  164. ), $data, $this ); 
  165.  
  166. $webhook_id = wp_insert_post( $webhook_data ); 
  167.  
  168. if ( is_wp_error( $webhook_id ) || ! $webhook_id ) { 
  169. throw new WC_API_Exception( 'woocommerce_api_cannot_create_webhook', sprintf( __( 'Cannot create webhook: %s', 'woocommerce' ), is_wp_error( $webhook_id ) ? implode( ', ', $webhook_id->get_error_messages() ) : '0' ), 500 ); 
  170.  
  171. $webhook = new WC_Webhook( $webhook_id ); 
  172.  
  173. // set topic, delivery URL, and optional secret 
  174. $webhook->set_topic( $data['topic'] ); 
  175. $webhook->set_delivery_url( $data['delivery_url'] ); 
  176.  
  177. // set secret if provided, defaults to API users consumer secret 
  178. $webhook->set_secret( ! empty( $data['secret'] ) ? $data['secret'] : '' ); 
  179.  
  180. // Set API version to legacy v3. 
  181. $webhook->set_api_version( 'legacy_v3' ); 
  182.  
  183. // send ping 
  184. $webhook->deliver_ping(); 
  185.  
  186. // HTTP 201 Created 
  187. $this->server->send_status( 201 ); 
  188.  
  189. do_action( 'woocommerce_api_create_webhook', $webhook->id, $this ); 
  190.  
  191. delete_transient( 'woocommerce_webhook_ids' ); 
  192.  
  193. return $this->get_webhook( $webhook->id ); 
  194.  
  195. } catch ( WC_API_Exception $e ) { 
  196.  
  197. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  198.  
  199. /** 
  200. * Edit a webhook 
  201. * @since 2.2 
  202. * @param int $id webhook ID 
  203. * @param array $data parsed webhook data 
  204. * @return array 
  205. */ 
  206. public function edit_webhook( $id, $data ) { 
  207.  
  208. try { 
  209. if ( ! isset( $data['webhook'] ) ) { 
  210. throw new WC_API_Exception( 'woocommerce_api_missing_webhook_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'webhook' ), 400 ); 
  211.  
  212. $data = $data['webhook']; 
  213.  
  214. $id = $this->validate_request( $id, 'shop_webhook', 'edit' ); 
  215.  
  216. if ( is_wp_error( $id ) ) { 
  217. return $id; 
  218.  
  219. $data = apply_filters( 'woocommerce_api_edit_webhook_data', $data, $id, $this ); 
  220.  
  221. $webhook = new WC_Webhook( $id ); 
  222.  
  223. // update topic 
  224. if ( ! empty( $data['topic'] ) ) { 
  225.  
  226. if ( wc_is_webhook_valid_topic( strtolower( $data['topic'] ) ) ) { 
  227.  
  228. $webhook->set_topic( $data['topic'] ); 
  229.  
  230. } else { 
  231. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_topic', __( 'Webhook topic must be valid.', 'woocommerce' ), 400 ); 
  232.  
  233. // update delivery URL 
  234. if ( ! empty( $data['delivery_url'] ) ) { 
  235. if ( wc_is_valid_url( $data['delivery_url'] ) ) { 
  236.  
  237. $webhook->set_delivery_url( $data['delivery_url'] ); 
  238.  
  239. } else { 
  240. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_url', __( 'Webhook delivery URL must be a valid URL starting with http:// or https://', 'woocommerce' ), 400 ); 
  241.  
  242. // update secret 
  243. if ( ! empty( $data['secret'] ) ) { 
  244. $webhook->set_secret( $data['secret'] ); 
  245.  
  246. // update status 
  247. if ( ! empty( $data['status'] ) ) { 
  248. $webhook->update_status( $data['status'] ); 
  249.  
  250. // update user ID 
  251. $webhook_data = array( 
  252. 'ID' => $webhook->id,  
  253. 'post_author' => get_current_user_id(),  
  254. ); 
  255.  
  256. // update name 
  257. if ( ! empty( $data['name'] ) ) { 
  258. $webhook_data['post_title'] = $data['name']; 
  259.  
  260. // update post 
  261. wp_update_post( $webhook_data ); 
  262.  
  263. do_action( 'woocommerce_api_edit_webhook', $webhook->id, $this ); 
  264.  
  265. delete_transient( 'woocommerce_webhook_ids' ); 
  266.  
  267. return $this->get_webhook( $id ); 
  268.  
  269. } catch ( WC_API_Exception $e ) { 
  270.  
  271. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  272.  
  273. /** 
  274. * Delete a webhook 
  275. * @since 2.2 
  276. * @param int $id webhook ID 
  277. * @return array 
  278. */ 
  279. public function delete_webhook( $id ) { 
  280.  
  281. $id = $this->validate_request( $id, 'shop_webhook', 'delete' ); 
  282.  
  283. if ( is_wp_error( $id ) ) { 
  284. return $id; 
  285.  
  286. do_action( 'woocommerce_api_delete_webhook', $id, $this ); 
  287.  
  288. delete_transient( 'woocommerce_webhook_ids' ); 
  289.  
  290. // no way to manage trashed webhooks at the moment, so force delete 
  291. return $this->delete( $id, 'webhook', true ); 
  292.  
  293. /** 
  294. * Helper method to get webhook post objects 
  295. * @since 2.2 
  296. * @param array $args request arguments for filtering query 
  297. * @return WP_Query 
  298. */ 
  299. private function query_webhooks( $args ) { 
  300.  
  301. // Set base query arguments 
  302. $query_args = array( 
  303. 'fields' => 'ids',  
  304. 'post_type' => 'shop_webhook',  
  305. ); 
  306.  
  307. // Add status argument 
  308. if ( ! empty( $args['status'] ) ) { 
  309.  
  310. switch ( $args['status'] ) { 
  311. case 'active': 
  312. $query_args['post_status'] = 'publish'; 
  313. break; 
  314. case 'paused': 
  315. $query_args['post_status'] = 'draft'; 
  316. break; 
  317. case 'disabled': 
  318. $query_args['post_status'] = 'pending'; 
  319. break; 
  320. default: 
  321. $query_args['post_status'] = 'publish'; 
  322. unset( $args['status'] ); 
  323.  
  324. $query_args = $this->merge_query_args( $query_args, $args ); 
  325.  
  326. return new WP_Query( $query_args ); 
  327.  
  328. /** 
  329. * Get deliveries for a webhook 
  330. * @since 2.2 
  331. * @param string $webhook_id webhook ID 
  332. * @param string|null $fields fields to include in response 
  333. * @return array 
  334. */ 
  335. public function get_webhook_deliveries( $webhook_id, $fields = null ) { 
  336.  
  337. // Ensure ID is valid webhook ID 
  338. $webhook_id = $this->validate_request( $webhook_id, 'shop_webhook', 'read' ); 
  339.  
  340. if ( is_wp_error( $webhook_id ) ) { 
  341. return $webhook_id; 
  342.  
  343. $webhook = new WC_Webhook( $webhook_id ); 
  344. $logs = $webhook->get_delivery_logs(); 
  345. $delivery_logs = array(); 
  346.  
  347. foreach ( $logs as $log ) { 
  348.  
  349. // Add timestamp 
  350. $log['created_at'] = $this->server->format_datetime( $log['comment']->comment_date_gmt ); 
  351.  
  352. // Remove comment object 
  353. unset( $log['comment'] ); 
  354.  
  355. $delivery_logs[] = $log; 
  356.  
  357. return array( 'webhook_deliveries' => $delivery_logs ); 
  358.  
  359. /** 
  360. * Get the delivery log for the given webhook ID and delivery ID 
  361. * @since 2.2 
  362. * @param string $webhook_id webhook ID 
  363. * @param string $id delivery log ID 
  364. * @param string|null $fields fields to limit response to 
  365. * @return array 
  366. */ 
  367. public function get_webhook_delivery( $webhook_id, $id, $fields = null ) { 
  368. try { 
  369. // Validate webhook ID 
  370. $webhook_id = $this->validate_request( $webhook_id, 'shop_webhook', 'read' ); 
  371.  
  372. if ( is_wp_error( $webhook_id ) ) { 
  373. return $webhook_id; 
  374.  
  375. $id = absint( $id ); 
  376.  
  377. if ( empty( $id ) ) { 
  378. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_id', __( 'Invalid webhook delivery ID.', 'woocommerce' ), 404 ); 
  379.  
  380. $webhook = new WC_Webhook( $webhook_id ); 
  381.  
  382. $log = $webhook->get_delivery_log( $id ); 
  383.  
  384. if ( ! $log ) { 
  385. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_id', __( 'Invalid webhook delivery.', 'woocommerce' ), 400 ); 
  386.  
  387. $delivery_log = $log; 
  388.  
  389. // Add timestamp 
  390. $delivery_log['created_at'] = $this->server->format_datetime( $log['comment']->comment_date_gmt ); 
  391.  
  392. // Remove comment object 
  393. unset( $delivery_log['comment'] ); 
  394.  
  395. return array( 'webhook_delivery' => apply_filters( 'woocommerce_api_webhook_delivery_response', $delivery_log, $id, $fields, $log, $webhook_id, $this ) ); 
  396. } catch ( WC_API_Exception $e ) { 
  397. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
/includes/api/legacy/v3/class-wc-api-webhooks.php  
  1. class WC_API_Webhooks extends WC_API_Resource { 
  2.  
  3. /** @var string $base the route base */ 
  4. protected $base = '/webhooks'; 
  5.  
  6. /** 
  7. * Register the routes for this class 
  8. * @since 2.2 
  9. * @param array $routes 
  10. * @return array 
  11. */ 
  12. public function register_routes( $routes ) { 
  13.  
  14. # GET|POST /webhooks 
  15. $routes[ $this->base ] = array( 
  16. array( array( $this, 'get_webhooks' ), WC_API_Server::READABLE ),  
  17. array( array( $this, 'create_webhook' ), WC_API_Server::CREATABLE | WC_API_Server::ACCEPT_DATA ),  
  18. ); 
  19.  
  20. # GET /webhooks/count 
  21. $routes[ $this->base . '/count' ] = array( 
  22. array( array( $this, 'get_webhooks_count' ), WC_API_Server::READABLE ),  
  23. ); 
  24.  
  25. # GET|PUT|DELETE /webhooks/<id> 
  26. $routes[ $this->base . '/(?P<id>\d+)' ] = array( 
  27. array( array( $this, 'get_webhook' ), WC_API_Server::READABLE ),  
  28. array( array( $this, 'edit_webhook' ), WC_API_Server::EDITABLE | WC_API_Server::ACCEPT_DATA ),  
  29. array( array( $this, 'delete_webhook' ), WC_API_Server::DELETABLE ),  
  30. ); 
  31.  
  32. # GET /webhooks/<id>/deliveries 
  33. $routes[ $this->base . '/(?P<webhook_id>\d+)/deliveries' ] = array( 
  34. array( array( $this, 'get_webhook_deliveries' ), WC_API_Server::READABLE ),  
  35. ); 
  36.  
  37. # GET /webhooks/<webhook_id>/deliveries/<id> 
  38. $routes[ $this->base . '/(?P<webhook_id>\d+)/deliveries/(?P<id>\d+)' ] = array( 
  39. array( array( $this, 'get_webhook_delivery' ), WC_API_Server::READABLE ),  
  40. ); 
  41.  
  42. return $routes; 
  43.  
  44. /** 
  45. * Get all webhooks 
  46. * @since 2.2 
  47. * @param array $fields 
  48. * @param array $filter 
  49. * @param int $page 
  50. * @return array 
  51. */ 
  52. public function get_webhooks( $fields = null, $filter = array(), $status = null, $page = 1 ) { 
  53.  
  54. if ( ! empty( $status ) ) { 
  55. $filter['status'] = $status; 
  56.  
  57. $filter['page'] = $page; 
  58.  
  59. $query = $this->query_webhooks( $filter ); 
  60.  
  61. $webhooks = array(); 
  62.  
  63. foreach ( $query->posts as $webhook_id ) { 
  64.  
  65. if ( ! $this->is_readable( $webhook_id ) ) { 
  66. continue; 
  67.  
  68. $webhooks[] = current( $this->get_webhook( $webhook_id, $fields ) ); 
  69.  
  70. $this->server->add_pagination_headers( $query ); 
  71.  
  72. return array( 'webhooks' => $webhooks ); 
  73.  
  74. /** 
  75. * Get the webhook for the given ID 
  76. * @since 2.2 
  77. * @param int $id webhook ID 
  78. * @param array $fields 
  79. * @return array 
  80. */ 
  81. public function get_webhook( $id, $fields = null ) { 
  82.  
  83. // ensure webhook ID is valid & user has permission to read 
  84. $id = $this->validate_request( $id, 'shop_webhook', 'read' ); 
  85.  
  86. if ( is_wp_error( $id ) ) { 
  87. return $id; 
  88.  
  89. $webhook = new WC_Webhook( $id ); 
  90.  
  91. $webhook_data = array( 
  92. 'id' => $webhook->id,  
  93. 'name' => $webhook->get_name(),  
  94. 'status' => $webhook->get_status(),  
  95. 'topic' => $webhook->get_topic(),  
  96. 'resource' => $webhook->get_resource(),  
  97. 'event' => $webhook->get_event(),  
  98. 'hooks' => $webhook->get_hooks(),  
  99. 'delivery_url' => $webhook->get_delivery_url(),  
  100. 'created_at' => $this->server->format_datetime( $webhook->get_post_data()->post_date_gmt ),  
  101. 'updated_at' => $this->server->format_datetime( $webhook->get_post_data()->post_modified_gmt ),  
  102. ); 
  103.  
  104. return array( 'webhook' => apply_filters( 'woocommerce_api_webhook_response', $webhook_data, $webhook, $fields, $this ) ); 
  105.  
  106. /** 
  107. * Get the total number of webhooks 
  108. * @since 2.2 
  109. * @param string $status 
  110. * @param array $filter 
  111. * @return array 
  112. */ 
  113. public function get_webhooks_count( $status = null, $filter = array() ) { 
  114. try { 
  115. if ( ! current_user_can( 'read_private_shop_webhooks' ) ) { 
  116. throw new WC_API_Exception( 'woocommerce_api_user_cannot_read_webhooks_count', __( 'You do not have permission to read the webhooks count', 'woocommerce' ), 401 ); 
  117.  
  118. if ( ! empty( $status ) ) { 
  119. $filter['status'] = $status; 
  120.  
  121. $query = $this->query_webhooks( $filter ); 
  122.  
  123. return array( 'count' => (int) $query->found_posts ); 
  124. } catch ( WC_API_Exception $e ) { 
  125. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  126.  
  127. /** 
  128. * Create an webhook 
  129. * @since 2.2 
  130. * @param array $data parsed webhook data 
  131. * @return array 
  132. */ 
  133. public function create_webhook( $data ) { 
  134.  
  135. try { 
  136. if ( ! isset( $data['webhook'] ) ) { 
  137. throw new WC_API_Exception( 'woocommerce_api_missing_webhook_data', sprintf( __( 'No %1$s data specified to create %1$s', 'woocommerce' ), 'webhook' ), 400 ); 
  138.  
  139. $data = $data['webhook']; 
  140.  
  141. // permission check 
  142. if ( ! current_user_can( 'publish_shop_webhooks' ) ) { 
  143. throw new WC_API_Exception( 'woocommerce_api_user_cannot_create_webhooks', __( 'You do not have permission to create webhooks.', 'woocommerce' ), 401 ); 
  144.  
  145. $data = apply_filters( 'woocommerce_api_create_webhook_data', $data, $this ); 
  146.  
  147. // validate topic 
  148. if ( empty( $data['topic'] ) || ! wc_is_webhook_valid_topic( strtolower( $data['topic'] ) ) ) { 
  149. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_topic', __( 'Webhook topic is required and must be valid.', 'woocommerce' ), 400 ); 
  150.  
  151. // validate delivery URL 
  152. if ( empty( $data['delivery_url'] ) || ! wc_is_valid_url( $data['delivery_url'] ) ) { 
  153. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_url', __( 'Webhook delivery URL must be a valid URL starting with http:// or https://', 'woocommerce' ), 400 ); 
  154.  
  155. $webhook_data = apply_filters( 'woocommerce_new_webhook_data', array( 
  156. 'post_type' => 'shop_webhook',  
  157. 'post_status' => 'publish',  
  158. 'ping_status' => 'closed',  
  159. 'post_author' => get_current_user_id(),  
  160. 'post_password' => strlen( ( $password = uniqid( 'webhook_' ) ) ) > 20 ? substr( $password, 0, 20 ) : $password,  
  161. // @codingStandardsIgnoreStart 
  162. 'post_title' => ! empty( $data['name'] ) ? $data['name'] : sprintf( __( 'Webhook created on %s', 'woocommerce' ), strftime( _x( '%b %d, %Y @ %I:%M %p', 'Webhook created on date parsed by strftime', 'woocommerce' ) ) ),  
  163. // @codingStandardsIgnoreEnd 
  164. ), $data, $this ); 
  165.  
  166. $webhook_id = wp_insert_post( $webhook_data ); 
  167.  
  168. if ( is_wp_error( $webhook_id ) || ! $webhook_id ) { 
  169. throw new WC_API_Exception( 'woocommerce_api_cannot_create_webhook', sprintf( __( 'Cannot create webhook: %s', 'woocommerce' ), is_wp_error( $webhook_id ) ? implode( ', ', $webhook_id->get_error_messages() ) : '0' ), 500 ); 
  170.  
  171. $webhook = new WC_Webhook( $webhook_id ); 
  172.  
  173. // set topic, delivery URL, and optional secret 
  174. $webhook->set_topic( $data['topic'] ); 
  175. $webhook->set_delivery_url( $data['delivery_url'] ); 
  176.  
  177. // set secret if provided, defaults to API users consumer secret 
  178. $webhook->set_secret( ! empty( $data['secret'] ) ? $data['secret'] : '' ); 
  179.  
  180. // Set API version to legacy v3. 
  181. $webhook->set_api_version( 'legacy_v3' ); 
  182.  
  183. // send ping 
  184. $webhook->deliver_ping(); 
  185.  
  186. // HTTP 201 Created 
  187. $this->server->send_status( 201 ); 
  188.  
  189. do_action( 'woocommerce_api_create_webhook', $webhook->id, $this ); 
  190.  
  191. delete_transient( 'woocommerce_webhook_ids' ); 
  192.  
  193. return $this->get_webhook( $webhook->id ); 
  194.  
  195. } catch ( WC_API_Exception $e ) { 
  196.  
  197. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  198.  
  199. /** 
  200. * Edit a webhook 
  201. * @since 2.2 
  202. * @param int $id webhook ID 
  203. * @param array $data parsed webhook data 
  204. * @return array 
  205. */ 
  206. public function edit_webhook( $id, $data ) { 
  207.  
  208. try { 
  209. if ( ! isset( $data['webhook'] ) ) { 
  210. throw new WC_API_Exception( 'woocommerce_api_missing_webhook_data', sprintf( __( 'No %1$s data specified to edit %1$s', 'woocommerce' ), 'webhook' ), 400 ); 
  211.  
  212. $data = $data['webhook']; 
  213.  
  214. $id = $this->validate_request( $id, 'shop_webhook', 'edit' ); 
  215.  
  216. if ( is_wp_error( $id ) ) { 
  217. return $id; 
  218.  
  219. $data = apply_filters( 'woocommerce_api_edit_webhook_data', $data, $id, $this ); 
  220.  
  221. $webhook = new WC_Webhook( $id ); 
  222.  
  223. // update topic 
  224. if ( ! empty( $data['topic'] ) ) { 
  225.  
  226. if ( wc_is_webhook_valid_topic( strtolower( $data['topic'] ) ) ) { 
  227.  
  228. $webhook->set_topic( $data['topic'] ); 
  229.  
  230. } else { 
  231. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_topic', __( 'Webhook topic must be valid.', 'woocommerce' ), 400 ); 
  232.  
  233. // update delivery URL 
  234. if ( ! empty( $data['delivery_url'] ) ) { 
  235. if ( wc_is_valid_url( $data['delivery_url'] ) ) { 
  236.  
  237. $webhook->set_delivery_url( $data['delivery_url'] ); 
  238.  
  239. } else { 
  240. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_url', __( 'Webhook delivery URL must be a valid URL starting with http:// or https://', 'woocommerce' ), 400 ); 
  241.  
  242. // update secret 
  243. if ( ! empty( $data['secret'] ) ) { 
  244. $webhook->set_secret( $data['secret'] ); 
  245.  
  246. // update status 
  247. if ( ! empty( $data['status'] ) ) { 
  248. $webhook->update_status( $data['status'] ); 
  249.  
  250. // update user ID 
  251. $webhook_data = array( 
  252. 'ID' => $webhook->id,  
  253. 'post_author' => get_current_user_id(),  
  254. ); 
  255.  
  256. // update name 
  257. if ( ! empty( $data['name'] ) ) { 
  258. $webhook_data['post_title'] = $data['name']; 
  259.  
  260. // update post 
  261. wp_update_post( $webhook_data ); 
  262.  
  263. do_action( 'woocommerce_api_edit_webhook', $webhook->id, $this ); 
  264.  
  265. delete_transient( 'woocommerce_webhook_ids' ); 
  266.  
  267. return $this->get_webhook( $id ); 
  268.  
  269. } catch ( WC_API_Exception $e ) { 
  270.  
  271. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) ); 
  272.  
  273. /** 
  274. * Delete a webhook 
  275. * @since 2.2 
  276. * @param int $id webhook ID 
  277. * @return array 
  278. */ 
  279. public function delete_webhook( $id ) { 
  280.  
  281. $id = $this->validate_request( $id, 'shop_webhook', 'delete' ); 
  282.  
  283. if ( is_wp_error( $id ) ) { 
  284. return $id; 
  285.  
  286. do_action( 'woocommerce_api_delete_webhook', $id, $this ); 
  287.  
  288. delete_transient( 'woocommerce_webhook_ids' ); 
  289.  
  290. // no way to manage trashed webhooks at the moment, so force delete 
  291. return $this->delete( $id, 'webhook', true ); 
  292.  
  293. /** 
  294. * Helper method to get webhook post objects 
  295. * @since 2.2 
  296. * @param array $args request arguments for filtering query. 
  297. * @return WP_Query 
  298. */ 
  299. private function query_webhooks( $args ) { 
  300.  
  301. // Set base query arguments. 
  302. $query_args = array( 
  303. 'fields' => 'ids',  
  304. 'post_type' => 'shop_webhook',  
  305. ); 
  306.  
  307. // Add status argument. 
  308. if ( ! empty( $args['status'] ) ) { 
  309. switch ( $args['status'] ) { 
  310. case 'active' : 
  311. $query_args['post_status'] = 'publish'; 
  312. break; 
  313. case 'paused' : 
  314. $query_args['post_status'] = 'draft'; 
  315. break; 
  316. case 'disabled' : 
  317. $query_args['post_status'] = 'pending'; 
  318. break; 
  319. case 'all' : 
  320. $query_args['post_status'] = 'any'; 
  321. break; 
  322. default : 
  323. $query_args['post_status'] = 'publish'; 
  324. break; 
  325. unset( $args['status'] ); 
  326.  
  327. $query_args = $this->merge_query_args( $query_args, $args ); 
  328.  
  329. return new WP_Query( $query_args ); 
  330.  
  331. /** 
  332. * Get deliveries for a webhook 
  333. * @since 2.2 
  334. * @param string $webhook_id webhook ID 
  335. * @param string|null $fields fields to include in response 
  336. * @return array 
  337. */ 
  338. public function get_webhook_deliveries( $webhook_id, $fields = null ) { 
  339.  
  340. // Ensure ID is valid webhook ID 
  341. $webhook_id = $this->validate_request( $webhook_id, 'shop_webhook', 'read' ); 
  342.  
  343. if ( is_wp_error( $webhook_id ) ) { 
  344. return $webhook_id; 
  345.  
  346. $webhook = new WC_Webhook( $webhook_id ); 
  347. $logs = $webhook->get_delivery_logs(); 
  348. $delivery_logs = array(); 
  349.  
  350. foreach ( $logs as $log ) { 
  351.  
  352. // Add timestamp 
  353. $log['created_at'] = $this->server->format_datetime( $log['comment']->comment_date_gmt ); 
  354.  
  355. // Remove comment object 
  356. unset( $log['comment'] ); 
  357.  
  358. $delivery_logs[] = $log; 
  359.  
  360. return array( 'webhook_deliveries' => $delivery_logs ); 
  361.  
  362. /** 
  363. * Get the delivery log for the given webhook ID and delivery ID 
  364. * @since 2.2 
  365. * @param string $webhook_id webhook ID 
  366. * @param string $id delivery log ID 
  367. * @param string|null $fields fields to limit response to 
  368. * @return array 
  369. */ 
  370. public function get_webhook_delivery( $webhook_id, $id, $fields = null ) { 
  371. try { 
  372. // Validate webhook ID 
  373. $webhook_id = $this->validate_request( $webhook_id, 'shop_webhook', 'read' ); 
  374.  
  375. if ( is_wp_error( $webhook_id ) ) { 
  376. return $webhook_id; 
  377.  
  378. $id = absint( $id ); 
  379.  
  380. if ( empty( $id ) ) { 
  381. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_id', __( 'Invalid webhook delivery ID.', 'woocommerce' ), 404 ); 
  382.  
  383. $webhook = new WC_Webhook( $webhook_id ); 
  384.  
  385. $log = $webhook->get_delivery_log( $id ); 
  386.  
  387. if ( ! $log ) { 
  388. throw new WC_API_Exception( 'woocommerce_api_invalid_webhook_delivery_id', __( 'Invalid webhook delivery.', 'woocommerce' ), 400 ); 
  389.  
  390. $delivery_log = $log; 
  391.  
  392. // Add timestamp 
  393. $delivery_log['created_at'] = $this->server->format_datetime( $log['comment']->comment_date_gmt ); 
  394.  
  395. // Remove comment object 
  396. unset( $delivery_log['comment'] ); 
  397.  
  398. return array( 'webhook_delivery' => apply_filters( 'woocommerce_api_webhook_delivery_response', $delivery_log, $id, $fields, $log, $webhook_id, $this ) ); 
  399. } catch ( WC_API_Exception $e ) { 
  400. return new WP_Error( $e->getErrorCode(), $e->getMessage(), array( 'status' => $e->getCode() ) );