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

Leave a Reply

Your email address will not be published. Required fields are marked *