getMessage() ); } } public static function body( string $event, int $order_id, int $refund_id ): ?string { if ( ! Options::is_connected() || '' === Options::webhook_secret() ) { return null; } $order = wc_get_order( $order_id ); if ( ! $order instanceof \WC_Order ) { return null; } if ( 'order.paid' === $event ) { return (string) wp_json_encode( OrderEventPayload::paid( $order ) ); } if ( 'order.refunded' === $event ) { $refund = wc_get_order( $refund_id ); return $refund instanceof \WC_Order_Refund ? (string) wp_json_encode( OrderEventPayload::refunded( $order, $refund ) ) : null; } return null; } /** * @return string 'sent', 'retry' or 'stop'. */ public static function post( string $body ): string { $response = wp_remote_post( Config::api_base() . '/webhooks/woo/orders', array( 'timeout' => self::TIMEOUT, 'redirection' => 0, 'sslverify' => true, 'headers' => array( 'Content-Type' => 'application/json', // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- HMAC signature encoding, as in contract §4. 'X-Cortex-Signature' => base64_encode( hash_hmac( 'sha256', $body, Options::webhook_secret(), true ) ), ), 'body' => $body, ) ); if ( is_wp_error( $response ) ) { return 'retry'; } $status = (int) wp_remote_retrieve_response_code( $response ); if ( $status >= 200 && $status < 300 ) { return 'sent'; } // 3xx is a permanent refusal here: redirection is 0 above, so we never follow one, and there is no // sense in which a redirect would resolve itself on a later attempt. if ( 0 === $status || 408 === $status || 429 === $status || $status >= 500 ) { return 'retry'; } Log::warning( 'CortexCommerce refused an order event: HTTP ' . $status ); return 'stop'; } private static function retry( string $event, int $order_id, int $refund_id, int $attempt ): void { if ( $attempt >= count( self::DELAYS ) ) { Log::warning( sprintf( 'Order event %s for order %d not delivered after %d attempts.', $event, $order_id, $attempt + 1 ) ); return; } as_schedule_single_action( time() + self::DELAYS[ $attempt ], OrderEvents::HOOK, array( $event, $order_id, $refund_id, $attempt + 1 ), OrderEvents::GROUP ); } }