Lesson 73: Capturing and Validating the Buyer’s Selected Payment Method

Objective

In the previous lesson, we introduced a dynamic payment gateway selection interface. Buyers can now see the available payment methods, but their selection is not yet processed.

In this lesson, we’ll begin building the actual checkout workflow by wrapping the gateway list inside a form, capturing the selected payment method, validating it on submission, and preparing the plugin for gateway-specific payment processing.

Although real payment gateways are still not connected, this lesson establishes the core workflow that every future payment provider will use.


Why This Lesson Matters

A payment page is only useful if it can process the buyer’s choice.

Instead of immediately integrating Stripe, PayPal, or Escrow.com APIs, we first need a common checkout workflow that:

  • accepts the selected gateway
  • validates user input
  • prevents invalid gateway selections
  • prepares the transaction for payment
  • redirects to the appropriate payment handler

Once this workflow exists, every new payment provider can plug into it.


What We’ll Build

The payment page will evolve from:

○ Escrow.com
● Manual Payment
○ Stripe
○ PayPal

[Continue (Disabled)]

into:

○ Escrow.com
● Manual Payment
○ Stripe
○ PayPal

[Continue to Payment]

When the buyer clicks the button:

  1. The selected gateway is submitted.
  2. The selection is validated.
  3. Disabled gateways cannot be submitted.
  4. Manual Payment continues to the next step.
  5. Future gateways display an informative placeholder message.

Files We’ll Modify

Existing

includes/class-payment-page.php

Existing

includes/class-payment-manager.php

Features to Implement

1. Wrap Gateway Selection Inside a Form

Convert the payment gateway section into a proper HTML form.

The form will submit the selected gateway using the POST method.


2. Enable the Continue Button

Replace the disabled placeholder button with an active submit button.

Example:

Continue to Payment

3. Capture Buyer Selection

Read the submitted gateway using:

$_POST['payment_gateway']

Sanitize the value before processing.


4. Validate the Selected Gateway

Verify that:

  • the gateway exists
  • the gateway is currently enabled

If validation fails, display a user-friendly error message.


5. Prepare Gateway Routing

Rather than processing payments directly, create routing logic similar to:

if Manual Payment
    continue to manual payment workflow

if Escrow
    placeholder

if Stripe
    placeholder

if PayPal
    placeholder

This architecture allows future lessons to implement each gateway independently.


User Experience

Current:

Choose Gateway

Manual Payment

Continue (disabled)

After Lesson 73:

Choose Gateway

Manual Payment

Continue to Payment

Upon submission:

Selected Gateway:
Manual Payment

or

Escrow.com integration is coming soon.

depending on the selected gateway.


Architecture Improvement

Before Lesson 73:

Payment Page

↓

Display Gateways

After Lesson 73:

Payment Page

↓

Capture Form

↓

Validate Gateway

↓

Route to Selected Payment Method

↓

Future Gateway Handler

This creates a reusable payment flow that every payment provider will follow.


Benefits

By the end of this lesson, Flipnzee Auctions will have:

  • Functional payment selection form
  • Gateway validation
  • Secure handling of buyer input
  • Centralized routing logic
  • Foundation for integrating Escrow.com, Stripe, PayPal, Razorpay, and cryptocurrency payments

What We Won’t Build Yet

To keep the implementation stable, we are not implementing:

  • Escrow.com API
  • Stripe Checkout
  • PayPal Checkout
  • Razorpay API
  • Cryptocurrency payments
  • Payment confirmation
  • Webhooks
  • Automatic transaction updates

Those will be introduced in future lessons after the payment workflow has been completed.


Expected Outcome

By the end of Lesson 73, the Payment page will evolve from a static gateway selection interface into the first stage of a real checkout process. Buyers will be able to submit their chosen payment method, the plugin will validate the selection securely, and the architecture will be ready to hand control to the appropriate payment gateway implementation in future lessons.

Lesson 72 Implementation: Building a Future-Ready Payment Gateway Selection Interface

As the Flipnzee Auctions plugin continues to evolve into a professional website marketplace, one of the most important architectural decisions is how payment gateways will be integrated. Rather than hardcoding a single payment provider, this lesson introduces a flexible gateway selection system that can easily support multiple payment methods in the future.

Although no real payment gateways are connected yet, the plugin now provides a scalable framework for adding Escrow.com, Stripe, PayPal, Razorpay, cryptocurrency payments, and other providers without redesigning the payment page.


Why This Lesson Was Needed

Until the previous lesson, buyers could only see the transaction details and a placeholder payment gateway.

While functional, that approach wasn’t scalable. Every time a new payment provider was added, the payment page would need to be rewritten.

Instead, the payment page should simply ask:

“Which payment gateways are currently available?”

The Payment Manager should answer that question.

This separation of responsibilities makes the code easier to maintain and extend.


Objectives

In this lesson we:

  • Centralized payment gateway definitions
  • Added a helper method to retrieve available gateways
  • Introduced Escrow.com as the planned primary marketplace payment method
  • Generated the payment method list dynamically
  • Displayed future gateways as disabled
  • Added a disabled “Continue to Payment” button
  • Prepared the plugin for future payment gateway integrations

Step 1 – Centralizing Available Payment Gateways

Inside:

includes/class-payment-manager.php

a new helper method was introduced:

/**
 * Get available payment gateways.
 *
 * @return array
 */
public static function get_available_gateways() {

    return array(

        'escrow' => array(
            'label'   => 'Escrow.com (Recommended)',
            'enabled' => false,
        ),

        'manual' => array(
            'label'   => 'Manual Payment',
            'enabled' => true,
        ),

        'stripe' => array(
            'label'   => 'Stripe',
            'enabled' => false,
        ),

        'paypal' => array(
            'label'   => 'PayPal',
            'enabled' => false,
        ),

        'razorpay' => array(
            'label'   => 'Razorpay',
            'enabled' => false,
        ),

        'crypto' => array(
            'label'   => 'USDT Cryptocurrency',
            'enabled' => false,
        ),

    );

}

Instead of hardcoding gateway names inside the payment page, all available gateways are now managed from a single location.


Step 2 – Loading Gateways in the Payment Page

After validating the transaction, the payment page now requests the available gateways from the Payment Manager.

$gateways = Flipnzee_Payment_Manager::get_available_gateways();

This keeps the page independent from payment logic and allows new gateways to be introduced without modifying the frontend.


Step 3 – Rendering Gateway Options Dynamically

The payment page now loops through the available gateways to generate the interface.

<h3>Select Payment Method</h3>

<div class="flipnzee-payment-gateways">

<?php foreach ( $gateways as $gateway_id => $gateway ) : ?>

    <p>

        <label>

            <input
                type="radio"
                name="payment_gateway"
                value="<?php echo esc_attr( $gateway_id ); ?>"
                <?php checked( $gateway['enabled'] ); ?>
                <?php disabled( ! $gateway['enabled'] ); ?>
            >

            <?php echo esc_html( $gateway['label'] ); ?>

            <?php if ( ! $gateway['enabled'] ) : ?>

                <em>(Coming Soon)</em>

            <?php endif; ?>

        </label>

    </p>

<?php endforeach; ?>

</div>

This approach automatically displays every configured gateway without manually writing HTML for each payment provider.


Step 4 – Adding a Checkout Placeholder

Since actual payment processing has not yet been implemented, a disabled button was added.

<p class="flipnzee-payment-actions">

    <button
        type="button"
        class="button button-primary"
        disabled
    >
        Continue to Payment (Coming Soon)
    </button>

</p>

The button clearly communicates that payment processing will be introduced in a future lesson while maintaining a professional checkout layout.


Why Escrow.com Appears First

During implementation, the payment architecture was adjusted to better reflect Flipnzee’s purpose.

Instead of treating Stripe or PayPal as the primary payment method, the gateway list now starts with:

  • Escrow.com (Recommended)
  • Manual Payment
  • Stripe
  • PayPal
  • Razorpay
  • USDT Cryptocurrency

Since Flipnzee is designed as a marketplace for buying and selling websites, Escrow.com is expected to become the primary payment solution once its API integration is implemented.

Until then, it remains disabled and marked as “Coming Soon.”


Testing

After implementing the changes:

  • The Payment page continued displaying transaction information correctly.
  • Payment gateways were loaded dynamically.
  • Manual Payment appeared as the only selectable option.
  • Future gateways appeared disabled.
  • Escrow.com was displayed as the recommended marketplace payment solution.
  • The “Continue to Payment” button appeared in a disabled state.

No PHP syntax errors were encountered during testing.


Lessons Learned

This lesson reinforced several important software design principles:

  • Business logic should be separated from presentation logic.
  • Payment providers should be managed centrally.
  • Dynamic rendering reduces future maintenance.
  • Building a scalable architecture early simplifies later integrations.
  • Placeholder interfaces help guide future development while keeping the application stable.

Current Progress

The Flipnzee Auctions plugin now includes:

  • Auction management
  • Transaction creation
  • Purchase history
  • Individual purchase details
  • Dedicated payment page
  • Payment gateway architecture
  • Dynamic gateway selection interface
  • Escrow-ready payment framework

Although real payment processing has not yet been added, the plugin now has a solid architectural foundation that will make future integrations significantly easier.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Next Lesson

In Lesson 73, we’ll move beyond the static gateway list and begin building the actual payment flow by allowing buyers to submit their selected payment method, validating their choice, storing it with the transaction, and preparing the plugin to route users toward the appropriate payment handler. This will transform the current placeholder interface into the first stage of a working checkout process.

Lesson 72: Building the Payment Gateway Selection Interface

Objective

With the payment architecture now prepared, the next logical step is to give buyers the ability to choose how they would like to pay.

In this lesson, we will introduce a Payment Method Selection section on the Payment page. Although only a placeholder gateway exists today, the interface will be built so future gateways (Stripe, PayPal, Razorpay, Bank Transfer, Crypto, etc.) can be added with almost no changes to the frontend.

This lesson focuses entirely on UI architecture, not actual payment processing.


What We’ll Build

Instead of only showing:

Payment Gateway
Manual Payment (Coming Soon)

the payment page will display something like:

Select Payment Method

(•) Manual Payment (Coming Soon)
( ) Stripe
( ) PayPal
( ) Razorpay
( ) Cryptocurrency (USDT)

[Continue]

Only Manual Payment will be enabled.

The remaining gateways will appear disabled with a “Coming Soon” label.


Why This Lesson Matters

This is an important architectural step because:

  • separates payment UI from payment logic
  • allows new gateways without redesigning pages
  • provides a familiar checkout experience
  • keeps the plugin scalable
  • prepares for future gateway plugins

Files We’ll Modify

Existing

includes/class-payment-page.php

Existing

includes/class-payment-manager.php

(add helper function for available gateways)


New Features

1. Payment Gateway List

Create a helper such as:

Flipnzee_Payment_Manager::get_available_gateways()

which returns an array like

array(
    'manual' => array(
        'label' => 'Manual Payment',
        'enabled' => true,
    ),
    'stripe' => array(
        'label' => 'Stripe',
        'enabled' => false,
    ),
    'paypal' => array(
        'label' => 'PayPal',
        'enabled' => false,
    ),
    'razorpay' => array(
        'label' => 'Razorpay',
        'enabled' => false,
    ),
    'crypto' => array(
        'label' => 'USDT Cryptocurrency',
        'enabled' => false,
    ),
);

2. Display Gateway Choices

Show all gateways as radio buttons.

Only enabled gateways are selectable.

Disabled gateways display:

Coming Soon

3. Continue Button

Display

Continue to Payment

No payment processing yet.


4. Clean HTML Structure

Wrap the section in

<div class="flipnzee-payment-gateways">

for future styling.


User Experience

Current page:

Transaction Details

Gateway:
Manual Payment

New page:

Transaction Details

Select Payment Method

○ Stripe
○ PayPal
● Manual Payment
○ Razorpay
○ Crypto

Continue

Benefits

After this lesson the plugin will have:

  • scalable payment architecture
  • configurable gateway list
  • reusable gateway rendering
  • future-ready checkout interface
  • no dependency on a specific payment provider

What We Won’t Build Yet

To keep the project stable, we are not implementing:

  • Stripe API
  • PayPal API
  • Razorpay API
  • Crypto payments
  • Order confirmation
  • Payment verification

Those will come in later lessons.


Expected Outcome

By the end of Lesson 72, buyers will see a professional payment method selection interface with a working placeholder for Manual Payment and clearly marked future payment options, laying the foundation for integrating real payment gateways in the upcoming lessons.

Lesson 71 Implementation: Introducing the Payment Manager for Transaction Validation

After successfully creating the buyer payment page in the previous lesson, the next logical improvement was to separate payment-related business logic from the presentation layer. Instead of allowing the payment page to directly decide whether a transaction could be paid, a dedicated Payment Manager class was introduced.

This lesson focuses on improving the plugin architecture while preparing the foundation for future payment gateway integrations such as Stripe, PayPal, Razorpay, or manual bank transfer.


Objective

The goals of this lesson were to:

  • Create a dedicated Flipnzee_Payment_Manager class.
  • Centralize payment validation logic.
  • Validate transactions before displaying the payment page.
  • Prepare a placeholder method for future payment gateway integrations.
  • Keep the payment page clean and easier to maintain.

Why This Refactoring Was Needed

In Lesson 70, the payment page displayed transaction details directly after fetching the transaction.

As more features are added, such as:

  • payment expiry
  • completed payments
  • cancelled transactions
  • multiple payment gateways

placing all validation logic inside the page would quickly become difficult to maintain.

Instead, all payment-related decisions should live inside a dedicated manager.

This follows the Single Responsibility Principle, where each class has one clear responsibility.


Step 1 — Creating the Payment Manager

A new file was created:

includes/class-payment-manager.php

The initial class structure:

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Flipnzee_Payment_Manager {

}

This class will eventually become the central place for everything related to buyer payments.


Step 2 — Registering the New Class

The loader was updated so WordPress loads the new class automatically.

Example:

require_once FLIPNZEE_AUCTIONS_PLUGIN_DIR . 'includes/class-payment-manager.php';

Step 3 — Moving Validation into the Manager

Instead of checking the transaction status directly inside the payment page, a reusable validation method was created.

public static function can_pay( $transaction ) {

    if ( ! $transaction ) {
        return false;
    }

    if ( strtolower( trim( $transaction->status ) ) !== 'pending' ) {
        return false;
    }

    return true;
}

Why strtolower()?

During testing, it was discovered that database values may use different capitalization.

Examples:

Pending
pending
PENDING

Using:

strtolower( trim( $transaction->status ) )

ensures all of these are treated consistently.


Step 4 — Validating the Transaction

The payment page now retrieves the transaction:

$transaction = Flipnzee_Payment_Manager::get_transaction(
    $transaction_id
);

If nothing is found:

if ( ! $transaction ) {
    return '<p>Transaction not found.</p>';
}

Then the Payment Manager determines whether payment is still allowed.

if ( ! Flipnzee_Payment_Manager::can_pay( $transaction ) ) {
    return '<p>This transaction is no longer available for payment.</p>';
}

This keeps the page itself very clean.


Step 5 — Preparing Gateway Support

Since payment gateways will be implemented in future lessons, a placeholder method was added.

public static function get_gateway_name( $transaction ) {

    return 'Manual Payment (Coming Soon)';
}

The payment page simply calls:

echo esc_html(
    Flipnzee_Payment_Manager::get_gateway_name( $transaction )
);

Later, this method will automatically return:

  • Manual Bank Transfer
  • Stripe
  • Razorpay
  • PayPal

without changing the payment page.


Debugging Along the Way

During implementation, a few useful issues were discovered.

1. Transaction Status Case Sensitivity

Initially the validation checked:

$transaction->status !== 'Pending'

However, the database stored:

pending

As a result, every payment was incorrectly rejected.

The validation was updated to:

strtolower( trim( $transaction->status ) ) !== 'pending'

making it much more reliable.


2. Missing Payment Gateway Column

An attempt was made to display:

$transaction->payment_gateway

This produced an undefined property warning because the database table does not yet contain a payment_gateway column.

Instead of adding a temporary workaround, the gateway display was moved into:

Flipnzee_Payment_Manager::get_gateway_name()

which currently returns a placeholder while the database schema is prepared in a future lesson.


Testing

Several scenarios were tested.

✅ Existing transaction loads correctly.

✅ Pending transaction is accepted.

✅ Invalid transaction ID displays:

Transaction not found.

✅ Placeholder payment gateway displays:

Manual Payment (Coming Soon)

No PHP warnings remain.


Final Result

The payment page now displays:

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

with validation handled entirely by the Payment Manager.

The interface remains clean while the underlying architecture becomes much more maintainable.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


What Was Learned

This lesson demonstrated the value of separating business logic from presentation.

Instead of embedding validation throughout the payment page, all payment-related decisions are now centralized in a dedicated manager. This approach makes the code easier to read, easier to test, and far simpler to extend as new payment gateways and payment workflows are introduced.

It also highlighted the importance of real-world debugging—such as handling inconsistent database values (e.g., Pending vs. pending) and recognizing when a database schema needs to evolve rather than patching around missing fields.

With the Flipnzee_Payment_Manager now in place, the plugin has a solid foundation for implementing gateway-specific payment processing in upcoming lessons while keeping the payment page itself clean and focused.

Lesson 71: Preparing the Payment Gateway Architecture for Future Integrations

Introduction

With a dedicated buyer payment page now operational, the next step is to prepare the plugin for actual payment gateway integration. Rather than immediately connecting to a provider like Stripe or PayPal, it is better to first build a clean, reusable architecture that allows multiple payment gateways to be added later without rewriting the auction workflow.

In this lesson, we’ll introduce a centralized payment manager that becomes responsible for generating payment requests, validating transactions, and routing buyers to the selected payment gateway. Although no real payment processing will occur yet, this lesson lays the foundation for supporting Stripe, PayPal, Razorpay, cryptocurrency payments, and additional gateways in future releases.


Learning Objectives

By the end of this lesson, you will learn how to:

  • Design a scalable payment architecture.
  • Separate payment logic from page rendering.
  • Create a dedicated Payment Manager class.
  • Validate transactions before initiating payment.
  • Prepare the plugin for multiple payment gateways.
  • Keep the codebase modular and maintainable.

Why This Lesson Is Important

A common mistake is embedding payment code directly inside the payment page shortcode. That approach quickly becomes difficult to maintain when additional gateways are introduced.

Instead, we’ll separate responsibilities:

  • Payment Page → displays information to the buyer.
  • Payment Manager → handles payment processing logic.
  • Gateway Classes (future lessons) → communicate with Stripe, PayPal, Razorpay, crypto wallets, etc.

This layered architecture follows good software engineering principles and makes the plugin easier to extend.


What We’ll Build

At the end of this lesson, the payment flow will look like this:

Buyer
   │
   ▼
Payment Page
   │
   ▼
Payment Manager
   │
   ▼
Selected Gateway
   │
   ├── Stripe (future)
   ├── PayPal (future)
   ├── Razorpay (future)
   └── Crypto (future)

Planned Implementation

During this lesson we will:

Step 1

Create

includes/class-payment-manager.php

Step 2

Move payment-related business logic into this class.


Step 3

Add a function to validate a transaction before payment begins.


Step 4

Create a placeholder method that returns the payment URL for the selected gateway.


Step 5

Update the payment page so it requests payment information from the Payment Manager instead of containing all business logic itself.


Step 6

Register and load the new class using the plugin loader.


Expected Folder Structure

includes/

class-payment-manager.php
class-payment-page.php
class-transaction-manager.php
class-my-purchases.php
class-my-purchase-details.php

Benefits

After completing this lesson, the plugin will have:

  • Better separation of concerns.
  • Easier maintenance.
  • Cleaner code.
  • Support for multiple gateways.
  • Simpler testing.
  • Future-proof architecture.

Skills You’ll Learn

  • Object-Oriented Programming (OOP)
  • Separation of Concerns
  • WordPress Plugin Architecture
  • Business Logic vs Presentation
  • Designing Extensible Systems
  • Preparing APIs for Third-Party Integrations

What Comes Next?

With the Payment Manager in place, the next lessons can focus on implementing real payment gateways without modifying the auction or transaction workflow.

A possible roadmap is:

  • Lesson 72: Creating the Payment Manager and Transaction Validation
  • Lesson 73: Adding a Gateway Interface and Default Gateway Selection
  • Lesson 74: Integrating the First Payment Gateway (e.g., Stripe or Razorpay Sandbox)
  • Lesson 75: Handling Payment Callbacks and Updating Transaction Status

By first building the architecture rather than jumping straight into gateway code, the Flipnzee Auctions plugin will remain clean, scalable, and capable of supporting multiple payment providers as the marketplace grows.

Lesson 70: Building a Dedicated Payment Page for Flipnzee Auctions

After completing the buyer purchase history and purchase details pages in the previous lesson, the next logical step was to create a dedicated payment page. Instead of redirecting buyers to a non-existent URL after clicking “Pay Now”, the plugin now provides a proper payment page that serves as the foundation for future payment gateway integration.

Although no payment gateway is connected yet, this lesson establishes the complete page architecture that future lessons will build upon.


Objective

The goal of this lesson was to:

  • Create a dedicated payment page.
  • Register a new shortcode for the payment page.
  • Display transaction information securely.
  • Ensure only logged-in users can access the page.
  • Prepare the plugin for Stripe, PayPal and other payment integrations.

What We Built

The payment workflow now looks like this:

Completed Auction
        │
        ▼
Transaction Created
        │
        ▼
Buyer clicks "Pay Now"
        │
        ▼
/payment/?transaction_id=1
        │
        ▼
Payment Page
        │
        ▼
(Future)
Stripe / PayPal / Crypto Payment

Step 1 — Create a New Payment Page Class

A new file was created:

includes/class-payment-page.php

The file begins with the standard WordPress security check.

<?php

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Flipnzee_Payment_Page {

    public static function render() {

        if ( ! is_user_logged_in() ) {
            return '<p>Please log in to continue.</p>';
        }

        ob_start();

        $transaction_id = isset( $_GET['transaction_id'] )
            ? absint( $_GET['transaction_id'] )
            : 0;

        // Display payment information here.

        return ob_get_clean();
    }
}

Step 2 — Register a New Shortcode

The shortcode registry inside

includes/class-shortcodes.php

was extended with a new shortcode.

add_shortcode(
    'flipnzee_payment_page',
    array(
        'Flipnzee_Payment_Page',
        'render'
    )
);

This allows WordPress pages to render the payment interface using:

[flipnzee_payment_page]

Step 3 — Load the Payment Page Class

The plugin loader was updated so the new class becomes available throughout the plugin.

Example:

require_once FLIPNZEE_PLUGIN_PATH . 'includes/class-payment-page.php';

Without loading the class, WordPress would be unable to locate the shortcode callback.


Step 4 — Retrieve the Transaction ID

The page accepts the transaction through the URL.

Example:

/payment/?transaction_id=1

The transaction ID is safely extracted using:

$transaction_id = isset( $_GET['transaction_id'] )
    ? absint( $_GET['transaction_id'] )
    : 0;

Using absint() ensures only positive integer IDs are accepted.


Step 5 — Fetch Transaction Details

Using the transaction ID, the plugin queries the transaction table.

Example:

global $wpdb;

$table = $wpdb->prefix . 'flipnzee_transactions';

$transaction = $wpdb->get_row(
    $wpdb->prepare(
        "SELECT * FROM {$table} WHERE id = %d",
        $transaction_id
    )
);

This returns the complete transaction record for display.


Step 6 — Display Payment Information

The page currently displays essential information including:

  • Transaction ID
  • Winning Bid
  • Transaction Status
  • Payment Status

Example output:

Payment

Transaction ID     1
Winning Bid        ₹55,555,609
Status             Pending
Payment Status     Pending

This provides buyers with confirmation that the transaction exists before payment processing is added.


Step 7 — Create a WordPress Payment Page

A new WordPress page was created:

Payment

The page content contains only the shortcode:

[flipnzee_payment_page]

This keeps presentation separate from business logic, making the system easier to maintain.


Testing

The payment page was tested by visiting:

/payment/?transaction_id=1

The page correctly displayed:

  • Transaction ID
  • Winning Bid
  • Pending Status
  • Pending Payment Status

The previous 404 Not Found error was successfully resolved.


Files Modified

includes/class-payment-page.php (new)
includes/class-shortcodes.php
includes/class-loader.php (or plugin loader)

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Lessons Learned

During implementation, several important WordPress plugin development concepts were reinforced:

  • Create reusable functionality using dedicated classes.
  • Register features using WordPress shortcodes.
  • Load new classes through the plugin loader.
  • Validate user input using absint().
  • Protect pages by requiring user authentication.
  • Use output buffering (ob_start() / ob_get_clean()) for shortcode rendering.
  • Keep page layout separate from business logic.

Current Workflow

Auction Ends
      │
      ▼
Winner Determined
      │
      ▼
Transaction Created
      │
      ▼
"My Purchases"
      │
      ▼
Pay Now
      │
      ▼
Payment Page
      │
      ▼
(Future)
Payment Gateway Integration

What’s Next?

With the payment page now in place, the plugin is ready for the next phase of development. Future lessons will focus on transforming this informational page into a fully functional checkout by adding payment gateway integration, order summaries, payment processing, status updates, and buyer/seller notifications.

Lesson 70 establishes the foundation that all future payment functionality will build upon.

Lesson 70: Building the Payment Page Foundation for Completed Auctions


Introduction

After successfully completing the auction lifecycle in the previous lessons, the next logical step is to allow auction winners to complete their purchase.

By the end of Lesson 69, Flipnzee Auctions was already capable of:

  • Creating and managing auctions
  • Automatically closing expired auctions
  • Determining the winning bidder
  • Recording transactions
  • Displaying transactions in the WordPress admin
  • Showing buyers their purchases
  • Displaying purchase details
  • Providing a Pay Now button for unpaid purchases

Although the Pay Now button existed, clicking it resulted in a 404 Page Not Found error because the payment page itself had not yet been implemented.

Lesson 70 focuses on solving this problem by creating the foundation of the payment workflow.


Why This Lesson Is Important

Every online marketplace requires a secure payment flow after an auction ends.

Instead of jumping directly into integrating a payment gateway like Stripe or PayPal, it is better to build the underlying architecture first.

This lesson concentrates on creating the page that receives the transaction, validates it, and displays the purchase before any actual payment processing takes place.

Building the foundation first makes later gateway integration much cleaner and easier.


Objectives

In this lesson we will:

  • Create the Payment Page shortcode
  • Build a dedicated Payment Page class
  • Register the shortcode with the plugin loader
  • Display transaction information
  • Validate transaction IDs
  • Handle missing or invalid transactions gracefully
  • Prepare the page for future payment gateway integration

Planned Workflow

To keep development safe and manageable, this lesson will be completed in several small checkpoints.

Checkpoint 1

Create the Payment Page class.


Checkpoint 2

Register the payment shortcode.


Checkpoint 3

Display transaction information.


Checkpoint 4

Handle invalid transactions.


Checkpoint 5

Test the page using existing auction transactions.


Checkpoint 6

Commit the completed lesson to Git.


Expected User Flow

Auction Ends
        │
        ▼
Winner Determined
        │
        ▼
Transaction Created
        │
        ▼
Buyer Visits "My Purchases"
        │
        ▼
Clicks "Pay Now"
        │
        ▼
Payment Page Opens
        │
        ▼
Transaction Validated
        │
        ▼
Ready for Payment Gateway

Development Strategy

One important improvement in our workflow is the use of small Git checkpoints.

At the beginning of this lesson, the entire project was restored to the stable Lesson 69 state and committed to GitHub. This provides a reliable rollback point before introducing the payment workflow.

Rather than implementing the complete payment system in one attempt, each stage will be developed, tested, and committed separately. This incremental approach reduces risk, simplifies debugging, and ensures that any issues can be isolated without affecting previously completed features.


What We’ll Build Next

By the end of Lesson 70, clicking the Pay Now button should no longer produce a 404 error. Instead, buyers will be taken to a dedicated payment page displaying the transaction details, confirming the amount due, and preparing the auction purchase for payment processing in the upcoming lessons.


Next Lesson: Implementing the Payment Page and Connecting the “Pay Now” Workflow.

Lesson 69: Adding a Payment Page and Payment Links for Auction Winners in the Flipnzee Auctions Plugin

As the Flipnzee Auctions plugin continues to evolve, one of the next logical improvements was to guide auction winners toward completing their purchase. In previous lessons, buyers could view their purchases and transaction details, but there was no dedicated page to begin the payment process.

In this lesson, a frontend payment page was introduced along with contextual payment links, creating a smoother purchasing experience for buyers.


Objective

The goal of this lesson was to:

  • Create a dedicated Payment page.
  • Add a new payment shortcode.
  • Display a Pay Now action for pending purchases.
  • Keep View Details available for completed purchases.
  • Build the foundation for integrating real payment gateways in future lessons.

Step 1: Created the Payment Page Class

A new file was added:

includes/class-payment-page.php

This class is responsible for rendering the payment page using a shortcode.

It retrieves the transaction ID from the URL, validates the request, and prepares the page for displaying payment-related information.


Step 2: Loaded the New Class

The main plugin file was updated to load the payment page class.

require_once FLIPNZEE_AUCTION_PATH .
    'includes/class-payment-page.php';

This ensures the payment functionality becomes available whenever the plugin loads.


Step 3: Registered a New Shortcode

A new shortcode was registered for the payment page.

Example:

[flipnzee_payment]

This shortcode can be placed on any WordPress page to create a dedicated payment screen.


Step 4: Created the Payment Page

Inside WordPress, a new page named:

Payment

was created.

Its content simply contains:

[flipnzee_payment]

This allows buyers to visit:

https://example.com/payment/

and access their payment page.


Step 5: Added Dynamic Payment Links

The My Purchases table was enhanced with conditional action links.

If a purchase is still pending:

Pay Now

is displayed.

If payment has already been completed:

View Details

is displayed.

This creates a cleaner and more intuitive workflow for buyers.


Step 6: Passed the Transaction ID

When the buyer clicks Pay Now, the transaction ID is automatically included in the URL.

Example:

/payment/?transaction_id=5

The payment page then knows exactly which purchase is being processed.


Step 7: Improved User Experience

Originally, the purchase details shortcode displayed:

Invalid transaction.

when no transaction ID was present.

This was changed so that the shortcode quietly returns nothing instead.

As a result:

  • The My Purchases page remains clean.
  • Purchase details only appear after selecting a specific transaction.

Step 8: Displayed Both Actions for Pending Purchases

To make the interface more useful, pending purchases now display both actions.

Pay Now

View Details

This allows buyers to review their purchase before completing payment.


Testing Performed

The following scenarios were successfully tested:

  • Plugin activation
  • Payment page loading
  • Payment shortcode rendering
  • Pending purchases displaying Pay Now
  • Paid purchases displaying View Details
  • Purchase Details page opening correctly
  • Transaction IDs passed correctly through URLs
  • No PHP syntax errors
  • No fatal errors after implementation

Result

The buyer journey has now become much more complete.

Auction Listing
        ↓
Place Bid
        ↓
Auction Ends
        ↓
Transaction Created
        ↓
My Purchases
        ↓
Pay Now
        ↓
Purchase Details

Although the payment page currently serves as a placeholder, it establishes the structure required for integrating payment gateways such as Stripe, Razorpay, PayPal, or WooCommerce Payments in future lessons.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


What I Learned

This lesson demonstrated several important WordPress plugin development concepts:

  • Creating additional frontend components using shortcodes.
  • Passing data securely through URL parameters.
  • Building conditional user interfaces based on transaction status.
  • Improving usability by displaying context-sensitive actions.
  • Designing a scalable workflow that can later support real payment gateways.

Conclusion

Lesson 69 transformed the Flipnzee Auctions plugin from simply tracking purchases into guiding buyers through the next stage of the auction process. By introducing a dedicated payment page and dynamic action links, the plugin now provides a more complete end-to-end purchasing experience while laying the groundwork for future payment gateway integration.

Lesson 69: Build the Buyer Payment Page


Why This Lesson?

A buyer can now:

  • Browse auctions.
  • Place bids.
  • Win an auction.
  • View purchases.
  • View transaction details.

The next logical step is allowing the buyer to proceed to payment.

Although payment gateways (Stripe, Razorpay, PayPal, etc.) will be integrated later, we should first build the payment page and workflow.


What We Will Build

A new frontend shortcode:

[flipnzee_payment]

This page will display:

Payment

Auction:
Wpnzee.com

Transaction ID:
#2

Winning Bid:
₹55,555,609.00

Status:
Pending

------------------------------------------------

Proceed to Payment

Initially, the button will simply display a placeholder message.

In later lessons it will connect to:

  • Stripe
  • Razorpay
  • PayPal

without redesigning the page.


New Workflow

My Purchases
      │
      ▼
View Details
      │
      ▼
Purchase Details
      │
      ▼
Proceed to Payment

Features

During this lesson we will:

  • Create a Payment shortcode.
  • Verify the buyer owns the transaction.
  • Retrieve transaction details.
  • Display payment summary.
  • Show a “Proceed to Payment” button.
  • Hide the button once the transaction is already marked as Paid.

Files Expected to Change

includes/class-payment.php
includes/class-shortcodes.php
flipnzee-auctions.php
includes/class-my-purchase-details.php

New Shortcode

[flipnzee_payment]

Payment Summary

The page will display:

FieldExample
Transaction ID#2
AuctionWpnzee.com
Winning Bid₹55,555,609.00
StatusPending

Button Behaviour

If:

Status = Pending

display

Proceed to Payment

If:

Status = Paid

display

✓ Payment Received

This provides immediate visual feedback and prevents duplicate payment attempts.


Skills You’ll Learn

During this lesson you’ll learn how to:

  • Build another reusable frontend shortcode.
  • Reuse secure transaction validation.
  • Conditionally display interface elements.
  • Create a payment-ready architecture.
  • Design pages that can later integrate with payment gateways without major refactoring.

Expected Outcome

By the end of Lesson 69, Flipnzee Auctions will have a complete post-purchase navigation flow:

Auction
      │
      ▼
Bid
      │
      ▼
Winner
      │
      ▼
My Purchases
      │
      ▼
Purchase Details
      │
      ▼
Payment Page

Although no real payment will be processed yet, the platform will be structurally ready for payment gateway integration in subsequent lessons.


Why this is a good next step

Instead of postponing payment until the end of development, we’re building the user journey in the same order a real buyer experiences it. When you later integrate Stripe, Razorpay, or another gateway, you’ll only need to replace the placeholder button action rather than redesign the buyer workflow. This keeps the development incremental and makes Version 1 feel complete from a user’s perspective.

Lesson 68 Implementation: Building a Secure Buyer Purchase Details Page in Flipnzee Auctions

In the previous lesson, buyers gained access to a My Purchases dashboard where they could see every website they had won through Flipnzee Auctions. While that was a major improvement, buyers still had no way to inspect an individual transaction.

Lesson 68 addresses this by introducing a dedicated Purchase Details page. Buyers can now click a transaction from their purchase history and securely view its complete details.


What We Built

During this lesson, a new frontend component was created specifically for buyers.

The new class:

Flipnzee_My_Purchase_Details

is responsible for displaying the details of a single purchase.

The page is powered by a new shortcode:

[flipnzee_purchase_details]

Creating the Purchase Details Class

A new file was added to the plugin:

includes/class-my-purchase-details.php

Initially, the class simply:

  • Prevented direct access.
  • Checked whether the visitor was logged in.
  • Displayed a placeholder heading.

Building the page incrementally allowed each stage to be tested before adding more functionality.


Loading the Class

The new class was loaded inside the main plugin file.

require_once FLIPNZEE_AUCTION_PATH .
	'includes/class-my-purchase-details.php';

After every modification, syntax was verified using:

php -l flipnzee-auctions.php

Registering the Shortcode

Next, the shortcode was registered inside the shortcode manager.

[flipnzee_purchase_details]

This allows the purchase details page to be inserted on any WordPress page using a shortcode, keeping the implementation flexible and reusable.


Reading the Transaction ID

Unlike the purchase history page, the details page must know which transaction to display.

The transaction ID is retrieved from the URL.

Example:

https://flipnzee.com/purchase-details/?transaction_id=2

The value is sanitised using:

absint()

If no transaction ID is supplied, a friendly error message is shown instead of attempting a database query.


Secure Database Lookup

One of the most important parts of this lesson was securing access to transaction data.

Instead of loading a transaction using only its ID, the query verifies both:

  • Transaction ID
  • Logged-in Buyer ID

The SQL query therefore ensures buyers can only access their own purchases.

Even if someone manually changes:

?transaction_id=1

to

?transaction_id=50

they cannot view another user’s transaction unless they are the rightful buyer.

This is an essential security practice for any marketplace application.


Building the Purchase Details Page

Once the transaction is retrieved successfully, the page displays a professional summary.

Information shown includes:

  • Transaction ID
  • Auction Title
  • Winning Bid
  • Transaction Status
  • Purchase Date

Instead of returning plain HTML strings, PHP output buffering was used.

ob_start();
...
return ob_get_clean();

This keeps the template much easier to read and maintain.


Adding Navigation from My Purchases

The purchase history table was then enhanced with a brand new Details column.

Each purchase now contains a View Details link.

Clicking the link automatically opens the Purchase Details page for the selected transaction.

The navigation flow now becomes:

My Purchases
      │
      ▼
View Details
      │
      ▼
Purchase Details

This creates a far more natural user experience than requiring buyers to manually edit URLs.


Testing

Several scenarios were tested during implementation.

Missing Transaction ID

Without a transaction ID:

/testing/

the page correctly displayed:

Invalid transaction.

Valid Transaction

When a valid transaction was supplied:

/testing/?transaction_id=2

the page successfully displayed the transaction details.


Invalid Transaction

Using an invalid transaction ID correctly returned:

Transaction not found.

This confirms the validation logic is working correctly.


Final Result

The completed Purchase Details page now displays information similar to:

FieldValue
Transaction ID2
AuctionWpnzee.com
Winning Bid₹55,555,609.00
StatusPaid
Purchased2026-07-06 05:42:05

The page is accessible directly from the buyer’s purchase history through the View Details link.


Lessons Learned

This lesson reinforced several important WordPress development concepts.

  • Building reusable shortcode-based pages.
  • Reading and sanitising URL parameters.
  • Using $wpdb->prepare() for secure database queries.
  • Verifying ownership before displaying private information.
  • Using output buffering to generate HTML templates.
  • Creating navigation between frontend pages.
  • Improving usability through contextual links.

Download Source Code

Download the starting version of the plugin before the lesson:

Download the completed version after this lesson:


Why This Feature Matters

Lesson 68 completes the buyer transaction workflow within Flipnzee Auctions.

Previously, buyers could only see a list of purchases. They can now drill down into individual transactions and review important information without needing administrator assistance.

Combined with the My Purchases dashboard introduced in Lesson 67, buyers now have a professional frontend experience that mirrors the functionality commonly found in commercial marketplace platforms.

As Flipnzee evolves, this page can be expanded further with payment confirmations, downloadable invoices, escrow status, support requests, digital asset delivery, and other post-purchase features. It provides a strong and secure foundation for the buyer experience while bringing the Flipnzee Auctions plugin another significant step closer to a production-ready Version 1 release.