stallation_id %s $error_message */ __( 'Failed to fetch iframe Management URI. wa_installation_id: %1$s, error message: %2$s', 'facebook-for-woocommerce' ), $wa_installation_id, $error_message, ) ); return ''; } else { wc_get_logger()->info( sprintf( __( 'WhatsApp Utility Messages Iframe Management Url successfully fetched', 'facebook-for-woocommerce' ), ) ); } return $response_object->iframe_management_uri; } /** * Trigger WhatsApp Message Sends for Processed Order * * @param object $plugin The plugin instance. * @param string $event Order Management event * @param string $order_id Order id * @param string $order_details_link Order Details Link * @param string $phone_number Customer phone number * @param string $first_name Customer first name * @param int $refund_value Amount refunded to the Customer * @param string $currency Currency code * @param string $country_code Customer country code * @param array $order_metadata Optional order metadata used to build rich order status * * @return string * @since 3.5.0 */ public static function process_whatsapp_utility_message_event( $plugin, $event, $order_id, $order_details_link, $phone_number, $first_name, $refund_value, $currency, $country_code, $order_metadata = array() ) { $whatsapp_connection = $plugin->get_whatsapp_connection_handler(); $is_connected = $whatsapp_connection->is_connected(); if ( ! $is_connected ) { wc_get_logger()->info( sprintf( /* translators: %s $order_id */ __( 'Customer Events Post API call for Order id %1$s Failed due to failed connection ', 'facebook-for-woocommerce' ), $order_id, ) ); return; } $wa_installation_id = $whatsapp_connection->get_wa_installation_id(); $base_url = array( self::BASE_STEFI_ENDPOINT_URL, 'whatsapp/business', $wa_installation_id, 'customer_events' ); $base_url = esc_url( implode( '/', $base_url ) ); $bisu_token = $whatsapp_connection->get_access_token(); $event_lowercase = strtolower( $event ); $event_object = self::get_object_for_event( $event, $order_details_link, $refund_value, $currency ); $event_base_object = array( 'id' => "#{$order_id}", 'type' => $event, ); if ( ! empty( $event_object ) ) { $event_base_object[ $event_lowercase ] = $event_object; } // Always attach rich_order_status when order_metadata is provided. if ( ! empty( $order_metadata ) ) { try { $rich_status = self::build_rich_order_status( $order_metadata ); if ( ! empty( $rich_status ) ) { $event_base_object['rich_order_status'] = $rich_status; } } catch ( \Throwable $e ) { wc_get_logger()->info( 'Error building rich_order_status: ' . $e->getMessage() ); } } $options = array( 'headers' => array( 'Authorization' => 'Bearer ' . $bisu_token, ), 'body' => array( 'customer' => array( 'id' => $phone_number, 'type' => 'GUEST', 'first_name' => $first_name, 'country_code' => $country_code, 'language' => get_user_locale(), ), 'event' => $event_base_object, ), 'timeout' => 3000, // 5 minutes ); $response = wp_remote_post( $base_url, $options ); $status_code = wp_remote_retrieve_response_code( $response ); $data = explode( "\n", wp_remote_retrieve_body( $response ) ); $response_object = json_decode( $data[0] ); if ( is_wp_error( $response ) || 200 !== $status_code ) { $error_message = $response_object->detail ?? $response_object->title ?? 'Something went wrong. Please try again later!'; wc_get_logger()->info( sprintf( /* translators: %s $order_id %s $error_message */ __( 'Customer Events Post API call for Order id %1$s Failed %2$s ', 'facebook-for-woocommerce' ), $order_id, $error_message, ) ); } else { wc_get_logger()->info( sprintf( /* translators: %s $order_id */ __( 'Customer Events Post API call for Order id %1$s Succeeded.', 'facebook-for-woocommerce' ), $order_id ) ); } return; } /** * Build the rich_order_status array from order metadata. * * @param array $order_metadata The order metadata containing order details. * @return array An array with keys: order_url, order_date, currency, shipping_method, items (each item has: name, quantity, amount_1000, image_url) */ public static function build_rich_order_status( $order_metadata ) { $rich_status_object = array( 'order_url' => $order_metadata['order_url'] ?? '', 'order_date' => $order_metadata['order_date'] ?? '', 'currency' => $order_metadata['currency'] ?? '', 'shipping_method' => $order_metadata['shipping_method'] ?? '', 'items' => array(), ); if ( ! empty( $order_metadata['items'] ) && is_array( $order_metadata['items'] ) ) { foreach ( $order_metadata['items'] as $order_item ) { $item_arr = array(); $item_arr['name'] = $order_item['name'] ?? ( $order_item['product_name'] ?? '' ); $item_arr['quantity'] = isset( $order_item['quantity'] ) ? intval( $order_item['quantity'] ) : null; // Ensure `amount_1000` is present for the server consumer. // Derived from numeric `amount`. if ( isset( $order_item['amount'] ) ) { // Derive from numeric amount; scale to cents per current server expectation. $item_arr['amount_1000'] = (int) round( (float) $order_item['amount'] * 100 ); } $image_url = ''; if ( ! empty( $order_item['product_id'] ) ) { try { $product = wc_get_product( $order_item['product_id'] ); if ( $product ) { $image_id = method_exists( $product, 'get_image_id' ) ? $product->get_image_id() : null; if ( $image_id ) { $img = wp_get_attachment_image_url( $image_id, 'large' ); $image_url = $img ? $img : wp_get_attachment_url( $image_id ); // Ensure HTTPS protocol for image URLs $image_url = preg_replace( '/^http:/', 'https:', $image_url ); } } } catch ( \Throwable $e ) { wc_get_logger()->info( 'Error fetching product image: ' . $e->getMessage() ); } } $item_arr['image_url'] = $image_url; $rich_status_object['items'][] = $item_arr; } } return $rich_status_object; } /** * Gets event data tied to Order Management Event * * @param string $event Order Management event * @param string $order_details_link Order details link * @param string $refund_value Amount refunded to the Customer * @param string $currency Currency code */ public static function get_object_for_event( $event, $order_details_link, $refund_value, $currency ) { switch ( $event ) { case 'ORDER_PLACED': return array( 'order_details_url' => $order_details_link, ); case 'ORDER_FULFILLED': return array( 'tracking_url' => $order_details_link, ); case 'ORDER_REFUNDED': return array( 'amount_1000' => $refund_value, 'currency' => $currency, ); default: return array(); } } }