build_merge_fields( $form, $values ); $status = ! empty( $settings['double_optin'] ) ? 'pending' : 'subscribed'; self::$pending_form_id = $form['id']; self::$pending_context = [ 'values' => $values, 'form' => $form, 'entry_id' => $entry_id, 'settings' => $settings, 'attempt' => $attempt, ]; $result = Mailchimp_Client::upsert_member( $api_key, $list_id, $email, $merge_fields, $status ); if ( is_wp_error( $result ) ) { $data = $result->get_error_data(); Api_Log::log( 'mailchimp', $form['id'], "/lists/{$list_id}/members", $data['status'] ?? null, $result->get_error_message() ); $this->maybe_retry( $attempt ); self::$pending_form_id = null; self::$pending_context = null; return; } Api_Log::log( 'mailchimp', $form['id'], "/lists/{$list_id}/members", 200, sprintf( /* translators: %s: subscriber status */ __( 'Subscribed (%s).', 'chargeforms' ), $status ) ); $tags = $this->parse_tags( $settings['tags'] ?? '' ); if ( ! empty( $tags ) ) { $tag_result = Mailchimp_Client::set_tags( $api_key, $list_id, $email, $tags ); if ( is_wp_error( $tag_result ) ) { Api_Log::log( 'mailchimp', $form['id'], "/lists/{$list_id}/members/tags", null, $tag_result->get_error_message() ); } } self::$pending_form_id = null; self::$pending_context = null; } /** WP-Cron callback — re-attempts a delivery that previously failed, same shape as Webhook_Integration::handle_retry(). */ public static function handle_retry( $values, $form, $entry_id, $settings, $attempt ) { ( new self() )->process( $values, $form, $entry_id, $settings, $attempt ); } private function maybe_retry( $attempt ) { if ( ! self::$pending_context || $attempt >= self::MAX_ATTEMPTS ) { return; } $ctx = self::$pending_context; wp_schedule_single_event( time() + self::RETRY_DELAY_SECONDS, self::RETRY_HOOK, [ $ctx['values'], $ctx['form'], $ctx['entry_id'], $ctx['settings'], $ctx['attempt'] + 1 ] ); } private function build_merge_fields( array $form, array $values ) { $name = Contact_Field_Mapper::split_name( $form, $values ); if ( empty( $name ) ) { return []; } $merge = [ 'FNAME' => $name['first'] ]; if ( ! empty( $name['last'] ) ) { $merge['LNAME'] = $name['last']; } return $merge; } /** Comma-separated tag list → trimmed, non-empty tag names. */ private function parse_tags( $raw ) { return array_values( array_filter( array_map( 'trim', explode( ',', (string) $raw ) ) ) ); } }