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.



