$method, 'timeout' => 12, 'redirection' => 0, 'headers' => [ $header => $token, 'Content-Type' => 'application/json', 'Accept' => 'application/json' ] ]; if ( null !== $body ) { $args['body'] = wp_json_encode( $body ); } $response = wp_safe_remote_request( $url . $path, $args ); if ( is_wp_error( $response ) ) { return new \WP_Error( 'marketing_network', __( 'The service could not be reached. Please try again.', 'chargeforms' ), [ 'retryable' => true ] ); } $code = wp_remote_retrieve_response_code( $response ); if ( $code < 200 || $code >= 300 ) { return new \WP_Error( 'marketing_http', sprintf( /* translators: %d: HTTP status */ __( 'The service returned HTTP %d. Check your credentials and list settings.', 'chargeforms' ), $code ), [ 'status' => $code, 'retryable' => 429 === $code || $code >= 500 ] ); } if ( 204 === $code ) { return []; } $data = json_decode( wp_remote_retrieve_body( $response ), true ); return is_array( $data ) ? $data : new \WP_Error( 'marketing_response', __( 'The service returned an unreadable response.', 'chargeforms' ) ); } public static function ping( $provider, $token, $base = '' ) { $result = self::request( $provider, $token, $base, 'GET', 'brevo' === $provider ? '/account' : '/users/me' ); return is_wp_error( $result ) ? $result : true; } public static function upsert( $provider, $token, $base, $email, array $name, array $settings ) { $list = absint( $settings['list_id'] ?? 0 ); if ( ! is_email( $email ) || ! $list ) { return new \WP_Error( 'marketing_config', __( 'A valid email and list ID are required.', 'chargeforms' ) ); } if ( 'brevo' === $provider ) { $attributes = []; foreach ( [ 'first', 'last' ] as $part ) { $attribute = $settings[ $part . '_attribute' ] ?? ''; if ( preg_match( '/^[A-Z][A-Z0-9_]*$/', $attribute ) && ! empty( $name[ $part ] ) ) { $attributes[ $attribute ] = $name[ $part ]; } } $body = [ 'email' => $email, 'listIds' => [ $list ], 'updateEnabled' => true ]; if ( $attributes ) { $body['attributes'] = $attributes; } // Never reset blacklist flags or force-merge contacts. return self::request( $provider, $token, $base, 'POST', '/contacts', $body ); } $contact = [ 'email' => $email ]; if ( ! empty( $name['first'] ) ) { $contact['firstName'] = $name['first']; } if ( ! empty( $name['last'] ) ) { $contact['lastName'] = $name['last']; } $result = self::request( $provider, $token, $base, 'POST', '/contact/sync', [ 'contact' => $contact ] ); if ( is_wp_error( $result ) ) { return $result; } $id = $result['contact']['id'] ?? ''; if ( ! ctype_digit( (string) $id ) || (int) $id < 1 ) { return new \WP_Error( 'marketing_contact_id', __( 'The service did not return a contact ID.', 'chargeforms' ) ); } return self::request( $provider, $token, $base, 'POST', '/contactLists', [ 'contactList' => [ 'contact' => (string) $id, 'list' => (string) $list, 'status' => 1 ] ] ); } }