Lesson 123: Displaying External Provider Information in the Transaction Details Screen


Overview

In the previous lesson, we introduced persistent storage for external provider transactions. Every completed payment now creates a provider record containing the provider name, escrow reference, timestamps, status, and notes.

However, this information is only available by directly inspecting the database.

In this lesson, we’ll integrate the External Provider Manager with the WordPress administration interface so administrators can view provider information directly from the Transaction Details page.

This represents an important shift from building backend infrastructure to exposing meaningful operational information through the plugin’s user interface.


Why this lesson?

At the moment, an administrator managing a website sale has no immediate visibility into the external provider handling the transaction.

To answer questions such as:

  • Which provider is managing this payment?
  • What is the escrow reference?
  • Has the provider transaction been created?
  • What status is the provider reporting?
  • Were any notes recorded?

the administrator must manually inspect the database.

The goal of this lesson is to eliminate that requirement.


Objectives

By the end of this lesson we will:

  • Retrieve provider information using Flipnzee_External_Provider_Manager
  • Associate provider records with auction transactions
  • Display provider details inside the Transaction Details page
  • Gracefully handle transactions without a provider record
  • Lay the foundation for future provider actions and status synchronization

Planned Interface

The Transaction Details page will gain a new section similar to:

──────────────────────────────────────────
External Provider
──────────────────────────────────────────

Provider
Escrow.com

Reference
ESCROW-20260724010512-34

Status
Created

Started
24 Jul 2026 06:35

Completed
—

Notes
Simulated escrow transaction created.

If no provider record exists, the interface will instead display:

External Provider

No provider information is available for this transaction.

This ensures the interface remains informative without producing errors for historical transactions.


Architectural Improvements

Rather than querying the database directly from the admin screen, the page will use:

Flipnzee_External_Provider_Manager::get_provider_by_transaction()

This maintains a clear separation of responsibilities:

  • External Provider Manager retrieves provider data.
  • Admin Transaction Details focuses solely on presentation.
  • Escrow Provider remains responsible for provider creation.
  • Transaction Lifecycle Manager continues orchestrating the workflow.

This follows the object-oriented architecture established throughout the project.


Benefits

After completing this lesson:

  • Administrators can inspect provider information without leaving WordPress.
  • Transaction debugging becomes significantly easier.
  • Escrow references become immediately accessible.
  • Provider status is visible during transaction processing.
  • The UI becomes ready for future actions such as “Open Escrow Transaction”, “Refresh Provider Status”, or “Retry Provider Synchronization”.

What We’ll Build

The implementation will involve three primary steps:

  1. Retrieve provider information for the current transaction.
  2. Add a dedicated External Provider panel to the Transaction Details page.
  3. Display provider fields using WordPress admin styling and proper escaping.

No database changes are required, as the persistence layer introduced in Lesson 122 already provides everything needed.


Looking Ahead

Displaying provider information is only the first step toward a fully integrated provider management system.

Future lessons will build on this interface by allowing administrators to:

  • Synchronize provider status with external services.
  • View provider history.
  • Launch provider-specific actions.
  • Integrate with the real Escrow.com API.
  • Support multiple external payment and escrow providers through the same abstraction layer.

With provider information now visible inside the administration interface, the Flipnzee Auctions plugin moves one step closer to providing a complete transaction management experience for buying and selling websites.

Lesson 122: Persisting Escrow Provider Information for Future API Integration

In the previous lesson, Flipnzee Auctions introduced its first Escrow Provider Engine. Payment completion automatically created a simulated escrow transaction and generated a unique escrow reference.

While that proved the event-driven architecture worked, the generated reference only existed during execution. Once the request finished, there was no permanent record of the escrow transaction.

In this lesson, the plugin takes the next step by designing a persistent storage strategy for external providers.


Why Store Escrow Information?

Real-world escrow services return much more than a reference number.

An external provider may return:

  • Provider transaction ID
  • Escrow reference
  • Current escrow status
  • Creation timestamp
  • Last update timestamp
  • API response details
  • Provider-specific metadata

Without storing this information, the plugin would have no way to:

  • check escrow progress
  • synchronize status
  • reopen existing escrow transactions
  • display escrow details inside the admin panel

Persistence is therefore essential.


Objectives

By the end of this lesson the plugin architecture will support:

  • persistent escrow references
  • provider-specific transaction identifiers
  • provider status tracking
  • future API synchronization
  • support for multiple external providers

Thinking Beyond Escrow.com

Although Flipnzee Auctions is initially designed around Escrow.com, the architecture should never assume only one provider exists.

Instead of storing fields like:

escrow_reference
escrow_status

the plugin adopts more generic terminology.

For example:

provider
provider_reference
provider_transaction_id
provider_status

This makes the database independent of any specific vendor.

Future providers could include:

  • Escrow.com
  • custom enterprise escrow
  • regional payment escrow services
  • internal manual escrow workflows

Extending the Transaction Model

The transaction lifecycle now grows beyond internal auction information.

Auction
        │
        ▼
Transaction
        │
        ▼
External Provider
        │
        ▼
Escrow Workflow

Instead of treating external services as an afterthought, they become a first-class component of the transaction architecture.


Recommended Provider Fields

A professional transaction record may eventually include:

FieldPurpose
providerName of the provider
provider_referenceHuman-readable reference
provider_transaction_idExternal system ID
provider_statusCurrent provider status
provider_created_atProvider creation time
provider_updated_atLast synchronization
provider_responseRaw API response (optional)

Not every provider will use every field, but the structure remains flexible.


Keeping Responsibilities Separate

The Transaction Manager remains responsible for:

  • internal auction transactions
  • payment information
  • ownership workflow

The Escrow Provider becomes responsible for:

  • creating provider records
  • communicating with external APIs
  • interpreting provider responses
  • tracking provider-specific statuses

This clear separation keeps the plugin easier to maintain.


Future Synchronization

Creating an escrow transaction is only the beginning.

Eventually the plugin should support periodic synchronization.

Escrow Created
        │
        ▼
Store Provider Details
        │
        ▼
Scheduled Status Check
        │
        ▼
Retrieve Latest Status
        │
        ▼
Update Local Database

This enables administrators to see real-time escrow progress without manually checking the provider website.


Benefits of Persistent Storage

Persisting provider information allows administrators to:

  • search escrow transactions
  • troubleshoot failed payments
  • view escrow references
  • synchronize provider status
  • audit completed transactions
  • generate financial reports

These capabilities become increasingly valuable as transaction volume grows.


Preparing for API Integration

Most modern payment and escrow APIs follow a similar lifecycle:

  1. Create transaction
  2. Receive external reference
  3. Store the response
  4. Poll or receive status updates
  5. Finalize the transaction

Because Flipnzee Auctions now separates provider logic from transaction logic, integrating a live API becomes a matter of implementing provider-specific communication rather than rewriting the auction system.


Architectural Benefits

This lesson strengthens several important software engineering principles:

  • Separation of concerns
  • Single responsibility
  • Provider abstraction
  • Extensibility
  • Maintainability

By treating external providers as independent services, the plugin becomes easier to evolve as new payment technologies emerge.


What We Accomplished

In this lesson we:

  • designed a persistent model for external provider information
  • separated provider data from transaction data
  • prepared the database for long-term escrow tracking
  • laid the groundwork for status synchronization
  • ensured future provider integrations remain modular
  • continued evolving Flipnzee Auctions into a production-ready architecture

Looking Ahead

With provider persistence planned, the next stage is to build the synchronization layer that keeps local transaction records aligned with external escrow providers.

This will allow Flipnzee Auctions to automatically monitor escrow progress, refresh statuses, and provide administrators with an accurate, real-time view of every transaction without relying on manual updates.

Lesson 116: Refactoring the Buyer Payment Page into a State-Driven Workflow

As the Flipnzee Auctions plugin continues to mature, the buyer payment page has evolved beyond a simple form. It now manages multiple stages of a transaction—from selecting a payment method to uploading payment proof and tracking verification status. As additional payment gateways and workflows are planned, maintaining everything inside a single method would quickly become difficult.

In this lesson, the payment page is refactored into a cleaner, state-driven architecture while preserving the existing functionality.


Why Refactor?

The original implementation mixed several responsibilities inside one method:

  • Validating the transaction
  • Handling payment gateway selection
  • Uploading payment proof
  • Displaying transaction details
  • Rendering different payment states
  • Showing payment instructions

Although functional, this structure made future enhancements increasingly difficult.

The objective was to separate these responsibilities into focused methods that each perform one task.


Design Goals

The refactoring focused on four principles:

  • Smaller, easier-to-read methods
  • Separation of business logic and presentation
  • State-driven rendering
  • A scalable foundation for future payment gateways

This approach aligns more closely with object-oriented design and WordPress coding standards.


Simplifying render()

The render() method now serves primarily as the controller for the page.

Its responsibilities are limited to:

  • Validating the request
  • Loading the transaction
  • Processing payment proof uploads
  • Delegating payment actions
  • Rendering the appropriate payment state

Instead of containing hundreds of lines of mixed logic, it now orchestrates the workflow through dedicated helper methods.


Extracting Payment Submission Logic

Payment gateway processing was moved into its own method:

private static function handle_payment_submission()

This method now handles:

  • nonce validation
  • selected gateway validation
  • gateway routing
  • unsupported gateway messaging

The result is a much cleaner entry point that will make future integrations significantly easier.


Introducing a State Machine

Rather than scattering conditional statements throughout the page, the buyer interface now behaves like a simple state machine.

Current payment states include:

  • Pending
  • Submitted
  • Verified
  • Completed

A single controller determines which section should be displayed.

render_payment_state()

Internally it delegates to dedicated rendering methods for each state.


Dedicated Rendering Methods

Instead of one large template, each payment state now has its own renderer.

Examples include:

  • render_pending_state()
  • render_submitted_state()
  • render_verified_state()
  • render_completed_state()

Each method focuses on presenting one stage of the payment lifecycle.

This improves readability while making future UI enhancements much safer.


Payment Proof Upload

The payment proof upload process remains fully functional after the refactor.

The workflow now becomes:

  1. Buyer selects Manual Payment.
  2. Payment instructions are displayed.
  3. Buyer uploads proof of payment.
  4. The proof is stored.
  5. Payment status changes to Submitted.
  6. The buyer now sees a confirmation message instead of the upload form.

This creates a much clearer user experience while preventing duplicate uploads.


Transaction Summary

The transaction summary has also been isolated into its own renderer.

It displays:

  • Transaction ID
  • Winning Bid
  • Transaction Status
  • Payment Status
  • Selected Payment Gateway

Keeping this component separate makes future additions—such as payment timestamps or invoice numbers—straightforward.


Benefits of the Refactor

Compared to the previous implementation, the payment page is now:

  • Easier to read
  • Easier to debug
  • Easier to test
  • Easier to extend
  • Better aligned with object-oriented design

Future payment gateways such as Escrow.com, Stripe, PayPal, Wise, and cryptocurrency integrations can now be added with minimal impact on the rest of the codebase.


Lessons Learned

One important takeaway from this refactor is that working code is not always well-structured code.

As software grows, periodically revisiting earlier implementations helps improve maintainability without changing the user-facing behaviour.

By separating responsibilities into focused methods, the payment page becomes easier to understand today while reducing technical debt for future development.


Current Payment Lifecycle

The buyer payment workflow now follows a clear sequence:

Auction Won
        │
        ▼
Pending Payment
        │
        ▼
Select Payment Gateway
        │
        ▼
View Payment Instructions
        │
        ▼
Upload Payment Proof
        │
        ▼
Submitted
        │
        ▼
Verified (Admin)
        │
        ▼
Ownership Transfer
        │
        ▼
Completed

Conclusion

Although this lesson introduces very few visible changes to the buyer interface, it represents an important architectural milestone for the Flipnzee Auctions plugin. The payment page has been transformed from a monolithic implementation into a modular, state-driven workflow that is easier to maintain and extend.

With this foundation in place, the next lessons can focus on the administrative side of the payment lifecycle, including payment verification, ownership transfer, transaction completion, and integration with additional payment gateways, all without requiring major structural changes to the buyer-facing code.

https://github.com/SplendidDigital/flipnzee-auctions/releases/tag/lesson-116-payment-page-refactor

Lesson 115: Buy Now Auction Completion Workflow (Planning)

Introduction

Until now, the Flipnzee Auctions plugin has treated every bid in the same way. Regardless of the bid amount, the auction remains active until its scheduled end time, where a scheduled process later determines the winner.

However, this behavior is not how a traditional Buy Now feature is expected to work.

When a bidder agrees to pay the Buy Now price, they are effectively accepting the seller’s asking price. At that point there should be no reason to keep the auction running or allow additional bids.

This lesson focuses on transforming Buy Now from a simple display price into an action that immediately completes the auction.


Current Problem

Suppose an auction has:

  • Start Price: $120
  • Current Bid: $1,200
  • Buy Now Price: $5,000

If a buyer places a bid of exactly $5,000, the plugin currently:

  • accepts the bid,
  • updates the current bid,
  • leaves the auction active,
  • allows other users to continue bidding.

This defeats the purpose of having a Buy Now option.


Expected Behaviour

The expected workflow should become:

Buyer submits Buy Now bid
        │
        ▼
Bid is accepted
        │
        ▼
Buy Now condition detected
        │
        ▼
Auction closes immediately
        │
        ▼
Winner determined
        │
        ▼
Winner notifications sent
        │
        ▼
Transaction created
        │
        ▼
Buyer redirected to payment

Instead of waiting until the scheduled auction end, the auction lifecycle should complete immediately.


Why This Matters

This change transforms the auction from a passive bidding system into an actual marketplace transaction.

It establishes a complete workflow where:

  • bidding,
  • winner determination,
  • transaction creation,
  • payment,
  • ownership transfer

all become part of a single automated process.

Without this behaviour, Buy Now is merely another bid amount rather than an instant purchase mechanism.


Design Considerations

Rather than scattering Buy Now logic throughout the plugin, we will introduce a clear sequence of responsibilities.

The bid handler should remain responsible for accepting bids.

Once a valid bid has been recorded, it should ask one simple question:

“Did this bid satisfy the Buy Now price?”

If the answer is yes, the auction manager will immediately close the auction and the existing winner determination workflow can continue unchanged.

This approach reuses the infrastructure already built in previous lessons instead of creating an entirely separate purchase system.


Objectives

By the end of this lesson we will:

  • Detect when a submitted bid reaches the Buy Now price.
  • Close the auction immediately.
  • Determine the winning bidder instantly.
  • Reuse the existing notification system.
  • Automatically create the buyer transaction.
  • Launch the payment workflow without waiting for auction expiry.

What We’ll Build

At the end of this lesson, the auction lifecycle will look like this:

Auction Created
        │
        ▼
Buyer Places Bid
        │
        ▼
Buy Now Price Reached
        │
        ▼
Auction Closed Immediately
        │
        ▼
Winner Determined
        │
        ▼
Notifications Sent
        │
        ▼
Transaction Created
        │
        ▼
Buyer Payment Page

This is one of the most important milestones in the Flipnzee Auctions project, as it connects bidding with the complete post-auction purchase workflow.


Lesson 114 – Refactoring the Buyer Payment Page with a State-Driven Interface

One of the goals of the Flipnzee Auctions project is to continuously improve the codebase while keeping the plugin functional at every stage. Rather than adding new features immediately, this lesson focuses on improving the buyer payment experience by making the interface respond to the current payment status.

Instead of always displaying payment options regardless of the transaction state, the payment page now renders different views depending on where the buyer is in the payment process.


Project Goals

In previous lessons, the payment workflow allowed buyers to:

  • View transaction details
  • Choose a payment gateway
  • View manual payment instructions
  • Upload payment proof

Although functional, the payment page continued to display payment controls even after payment proof had already been submitted. This could confuse buyers and encourage duplicate submissions.

The objective of this lesson was to make the payment page aware of the payment lifecycle.


Problems with the Previous Implementation

Previously, the payment page always rendered:

  • Transaction summary
  • Gateway selector
  • Payment buttons

regardless of whether the buyer had already submitted payment proof.

This produced an interface similar to:

Transaction Summary

↓

Payment Gateway Selection

↓

Manual Payment Instructions

↓

Upload Proof

↓

Payment Gateway Selection (still visible)

The buyer could continue interacting with payment controls that were no longer relevant.


Design Objective

The payment page should automatically display information that matches the transaction’s current state.

Instead of asking the buyer what to do next, the interface should guide them naturally through the workflow.


State-Driven Rendering

A new rendering controller was introduced:

self::render_payment_state(
    $transaction,
    $gateways
);

Instead of directly rendering the gateway selector, the payment page now delegates rendering to a state-aware method.


Payment States

The renderer evaluates the current payment status.

switch ( strtolower( $transaction->payment_status ) ) {

    case 'submitted':
        ...
        break;

    case 'verified':
        ...
        break;

    case 'completed':
        ...
        break;

    default:
        ...
}

Each payment status now has its own dedicated renderer.


Pending State

Pending transactions continue using the existing payment workflow.

private static function render_pending_state(
    $transaction,
    $gateways
) {

    self::render_gateway_selector(
        $gateways
    );

}

From the buyer’s perspective, nothing changes until payment has actually been submitted.


Submitted State

After payment proof is uploaded, the page now replaces the gateway selector with a confirmation message.

Example:

Payment Submitted

Your payment proof has been received.

Our team will verify your payment before ownership transfer begins.

This prevents unnecessary duplicate uploads while reassuring the buyer that their submission has been received.


Verified State

Future lessons will allow administrators to verify payments.

Once verification occurs, buyers will see a confirmation such as:

Payment Verified

Ownership transfer has started.

No additional payment actions are displayed.


Completed State

When ownership transfer has been completed, the payment page will display a completion message instead of payment controls.

Example:

Transaction Completed

Ownership has been transferred successfully.

This provides a natural end to the purchase workflow.


Transaction Summary

The transaction summary remains available throughout every stage.

Information displayed includes:

  • Transaction ID
  • Winning Bid
  • Transaction Status
  • Payment Status
  • Selected Payment Gateway

This allows buyers to monitor the progress of their purchase without losing important transaction details.


User Experience Improvements

Before this lesson:

Payment Summary

↓

Gateway Selection

↓

Manual Payment

↓

Upload Proof

↓

Gateway Selection still visible

After this lesson:

Payment Summary

↓

Pending

↓

Gateway Selection

↓

Upload Proof

↓

Submitted

↓

Waiting for Verification

↓

Verified

↓

Ownership Transfer

↓

Completed

The payment page now behaves more like a modern checkout portal, displaying only the actions that are appropriate for the buyer’s current stage.


Architectural Benefits

Although this lesson introduced only a small visible change, it significantly improved the overall design.

Benefits include:

  • State-driven rendering
  • Reduced UI clutter
  • Clear buyer guidance
  • Easier maintenance
  • Better separation between transaction information and payment workflow
  • Foundation for future payment gateways

Lessons Learned

One important lesson during development was recognizing the difference between refactoring and rewriting.

Several attempts were made to extract large portions of the payment processing logic into separate methods. While architecturally appealing, making too many structural changes at once introduced unnecessary complexity during debugging.

The final implementation adopted a more conservative approach by refactoring only the rendering layer while preserving the existing payment processing logic. This resulted in a cleaner user interface without risking regressions in the working payment workflow.

This incremental strategy is often preferable in production software, where maintaining stability is just as important as improving code quality.


Conclusion

Lesson 114 transformed the Buyer Payment Page from a static form into a state-driven interface that responds intelligently to the payment lifecycle.

While the underlying payment processing remains unchanged, buyers now receive a clearer and more intuitive experience, and the architecture is better prepared for future enhancements such as administrator payment verification and automated ownership transfers.

In the next lesson, we will build the Admin Payment Verification Workflow, allowing administrators to approve submitted payments and advance transactions to the ownership transfer stage.

lesson-114-stable: Lesson 114: Refactor buyer payment page with state-driven rendering