# easy-invoice/2.4.2/templates/payment-section.php

Easy Invoice – Invoice Generator, PDF Quotes &amp; Payments, version 2.4.2. 1,085 lines.

- Page: https://pluginprobe.com/plugins/easy-invoice/2.4.2/code/templates/payment-section.php
- Raw: https://pluginprobe.com/plugins/easy-invoice/2.4.2/raw/templates/payment-section.php
- Modified: 2026-09-29T05:21:04+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/easy-invoice/2.4.2/code/templates/payment-section.php#L10-L20`.

```php
<?php
/**
 * Payment Section Template
 * 
 * Displays payment options and processing UI
 * 
 * @package EasyInvoice
 * @since 1.0.0
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}
// Get invoice data
$invoice_id = get_the_ID();
// The access token the AJAX calls below present back to the payment endpoints:
// the ?ik= from an emailed link, or whatever another proof of access (a signed
// secure link) supplies through the filter.
/** This filter is documented in includes/Controllers/InvoiceController.php */
$ei_ps_access_token = (string) apply_filters('easy_invoice_presented_access_token', isset($_GET['ik']) ? sanitize_text_field(wp_unslash($_GET['ik'])) : '', 'invoice'); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$invoice = new \EasyInvoice\Models\Invoice(get_post($invoice_id));
// What is owed now: total less payments received and credit notes.
$total_amount = \EasyInvoice\Services\InvoiceBalance::due($invoice);
$currency_code = $invoice->getCurrencyCode() ?: 'USD';

// If currency is "global", use the global setting
if ($currency_code === 'global') {
    $currency_code = get_option('easy_invoice_currency_code', 'USD');
}

$currency_symbol = \EasyInvoice\Helpers\CurrencyHelper::getCurrencySymbol($currency_code);

// Get available payment gateways
$payment_controller = new \EasyInvoice\Controllers\PaymentController();
$available_gateways = $payment_controller->getAvailableGateways($invoice_id);

// Get nonce for AJAX security
$payment_nonce = wp_create_nonce('easy_invoice_payment');


?>
<?php
if (!function_exists('easy_invoice_payment_icon')) {
    /**
     * An inline icon for a payment method. The public page loads no icon
     * font, so Font Awesome class names rendered as empty boxes; a gateway
     * may still hand over an image URL.
     *
     * @param string $gateway_id Gateway id.
     * @param string $icon       Icon the gateway declared (class name or URL).
     * @return string HTML.
     */
    function easy_invoice_payment_icon(string $gateway_id, string $icon = ''): string {
        if ('' !== $icon && preg_match('#^(https?:)?//|^/#', $icon)) {
            return '<img src="' . esc_url($icon) . '" alt="" style="width:22px;height:22px;object-fit:contain;">';
        }
        $a = 'width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"';
        $paths = [
            'bank'   => '<path d="M3 10h18M5 10v9M9 10v9M15 10v9M19 10v9M2 19h20M12 3l9 6H3l9-6z"/>',
            'cheque' => '<rect x="3" y="6" width="18" height="12" rx="2"/><path d="M7 10h6M7 14h3M15 14h2"/>',
            'cash'   => '<rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="3"/><path d="M6 9h.01M18 15h.01"/>',
            'card'   => '<rect x="2" y="5" width="20" height="14" rx="2"/><path d="M2 10h20M6 15h4"/>',
            'wallet' => '<path d="M3 7a2 2 0 0 1 2-2h14v4"/><rect x="3" y="7" width="18" height="12" rx="2"/><path d="M16 13h.01"/>',
        ];
        $id  = strtolower($gateway_id);
        $key = 'card';
        if (isset($paths[strtolower($icon)])) { $key = strtolower($icon); }
        elseif (false !== strpos($id, 'bank') || false !== strpos($id, 'transfer') || false !== strpos($id, 'wire')) { $key = 'bank'; }
        elseif (false !== strpos($id, 'cheque') || false !== strpos($id, 'check')) { $key = 'cheque'; }
        elseif (false !== strpos($id, 'cash')) { $key = 'cash'; }
        elseif (false !== strpos($id, 'paypal') || false !== strpos($id, 'paystack') || false !== strpos($id, 'mollie')) { $key = 'wallet'; }
        return '<svg ' . $a . '>' . $paths[$key] . '</svg>';
    }
}
?>


<div class="easy-invoice-payment-sidebar">
    <div class="payment-header">
        <div class="header-content">
            <h2><?php esc_html_e('Payment', 'easy-invoice'); ?></h2>
            <div class="invoice-summary">
                <span class="invoice-number"><?php echo esc_html($invoice->getNumber()); ?></span>
                <span class="invoice-date"><?php echo esc_html(date_i18n('M j, Y', strtotime($invoice->getIssueDate()))); ?></span>
            </div>
        </div>

        <div class="amount-display">
            <div class="amount-label"><?php echo esc_html((float) $invoice->getTotal() - $total_amount > 0.005 ? __('Amount Due', 'easy-invoice') : __('Total Amount', 'easy-invoice')); ?></div>
            <div class="amount-value">
                <?php echo esc_html(easy_invoice_format_money($total_amount, $invoice)); ?>
            </div>
        </div>
    </div>

    <?php if (empty($available_gateways)): ?>
        <div class="no-payment-methods">
            <div class="empty-state">
                <div class="empty-icon">
                    <?php echo easy_invoice_payment_icon('card'); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
                </div>
                <h3><?php esc_html_e('No Payment Methods', 'easy-invoice'); ?></h3>
                <p><?php esc_html_e('Payment methods are not configured for this invoice.', 'easy-invoice'); ?></p>
            </div>
        </div>
    <?php else: ?>
        <form id="easy-invoice-payment-form" class="payment-form">
            <input type="hidden" name="invoice_id" value="<?php echo esc_attr($invoice_id); ?>">
            <input type="hidden" name="payment_nonce" value="<?php echo esc_attr($payment_nonce); ?>">
            <input type="hidden" name="payment_amount" id="payment_amount" value="<?php echo esc_attr($total_amount); ?>">
            <input type="hidden" name="payment_note" id="payment_note" value="">
            <input type="hidden" name="action" value="easy_invoice_process_payment">
            <input type="hidden" name="is_partial_payment" id="is_partial_payment" value="0">
            <input type="hidden" name="payment_method" id="payment_method" value="">
            
            <?php 
            // Add partial payments form before payment gateways (only if enabled)
            do_action('easy_invoice_payment_gateways_before', $invoice);
            
            ?>
            
            <div class="payment-methods">
                <label class="section-label"><?php esc_html_e('Payment Method', 'easy-invoice'); ?></label>
                
                <div class="method-options">
                <?php foreach ($available_gateways as $gateway): ?>
                        <div class="method-option" data-gateway="<?php echo esc_attr($gateway['id']); ?>">
                            <input type="radio" 
                                   name="payment_method_radio" 
                                   id="payment_method_<?php echo esc_attr($gateway['id']); ?>"
                                   value="<?php echo esc_attr($gateway['id']); ?>"
                                   class="method-radio">
                            
                            <label for="payment_method_<?php echo esc_attr($gateway['id']); ?>" class="method-label">
                                <div class="method-content">
                                    <div class="method-icon">
                                        <?php echo easy_invoice_payment_icon((string) $gateway['id'], (string) ($gateway['icon'] ?? '')); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- inline SVG / escaped img. ?>
                                    </div>
                                    
                                    <div class="method-details">
                                        <div class="method-name"><?php echo esc_html($gateway['title']); ?></div>
                                        <?php if (!empty($gateway['description'])): ?>
                                            <div class="method-description"><?php echo esc_html($gateway['description']); ?></div>
                                        <?php endif; ?>
                                    </div>
                                    
                                    <div class="method-check">
                                        <div class="checkmark"></div>
                                    </div>
                                </div>
                            </label>
                            
                            <div class="gateway-content" id="gateway-content-<?php echo esc_attr($gateway['id']); ?>" style="display: none;"></div>
                        </div>
                    <?php endforeach; ?>
                </div>
            </div>

            <div class="message-area" id="payment-message-area"></div>

            <div class="submit-section">
                <button type="submit" id="pay-now-button" class="submit-button" disabled>
                    <span class="button-text"><?php esc_html_e('Pay', 'easy-invoice'); ?> <?php echo esc_html(easy_invoice_format_money($total_amount, $invoice)); ?></span>
                    <div class="button-loader hidden">
                        <div class="loader"></div>
                        <span><?php esc_html_e('Processing...', 'easy-invoice'); ?></span>
                    </div>
                </button>
                
                <div class="security-note">
                    <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" style="vertical-align:-2px;margin-right:4px;"><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 0 1 8 0v4"/></svg>
                    <span><?php esc_html_e('Your payment is secure and encrypted', 'easy-invoice'); ?></span>
                </div>
            </div>
        </form>
    <?php endif; ?>
</div>

<style>
/* Clean SaaS Payment Sidebar */
.easy-invoice-payment-sidebar {
    background: #ffffff;
    height: 100vh;
    display: flex;
    flex-direction: column;
    border-left: 1px solid #e5e7eb;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    box-shadow: -4px 0 12px rgba(0, 0, 0, 0.05);
}

/* Header */
.payment-header {
    padding: 32px 24px 24px;
    border-bottom: 1px solid #f3f4f6;
    background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
}

.header-content h2 {
    margin: 0 0 8px 0;
    font-size: 24px;
    font-weight: 600;
    color: #111827;
    line-height: 1.2;
}

.invoice-summary {
    display: flex;
    align-items: center;
    gap: 12px;
    font-size: 14px;
    color: #6b7280;
}

.invoice-number {
    font-weight: 500;
    color: #374151;
}

.invoice-date {
    color: #9ca3af;
}

.amount-display {
    margin-top: 20px;
    padding: 20px;
    background: #ffffff;
    border: 1px solid #e5e7eb;
    border-radius: 12px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
}

.amount-label {
    font-size: 12px;
    font-weight: 500;
    color: #6b7280;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    margin-bottom: 4px;
}

.amount-value {
    font-size: 18px;
    font-weight: 700;
    color: #111827;
    line-height: 1;
}

/* No Payment Methods */
.no-payment-methods {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px 24px;
}

.empty-state {
    text-align: center;
    max-width: 280px;
}

.empty-icon {
    width: 48px;
    height: 48px;
    background: #f3f4f6;
    border-radius: 12px;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 16px;
    color: #9ca3af;
    font-size: 20px;
}

.empty-state h3 {
    margin: 0 0 8px 0;
    font-size: 16px;
    font-weight: 600;
    color: #374151;
}

.empty-state p {
    margin: 0;
    font-size: 14px;
    color: #6b7280;
    line-height: 1.5;
}

/* Payment Form */
.payment-form {
    flex: 1;
    display: flex;
    flex-direction: column;
    padding: 24px;
    overflow-y: auto;
}

/* Payment Methods */
.payment-methods {
    margin-bottom: 24px;
}

.section-label {
    display: block;
    font-size: 14px;
    font-weight: 600;
    color: #374151;
    margin-bottom: 16px;
}

.method-options {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Gateway Content */
.gateway-content {
    padding: 20px;
    background: #ffffff;
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    border-top: 2px solid #10b981;
}

.gateway-content h4 {
    margin: 0 0 16px 0;
    font-size: 16px;
    font-weight: 600;
    color: #111827;
    line-height: 1.4;
}

.gateway-content p {
    margin: 0 0 12px 0;
    font-size: 14px;
    line-height: 1.5;
    color: #374151;
}

.gateway-content .bank-details,
.gateway-content .payment-reference {
    margin: 16px 0;
    padding: 16px;
    background: #f8fafc;
    border-radius: 8px;
    border: 1px solid #e5e7eb;
}

.gateway-content .payment-reference {
    background: #f0f7ff;
    border-left: 4px solid #0073aa;
}

.gateway-content .reference-note {
    font-style: italic;
    color: #6b7280;
    margin-top: 8px;
    font-size: 13px;
}

.gateway-content .ei-offline h4 { margin: 0 0 10px; font-size: 15px; font-weight: 600; color: #111827; }
.gateway-content .ei-offline__details { width: 100%; border-collapse: collapse; margin-bottom: 12px; font-size: 13px; }
.gateway-content .ei-offline__details th { text-align: left; padding: 6px 8px 6px 0; color: #6b7280; font-weight: 500; width: 40%; vertical-align: top; }
.gateway-content .ei-offline__details td { padding: 6px 0; color: #111827; font-weight: 600; word-break: break-word; }
.gateway-content .ei-offline__instructions { font-size: 13px; color: #374151; line-height: 1.5; margin-bottom: 10px; }
.gateway-content .ei-offline__instructions p { margin: 0 0 8px; }
.gateway-content .ei-offline__form { margin-top: 14px; padding-top: 14px; border-top: 1px solid #e5e7eb; }
.gateway-content .ei-offline__lead { font-size: 13px; color: #374151; margin: 0 0 10px; }
.gateway-content .ei-offline__form .form-group { margin-bottom: 12px; }
.gateway-content .ei-offline__form label { display: block; font-size: 13px; font-weight: 600; color: #111827; margin-bottom: 4px; }
.gateway-content .ei-offline__optional { font-weight: 400; color: #6b7280; }
.gateway-content .ei-offline__required { color: #dc2626; }
.gateway-content .ei-offline__form input[type="text"],
.gateway-content .ei-offline__form textarea { width: 100%; box-sizing: border-box; border: 1px solid #d1d5db; border-radius: 8px; padding: 9px 12px; font-size: 14px; background: #fff; }
.gateway-content .ei-offline__form input[type="file"] { display: block; width: 100%; font-size: 13px; color: #374151; }
.gateway-content .ei-offline__form .reference-note { margin: 4px 0 0; font-size: 12px; color: #6b7280; }
.gateway-content .payment-proof-form {
    margin-top: 24px;
    padding-top: 20px;
    border-top: 1px solid #e5e7eb;
}



/* Gateway-specific instruction styles */
.gateway-content .bank-transfer-instructions,
.gateway-content .cheque-payment-instructions,
.gateway-content .cash-payment-instructions {
    margin: 0;
    padding: 0;
    background: transparent;
    border: none;
    border-radius: 0;
    border-left: none;
}

.gateway-content .bank-details-table {
    width: 100%;
    border-collapse: collapse;
    margin-bottom: 16px;
}

.gateway-content .bank-details-table th,
.gateway-content .bank-details-table td {
    padding: 8px 12px;
    border-bottom: 1px solid #e5e7eb;
    text-align: left;
}

.gateway-content .bank-details-table th {
    width: 40%;
    font-weight: 600;
    color: #374151;
}

.gateway-content .cheque-details,
.gateway-content .cash-details {
    margin-bottom: 16px;
}

.gateway-content .payable-to,
.gateway-content .invoice-number {
    font-size: 16px;
    margin: 8px 0 16px;
    color: #0073aa;
    font-weight: 600;
}

.gateway-content .mailing-address {
    padding: 12px;
    background: #f0f7ff;
    border-left: 3px solid #0073aa;
    margin-top: 8px;
    border-radius: 6px;
}

.gateway-content .cheque-notification-form {
    margin-top: 20px;
    border-top: 1px solid #e5e7eb;
    padding-top: 16px;
}

.gateway-content .submit-notification-btn {
    background: #0073aa;
    color: white;
    padding: 10px 20px;
    border: none;
    border-radius: 6px;
    cursor: pointer;
    font-size: 14px;
    font-weight: 500;
    transition: background-color 0.2s ease;
}

.gateway-content .submit-notification-btn:hover {
    background: #005d8c;
}

.gateway-content .submit-notification-btn:disabled {
    background: #9ca3af;
    cursor: not-allowed;
}



.method-option {
    border: 2px solid #e5e7eb;
    border-radius: 12px;
    transition: all 0.2s ease;
    background: #ffffff;
    overflow: hidden;
}

.method-option:hover {
    border-color: #d1d5db;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
    transform: translateY(-1px);
}

.method-option.selected {
    border-color: #10b981;
    box-shadow: 0 0 0 3px rgba(16, 185, 129, 0.1);
    background: #f0fdf4;
}

.method-radio {
    display: none;
}

.method-label {
    display: block;
    padding: 20px;
    cursor: pointer;
    margin: 0;
}

.method-content {
    display: flex;
    align-items: center;
    gap: 16px;
}

.method-icon {
    width: 40px;
    height: 40px;
    background: #f9fafb;
    border-radius: 10px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #6b7280;
    font-size: 18px;
    flex-shrink: 0;
    transition: all 0.2s ease;
}

.method-option.selected .method-icon {
    background: #10b981;
    color: #ffffff;
}

.method-details {
    flex: 1;
    min-width: 0;
}

.method-name {
    font-weight: 600;
    font-size: 15px;
    color: #111827;
    margin-bottom: 4px;
}

.method-description {
    font-size: 13px;
    color: #6b7280;
    line-height: 1.4;
}

.method-check {
    flex-shrink: 0;
}

.checkmark {
    width: 24px;
    height: 24px;
    border: 2px solid #d1d5db;
    border-radius: 50%;
    position: relative;
    transition: all 0.2s ease;
}

.checkmark::after {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 10px;
    height: 10px;
    background: #ffffff;
    border-radius: 50%;
    opacity: 0;
    transition: opacity 0.2s ease;
}

.method-option.selected .checkmark {
    background: #10b981;
    border-color: #10b981;
}

.method-option.selected .checkmark::after {
    opacity: 1;
}



/* Message Area */
.message-area {
    margin-bottom: 24px;
    min-height: 20px;
}

.payment-message {
    padding: 16px 20px;
    border-radius: 8px;
    font-size: 14px;
    display: flex;
    align-items: center;
    gap: 12px;
    border: 1px solid;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.04);
}

.payment-message.success {
    background: #f0fdf4;
    color: #166534;
    border-color: #bbf7d0;
}

.payment-message.error {
    background: #fef2f2;
    color: #dc2626;
    border-color: #fecaca;
}

.payment-message.warning {
    background: #fffbeb;
    color: #d97706;
    border-color: #fed7aa;
}

.payment-message.info {
    background: #eff6ff;
    color: #1d4ed8;
    border-color: #bfdbfe;
}



/* Submit Section */
.submit-section {
    margin-top: auto;
    padding-top: 24px;
    border-top: 1px solid #f3f4f6;
}

.submit-button {
    width: 100%;
    padding: 18px 24px;
    background: linear-gradient(135deg, #10b981 0%, #059669 100%);
    color: #ffffff;
    border: none;
    border-radius: 12px;
    font-size: 16px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    position: relative;
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}

.submit-button:hover:not(:disabled) {
    background: linear-gradient(135deg, #059669 0%, #047857 100%);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(16, 185, 129, 0.4);
}

.submit-button:active:not(:disabled) {
    transform: translateY(0);
    box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);
}

.submit-button:disabled {
    background: #9ca3af;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.button-loader {
    display: flex;
    align-items: center;
    gap: 10px;
}

.button-loader.hidden {
    display: none;
}

.loader {
    width: 18px;
    height: 18px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-top: 2px solid #ffffff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

.security-note {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin-top: 16px;
    font-size: 13px;
    color: #6b7280;
    padding: 12px;
    background: #f9fafb;
    border-radius: 8px;
}

.security-note i {
    font-size: 14px;
    color: #10b981;
}

/* Responsive */
@media (max-width: 768px) {
    .easy-invoice-payment-sidebar {
        width: 100%;
        height: 100vh;
    }
    
    .payment-header {
        padding: 24px 20px 20px;
    }
    
    .payment-form {
        padding: 20px;
    }
    
    .method-label {
        padding: 16px;
    }
    
    .submit-button {
        padding: 16px 20px;
    }
}

/* Scrollbar */
.payment-form::-webkit-scrollbar {
    width: 6px;
}

.payment-form::-webkit-scrollbar-track {
    background: #f1f5f9;
    border-radius: 3px;
}

.payment-form::-webkit-scrollbar-thumb {
    background: #cbd5e1;
    border-radius: 3px;
}

.payment-form::-webkit-scrollbar-thumb:hover {
    background: #94a3b8;
}



/* Utility */
.hidden {
    display: none !important;
}
</style>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const paymentForm = document.getElementById('easy-invoice-payment-form');
    const payButton = document.getElementById('pay-now-button');
    const messageArea = document.getElementById('payment-message-area');
    const paymentMethods = document.querySelectorAll('input[name="payment_method_radio"]');
    const paymentAmountInput = document.getElementById('payment_amount');
    
    window.selectedGateway = null;
    
    // Initialize payment methods
    paymentMethods.forEach(method => {
        method.addEventListener('change', handlePaymentMethodChange);
    });
    
    // Handle payment amount changes
    if (paymentAmountInput) {
        paymentAmountInput.addEventListener('input', updatePayButtonText);
        paymentAmountInput.addEventListener('change', updatePayButtonText);
    }
    
    // Initialize button text on page load (always call this)
    updatePayButtonText();
    
    // Also call it after a short delay to ensure all elements are loaded
    setTimeout(() => {
        updatePayButtonText();
    }, 500);
    
    // Handle form submission
    paymentForm.addEventListener('submit', handlePaymentSubmit);
    
    function handlePaymentMethodChange(e) {
        window.selectedGateway = e.target.value;
        const methodEntry = e.target.closest('.method-option');

        // Update UI
        document.querySelectorAll('.method-option').forEach(entry => {
            entry.classList.remove('selected');
        });
        methodEntry.classList.add('selected');
        
        // Update hidden payment_method field
        const paymentMethodField = document.getElementById('payment_method');
        if (paymentMethodField) {
            paymentMethodField.value = window.selectedGateway;
        }
        
        // Enable pay button
        payButton.disabled = false;

        // Load gateway-specific content
        loadGatewayContent(window.selectedGateway);
    }
    
    function loadGatewayContent(gateway) {
        // Find the specific gateway content div for this gateway
        const contentDiv = document.getElementById('gateway-content-' + gateway);
        
        if (!contentDiv) {
            console.error('Gateway content div not found for:', gateway);
            return;
        }
        
        // Hide all gateway content divs first
        document.querySelectorAll('.gateway-content').forEach(div => {
            div.style.display = 'none';
        });
        
        // Clear existing content
        contentDiv.innerHTML = '';
        

            // Load gateway content via AJAX
            const formData = new FormData();
            formData.append('action', 'easy_invoice_get_payment_instructions');
            formData.append('gateway', gateway);
            formData.append('invoice_id', document.querySelector('input[name="invoice_id"]').value);
            formData.append('nonce', document.querySelector('input[name="payment_nonce"]').value);
            // Per-invoice access token from the emailed link (?ik=...); the server
            // authorises the request on it. Without it an anonymous client holding a
            // legitimate link could not load their own payment instructions.
            formData.append('access_token', <?php echo wp_json_encode($ei_ps_access_token); ?>);

            fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', {
                method: 'POST',
                body: formData
            })
            .then(response => {
                if (!response.ok) {
                    throw new Error('Network response was not ok');
                }
                return response.json();
            })
            .then(response => {
                if (response.success && response.data.instructions) {
                    contentDiv.innerHTML = response.data.instructions;
                    contentDiv.style.display = 'block';
                    applyOfflineState(contentDiv);
                } else {
                    contentDiv.style.display = 'none';
                }
            })
            .catch(error => {
                console.error('Error loading gateway content:', error);
                contentDiv.style.display = 'none';
            });
    }
    
    function loadGatewayContentViaAjax(gateway, contentDiv) {
        const formData = new FormData();
        formData.append('action', 'easy_invoice_get_payment_instructions');
        formData.append('gateway', gateway);
        formData.append('invoice_id', document.querySelector('input[name="invoice_id"]').value);
        formData.append('nonce', document.querySelector('input[name="payment_nonce"]').value);
        formData.append('access_token', <?php echo wp_json_encode($ei_ps_access_token); ?>);

        fetch('<?php echo esc_url(admin_url('admin-ajax.php')); ?>', {
            method: 'POST',
            body: formData
        })
        .then(response => response.json())
        .then(response => {
            if (response.success && response.data.instructions) {
                contentDiv.innerHTML = response.data.instructions;
                contentDiv.style.display = 'block';
            } else {
                contentDiv.style.display = 'none';
            }
        })
        .catch(error => {
            console.error('Error loading gateway content:', error);
            contentDiv.style.display = 'none';
        });
    }
    

    
    // An offline method (bank transfer, cheque, cash, …) is not charged here:
    // the button becomes "Submit payment details" and a required receipt is
    // checked before anything is sent.
    window.eiOfflineSelected = false;
    function applyOfflineState(contentDiv) {
        var offline = contentDiv ? contentDiv.querySelector('[data-ei-offline]') : null;
        window.eiOfflineSelected = !!offline;
        if (!payButton || !payButton.querySelector('.button-text')) { return; }
        if (offline) {
            payButton.querySelector('.button-text').textContent = offline.getAttribute('data-ei-submit-label') || 'Submit payment details';
        } else {
            updatePayButtonText();
        }
    }

    function handlePaymentSubmit(e) {
        e.preventDefault();
        payButton.disabled = true;
        
        if (!window.selectedGateway) {
            showPaymentMessage('Please select a payment method first.', 'error');
            payButton.disabled = false;
            return;
        }
        if (window.eiOfflineSelected) {
            var required = paymentForm.querySelector('input[type="file"][data-ei-required]');
            if (required && !(required.files && required.files.length)) {
                showPaymentMessage(<?php echo wp_json_encode(__('Please attach your receipt or proof of payment.', 'easy-invoice')); ?>, 'error');
                payButton.disabled = false;
                required.focus();
                return;
            }
        }
        
        // Show loading state
        payButton.querySelector('.button-text').classList.add('hidden');
        payButton.querySelector('.button-loader').classList.remove('hidden');
        
        // Handle all payment methods (PayPal, etc.)
        processStandardPayment();
    }
    

    
    function processStandardPayment() {
        const formData = new FormData(paymentForm);
        formData.append('payment_method', window.selectedGateway);
        // The per-invoice access token from the emailed link. processPayment()
        // authorises on it before anything else; without it a client who
        // arrived by their own link was refused with "Invalid invoice" the
        // moment they chose bank transfer, cheque or cash.
        formData.append('access_token', <?php echo wp_json_encode($ei_ps_access_token); ?>);

        // Get AJAX URL from WordPress
        const ajaxUrl = '<?php echo esc_url(admin_url('admin-ajax.php')); ?>';
        
        fetch(ajaxUrl, {
            method: 'POST',
            body: formData
        })
        .then(response => response.json())
        .then(response => {
            if (response.success) {
                handlePaymentSuccess(response.data);
            } else {
                const errorMsg = response.data && response.data.message 
                    ? response.data.message 
                    : 'Payment processing failed.';
                showPaymentMessage(errorMsg, 'error');
                resetPayButton();
            }
        })
        .catch(error => {
            console.error('Payment AJAX error:', error);
            showPaymentMessage('Server error during payment. Please try again.', 'error');
            resetPayButton();
        });
    }
    

    
    function handlePaymentSuccess(data) {
        // Handle redirect if provided (for PayPal and other external gateways)
        if (data.redirect_url) {
            // Get gateway-specific message or use default
            const redirectMessage = data.message || 'Redirecting to payment gateway to complete your payment...';
            
            // Update button state to show redirecting
            payButton.querySelector('.button-text').textContent = 'Processing...';
            payButton.querySelector('.button-loader').classList.add('hidden');
            payButton.querySelector('.button-text').classList.remove('hidden');
            payButton.disabled = true;
            
            // Show redirect message
            showPaymentMessage(redirectMessage, 'info');
            
            // Redirect immediately
            setTimeout(() => {
                window.location.href = data.redirect_url;
            }, 1000);
            return;
        }
        
        if (data.offline) {
            payButton.querySelector('.button-loader').classList.add('hidden');
            payButton.querySelector('.button-text').classList.remove('hidden');
            payButton.querySelector('.button-text').textContent = <?php echo wp_json_encode(__('Submitted', 'easy-invoice')); ?>;
            payButton.disabled = true;
            showPaymentMessage(data.message || 'Thank you — we will confirm your payment shortly.', 'success');
            setTimeout(function () { window.location.reload(); }, 2500);
            return;
        }
        // For successful payments without redirect
        // Update button state
        payButton.querySelector('.button-text').textContent = 'Payment Successful!';
        payButton.querySelector('.button-loader').classList.add('hidden');
        payButton.querySelector('.button-text').classList.remove('hidden');
        payButton.disabled = true;
        
        // Show success message
        showPaymentMessage(data.message || 'Payment successful!', 'success');
        
        // Reload the page after delay
        setTimeout(() => {
            window.location.reload();
        }, 2000);
    }
    
    function showPaymentMessage(message, type) {
        let icon = 'info-circle';
        if (type === 'success') {
            icon = 'check-circle';
        } else if (type === 'error') {
            icon = 'exclamation-triangle';
        } else if (type === 'warning') {
            icon = 'exclamation-triangle';
        }
        
        messageArea.innerHTML = `
            <div class="payment-message ${type}">
                ${message}
            </div>
        `;
    }
    
    function updatePayButtonText() {
        // No button when the panel has no payment methods to offer.
        if (!payButton || !payButton.querySelector('.button-text')) { return; }
        if (window.eiOfflineSelected) { return; }
        const hiddenPaymentAmount = document.getElementById('payment_amount');
        const paymentAmount = hiddenPaymentAmount ? hiddenPaymentAmount.value : '0';
        const money = <?php echo wp_json_encode(easy_invoice_money_format_spec($invoice)); ?>;
        const payLabel = <?php echo wp_json_encode(__('Pay', 'easy-invoice')); ?>;

        if (paymentAmount && paymentAmount > 0) {
            // Same rules as the PHP formatter: separators, precision, symbol position.
            const n = parseFloat(paymentAmount).toFixed(money.precision);
            const [int, dec] = n.split('.');
            const grouped = int.replace(/\B(?=(\d{3})+(?!\d))/g, money.thousands);
            const number = dec !== undefined ? grouped + money.decimal + dec : grouped;
            const formatted = (money.position === 'after' || money.position === 'right') ? number + money.symbol
                : (money.position === 'right_space') ? number + ' ' + money.symbol
                : (money.position === 'left_space') ? money.symbol + ' ' + number
                : money.symbol + number;
            payButton.querySelector('.button-text').textContent = `${payLabel} ${formatted}`;
        } else {
            payButton.querySelector('.button-text').textContent = 'Pay';
        }
    }
    
    // Make the function globally accessible
    window.updatePayButtonText = updatePayButtonText;
    
    function resetPayButton() {
        payButton.querySelector('.button-text').textContent = 'Pay Now';
        payButton.querySelector('.button-loader').classList.add('hidden');
        payButton.querySelector('.button-text').classList.remove('hidden');
        payButton.disabled = false;
    }
    

    

});
</script>

<?php 
// Allow Pro plugins to add additional variables
do_action('easy_invoice_payment_form_variables');
?>
```
