Initial commit: Complete Event Tickets Mail-In Payment Gateway
- Complete mail-in payment gateway for Event Tickets Commerce - Support for check payments with collapsible checkout interface - Admin interface for managing check payments and order status - Professional asset organization with proper WordPress enqueuing - Order management with status tracking (pending, received, bounced) - Template system with responsive design and accessibility features - Integration with Event Tickets Commerce order system - Settings page for configuring payment instructions and addresses
This commit is contained in:
commit
8fd8d9708c
18 changed files with 4124 additions and 0 deletions
221
README.md
Normal file
221
README.md
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
# Event Tickets - Mail-In Payment Gateway
|
||||||
|
|
||||||
|
A complementary WordPress plugin that adds a mail-in payment gateway for Event Tickets Commerce, allowing customers to pay by mailing checks.
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
This plugin extends the Event Tickets plugin by adding a "Mail-In Payment (Check)" gateway that allows customers to reserve tickets and pay by mailing a check. It provides comprehensive order management features for administrators to track and process check payments.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Check Payment Gateway**: Seamlessly integrates with Event Tickets Commerce
|
||||||
|
- **Order Management**: Admin interface to track pending check payments
|
||||||
|
- **Email Notifications**: Automated emails for payment instructions, confirmations, and cancellations
|
||||||
|
- **Customizable Settings**: Configure mailing address, payment instructions, and reservation periods
|
||||||
|
- **Order Tracking**: Track check received status, bounce handling, and order notes
|
||||||
|
- **Auto-Cancellation**: Optional automatic cancellation of expired orders
|
||||||
|
- **Template System**: Customizable checkout and email templates
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- WordPress 6.6 or higher
|
||||||
|
- PHP 7.4 or higher
|
||||||
|
- Event Tickets plugin (with Commerce module)
|
||||||
|
- The Events Calendar plugin (recommended)
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Download the plugin files
|
||||||
|
2. Upload the `event-tickets-mail-in-payment` folder to `/wp-content/plugins/`
|
||||||
|
3. Activate the plugin through the 'Plugins' menu in WordPress
|
||||||
|
4. Configure the gateway settings under **Tickets > Settings > Payments**
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Basic Setup
|
||||||
|
|
||||||
|
1. Navigate to **Tickets > Settings > Payments**
|
||||||
|
2. Find the "Mail-In Payment (Check) Settings" section
|
||||||
|
3. Configure the required settings:
|
||||||
|
- **Enable Mail-In Payments**: Check to activate the gateway
|
||||||
|
- **Make Check Payable To**: Organization or person name for checks
|
||||||
|
- **Mailing Address**: Complete address where checks should be sent
|
||||||
|
- **Payment Instructions**: Custom instructions for customers
|
||||||
|
|
||||||
|
### Advanced Settings
|
||||||
|
|
||||||
|
- **Payment Method Title**: Customize the gateway name shown to customers
|
||||||
|
- **Payment Method Description**: Brief description shown during checkout
|
||||||
|
- **Reservation Period**: Number of days to hold tickets while awaiting payment
|
||||||
|
- **Auto-Cancel Expired Orders**: Automatically cancel orders after reservation period
|
||||||
|
|
||||||
|
## Order Management
|
||||||
|
|
||||||
|
### Admin Interface
|
||||||
|
|
||||||
|
Access mail-in payment management through:
|
||||||
|
- **Tickets > Orders > Mail-In Payments** - Dedicated management page
|
||||||
|
- Individual order edit screens include mail-in payment details
|
||||||
|
|
||||||
|
### Order Processing
|
||||||
|
|
||||||
|
1. **Pending Orders**: Orders awaiting check payment appear in the management interface
|
||||||
|
2. **Mark as Received**: When a check arrives, mark it as received with optional notes
|
||||||
|
3. **Mark as Bounced**: Handle returned/bounced checks with reason tracking
|
||||||
|
4. **Automatic Emails**: System sends confirmation emails when status changes
|
||||||
|
|
||||||
|
### Order Statuses
|
||||||
|
|
||||||
|
- **Pending/Approved**: Order created, awaiting check payment
|
||||||
|
- **Completed**: Check received and processed
|
||||||
|
- **Denied**: Check bounced or order manually cancelled
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
### Customization
|
||||||
|
|
||||||
|
Templates can be overridden by copying them to your theme:
|
||||||
|
|
||||||
|
```
|
||||||
|
wp-content/themes/[your-theme]/event-tickets-mail-in/
|
||||||
|
├── checkout/
|
||||||
|
│ └── mail-in-form.php
|
||||||
|
├── emails/
|
||||||
|
│ ├── payment-instructions.php
|
||||||
|
│ ├── payment-confirmation.php
|
||||||
|
│ └── order-cancelled.php
|
||||||
|
└── admin/
|
||||||
|
├── mail-in-orders.php
|
||||||
|
└── order-meta-box.php
|
||||||
|
```
|
||||||
|
|
||||||
|
### Available Templates
|
||||||
|
|
||||||
|
- **Checkout Form**: `checkout/mail-in-form.php` - Payment method display during checkout
|
||||||
|
- **Email Templates**: Complete HTML email templates for all notifications
|
||||||
|
- **Admin Templates**: Management interface templates
|
||||||
|
|
||||||
|
## Hooks and Filters
|
||||||
|
|
||||||
|
### Actions
|
||||||
|
|
||||||
|
```php
|
||||||
|
// Triggered when a check is marked as received
|
||||||
|
do_action( 'et_mail_in_check_received', $order_id, $notes );
|
||||||
|
|
||||||
|
// Triggered when a check is marked as bounced
|
||||||
|
do_action( 'et_mail_in_check_bounced', $order_id, $reason );
|
||||||
|
|
||||||
|
// Daily cleanup of expired orders
|
||||||
|
do_action( 'et_mail_in_cleanup_expired_orders' );
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filters
|
||||||
|
|
||||||
|
```php
|
||||||
|
// Customize payment instructions
|
||||||
|
add_filter( 'et_mail_in_payment_instructions', function( $instructions, $order ) {
|
||||||
|
return $instructions;
|
||||||
|
}, 10, 2 );
|
||||||
|
|
||||||
|
// Modify email content
|
||||||
|
add_filter( 'et_mail_in_email_content', function( $content, $template, $order ) {
|
||||||
|
return $content;
|
||||||
|
}, 10, 3 );
|
||||||
|
|
||||||
|
// Customize reservation period per order
|
||||||
|
add_filter( 'et_mail_in_reservation_days', function( $days, $order ) {
|
||||||
|
return $days;
|
||||||
|
}, 10, 2 );
|
||||||
|
```
|
||||||
|
|
||||||
|
## Email System
|
||||||
|
|
||||||
|
### Automated Emails
|
||||||
|
|
||||||
|
1. **Payment Instructions**: Sent when order is created
|
||||||
|
2. **Payment Confirmation**: Sent when check is marked as received
|
||||||
|
3. **Order Cancellation**: Sent when order is cancelled or expires
|
||||||
|
|
||||||
|
### Email Customization
|
||||||
|
|
||||||
|
- HTML templates with responsive design
|
||||||
|
- Includes order details, payment instructions, and mailing address
|
||||||
|
- Uses WordPress mail system with customizable headers
|
||||||
|
|
||||||
|
## Security Features
|
||||||
|
|
||||||
|
- **Nonce Verification**: All admin actions are protected with WordPress nonces
|
||||||
|
- **Capability Checks**: Admin functions require appropriate user permissions
|
||||||
|
- **Data Sanitization**: All user inputs are properly sanitized
|
||||||
|
- **Order Validation**: Prevents unauthorized access to order data
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
event-tickets-mail-in-payment/
|
||||||
|
├── event-tickets-mail-in-payment.php # Main plugin file
|
||||||
|
├── src/ # Core classes
|
||||||
|
│ ├── Gateway.php # Payment gateway implementation
|
||||||
|
│ ├── Order.php # Order management
|
||||||
|
│ ├── Settings.php # Configuration handling
|
||||||
|
│ ├── Provider.php # Service provider
|
||||||
|
│ └── Hooks.php # WordPress hooks
|
||||||
|
├── templates/ # Template files
|
||||||
|
│ ├── checkout/ # Frontend templates
|
||||||
|
│ ├── emails/ # Email templates
|
||||||
|
│ └── admin/ # Admin interface templates
|
||||||
|
└── README.md # Documentation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Extending the Plugin
|
||||||
|
|
||||||
|
The plugin is built with extensibility in mind:
|
||||||
|
|
||||||
|
- PSR-4 autoloading with namespace `ET_Mail_In_Payment`
|
||||||
|
- Service provider pattern for modular functionality
|
||||||
|
- Hook system for customization
|
||||||
|
- Template override system
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Gateway Not Appearing**: Ensure Event Tickets plugin is active and Commerce module is enabled
|
||||||
|
2. **Settings Not Saving**: Check file permissions and WordPress error logs
|
||||||
|
3. **Emails Not Sending**: Verify WordPress mail configuration
|
||||||
|
4. **Template Issues**: Clear any caching plugins after template changes
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
|
||||||
|
Enable WordPress debug mode to see detailed error messages:
|
||||||
|
|
||||||
|
```php
|
||||||
|
define( 'WP_DEBUG', true );
|
||||||
|
define( 'WP_DEBUG_LOG', true );
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
For support and questions:
|
||||||
|
|
||||||
|
1. Check the plugin settings and this documentation
|
||||||
|
2. Review WordPress error logs for any issues
|
||||||
|
3. Ensure all requirements are met
|
||||||
|
4. Contact the plugin developer for technical support
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This plugin is licensed under the GPL v2 or later.
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
### 1.0.0
|
||||||
|
- Initial release
|
||||||
|
- Mail-in payment gateway implementation
|
||||||
|
- Order management interface
|
||||||
|
- Email notification system
|
||||||
|
- Template system
|
||||||
|
- Settings configuration
|
||||||
122
assets/css/admin.css
Normal file
122
assets/css/admin.css
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Gateway Admin Styles
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
.et-mail-in-admin-page {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-orders-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-orders-table th,
|
||||||
|
.et-mail-in-orders-table td {
|
||||||
|
padding: 12px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-orders-table th {
|
||||||
|
background-color: #f1f1f1;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--pending {
|
||||||
|
background-color: #fff3cd;
|
||||||
|
color: #856404;
|
||||||
|
border: 1px solid #ffeaa7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--received {
|
||||||
|
background-color: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--bounced {
|
||||||
|
background-color: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-button {
|
||||||
|
padding: 6px 12px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
text-decoration: none;
|
||||||
|
display: inline-block;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-button--primary {
|
||||||
|
background-color: #0073aa;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-button--primary:hover {
|
||||||
|
background-color: #005a87;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-button--danger {
|
||||||
|
background-color: #dc3545;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-button--danger:hover {
|
||||||
|
background-color: #c82333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-meta-box {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid #ccd0d4;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-meta-row {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-meta-label {
|
||||||
|
font-weight: bold;
|
||||||
|
min-width: 150px;
|
||||||
|
color: #23282d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-meta-value {
|
||||||
|
flex: 1;
|
||||||
|
color: #32373c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-address-block {
|
||||||
|
background: #f9f9f9;
|
||||||
|
padding: 10px;
|
||||||
|
border-left: 3px solid #0073aa;
|
||||||
|
font-family: monospace;
|
||||||
|
white-space: pre-line;
|
||||||
|
border-radius: 0 3px 3px 0;
|
||||||
|
}
|
||||||
192
assets/css/checkout.css
Normal file
192
assets/css/checkout.css
Normal file
|
|
@ -0,0 +1,192 @@
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Gateway Checkout Styles
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in {
|
||||||
|
margin: 30px 0 15px 0 !important; /* More space above */
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #ddd !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle Button Styling */
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__toggle {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-bottom: 1px solid #dee2e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__toggle-button {
|
||||||
|
width: 100%;
|
||||||
|
padding: 18px 20px; /* Slightly more padding for larger appearance */
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
text-align: center; /* Center the text */
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 18px; /* Larger font size */
|
||||||
|
font-weight: 500; /* Slightly bolder */
|
||||||
|
color: #0073aa;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center; /* Center the content */
|
||||||
|
gap: 12px; /* Slightly more gap */
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__toggle-button:hover {
|
||||||
|
background: #e9ecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__toggle-button:focus {
|
||||||
|
outline: 2px solid #0073aa;
|
||||||
|
outline-offset: -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toggle-icon {
|
||||||
|
font-size: 12px;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
width: 12px;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content Styling */
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__content {
|
||||||
|
padding: 20px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__header h4 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__description {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
font-style: italic;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__instructions {
|
||||||
|
background: #fff;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__instructions strong {
|
||||||
|
color: #333;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__details {
|
||||||
|
margin: 15px 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__details {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__payable-to-name {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 5px 0;
|
||||||
|
color: #0073aa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__address-block {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 3px solid #0073aa;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note {
|
||||||
|
background: #fff3cd;
|
||||||
|
border: 1px solid #ffeaa7;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note strong {
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note ul {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note li {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form styling */
|
||||||
|
.tribe-tickets__commerce-checkout-purchaser-info {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #dee2e6;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-purchaser-info h4 {
|
||||||
|
margin: 0 0 15px 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-field {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-field label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-field .required {
|
||||||
|
color: #dc3545;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-field input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #ced4da;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-field input:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #0073aa;
|
||||||
|
box-shadow: 0 0 0 2px rgba(0, 115, 170, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-submit {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-submit-button {
|
||||||
|
background: #0073aa;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets__commerce-checkout-form-submit-button:hover {
|
||||||
|
background: #005a87;
|
||||||
|
}
|
||||||
63
assets/js/admin.js
Normal file
63
assets/js/admin.js
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Gateway Admin JavaScript
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Confirmation dialogs for admin actions
|
||||||
|
$('.et-mail-in-mark-received').on('click', function(e) {
|
||||||
|
const confirmMessage = etMailInAdmin.strings.confirm_received || 'Are you sure you want to mark this check as received?';
|
||||||
|
if (!confirm(confirmMessage)) {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.et-mail-in-mark-bounced').on('click', function(e) {
|
||||||
|
const confirmMessage = etMailInAdmin.strings.confirm_bounced || 'Are you sure you want to mark this check as bounced?';
|
||||||
|
if (!confirm(confirmMessage)) {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Auto-hide admin notices after 5 seconds
|
||||||
|
setTimeout(function() {
|
||||||
|
$('.notice.is-dismissible').fadeOut();
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
// Enhanced form validation
|
||||||
|
$('form[data-et-mail-in-form]').on('submit', function(e) {
|
||||||
|
const form = $(this);
|
||||||
|
const requiredFields = form.find('[required]');
|
||||||
|
let hasErrors = false;
|
||||||
|
|
||||||
|
requiredFields.each(function() {
|
||||||
|
const field = $(this);
|
||||||
|
const value = field.val().trim();
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
field.addClass('error');
|
||||||
|
hasErrors = true;
|
||||||
|
} else {
|
||||||
|
field.removeClass('error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasErrors) {
|
||||||
|
e.preventDefault();
|
||||||
|
alert('Please fill in all required fields.');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove error styling on input
|
||||||
|
$('input, textarea, select').on('input change', function() {
|
||||||
|
$(this).removeClass('error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
})(jQuery);
|
||||||
46
assets/js/checkout.js
Normal file
46
assets/js/checkout.js
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Gateway Checkout JavaScript
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const toggleButton = document.getElementById('mail-in-toggle-button');
|
||||||
|
const content = document.getElementById('mail-in-content');
|
||||||
|
const toggleIcon = toggleButton ? toggleButton.querySelector('.toggle-icon') : null;
|
||||||
|
|
||||||
|
// Only initialize if elements exist
|
||||||
|
if (!toggleButton || !content || !toggleIcon) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize accessibility attributes
|
||||||
|
toggleButton.setAttribute('aria-expanded', 'false');
|
||||||
|
toggleButton.setAttribute('aria-controls', 'mail-in-content');
|
||||||
|
content.setAttribute('aria-hidden', 'true');
|
||||||
|
|
||||||
|
toggleButton.addEventListener('click', function() {
|
||||||
|
const isExpanded = content.style.display !== 'none';
|
||||||
|
|
||||||
|
if (isExpanded) {
|
||||||
|
// Hide content
|
||||||
|
content.style.display = 'none';
|
||||||
|
toggleIcon.textContent = '▶';
|
||||||
|
toggleButton.setAttribute('aria-expanded', 'false');
|
||||||
|
content.setAttribute('aria-hidden', 'true');
|
||||||
|
} else {
|
||||||
|
// Show content
|
||||||
|
content.style.display = 'block';
|
||||||
|
toggleIcon.textContent = '▼';
|
||||||
|
toggleButton.setAttribute('aria-expanded', 'true');
|
||||||
|
content.setAttribute('aria-hidden', 'false');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle keyboard navigation
|
||||||
|
toggleButton.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Enter' || e.key === ' ') {
|
||||||
|
e.preventDefault();
|
||||||
|
toggleButton.click();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
185
event-tickets-mail-in-payment.php
Normal file
185
event-tickets-mail-in-payment.php
Normal file
|
|
@ -0,0 +1,185 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Plugin Name: Event Tickets - Mail-In Payment Gateway
|
||||||
|
* Plugin URI: https://github.com/yourusername/event-tickets-mail-in-payment
|
||||||
|
* Description: Adds a mail-in payment gateway for Event Tickets Commerce to accept check payments.
|
||||||
|
* Version: 1.0.0
|
||||||
|
* Requires at least: 6.6
|
||||||
|
* Requires PHP: 7.4
|
||||||
|
* Author: Your Name
|
||||||
|
* License: GPLv2 or later
|
||||||
|
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||||
|
* Text Domain: event-tickets-mail-in
|
||||||
|
* Domain Path: /languages/
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Prevent direct access
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define plugin constants
|
||||||
|
define( 'ET_MAIL_IN_VERSION', '1.0.0' );
|
||||||
|
define( 'ET_MAIL_IN_FILE', __FILE__ );
|
||||||
|
define( 'ET_MAIL_IN_PATH', plugin_dir_path( __FILE__ ) );
|
||||||
|
define( 'ET_MAIL_IN_URL', plugin_dir_url( __FILE__ ) );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main plugin class
|
||||||
|
*/
|
||||||
|
class ET_Mail_In_Payment {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Single instance of the class
|
||||||
|
*
|
||||||
|
* @var ET_Mail_In_Payment
|
||||||
|
*/
|
||||||
|
private static $instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get single instance
|
||||||
|
*
|
||||||
|
* @return ET_Mail_In_Payment
|
||||||
|
*/
|
||||||
|
public static function instance() {
|
||||||
|
if ( ! isset( self::$instance ) ) {
|
||||||
|
self::$instance = new self();
|
||||||
|
}
|
||||||
|
return self::$instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*/
|
||||||
|
private function __construct() {
|
||||||
|
add_action( 'plugins_loaded', [ $this, 'init' ] );
|
||||||
|
register_activation_hook( __FILE__, [ $this, 'activate' ] );
|
||||||
|
register_deactivation_hook( __FILE__, [ $this, 'deactivate' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the plugin
|
||||||
|
*/
|
||||||
|
public function init() {
|
||||||
|
// Check if Event Tickets is active
|
||||||
|
if ( ! $this->is_event_tickets_active() ) {
|
||||||
|
add_action( 'admin_notices', [ $this, 'event_tickets_missing_notice' ] );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load text domain
|
||||||
|
load_plugin_textdomain( 'event-tickets-mail-in', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
|
||||||
|
|
||||||
|
// Include required files
|
||||||
|
$this->includes();
|
||||||
|
|
||||||
|
// Initialize components
|
||||||
|
$this->init_components();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if Event Tickets is active
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
private function is_event_tickets_active() {
|
||||||
|
return class_exists( 'Tribe__Tickets__Main' ) &&
|
||||||
|
class_exists( 'TEC\Tickets\Commerce\Module' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Include required files
|
||||||
|
*/
|
||||||
|
private function includes() {
|
||||||
|
require_once ET_MAIL_IN_PATH . 'src/Gateway.php';
|
||||||
|
require_once ET_MAIL_IN_PATH . 'src/Order.php';
|
||||||
|
require_once ET_MAIL_IN_PATH . 'src/Settings.php';
|
||||||
|
require_once ET_MAIL_IN_PATH . 'src/Provider.php';
|
||||||
|
require_once ET_MAIL_IN_PATH . 'src/Hooks.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize components
|
||||||
|
*/
|
||||||
|
private function init_components() {
|
||||||
|
// Register our provider with dependency injection container
|
||||||
|
tribe_register_provider( ET_Mail_In_Payment\Provider::class );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin activation
|
||||||
|
*/
|
||||||
|
public function activate() {
|
||||||
|
// Check dependencies
|
||||||
|
if ( ! $this->is_event_tickets_active() ) {
|
||||||
|
deactivate_plugins( plugin_basename( __FILE__ ) );
|
||||||
|
wp_die(
|
||||||
|
__( 'Event Tickets - Mail-In Payment Gateway requires Event Tickets to be installed and activated.', 'event-tickets-mail-in' ),
|
||||||
|
__( 'Plugin Activation Error', 'event-tickets-mail-in' ),
|
||||||
|
[ 'back_link' => true ]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default options if they don't exist
|
||||||
|
$this->set_default_options();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin deactivation
|
||||||
|
*/
|
||||||
|
public function deactivate() {
|
||||||
|
// Clean up if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get default payment instructions
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function get_default_instructions() {
|
||||||
|
return __( 'Please mail your check to the address provided below. Your tickets will be reserved for 7 days while we wait for your payment to arrive. Include your order number on the check memo line.', 'event-tickets-mail-in' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default options on activation
|
||||||
|
*/
|
||||||
|
private function set_default_options() {
|
||||||
|
// Set default options if they don't exist
|
||||||
|
if ( false === tribe_get_option( 'tickets-commerce-mail-in-enabled' ) ) {
|
||||||
|
tribe_update_option( 'tickets-commerce-mail-in-enabled', true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( tribe_get_option( 'tickets-commerce-mail-in-title' ) ) ) {
|
||||||
|
tribe_update_option( 'tickets-commerce-mail-in-title', __( 'Mail-In Payment (Check)', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( tribe_get_option( 'tickets-commerce-mail-in-description' ) ) ) {
|
||||||
|
tribe_update_option( 'tickets-commerce-mail-in-description', __( 'Pay by mailing a check to our address.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( tribe_get_option( 'tickets-commerce-mail-in-instructions' ) ) ) {
|
||||||
|
tribe_update_option( 'tickets-commerce-mail-in-instructions', $this->get_default_instructions() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing purposes, set some default values
|
||||||
|
if ( empty( tribe_get_option( 'tickets-commerce-mail-in-address' ) ) ) {
|
||||||
|
tribe_update_option( 'tickets-commerce-mail-in-address', "123 Main Street\nAnytown, ST 12345\nUSA" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( tribe_get_option( 'tickets-commerce-mail-in-payable-to' ) ) ) {
|
||||||
|
tribe_update_option( 'tickets-commerce-mail-in-payable-to', "Your Organization Name" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display admin notice when Event Tickets is missing
|
||||||
|
*/
|
||||||
|
public function event_tickets_missing_notice() {
|
||||||
|
echo '<div class="notice notice-error"><p>';
|
||||||
|
echo esc_html__( 'Event Tickets - Mail-In Payment Gateway requires Event Tickets to be installed and activated.', 'event-tickets-mail-in' );
|
||||||
|
echo '</p></div>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the plugin
|
||||||
|
ET_Mail_In_Payment::instance();
|
||||||
546
src/Gateway.php
Normal file
546
src/Gateway.php
Normal file
|
|
@ -0,0 +1,546 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ET_Mail_In_Payment;
|
||||||
|
|
||||||
|
use TEC\Tickets\Commerce\Gateways\Contracts\Abstract_Gateway;
|
||||||
|
use TEC\Tickets\Commerce\Status;
|
||||||
|
use TEC\Tickets\Commerce\Utils\Value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Gateway class
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Gateway extends Abstract_Gateway {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway key identifier
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static string $key = 'mail-in';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway settings class
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static string $settings = Settings::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* No merchant class needed for mail-in payments
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static string $merchant = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported currencies (all currencies since it's manual)
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected static array $supported_currencies = [
|
||||||
|
'USD', 'EUR', 'GBP', 'CAD', 'AUD', 'JPY', 'CHF', 'CNY', 'SEK', 'NZD',
|
||||||
|
'MXN', 'SGD', 'HKD', 'NOK', 'PHP', 'DKK', 'PLN', 'CZK', 'HUF', 'ILS',
|
||||||
|
'CLP', 'TRY', 'RON', 'HRK', 'BGN', 'BRL', 'ARS', 'INR', 'KRW', 'THB',
|
||||||
|
'MYR', 'ZAR', 'RUB', 'UAH', 'EGP', 'MAD', 'TND', 'DZD', 'NGN', 'KES'
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the gateway key
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function get_key(): string {
|
||||||
|
return static::$key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the gateway label
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function get_label() {
|
||||||
|
return tribe_get_option( 'tickets-commerce-mail-in-title', __( 'Mail-In Payment (Check)', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the gateway is connected/configured
|
||||||
|
* Override Abstract_Gateway's merchant-dependent implementation
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_connected(): bool {
|
||||||
|
if ( ! static::should_show() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gateway is connected if mailing address is configured
|
||||||
|
$address = tribe_get_option( 'tickets-commerce-mail-in-address', '' );
|
||||||
|
$payable_to = tribe_get_option( 'tickets-commerce-mail-in-payable-to', '' );
|
||||||
|
|
||||||
|
return ! empty( $address ) && ! empty( $payable_to );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the gateway is active
|
||||||
|
* Override Abstract_Gateway's merchant-dependent implementation
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_active(): bool {
|
||||||
|
if ( ! static::should_show() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static::is_enabled() && static::is_connected();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the gateway should be shown
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function should_show() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the gateway is enabled
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function is_enabled(): bool {
|
||||||
|
$should_show = static::should_show();
|
||||||
|
$enabled_option = tribe_get_option( 'tickets-commerce-mail-in-enabled', false );
|
||||||
|
if ( ! $should_show ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tribe_is_truthy( $enabled_option );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this gateway renders solo (prevents other gateways from showing)
|
||||||
|
* Mail-in payments should coexist with other gateways
|
||||||
|
* Override Abstract_Gateway's default true
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function renders_solo(): bool {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get gateway description
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function get_description() {
|
||||||
|
return tribe_get_option(
|
||||||
|
'tickets-commerce-mail-in-description',
|
||||||
|
__( 'Pay by mailing a check to our address.', 'event-tickets-mail-in' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the checkout form
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $args Template arguments
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function checkout_form( $args = [] ) {
|
||||||
|
error_log( 'Mail-In Gateway: checkout_form called' );
|
||||||
|
|
||||||
|
$instructions = tribe_get_option( 'tickets-commerce-mail-in-instructions', '' );
|
||||||
|
$mailing_address = tribe_get_option( 'tickets-commerce-mail-in-address', '' );
|
||||||
|
$payable_to = tribe_get_option( 'tickets-commerce-mail-in-payable-to', '' );
|
||||||
|
|
||||||
|
// Direct output for debugging
|
||||||
|
echo '<div style="background: blue; border: 5px solid orange; padding: 20px; margin: 20px; color: white; font-size: 16px;">';
|
||||||
|
echo '<h3>🔵 MAIL-IN CHECKOUT FORM 🔵</h3>';
|
||||||
|
echo '<p><strong>Label:</strong> ' . esc_html( static::get_label() ) . '</p>';
|
||||||
|
echo '<p><strong>Description:</strong> ' . esc_html( static::get_description() ) . '</p>';
|
||||||
|
echo '<p><strong>Payable To:</strong> ' . esc_html( $payable_to ) . '</p>';
|
||||||
|
echo '<p><strong>Address:</strong> ' . esc_html( $mailing_address ) . '</p>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process the payment
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $order_data Order data
|
||||||
|
* @return array Processing result
|
||||||
|
*/
|
||||||
|
public function process_payment( $order_data ) {
|
||||||
|
// For mail-in payments, we create the order in "pending" status
|
||||||
|
// and provide payment instructions
|
||||||
|
try {
|
||||||
|
// Get cart instance
|
||||||
|
$cart = tribe( \TEC\Tickets\Commerce\Cart::class );
|
||||||
|
|
||||||
|
if ( ! $cart->has_items() ) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'message' => __( 'Your cart is empty.', 'event-tickets-mail-in' ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract purchaser data from order_data
|
||||||
|
$purchaser = null;
|
||||||
|
if ( isset( $order_data['purchaser_name'] ) || isset( $order_data['purchaser_email'] ) ) {
|
||||||
|
$purchaser = [
|
||||||
|
'purchaser_full_name' => $order_data['purchaser_name'] ?? '',
|
||||||
|
'purchaser_first_name' => $order_data['purchaser_first_name'] ?? '',
|
||||||
|
'purchaser_last_name' => $order_data['purchaser_last_name'] ?? '',
|
||||||
|
'purchaser_email' => $order_data['purchaser_email'] ?? '',
|
||||||
|
'purchaser_user_id' => $order_data['purchaser_user_id'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create order from current cart using the main Order class (like other gateways)
|
||||||
|
$order = tribe( \TEC\Tickets\Commerce\Order::class )->create_from_cart( $this, $purchaser );
|
||||||
|
|
||||||
|
if ( ! $order ) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'message' => __( 'Failed to create order. Please try again.', 'event-tickets-mail-in' ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set gateway order ID so success page can find the order
|
||||||
|
update_post_meta( $order->ID, '_tec_tc_order_gateway_order_id', $order->ID );
|
||||||
|
|
||||||
|
// Add mail-in specific metadata
|
||||||
|
$this->add_mail_in_meta( $order );
|
||||||
|
|
||||||
|
// Set order to pending status (waiting for check to arrive)
|
||||||
|
tribe( \TEC\Tickets\Commerce\Order::class )->modify_status( $order->ID, Status\Pending::SLUG );
|
||||||
|
|
||||||
|
// Clear the cart
|
||||||
|
$cart->clear_cart();
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => true,
|
||||||
|
'order_id' => $order->ID,
|
||||||
|
'redirect_url' => $this->get_success_url( $order ),
|
||||||
|
'message' => __( 'Order created successfully. Please mail your check as instructed.', 'event-tickets-mail-in' ),
|
||||||
|
];
|
||||||
|
|
||||||
|
} catch ( \Exception $e ) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'message' => sprintf(
|
||||||
|
__( 'Payment processing failed: %s', 'event-tickets-mail-in' ),
|
||||||
|
$e->getMessage()
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create order for mail-in payment
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $order_data Order data (contains purchaser info)
|
||||||
|
* @return \WP_Post|false
|
||||||
|
*/
|
||||||
|
protected function create_order( $order_data ) {
|
||||||
|
// Extract purchaser data from order_data
|
||||||
|
$purchaser = null;
|
||||||
|
if ( isset( $order_data['purchaser_name'] ) || isset( $order_data['purchaser_email'] ) ) {
|
||||||
|
$purchaser = [
|
||||||
|
'purchaser_full_name' => $order_data['purchaser_name'] ?? '',
|
||||||
|
'purchaser_first_name' => $order_data['purchaser_first_name'] ?? '',
|
||||||
|
'purchaser_last_name' => $order_data['purchaser_last_name'] ?? '',
|
||||||
|
'purchaser_email' => $order_data['purchaser_email'] ?? '',
|
||||||
|
'purchaser_user_id' => $order_data['purchaser_user_id'] ?? null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use the main Order class like other gateways
|
||||||
|
$order = tribe( \TEC\Tickets\Commerce\Order::class )->create_from_cart( $this, $purchaser );
|
||||||
|
|
||||||
|
if ( $order ) {
|
||||||
|
$this->add_mail_in_meta( $order );
|
||||||
|
}
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add mail-in payment specific metadata
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \WP_Post $order
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function add_mail_in_meta( $order ) {
|
||||||
|
$order_id = $order->ID;
|
||||||
|
|
||||||
|
// Store gateway identifier
|
||||||
|
update_post_meta( $order_id, '_tec_tc_gateway', 'mail-in' );
|
||||||
|
|
||||||
|
// Store payment method
|
||||||
|
update_post_meta( $order_id, '_tec_tc_payment_method', 'mail-in-check' );
|
||||||
|
|
||||||
|
// Store mailing instructions
|
||||||
|
$instructions = tribe_get_option( 'tickets-commerce-mail-in-instructions', '' );
|
||||||
|
if ( $instructions ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_instructions', $instructions );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store mailing address
|
||||||
|
$address = tribe_get_option( 'tickets-commerce-mail-in-address', '' );
|
||||||
|
if ( $address ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_mailing_address', $address );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store payable to
|
||||||
|
$payable_to = tribe_get_option( 'tickets-commerce-mail-in-payable-to', '' );
|
||||||
|
if ( $payable_to ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_payable_to', $payable_to );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set check received flag to false initially
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_received', false );
|
||||||
|
|
||||||
|
// Store creation date for tracking purposes
|
||||||
|
update_post_meta( $order_id, '_mail_in_created_date', current_time( 'mysql' ) );
|
||||||
|
|
||||||
|
// Add order note with payment instructions
|
||||||
|
$mailing_address = tribe_get_option( 'tickets-commerce-mail-in-address', '' );
|
||||||
|
$payable_to_name = tribe_get_option( 'tickets-commerce-mail-in-payable-to', '' );
|
||||||
|
|
||||||
|
$note = __( 'Order created for mail-in payment. Customer should mail check to:', 'event-tickets-mail-in' ) . "\n";
|
||||||
|
$note .= $mailing_address . "\n";
|
||||||
|
$note .= __( 'Make payable to:', 'event-tickets-mail-in' ) . ' ' . $payable_to_name;
|
||||||
|
|
||||||
|
$this->add_order_note( $order_id, $note );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add order note
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param int $order_id Order ID
|
||||||
|
* @param string $note Note content
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function add_order_note( $order_id, $note ) {
|
||||||
|
$existing_notes = get_post_meta( $order_id, '_tec_tc_order_notes', true );
|
||||||
|
if ( ! is_array( $existing_notes ) ) {
|
||||||
|
$existing_notes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing_notes[] = [
|
||||||
|
'date' => current_time( 'mysql' ),
|
||||||
|
'note' => $note,
|
||||||
|
'type' => 'system',
|
||||||
|
];
|
||||||
|
|
||||||
|
update_post_meta( $order_id, '_tec_tc_order_notes', $existing_notes );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate unique order ID for mail-in payments
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function generate_order_id() {
|
||||||
|
return 'mail-in-' . uniqid() . '-' . time();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get success page URL
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \WP_Post $order
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_success_url( $order ) {
|
||||||
|
return add_query_arg( [ 'tc-order-id' => $order->ID ], tribe( \TEC\Tickets\Commerce\Success::class )->get_url() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle refunds (not applicable for mail-in payments)
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order
|
||||||
|
* @param Value $amount
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function process_refund( $order, Value $amount ) {
|
||||||
|
return [
|
||||||
|
'success' => false,
|
||||||
|
'message' => __( 'Refunds for mail-in payments must be processed manually.', 'event-tickets-mail-in' ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get checkout template object
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return \Tribe__Template
|
||||||
|
*/
|
||||||
|
protected function get_template() {
|
||||||
|
return new \Tribe__Template();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate checkout data
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $data Checkout data
|
||||||
|
* @return bool|\WP_Error
|
||||||
|
*/
|
||||||
|
public function validate_checkout_data( $data ) {
|
||||||
|
// Basic validation - ensure required fields are present
|
||||||
|
if ( empty( $data['purchaser_email'] ) ) {
|
||||||
|
return new \WP_Error( 'missing_email', __( 'Email address is required.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( $data['purchaser_name'] ) ) {
|
||||||
|
return new \WP_Error( 'missing_name', __( 'Name is required.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get gateway-specific order notes
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_order_notes( $order ) {
|
||||||
|
$notes = [];
|
||||||
|
|
||||||
|
$notes[] = sprintf(
|
||||||
|
__( 'Mail-in payment order created. Order ID: %s', 'event-tickets-mail-in' ),
|
||||||
|
$order->get_gateway_order_id()
|
||||||
|
);
|
||||||
|
|
||||||
|
$mailing_address = get_option( 'et_mail_in_mailing_address', '' );
|
||||||
|
$payable_to = get_option( 'et_mail_in_check_payable_to', '' );
|
||||||
|
|
||||||
|
if ( $mailing_address ) {
|
||||||
|
$notes[] = sprintf(
|
||||||
|
__( 'Check should be mailed to: %s', 'event-tickets-mail-in' ),
|
||||||
|
$mailing_address
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $payable_to ) {
|
||||||
|
$notes[] = sprintf(
|
||||||
|
__( 'Check should be made payable to: %s', 'event-tickets-mail-in' ),
|
||||||
|
$payable_to
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $notes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get admin notices for the gateway
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_admin_notices() {
|
||||||
|
$notices = [];
|
||||||
|
|
||||||
|
// Check if gateway is properly configured
|
||||||
|
if ( ! self::is_connected() ) {
|
||||||
|
$notices[] = [
|
||||||
|
'type' => 'warning',
|
||||||
|
'message' => sprintf(
|
||||||
|
__( 'Mail-In Payment gateway is not properly configured. Please <a href="%s">configure the required settings</a>.', 'event-tickets-mail-in' ),
|
||||||
|
self::get_settings_url()
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $notices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get order details link by order
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \WP_Post $order Order post object
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_order_details_link_by_order( $order ): string {
|
||||||
|
// For mail-in payments, return the order ID as a simple string
|
||||||
|
return (string) $order->ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render checkout template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \Tribe__Template $template Template instance
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function render_checkout_template( \Tribe__Template $template ): string {
|
||||||
|
$instructions = tribe_get_option( 'tickets-commerce-mail-in-instructions', '' );
|
||||||
|
$mailing_address = tribe_get_option( 'tickets-commerce-mail-in-address', '' );
|
||||||
|
$payable_to = tribe_get_option( 'tickets-commerce-mail-in-payable-to', '' );
|
||||||
|
|
||||||
|
$context = [
|
||||||
|
'gateway' => $this,
|
||||||
|
'instructions' => $instructions,
|
||||||
|
'mailing_address' => $mailing_address,
|
||||||
|
'payable_to' => $payable_to,
|
||||||
|
];
|
||||||
|
|
||||||
|
// Use our template file
|
||||||
|
ob_start();
|
||||||
|
$template_file = ET_MAIL_IN_PATH . 'templates/v2/commerce/gateway/mail-in/container.php';
|
||||||
|
|
||||||
|
if ( file_exists( $template_file ) ) {
|
||||||
|
// Extract context variables for the template
|
||||||
|
extract( $context );
|
||||||
|
include $template_file;
|
||||||
|
} else {
|
||||||
|
// Fallback display if template file is missing
|
||||||
|
echo '<div class="tribe-tickets-commerce-gateway-mail-in">';
|
||||||
|
echo '<h4>' . esc_html( static::get_label() ) . '</h4>';
|
||||||
|
echo '<p>' . esc_html( static::get_description() ) . '</p>';
|
||||||
|
if ( $mailing_address ) {
|
||||||
|
echo '<p><strong>' . esc_html__( 'Mail your check to:', 'event-tickets-mail-in' ) . '</strong><br>';
|
||||||
|
echo esc_html( $mailing_address ) . '</p>';
|
||||||
|
}
|
||||||
|
if ( $payable_to ) {
|
||||||
|
echo '<p><strong>' . esc_html__( 'Make check payable to:', 'event-tickets-mail-in' ) . '</strong><br>';
|
||||||
|
echo esc_html( $payable_to ) . '</p>';
|
||||||
|
}
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = ob_get_clean();
|
||||||
|
|
||||||
|
// Output directly to handle any buffering issues with the shortcode
|
||||||
|
echo $output;
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
405
src/Hooks.php
Normal file
405
src/Hooks.php
Normal file
|
|
@ -0,0 +1,405 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ET_Mail_In_Payment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Hooks class
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Hooks {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register hooks
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register() {
|
||||||
|
// Template hooks
|
||||||
|
add_filter( 'tec_tickets_commerce_checkout_template_paths', [ $this, 'add_template_paths' ] );
|
||||||
|
|
||||||
|
// Email hooks
|
||||||
|
add_action( 'tec_tickets_commerce_order_created', [ $this, 'send_payment_instructions' ], 10, 2 );
|
||||||
|
|
||||||
|
// Order status hooks
|
||||||
|
add_action( 'tec_tickets_commerce_order_status_changed', [ $this, 'handle_status_change' ], 10, 3 );
|
||||||
|
|
||||||
|
// Cleanup hooks for expired orders
|
||||||
|
add_action( 'init', [ $this, 'schedule_cleanup' ] );
|
||||||
|
add_action( 'et_mail_in_cleanup_expired_orders', [ $this, 'cleanup_expired_orders' ] );
|
||||||
|
|
||||||
|
// Admin hooks
|
||||||
|
add_filter( 'tec_tickets_commerce_order_actions', [ $this, 'add_order_actions' ], 10, 2 );
|
||||||
|
|
||||||
|
// Gateway display hooks
|
||||||
|
add_filter( 'tec_tickets_commerce_gateway_checkout_template', [ $this, 'get_checkout_template' ], 10, 2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add template paths for mail-in payment templates
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $paths Template paths
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function add_template_paths( $paths ) {
|
||||||
|
$paths[] = ET_MAIL_IN_PATH . 'templates/';
|
||||||
|
return $paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send payment instructions email when order is created
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @param array $cart_data Cart data
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function send_payment_instructions( $order, $cart_data ) {
|
||||||
|
// Only for mail-in payment orders
|
||||||
|
if ( $order->get_gateway() !== 'mail-in' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->send_instructions_email( $order );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle order status changes
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @param string $old_status Previous status
|
||||||
|
* @param string $new_status New status
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle_status_change( $order, $old_status, $new_status ) {
|
||||||
|
// Only for mail-in payment orders
|
||||||
|
if ( $order->get_gateway() !== 'mail-in' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send confirmation email when payment is completed
|
||||||
|
if ( $new_status === 'completed' ) {
|
||||||
|
$this->send_confirmation_email( $order );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send cancellation email if order is cancelled
|
||||||
|
if ( in_array( $new_status, [ 'denied', 'cancelled', 'refunded' ] ) ) {
|
||||||
|
$this->send_cancellation_email( $order );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule cleanup of expired orders
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function schedule_cleanup() {
|
||||||
|
if ( ! wp_next_scheduled( 'et_mail_in_cleanup_expired_orders' ) ) {
|
||||||
|
wp_schedule_event( time(), 'daily', 'et_mail_in_cleanup_expired_orders' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleanup expired mail-in orders
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function cleanup_expired_orders() {
|
||||||
|
// Only run if auto-cancel is enabled
|
||||||
|
if ( ! tribe_get_option( 'tickets-commerce-mail-in-auto-cancel', false ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$reservation_days = absint( tribe_get_option( 'tickets-commerce-mail-in-reservation-days', 7 ) );
|
||||||
|
$cutoff_date = date( 'Y-m-d H:i:s', strtotime( "-{$reservation_days} days" ) );
|
||||||
|
|
||||||
|
$args = [
|
||||||
|
'post_type' => 'tec_tc_order',
|
||||||
|
'meta_query' => [
|
||||||
|
[
|
||||||
|
'key' => '_tec_tc_gateway',
|
||||||
|
'value' => 'mail-in',
|
||||||
|
'compare' => '='
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'key' => '_mail_in_check_received',
|
||||||
|
'value' => false,
|
||||||
|
'compare' => '='
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'key' => '_mail_in_created_date',
|
||||||
|
'value' => $cutoff_date,
|
||||||
|
'compare' => '<',
|
||||||
|
'type' => 'DATETIME'
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'post_status' => [ 'tec-tc-pending', 'tec-tc-approved' ],
|
||||||
|
'posts_per_page' => 50, // Process in batches
|
||||||
|
];
|
||||||
|
|
||||||
|
$expired_orders = new \WP_Query( $args );
|
||||||
|
$order_controller = new Order();
|
||||||
|
|
||||||
|
foreach ( $expired_orders->posts as $order_post ) {
|
||||||
|
$order = tribe( 'tickets.commerce.order' )->get_by_id( $order_post->ID );
|
||||||
|
|
||||||
|
if ( $order ) {
|
||||||
|
// Cancel the order
|
||||||
|
$order->update_status( 'denied' );
|
||||||
|
|
||||||
|
// Add order note
|
||||||
|
$order_controller->add_order_note(
|
||||||
|
$order_post->ID,
|
||||||
|
__( 'Order automatically cancelled due to expired payment deadline.', 'event-tickets-mail-in' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add custom actions to order admin page
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $actions Existing actions
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function add_order_actions( $actions, $order ) {
|
||||||
|
// Only for mail-in payment orders
|
||||||
|
if ( $order->get_gateway() !== 'mail-in' ) {
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_controller = new Order();
|
||||||
|
$details = $order_controller->get_mail_in_details( $order->get_id() );
|
||||||
|
|
||||||
|
// Add "Mark Check Received" action if check hasn't been received
|
||||||
|
if ( ! $details['check_received'] && ! $details['check_bounced'] ) {
|
||||||
|
$actions['mark_check_received'] = [
|
||||||
|
'label' => __( 'Mark Check Received', 'event-tickets-mail-in' ),
|
||||||
|
'url' => wp_nonce_url(
|
||||||
|
admin_url( 'admin-post.php?action=mark_check_received&order_id=' . $order->get_id() ),
|
||||||
|
'et_mail_in_admin'
|
||||||
|
),
|
||||||
|
'class' => 'button-secondary',
|
||||||
|
];
|
||||||
|
|
||||||
|
$actions['mark_check_bounced'] = [
|
||||||
|
'label' => __( 'Mark Check Bounced', 'event-tickets-mail-in' ),
|
||||||
|
'url' => wp_nonce_url(
|
||||||
|
admin_url( 'admin-post.php?action=mark_check_bounced&order_id=' . $order->get_id() ),
|
||||||
|
'et_mail_in_admin'
|
||||||
|
),
|
||||||
|
'class' => 'button-secondary',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $actions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get checkout template for mail-in payment
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param string $template Template name
|
||||||
|
* @param string $gateway Gateway key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_checkout_template( $template, $gateway ) {
|
||||||
|
if ( $gateway === 'mail-in' ) {
|
||||||
|
return 'checkout/mail-in-form';
|
||||||
|
}
|
||||||
|
return $template;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send payment instructions email
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function send_instructions_email( $order ) {
|
||||||
|
$purchaser_email = $order->get_purchaser_email();
|
||||||
|
if ( ! $purchaser_email ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subject = sprintf(
|
||||||
|
__( 'Payment Instructions for Order #%s', 'event-tickets-mail-in' ),
|
||||||
|
$order->get_order_number()
|
||||||
|
);
|
||||||
|
|
||||||
|
$order_controller = new Order();
|
||||||
|
$details = $order_controller->get_mail_in_details( $order->get_id() );
|
||||||
|
|
||||||
|
$message = $this->get_email_template( 'payment-instructions', [
|
||||||
|
'order' => $order,
|
||||||
|
'details' => $details,
|
||||||
|
] );
|
||||||
|
|
||||||
|
wp_mail( $purchaser_email, $subject, $message, $this->get_email_headers() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send payment confirmation email
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function send_confirmation_email( $order ) {
|
||||||
|
$purchaser_email = $order->get_purchaser_email();
|
||||||
|
if ( ! $purchaser_email ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subject = sprintf(
|
||||||
|
__( 'Payment Confirmed for Order #%s', 'event-tickets-mail-in' ),
|
||||||
|
$order->get_order_number()
|
||||||
|
);
|
||||||
|
|
||||||
|
$message = $this->get_email_template( 'payment-confirmation', [
|
||||||
|
'order' => $order,
|
||||||
|
] );
|
||||||
|
|
||||||
|
wp_mail( $purchaser_email, $subject, $message, $this->get_email_headers() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send order cancellation email
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function send_cancellation_email( $order ) {
|
||||||
|
$purchaser_email = $order->get_purchaser_email();
|
||||||
|
if ( ! $purchaser_email ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subject = sprintf(
|
||||||
|
__( 'Order Cancelled: #%s', 'event-tickets-mail-in' ),
|
||||||
|
$order->get_order_number()
|
||||||
|
);
|
||||||
|
|
||||||
|
$message = $this->get_email_template( 'order-cancelled', [
|
||||||
|
'order' => $order,
|
||||||
|
] );
|
||||||
|
|
||||||
|
wp_mail( $purchaser_email, $subject, $message, $this->get_email_headers() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get email template content
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param string $template Template name
|
||||||
|
* @param array $args Template arguments
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_email_template( $template, $args = [] ) {
|
||||||
|
$template_file = ET_MAIL_IN_PATH . "templates/emails/{$template}.php";
|
||||||
|
|
||||||
|
if ( ! file_exists( $template_file ) ) {
|
||||||
|
return $this->get_fallback_email_content( $template, $args );
|
||||||
|
}
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
extract( $args );
|
||||||
|
include $template_file;
|
||||||
|
return ob_get_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get fallback email content
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param string $template Template name
|
||||||
|
* @param array $args Template arguments
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_fallback_email_content( $template, $args ) {
|
||||||
|
switch ( $template ) {
|
||||||
|
case 'payment-instructions':
|
||||||
|
return $this->get_instructions_fallback( $args );
|
||||||
|
case 'payment-confirmation':
|
||||||
|
return $this->get_confirmation_fallback( $args );
|
||||||
|
case 'order-cancelled':
|
||||||
|
return $this->get_cancellation_fallback( $args );
|
||||||
|
default:
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get payment instructions fallback content
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $args Template arguments
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_instructions_fallback( $args ) {
|
||||||
|
$order = $args['order'];
|
||||||
|
$details = $args['details'];
|
||||||
|
|
||||||
|
$content = sprintf( __( 'Thank you for your order #%s!', 'event-tickets-mail-in' ), $order->get_order_number() ) . "\n\n";
|
||||||
|
$content .= $details['instructions'] . "\n\n";
|
||||||
|
$content .= sprintf( __( 'Mailing Address:\n%s', 'event-tickets-mail-in' ), $details['mailing_address'] ) . "\n\n";
|
||||||
|
$content .= sprintf( __( 'Make Check Payable To: %s', 'event-tickets-mail-in' ), $details['payable_to'] ) . "\n\n";
|
||||||
|
$content .= sprintf( __( 'Order Total: %s', 'event-tickets-mail-in' ), $order->get_total_value()->get_formatted() ) . "\n";
|
||||||
|
|
||||||
|
return $content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get confirmation fallback content
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $args Template arguments
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_confirmation_fallback( $args ) {
|
||||||
|
$order = $args['order'];
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
__( 'Your payment for order #%s has been received and processed. Your tickets are now confirmed!', 'event-tickets-mail-in' ),
|
||||||
|
$order->get_order_number()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cancellation fallback content
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $args Template arguments
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_cancellation_fallback( $args ) {
|
||||||
|
$order = $args['order'];
|
||||||
|
|
||||||
|
return sprintf(
|
||||||
|
__( 'Your order #%s has been cancelled. If you believe this is an error, please contact us.', 'event-tickets-mail-in' ),
|
||||||
|
$order->get_order_number()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get email headers
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
protected function get_email_headers() {
|
||||||
|
return [
|
||||||
|
'Content-Type: text/html; charset=UTF-8',
|
||||||
|
'From: ' . get_option( 'blogname' ) . ' <' . get_option( 'admin_email' ) . '>',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
251
src/Order.php
Normal file
251
src/Order.php
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ET_Mail_In_Payment;
|
||||||
|
|
||||||
|
use TEC\Tickets\Commerce\Abstract_Order;
|
||||||
|
use TEC\Tickets\Commerce\Order as Commerce_Order;
|
||||||
|
use TEC\Tickets\Commerce\Status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Order class
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Order extends Abstract_Order {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create order with mail-in payment gateway
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Gateways\Contracts\Gateway_Interface $gateway Gateway instance
|
||||||
|
* @param array|null $purchaser Purchaser data
|
||||||
|
* @return \TEC\Tickets\Commerce\Order|false
|
||||||
|
*/
|
||||||
|
public function create_from_gateway( \TEC\Tickets\Commerce\Gateways\Contracts\Gateway_Interface $gateway, $purchaser = null ) {
|
||||||
|
// Use the main Commerce Order class to create the order
|
||||||
|
$order = tribe( \TEC\Tickets\Commerce\Order::class )->create_from_cart( $gateway, $purchaser );
|
||||||
|
|
||||||
|
if ( ! $order ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add mail-in specific meta data
|
||||||
|
$this->add_mail_in_meta( $order );
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add mail-in payment specific metadata
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \TEC\Tickets\Commerce\Order $order
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function add_mail_in_meta( $order ) {
|
||||||
|
$order_id = $order->get_id();
|
||||||
|
|
||||||
|
// Store payment method
|
||||||
|
update_post_meta( $order_id, '_tec_tc_payment_method', 'mail-in-check' );
|
||||||
|
|
||||||
|
// Store mailing instructions
|
||||||
|
$instructions = get_option( 'et_mail_in_instructions', '' );
|
||||||
|
if ( $instructions ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_instructions', $instructions );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store mailing address
|
||||||
|
$address = get_option( 'et_mail_in_mailing_address', '' );
|
||||||
|
if ( $address ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_mailing_address', $address );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store payable to
|
||||||
|
$payable_to = get_option( 'et_mail_in_check_payable_to', '' );
|
||||||
|
if ( $payable_to ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_payable_to', $payable_to );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set check received flag to false initially
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_received', false );
|
||||||
|
|
||||||
|
// Store creation date for tracking purposes
|
||||||
|
update_post_meta( $order_id, '_mail_in_created_date', current_time( 'mysql' ) );
|
||||||
|
|
||||||
|
// Add order note
|
||||||
|
$this->add_order_note(
|
||||||
|
$order_id,
|
||||||
|
__( 'Mail-in payment order created. Awaiting check payment.', 'event-tickets-mail-in' )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark check as received
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param int $order_id Order ID
|
||||||
|
* @param string $notes Optional notes about the received check
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function mark_check_received( $order_id, $notes = '' ) {
|
||||||
|
$order = $this->get_order( $order_id );
|
||||||
|
|
||||||
|
if ( ! $order ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update check received status
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_received', true );
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_received_date', current_time( 'mysql' ) );
|
||||||
|
|
||||||
|
// Add notes if provided
|
||||||
|
if ( $notes ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_notes', $notes );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update order status to completed
|
||||||
|
tribe( \TEC\Tickets\Commerce\Order::class )->modify_status( $order_id, Status\Completed::SLUG );
|
||||||
|
|
||||||
|
// Add order note
|
||||||
|
$note = __( 'Check payment received and processed.', 'event-tickets-mail-in' );
|
||||||
|
if ( $notes ) {
|
||||||
|
$note .= ' ' . sprintf( __( 'Notes: %s', 'event-tickets-mail-in' ), $notes );
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->add_order_note( $order_id, $note );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mark check as bounced/failed
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param int $order_id Order ID
|
||||||
|
* @param string $reason Reason for bounce/failure
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function mark_check_bounced( $order_id, $reason = '' ) {
|
||||||
|
$order = $this->get_order( $order_id );
|
||||||
|
|
||||||
|
if ( ! $order ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update order status to denied
|
||||||
|
tribe( \TEC\Tickets\Commerce\Order::class )->modify_status( $order_id, Status\Denied::SLUG );
|
||||||
|
|
||||||
|
// Add bounce information
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_bounced', true );
|
||||||
|
update_post_meta( $order_id, '_mail_in_check_bounce_date', current_time( 'mysql' ) );
|
||||||
|
|
||||||
|
if ( $reason ) {
|
||||||
|
update_post_meta( $order_id, '_mail_in_bounce_reason', $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add order note
|
||||||
|
$note = __( 'Check payment bounced/failed.', 'event-tickets-mail-in' );
|
||||||
|
if ( $reason ) {
|
||||||
|
$note .= ' ' . sprintf( __( 'Reason: %s', 'event-tickets-mail-in' ), $reason );
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->add_order_note( $order_id, $note );
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get mail-in payment details for an order
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param int $order_id Order ID
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_mail_in_details( $order_id ) {
|
||||||
|
return [
|
||||||
|
'instructions' => get_post_meta( $order_id, '_mail_in_instructions', true ),
|
||||||
|
'mailing_address' => get_post_meta( $order_id, '_mail_in_mailing_address', true ),
|
||||||
|
'payable_to' => get_post_meta( $order_id, '_mail_in_payable_to', true ),
|
||||||
|
'check_received' => get_post_meta( $order_id, '_mail_in_check_received', true ),
|
||||||
|
'check_received_date' => get_post_meta( $order_id, '_mail_in_check_received_date', true ),
|
||||||
|
'check_notes' => get_post_meta( $order_id, '_mail_in_check_notes', true ),
|
||||||
|
'check_bounced' => get_post_meta( $order_id, '_mail_in_check_bounced', true ),
|
||||||
|
'bounce_reason' => get_post_meta( $order_id, '_mail_in_bounce_reason', true ),
|
||||||
|
'bounce_date' => get_post_meta( $order_id, '_mail_in_check_bounce_date', true ),
|
||||||
|
'created_date' => get_post_meta( $order_id, '_mail_in_created_date', true ),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add order note
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param int $order_id Order ID
|
||||||
|
* @param string $note Note content
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add_order_note( $order_id, $note ) {
|
||||||
|
$existing_notes = get_post_meta( $order_id, '_tec_tc_order_notes', true );
|
||||||
|
if ( ! is_array( $existing_notes ) ) {
|
||||||
|
$existing_notes = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$existing_notes[] = [
|
||||||
|
'date' => current_time( 'mysql' ),
|
||||||
|
'note' => $note,
|
||||||
|
'type' => 'system',
|
||||||
|
];
|
||||||
|
|
||||||
|
update_post_meta( $order_id, '_tec_tc_order_notes', $existing_notes );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get order by ID
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param int $order_id Order ID
|
||||||
|
* @return \WP_Post|false
|
||||||
|
*/
|
||||||
|
protected function get_order( $order_id ) {
|
||||||
|
$order = get_post( $order_id );
|
||||||
|
|
||||||
|
// Verify this is actually an order post
|
||||||
|
if ( ! $order || $order->post_type !== 'tec_tc_order' ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $order;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get pending mail-in orders (for admin management)
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $args Query arguments
|
||||||
|
* @return \WP_Query
|
||||||
|
*/
|
||||||
|
public function get_pending_orders( $args = [] ) {
|
||||||
|
$default_args = [
|
||||||
|
'post_type' => 'tec_tc_order',
|
||||||
|
'meta_query' => [
|
||||||
|
[
|
||||||
|
'key' => '_tec_tc_gateway',
|
||||||
|
'value' => 'mail-in',
|
||||||
|
'compare' => '='
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'key' => '_mail_in_check_received',
|
||||||
|
'value' => false,
|
||||||
|
'compare' => '='
|
||||||
|
]
|
||||||
|
],
|
||||||
|
'post_status' => [ 'tec-tc-pending', 'tec-tc-approved' ],
|
||||||
|
'orderby' => 'date',
|
||||||
|
'order' => 'DESC',
|
||||||
|
];
|
||||||
|
|
||||||
|
$args = wp_parse_args( $args, $default_args );
|
||||||
|
|
||||||
|
return new \WP_Query( $args );
|
||||||
|
}
|
||||||
|
}
|
||||||
442
src/Provider.php
Normal file
442
src/Provider.php
Normal file
|
|
@ -0,0 +1,442 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ET_Mail_In_Payment;
|
||||||
|
|
||||||
|
use TEC\Common\Contracts\Service_Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Service Provider
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Provider extends Service_Provider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register services
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register() {
|
||||||
|
// Register gateway with Commerce module - match PayPal's implementation
|
||||||
|
add_filter( 'tec_tickets_commerce_gateways', [ $this, 'filter_add_gateway' ], 10, 2 );
|
||||||
|
|
||||||
|
// Register hooks
|
||||||
|
$this->register_hooks();
|
||||||
|
|
||||||
|
// Register admin features
|
||||||
|
$this->register_admin_features();
|
||||||
|
|
||||||
|
// Register form processing
|
||||||
|
$this->register_form_processing();
|
||||||
|
|
||||||
|
// Register frontend assets
|
||||||
|
$this->register_frontend_assets();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add this gateway to the list of available gateways
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $gateways Existing gateways
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function filter_add_gateway( array $gateways = [] ) {
|
||||||
|
// Create our gateway instance and register it
|
||||||
|
return $this->container->make( Gateway::class )->register_gateway( $gateways );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register hooks and filters
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function register_hooks() {
|
||||||
|
$hooks = new Hooks();
|
||||||
|
$hooks->register();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register admin features
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function register_admin_features() {
|
||||||
|
if ( ! is_admin() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add admin menu for managing mail-in orders
|
||||||
|
add_action( 'admin_menu', [ $this, 'add_admin_menu' ] );
|
||||||
|
|
||||||
|
// Add admin scripts and styles
|
||||||
|
add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ] );
|
||||||
|
|
||||||
|
// Add order meta box for mail-in payments
|
||||||
|
add_action( 'add_meta_boxes', [ $this, 'add_order_meta_box' ] );
|
||||||
|
|
||||||
|
// Handle admin actions
|
||||||
|
add_action( 'admin_post_mark_check_received', [ $this, 'handle_mark_check_received' ] );
|
||||||
|
add_action( 'admin_post_mark_check_bounced', [ $this, 'handle_mark_check_bounced' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add admin menu for mail-in order management
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add_admin_menu() {
|
||||||
|
add_submenu_page(
|
||||||
|
'edit.php?post_type=tec_tc_order',
|
||||||
|
__( 'Mail-In Payments', 'event-tickets-mail-in' ),
|
||||||
|
__( 'Mail-In Payments', 'event-tickets-mail-in' ),
|
||||||
|
'manage_options',
|
||||||
|
'mail-in-payments',
|
||||||
|
[ $this, 'admin_page' ]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display admin page for managing mail-in payments
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function admin_page() {
|
||||||
|
$order_controller = new Order();
|
||||||
|
$pending_orders = $order_controller->get_pending_orders();
|
||||||
|
|
||||||
|
include ET_MAIL_IN_PATH . 'templates/admin/mail-in-orders.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue admin scripts and styles
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param string $hook Current admin page hook
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function admin_scripts( $hook ) {
|
||||||
|
// Only load on relevant admin pages
|
||||||
|
if ( ! in_array( $hook, [ 'edit.php', 'post.php', 'tickets_page_mail-in-payments' ] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_enqueue_style(
|
||||||
|
'et-mail-in-admin',
|
||||||
|
ET_MAIL_IN_URL . 'assets/css/admin.css',
|
||||||
|
[],
|
||||||
|
ET_MAIL_IN_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script(
|
||||||
|
'et-mail-in-admin',
|
||||||
|
ET_MAIL_IN_URL . 'assets/js/admin.js',
|
||||||
|
[ 'jquery' ],
|
||||||
|
ET_MAIL_IN_VERSION,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_localize_script( 'et-mail-in-admin', 'etMailInAdmin', [
|
||||||
|
'nonce' => wp_create_nonce( 'et_mail_in_admin' ),
|
||||||
|
'ajaxurl' => admin_url( 'admin-ajax.php' ),
|
||||||
|
'strings' => [
|
||||||
|
'confirm_received' => __( 'Are you sure you want to mark this check as received?', 'event-tickets-mail-in' ),
|
||||||
|
'confirm_bounced' => __( 'Are you sure you want to mark this check as bounced?', 'event-tickets-mail-in' ),
|
||||||
|
],
|
||||||
|
] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add meta box to order edit screen
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function add_order_meta_box() {
|
||||||
|
global $post;
|
||||||
|
|
||||||
|
// Only add to mail-in orders
|
||||||
|
if ( get_post_meta( $post->ID, '_tec_tc_gateway', true ) !== 'mail-in' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_meta_box(
|
||||||
|
'mail-in-payment-details',
|
||||||
|
__( 'Mail-In Payment Details', 'event-tickets-mail-in' ),
|
||||||
|
[ $this, 'order_meta_box_callback' ],
|
||||||
|
'tec_tc_order',
|
||||||
|
'normal',
|
||||||
|
'high'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render order meta box
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param \WP_Post $post Order post object
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function order_meta_box_callback( $post ) {
|
||||||
|
$order_controller = new Order();
|
||||||
|
$details = $order_controller->get_mail_in_details( $post->ID );
|
||||||
|
|
||||||
|
include ET_MAIL_IN_PATH . 'templates/admin/order-meta-box.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle marking check as received
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle_mark_check_received() {
|
||||||
|
// Verify nonce
|
||||||
|
if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'et_mail_in_admin' ) ) {
|
||||||
|
wp_die( __( 'Security check failed.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check permissions
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_die( __( 'You do not have permission to perform this action.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_id = absint( $_POST['order_id'] ?? 0 );
|
||||||
|
$notes = sanitize_textarea_field( $_POST['notes'] ?? '' );
|
||||||
|
|
||||||
|
if ( ! $order_id ) {
|
||||||
|
wp_die( __( 'Invalid order ID.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_controller = new Order();
|
||||||
|
$result = $order_controller->mark_check_received( $order_id, $notes );
|
||||||
|
|
||||||
|
if ( $result ) {
|
||||||
|
add_action( 'admin_notices', function() {
|
||||||
|
echo '<div class="notice notice-success is-dismissible"><p>' .
|
||||||
|
esc_html__( 'Check marked as received successfully.', 'event-tickets-mail-in' ) .
|
||||||
|
'</p></div>';
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
add_action( 'admin_notices', function() {
|
||||||
|
echo '<div class="notice notice-error is-dismissible"><p>' .
|
||||||
|
esc_html__( 'Failed to mark check as received.', 'event-tickets-mail-in' ) .
|
||||||
|
'</p></div>';
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect back
|
||||||
|
$redirect_url = $_POST['redirect_url'] ?? admin_url( 'edit.php?post_type=tec_tc_order&page=mail-in-payments' );
|
||||||
|
wp_redirect( $redirect_url );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle marking check as bounced
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle_mark_check_bounced() {
|
||||||
|
// Verify nonce
|
||||||
|
if ( ! wp_verify_nonce( $_POST['nonce'] ?? '', 'et_mail_in_admin' ) ) {
|
||||||
|
wp_die( __( 'Security check failed.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check permissions
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
wp_die( __( 'You do not have permission to perform this action.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_id = absint( $_POST['order_id'] ?? 0 );
|
||||||
|
$reason = sanitize_textarea_field( $_POST['reason'] ?? '' );
|
||||||
|
|
||||||
|
if ( ! $order_id ) {
|
||||||
|
wp_die( __( 'Invalid order ID.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$order_controller = new Order();
|
||||||
|
$result = $order_controller->mark_check_bounced( $order_id, $reason );
|
||||||
|
|
||||||
|
if ( $result ) {
|
||||||
|
add_action( 'admin_notices', function() {
|
||||||
|
echo '<div class="notice notice-success is-dismissible"><p>' .
|
||||||
|
esc_html__( 'Check marked as bounced successfully.', 'event-tickets-mail-in' ) .
|
||||||
|
'</p></div>';
|
||||||
|
} );
|
||||||
|
} else {
|
||||||
|
add_action( 'admin_notices', function() {
|
||||||
|
echo '<div class="notice notice-error is-dismissible"><p>' .
|
||||||
|
esc_html__( 'Failed to mark check as bounced.', 'event-tickets-mail-in' ) .
|
||||||
|
'</p></div>';
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect back
|
||||||
|
$redirect_url = $_POST['redirect_url'] ?? admin_url( 'edit.php?post_type=tec_tc_order&page=mail-in-payments' );
|
||||||
|
wp_redirect( $redirect_url );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register form processing
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function register_form_processing() {
|
||||||
|
// Handle checkout form submission
|
||||||
|
add_action( 'template_redirect', [ $this, 'handle_checkout_form' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle checkout form submission
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle_checkout_form() {
|
||||||
|
// Check if this is our gateway form submission
|
||||||
|
if ( empty( $_POST['tec_tc_gateway'] ) || $_POST['tec_tc_gateway'] !== 'mail-in' ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify nonce
|
||||||
|
if ( ! wp_verify_nonce( $_POST['tec_tickets_commerce_checkout_nonce'] ?? '', 'tec_tickets_commerce_checkout' ) ) {
|
||||||
|
wp_die( __( 'Security check failed.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get cart and process order directly
|
||||||
|
if ( ! class_exists( 'TEC\Tickets\Commerce\Module' ) ) {
|
||||||
|
wp_die( __( 'Commerce module not available.', 'event-tickets-mail-in' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get cart instance
|
||||||
|
$cart = tribe( \TEC\Tickets\Commerce\Cart::class );
|
||||||
|
|
||||||
|
// Check if cart has items
|
||||||
|
if ( ! $cart->has_items() ) {
|
||||||
|
wp_redirect( add_query_arg( 'tec_tc_error', urlencode( __( 'Your cart is empty.', 'event-tickets-mail-in' ) ), wp_get_referer() ) );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get purchaser data from form
|
||||||
|
$purchaser_data = [
|
||||||
|
'purchaser_name' => sanitize_text_field( $_POST['purchaser_name'] ?? '' ),
|
||||||
|
'purchaser_email' => sanitize_email( $_POST['purchaser_email'] ?? '' ),
|
||||||
|
];
|
||||||
|
|
||||||
|
// Validate required fields
|
||||||
|
if ( empty( $purchaser_data['purchaser_name'] ) ) {
|
||||||
|
wp_redirect( add_query_arg( 'tec_tc_error', urlencode( __( 'Full name is required.', 'event-tickets-mail-in' ) ), wp_get_referer() ) );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( empty( $purchaser_data['purchaser_email'] ) ) {
|
||||||
|
wp_redirect( add_query_arg( 'tec_tc_error', urlencode( __( 'Email address is required.', 'event-tickets-mail-in' ) ), wp_get_referer() ) );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the Mail-In gateway
|
||||||
|
$gateway = $this->container->make( Gateway::class );
|
||||||
|
|
||||||
|
// Process payment through gateway
|
||||||
|
$result = $gateway->process_payment( $purchaser_data );
|
||||||
|
|
||||||
|
if ( ! $result['success'] ) {
|
||||||
|
// Handle error
|
||||||
|
wp_redirect( add_query_arg( 'tec_tc_error', urlencode( $result['message'] ), wp_get_referer() ) );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Success - redirect to success page
|
||||||
|
if ( isset( $result['redirect_url'] ) ) {
|
||||||
|
wp_redirect( $result['redirect_url'] );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch ( \Exception $e ) {
|
||||||
|
wp_redirect( add_query_arg( 'tec_tc_error', urlencode( $e->getMessage() ), wp_get_referer() ) );
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register frontend assets
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function register_frontend_assets() {
|
||||||
|
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_frontend_assets' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enqueue frontend assets
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function enqueue_frontend_assets() {
|
||||||
|
// Only load on pages that might have the checkout shortcode
|
||||||
|
if ( ! $this->should_load_frontend_assets() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_enqueue_style(
|
||||||
|
'et-mail-in-checkout',
|
||||||
|
ET_MAIL_IN_URL . 'assets/css/checkout.css',
|
||||||
|
[],
|
||||||
|
ET_MAIL_IN_VERSION
|
||||||
|
);
|
||||||
|
|
||||||
|
wp_enqueue_script(
|
||||||
|
'et-mail-in-checkout',
|
||||||
|
ET_MAIL_IN_URL . 'assets/js/checkout.js',
|
||||||
|
[],
|
||||||
|
ET_MAIL_IN_VERSION,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we should load frontend assets
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function should_load_frontend_assets() {
|
||||||
|
global $post;
|
||||||
|
|
||||||
|
// Load on posts/pages with checkout shortcode
|
||||||
|
if ( $post && has_shortcode( $post->post_content, 'tec_tickets_checkout' ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load on checkout pages (if using different URL structure)
|
||||||
|
if ( is_page() && (
|
||||||
|
strpos( get_the_title(), 'checkout' ) !== false ||
|
||||||
|
strpos( get_the_title(), 'Checkout' ) !== false
|
||||||
|
) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load on pages that might contain Event Tickets Commerce elements
|
||||||
|
if ( is_page() && class_exists( 'TEC\Tickets\Commerce\Module' ) ) {
|
||||||
|
// Check if page content contains commerce-related content
|
||||||
|
if ( $post && (
|
||||||
|
strpos( $post->post_content, 'tec_tickets' ) !== false ||
|
||||||
|
strpos( $post->post_content, 'tribe_events' ) !== false
|
||||||
|
) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
410
src/Settings.php
Normal file
410
src/Settings.php
Normal file
|
|
@ -0,0 +1,410 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace ET_Mail_In_Payment;
|
||||||
|
|
||||||
|
use TEC\Tickets\Commerce\Gateways\Contracts\Abstract_Settings;
|
||||||
|
use Tribe__Tickets__Main;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mail-In Payment Settings class
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
class Settings extends Abstract_Settings {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public static $option_sandbox = 'et-mail-in-sandbox';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Settings option prefix
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected static string $option_prefix = 'et_mail_in_';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the list of settings for the gateway
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return array The list of settings for the gateway
|
||||||
|
*/
|
||||||
|
public function get_settings() {
|
||||||
|
// Return the actual settings fields that integrate with Tribe's settings system
|
||||||
|
return $this->get_settings_fields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the HTML for the connection box in the admin
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_connection_settings_html() {
|
||||||
|
$status = $this->get_connection_status();
|
||||||
|
|
||||||
|
$html = '<div class="tec-settings-form__element">';
|
||||||
|
$html .= '<h3>' . esc_html__( 'Mail-In Payment (Check)', 'event-tickets-mail-in' ) . '</h3>';
|
||||||
|
$html .= '<p class="description">' . esc_html( $status['message'] ) . '</p>';
|
||||||
|
|
||||||
|
if ( ! $status['is_active'] ) {
|
||||||
|
$html .= '<p class="description">' . esc_html__( 'Configure the settings below to enable this payment method.', 'event-tickets-mail-in' ) . '</p>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$html .= '</div>';
|
||||||
|
|
||||||
|
return $html;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get settings fields for internal use
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_settings_fields() {
|
||||||
|
$fields = [
|
||||||
|
'mail_in_section' => [
|
||||||
|
'type' => 'html',
|
||||||
|
'html' => '<h3>' . __( 'Mail-In Payment (Check) Settings', 'event-tickets-mail-in' ) . '</h3>',
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-enabled' => [
|
||||||
|
'type' => 'checkbox_bool',
|
||||||
|
'label' => __( 'Enable Mail-In Payments', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'Enable this payment method to allow customers to pay by mailing checks.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => false,
|
||||||
|
'validation_type' => 'boolean',
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-title' => [
|
||||||
|
'type' => 'text',
|
||||||
|
'label' => __( 'Payment Method Title', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'This is the title customers will see during checkout.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => __( 'Mail-In Payment (Check)', 'event-tickets-mail-in' ),
|
||||||
|
'validation_type' => 'html',
|
||||||
|
'size' => 'large',
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-description' => [
|
||||||
|
'type' => 'textarea',
|
||||||
|
'label' => __( 'Payment Method Description', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'Brief description shown to customers during checkout.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => __( 'Pay by mailing a check to our address.', 'event-tickets-mail-in' ),
|
||||||
|
'validation_type' => 'html',
|
||||||
|
'size' => 'large',
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-payable-to' => [
|
||||||
|
'type' => 'text',
|
||||||
|
'label' => __( 'Make Check Payable To', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'The name or organization that checks should be made payable to.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => '',
|
||||||
|
'validation_type' => 'html',
|
||||||
|
'size' => 'large',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-address' => [
|
||||||
|
'type' => 'textarea',
|
||||||
|
'label' => __( 'Mailing Address', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'The complete mailing address where checks should be sent.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => '',
|
||||||
|
'validation_type' => 'html',
|
||||||
|
'size' => 'large',
|
||||||
|
'required' => true,
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-instructions' => [
|
||||||
|
'type' => 'textarea',
|
||||||
|
'label' => __( 'Payment Instructions', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'Detailed instructions for customers on how to complete their payment.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => __( 'Please mail your check to the address provided below. Your tickets will be reserved for 7 days while we wait for your payment to arrive. Include your order number on the check memo line.', 'event-tickets-mail-in' ),
|
||||||
|
'validation_type' => 'html',
|
||||||
|
'size' => 'large',
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-reservation-days' => [
|
||||||
|
'type' => 'text',
|
||||||
|
'label' => __( 'Reservation Period (Days)', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'Number of days to hold tickets while waiting for check payment.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => '7',
|
||||||
|
'validation_type' => 'int',
|
||||||
|
'size' => 'small',
|
||||||
|
],
|
||||||
|
'tickets-commerce-mail-in-auto-cancel' => [
|
||||||
|
'type' => 'checkbox_bool',
|
||||||
|
'label' => __( 'Auto-Cancel Expired Orders', 'event-tickets-mail-in' ),
|
||||||
|
'tooltip' => __( 'Automatically cancel orders if payment is not received within the reservation period.', 'event-tickets-mail-in' ),
|
||||||
|
'default' => false,
|
||||||
|
'validation_type' => 'boolean',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
return $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the settings section for the Payments tab
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_settings_section() {
|
||||||
|
return [
|
||||||
|
'mail_in_payment_settings' => [
|
||||||
|
'priority' => 30,
|
||||||
|
'fields' => $this->get_settings_fields(),
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate settings before saving
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $input Settings input
|
||||||
|
* @param array $field Field configuration
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function validate_settings_field( $input, $field ) {
|
||||||
|
switch ( $field['validation_type'] ?? 'html' ) {
|
||||||
|
case 'boolean':
|
||||||
|
return (bool) $input;
|
||||||
|
|
||||||
|
case 'int':
|
||||||
|
return max( 1, absint( $input ) );
|
||||||
|
|
||||||
|
case 'html':
|
||||||
|
default:
|
||||||
|
return wp_kses_post( $input );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add custom validation for required fields
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $input All settings input
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function validate_settings( $input ) {
|
||||||
|
$validated = [];
|
||||||
|
$errors = [];
|
||||||
|
|
||||||
|
foreach ( $this->get_settings_fields() as $key => $field ) {
|
||||||
|
$value = $input[ $key ] ?? $field['default'] ?? '';
|
||||||
|
|
||||||
|
// Check required fields
|
||||||
|
if ( ! empty( $field['required'] ) && empty( $value ) ) {
|
||||||
|
$errors[] = sprintf(
|
||||||
|
__( '%s is required.', 'event-tickets-mail-in' ),
|
||||||
|
$field['label']
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$validated[ $key ] = $this->validate_settings_field( $value, $field );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display errors if any
|
||||||
|
if ( ! empty( $errors ) ) {
|
||||||
|
add_settings_error(
|
||||||
|
'et_mail_in_settings',
|
||||||
|
'validation_error',
|
||||||
|
implode( ' ', $errors ),
|
||||||
|
'error'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $validated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get connection status for admin display
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function get_connection_status() {
|
||||||
|
$address = tribe_get_option( 'tickets-commerce-mail-in-address', '' );
|
||||||
|
$payable_to = tribe_get_option( 'tickets-commerce-mail-in-payable-to', '' );
|
||||||
|
$enabled = tribe_get_option( 'tickets-commerce-mail-in-enabled', false );
|
||||||
|
|
||||||
|
$is_connected = ! empty( $address ) && ! empty( $payable_to );
|
||||||
|
|
||||||
|
$status = [
|
||||||
|
'is_connected' => $is_connected,
|
||||||
|
'is_enabled' => $enabled,
|
||||||
|
'is_active' => $enabled && $is_connected,
|
||||||
|
];
|
||||||
|
|
||||||
|
if ( $is_connected ) {
|
||||||
|
$status['message'] = __( 'Mail-in payment gateway is properly configured.', 'event-tickets-mail-in' );
|
||||||
|
$status['status'] = 'success';
|
||||||
|
} else {
|
||||||
|
$missing = [];
|
||||||
|
if ( empty( $address ) ) {
|
||||||
|
$missing[] = __( 'Mailing Address', 'event-tickets-mail-in' );
|
||||||
|
}
|
||||||
|
if ( empty( $payable_to ) ) {
|
||||||
|
$missing[] = __( 'Check Payable To', 'event-tickets-mail-in' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$status['message'] = sprintf(
|
||||||
|
__( 'Please configure the following required fields: %s', 'event-tickets-mail-in' ),
|
||||||
|
implode( ', ', $missing )
|
||||||
|
);
|
||||||
|
$status['status'] = 'error';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register settings with WordPress
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function register_settings() {
|
||||||
|
foreach ( $this->get_settings_fields() as $key => $field ) {
|
||||||
|
if ( $field['type'] === 'html' ) {
|
||||||
|
continue; // Skip HTML fields
|
||||||
|
}
|
||||||
|
|
||||||
|
register_setting(
|
||||||
|
'et_mail_in_settings',
|
||||||
|
$key,
|
||||||
|
[
|
||||||
|
'type' => $this->get_wp_setting_type( $field['validation_type'] ?? 'string' ),
|
||||||
|
'sanitize_callback' => [ $this, 'validate_settings_field' ],
|
||||||
|
'default' => $field['default'] ?? '',
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert validation type to WordPress setting type
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param string $validation_type
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function get_wp_setting_type( $validation_type ) {
|
||||||
|
switch ( $validation_type ) {
|
||||||
|
case 'boolean':
|
||||||
|
return 'boolean';
|
||||||
|
case 'int':
|
||||||
|
return 'integer';
|
||||||
|
default:
|
||||||
|
return 'string';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render settings template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param array $context Template context
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function render_settings_template( $context ) {
|
||||||
|
$gateway = $context['gateway'];
|
||||||
|
$status = $context['connection_status'];
|
||||||
|
$fields = $this->get_settings_fields();
|
||||||
|
|
||||||
|
ob_start();
|
||||||
|
?>
|
||||||
|
<div class="tec-settings-form__element tec-settings-form__element--full-width">
|
||||||
|
<div class="tec-tickets__admin-settings-tickets-commerce-gateway-wrapper">
|
||||||
|
|
||||||
|
<!-- Gateway Status -->
|
||||||
|
<div class="tec-tickets__admin-settings-tickets-commerce-gateway-status">
|
||||||
|
<div class="tec-tickets__admin-settings-tickets-commerce-gateway-status-icon">
|
||||||
|
<?php if ( $status['is_active'] ) : ?>
|
||||||
|
<span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
|
||||||
|
<?php else : ?>
|
||||||
|
<span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<div class="tec-tickets__admin-settings-tickets-commerce-gateway-status-text">
|
||||||
|
<h3><?php echo esc_html( $gateway::get_label() ); ?></h3>
|
||||||
|
<p class="description">
|
||||||
|
<?php echo esc_html( $status['message'] ); ?>
|
||||||
|
</p>
|
||||||
|
<?php if ( ! $status['is_active'] ) : ?>
|
||||||
|
<p class="description">
|
||||||
|
<?php esc_html_e( 'Configure the settings below to enable this payment method.', 'event-tickets-mail-in' ); ?>
|
||||||
|
</p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Settings Form -->
|
||||||
|
<div class="tec-tickets__admin-settings-tickets-commerce-gateway-settings">
|
||||||
|
<table class="form-table">
|
||||||
|
<tbody>
|
||||||
|
<?php foreach ( $fields as $field_key => $field ) : ?>
|
||||||
|
<?php if ( $field['type'] === 'html' ) : ?>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2"><?php echo wp_kses_post( $field['html'] ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php else : ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">
|
||||||
|
<label for="<?php echo esc_attr( $field_key ); ?>">
|
||||||
|
<?php echo esc_html( $field['label'] ); ?>
|
||||||
|
<?php if ( ! empty( $field['required'] ) ) : ?>
|
||||||
|
<span class="required" style="color: #d63638;">*</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</label>
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<?php $this->render_field( $field_key, $field ); ?>
|
||||||
|
<?php if ( ! empty( $field['tooltip'] ) ) : ?>
|
||||||
|
<p class="description"><?php echo esc_html( $field['tooltip'] ); ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
return ob_get_clean();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render individual field
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @param string $field_key Field key
|
||||||
|
* @param array $field Field configuration
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function render_field( $field_key, $field ) {
|
||||||
|
$value = tribe_get_option( $field_key, $field['default'] ?? '' );
|
||||||
|
$size_class = ! empty( $field['size'] ) ? 'class="' . esc_attr( $field['size'] ) . '-text"' : '';
|
||||||
|
|
||||||
|
switch ( $field['type'] ) {
|
||||||
|
case 'checkbox_bool':
|
||||||
|
echo '<label>';
|
||||||
|
echo '<input type="checkbox" name="' . esc_attr( $field_key ) . '" value="1" ' . checked( $value, true, false ) . ' />';
|
||||||
|
echo ' ' . esc_html( $field['label'] );
|
||||||
|
echo '</label>';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'textarea':
|
||||||
|
echo '<textarea name="' . esc_attr( $field_key ) . '" rows="4" cols="50" ' . $size_class . '>';
|
||||||
|
echo esc_textarea( $value );
|
||||||
|
echo '</textarea>';
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'text':
|
||||||
|
default:
|
||||||
|
echo '<input type="text" name="' . esc_attr( $field_key ) . '" value="' . esc_attr( $value ) . '" ' . $size_class . ' />';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
315
templates/admin/mail-in-orders.php
Normal file
315
templates/admin/mail-in-orders.php
Normal file
|
|
@ -0,0 +1,315 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Admin page for managing mail-in payment orders
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var \WP_Query $pending_orders Query object with pending orders
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="wrap">
|
||||||
|
<h1><?php esc_html_e( 'Mail-In Payment Orders', 'event-tickets-mail-in' ); ?></h1>
|
||||||
|
|
||||||
|
<div class="et-mail-in-admin-header">
|
||||||
|
<p><?php esc_html_e( 'Manage orders that are waiting for check payments to arrive.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php if ( $pending_orders->have_posts() ) : ?>
|
||||||
|
<div class="et-mail-in-orders-table">
|
||||||
|
<table class="wp-list-table widefat fixed striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Order', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Customer', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Event', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Amount', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Date', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Status', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<th scope="col"><?php esc_html_e( 'Actions', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php
|
||||||
|
$order_controller = new \ET_Mail_In_Payment\Order();
|
||||||
|
while ( $pending_orders->have_posts() ) :
|
||||||
|
$pending_orders->the_post();
|
||||||
|
$order_id = get_the_ID();
|
||||||
|
$order = tribe( 'tickets.commerce.order' )->get_by_id( $order_id );
|
||||||
|
$details = $order_controller->get_mail_in_details( $order_id );
|
||||||
|
$created_date = get_post_meta( $order_id, '_mail_in_created_date', true );
|
||||||
|
$event_id = get_post_meta( $order_id, '_tec_tc_order_event_id', true );
|
||||||
|
$event_title = $event_id ? get_the_title( $event_id ) : __( 'N/A', 'event-tickets-mail-in' );
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>
|
||||||
|
<a href="<?php echo esc_url( admin_url( 'post.php?post=' . $order_id . '&action=edit' ) ); ?>">
|
||||||
|
#<?php echo esc_html( $order->get_order_number() ); ?>
|
||||||
|
</a>
|
||||||
|
</strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?php echo esc_html( $order->get_purchaser_name() ); ?><br>
|
||||||
|
<small><?php echo esc_html( $order->get_purchaser_email() ); ?></small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?php if ( $event_id ) : ?>
|
||||||
|
<a href="<?php echo esc_url( admin_url( 'post.php?post=' . $event_id . '&action=edit' ) ); ?>">
|
||||||
|
<?php echo esc_html( $event_title ); ?>
|
||||||
|
</a>
|
||||||
|
<?php else : ?>
|
||||||
|
<?php echo esc_html( $event_title ); ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong><?php echo esc_html( $order->get_total_value()->get_formatted() ); ?></strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<?php echo esc_html( date_i18n( get_option( 'date_format' ), strtotime( $created_date ) ) ); ?>
|
||||||
|
<br><small><?php echo esc_html( human_time_diff( strtotime( $created_date ), current_time( 'timestamp' ) ) . ' ago' ); ?></small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="et-mail-in-status et-mail-in-status--pending">
|
||||||
|
<?php esc_html_e( 'Awaiting Payment', 'event-tickets-mail-in' ); ?>
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="et-mail-in-actions">
|
||||||
|
<button type="button" class="button button-secondary et-mail-in-mark-received"
|
||||||
|
data-order-id="<?php echo esc_attr( $order_id ); ?>"
|
||||||
|
data-order-number="<?php echo esc_attr( $order->get_order_number() ); ?>">
|
||||||
|
<?php esc_html_e( 'Mark Received', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="button button-secondary et-mail-in-mark-bounced"
|
||||||
|
data-order-id="<?php echo esc_attr( $order_id ); ?>"
|
||||||
|
data-order-number="<?php echo esc_attr( $order->get_order_number() ); ?>">
|
||||||
|
<?php esc_html_e( 'Mark Bounced', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endwhile; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
// Pagination
|
||||||
|
$pagination = paginate_links( [
|
||||||
|
'total' => $pending_orders->max_num_pages,
|
||||||
|
'current' => max( 1, get_query_var( 'paged' ) ),
|
||||||
|
'format' => '?paged=%#%',
|
||||||
|
'prev_text' => __( '« Previous', 'event-tickets-mail-in' ),
|
||||||
|
'next_text' => __( 'Next »', 'event-tickets-mail-in' ),
|
||||||
|
] );
|
||||||
|
|
||||||
|
if ( $pagination ) {
|
||||||
|
echo '<div class="tablenav bottom">';
|
||||||
|
echo '<div class="tablenav-pages">' . $pagination . '</div>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<?php else : ?>
|
||||||
|
<div class="et-mail-in-no-orders">
|
||||||
|
<p><?php esc_html_e( 'No pending mail-in payment orders found.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php wp_reset_postdata(); ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mark Received Modal -->
|
||||||
|
<div id="et-mail-in-received-modal" class="et-mail-in-modal" style="display: none;">
|
||||||
|
<div class="et-mail-in-modal-content">
|
||||||
|
<span class="et-mail-in-modal-close">×</span>
|
||||||
|
<h2><?php esc_html_e( 'Mark Check as Received', 'event-tickets-mail-in' ); ?></h2>
|
||||||
|
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
||||||
|
<input type="hidden" name="action" value="mark_check_received">
|
||||||
|
<input type="hidden" name="order_id" id="received-order-id">
|
||||||
|
<input type="hidden" name="nonce" value="<?php echo esc_attr( wp_create_nonce( 'et_mail_in_admin' ) ); ?>">
|
||||||
|
<input type="hidden" name="redirect_url" value="<?php echo esc_url( admin_url( 'edit.php?post_type=tec_tc_order&page=mail-in-payments' ) ); ?>">
|
||||||
|
|
||||||
|
<p id="received-order-info"></p>
|
||||||
|
|
||||||
|
<label for="received-notes"><?php esc_html_e( 'Notes (optional):', 'event-tickets-mail-in' ); ?></label>
|
||||||
|
<textarea name="notes" id="received-notes" rows="3" style="width: 100%;"></textarea>
|
||||||
|
|
||||||
|
<div class="et-mail-in-modal-actions">
|
||||||
|
<button type="submit" class="button button-primary">
|
||||||
|
<?php esc_html_e( 'Mark as Received', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="button et-mail-in-modal-cancel">
|
||||||
|
<?php esc_html_e( 'Cancel', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Mark Bounced Modal -->
|
||||||
|
<div id="et-mail-in-bounced-modal" class="et-mail-in-modal" style="display: none;">
|
||||||
|
<div class="et-mail-in-modal-content">
|
||||||
|
<span class="et-mail-in-modal-close">×</span>
|
||||||
|
<h2><?php esc_html_e( 'Mark Check as Bounced', 'event-tickets-mail-in' ); ?></h2>
|
||||||
|
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
||||||
|
<input type="hidden" name="action" value="mark_check_bounced">
|
||||||
|
<input type="hidden" name="order_id" id="bounced-order-id">
|
||||||
|
<input type="hidden" name="nonce" value="<?php echo esc_attr( wp_create_nonce( 'et_mail_in_admin' ) ); ?>">
|
||||||
|
<input type="hidden" name="redirect_url" value="<?php echo esc_url( admin_url( 'edit.php?post_type=tec_tc_order&page=mail-in-payments' ) ); ?>">
|
||||||
|
|
||||||
|
<p id="bounced-order-info"></p>
|
||||||
|
|
||||||
|
<label for="bounced-reason"><?php esc_html_e( 'Reason for bounce:', 'event-tickets-mail-in' ); ?></label>
|
||||||
|
<textarea name="reason" id="bounced-reason" rows="3" style="width: 100%;" required></textarea>
|
||||||
|
|
||||||
|
<div class="et-mail-in-modal-actions">
|
||||||
|
<button type="submit" class="button button-primary">
|
||||||
|
<?php esc_html_e( 'Mark as Bounced', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
<button type="button" class="button et-mail-in-modal-cancel">
|
||||||
|
<?php esc_html_e( 'Cancel', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.et-mail-in-admin-header {
|
||||||
|
background: #f1f1f1;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-orders-table {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status {
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--pending {
|
||||||
|
background: #fff3cd;
|
||||||
|
color: #856404;
|
||||||
|
border: 1px solid #ffeaa7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-actions .button {
|
||||||
|
font-size: 11px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-no-orders {
|
||||||
|
text-align: center;
|
||||||
|
padding: 40px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 1000;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal-content {
|
||||||
|
background-color: #fefefe;
|
||||||
|
margin: 10% auto;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
width: 80%;
|
||||||
|
max-width: 500px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal-close {
|
||||||
|
position: absolute;
|
||||||
|
right: 15px;
|
||||||
|
top: 15px;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal-close:hover {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal-actions {
|
||||||
|
margin-top: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal h2 {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-modal label {
|
||||||
|
display: block;
|
||||||
|
margin: 15px 0 5px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
jQuery(document).ready(function($) {
|
||||||
|
// Handle mark received button
|
||||||
|
$('.et-mail-in-mark-received').on('click', function() {
|
||||||
|
var orderId = $(this).data('order-id');
|
||||||
|
var orderNumber = $(this).data('order-number');
|
||||||
|
|
||||||
|
$('#received-order-id').val(orderId);
|
||||||
|
$('#received-order-info').text('Mark check as received for Order #' + orderNumber + '?');
|
||||||
|
$('#et-mail-in-received-modal').show();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle mark bounced button
|
||||||
|
$('.et-mail-in-mark-bounced').on('click', function() {
|
||||||
|
var orderId = $(this).data('order-id');
|
||||||
|
var orderNumber = $(this).data('order-number');
|
||||||
|
|
||||||
|
$('#bounced-order-id').val(orderId);
|
||||||
|
$('#bounced-order-info').text('Mark check as bounced for Order #' + orderNumber + '?');
|
||||||
|
$('#et-mail-in-bounced-modal').show();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle modal close
|
||||||
|
$('.et-mail-in-modal-close, .et-mail-in-modal-cancel').on('click', function() {
|
||||||
|
$('.et-mail-in-modal').hide();
|
||||||
|
$('textarea').val('');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Close modal when clicking outside
|
||||||
|
$(window).on('click', function(event) {
|
||||||
|
if ($(event.target).hasClass('et-mail-in-modal')) {
|
||||||
|
$('.et-mail-in-modal').hide();
|
||||||
|
$('textarea').val('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
218
templates/admin/order-meta-box.php
Normal file
218
templates/admin/order-meta-box.php
Normal file
|
|
@ -0,0 +1,218 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Order meta box template for mail-in payments
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var \WP_Post $post Order post object
|
||||||
|
* @var array $details Mail-in payment details
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="et-mail-in-order-details">
|
||||||
|
<table class="form-table">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Payment Method', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td><?php esc_html_e( 'Mail-In Payment (Check)', 'event-tickets-mail-in' ); ?></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Check Status', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<?php if ( $details['check_received'] ) : ?>
|
||||||
|
<span class="et-mail-in-status et-mail-in-status--received">
|
||||||
|
<?php esc_html_e( 'Received', 'event-tickets-mail-in' ); ?>
|
||||||
|
</span>
|
||||||
|
<?php if ( $details['check_received_date'] ) : ?>
|
||||||
|
<br><small><?php echo esc_html( sprintf( __( 'Received on: %s', 'event-tickets-mail-in' ), date_i18n( get_option( 'date_format' ), strtotime( $details['check_received_date'] ) ) ) ); ?></small>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php elseif ( $details['check_bounced'] ) : ?>
|
||||||
|
<span class="et-mail-in-status et-mail-in-status--bounced">
|
||||||
|
<?php esc_html_e( 'Bounced', 'event-tickets-mail-in' ); ?>
|
||||||
|
</span>
|
||||||
|
<?php if ( $details['bounce_date'] ) : ?>
|
||||||
|
<br><small><?php echo esc_html( sprintf( __( 'Bounced on: %s', 'event-tickets-mail-in' ), date_i18n( get_option( 'date_format' ), strtotime( $details['bounce_date'] ) ) ) ); ?></small>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php else : ?>
|
||||||
|
<span class="et-mail-in-status et-mail-in-status--pending">
|
||||||
|
<?php esc_html_e( 'Awaiting Payment', 'event-tickets-mail-in' ); ?>
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<?php if ( $details['created_date'] ) : ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Order Created', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<?php echo esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $details['created_date'] ) ) ); ?>
|
||||||
|
<br><small><?php echo esc_html( human_time_diff( strtotime( $details['created_date'] ), current_time( 'timestamp' ) ) . ' ago' ); ?></small>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $details['payable_to'] ) : ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Check Payable To', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td><strong><?php echo esc_html( $details['payable_to'] ); ?></strong></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $details['mailing_address'] ) : ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Mailing Address', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td>
|
||||||
|
<div class="et-mail-in-address">
|
||||||
|
<?php echo wp_kses_post( nl2br( $details['mailing_address'] ) ); ?>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $details['check_notes'] ) : ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Payment Notes', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td><?php echo wp_kses_post( nl2br( $details['check_notes'] ) ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $details['bounce_reason'] ) : ?>
|
||||||
|
<tr>
|
||||||
|
<th scope="row"><?php esc_html_e( 'Bounce Reason', 'event-tickets-mail-in' ); ?></th>
|
||||||
|
<td><?php echo wp_kses_post( nl2br( $details['bounce_reason'] ) ); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endif; ?>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<?php if ( ! $details['check_received'] && ! $details['check_bounced'] ) : ?>
|
||||||
|
<div class="et-mail-in-actions">
|
||||||
|
<h4><?php esc_html_e( 'Payment Actions', 'event-tickets-mail-in' ); ?></h4>
|
||||||
|
<p><?php esc_html_e( 'Use these actions to update the payment status when you receive or process the check.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
|
||||||
|
<div class="et-mail-in-action-buttons">
|
||||||
|
<button type="button" class="button button-primary et-mail-in-mark-received-single"
|
||||||
|
data-order-id="<?php echo esc_attr( $post->ID ); ?>">
|
||||||
|
<?php esc_html_e( 'Mark Check as Received', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" class="button button-secondary et-mail-in-mark-bounced-single"
|
||||||
|
data-order-id="<?php echo esc_attr( $post->ID ); ?>">
|
||||||
|
<?php esc_html_e( 'Mark Check as Bounced', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.et-mail-in-order-details .form-table th {
|
||||||
|
width: 150px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--pending {
|
||||||
|
background: #fff3cd;
|
||||||
|
color: #856404;
|
||||||
|
border: 1px solid #ffeaa7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--received {
|
||||||
|
background: #d4edda;
|
||||||
|
color: #155724;
|
||||||
|
border: 1px solid #c3e6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-status--bounced {
|
||||||
|
background: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-address {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #0073aa;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-actions {
|
||||||
|
margin-top: 20px;
|
||||||
|
padding-top: 20px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-actions h4 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-buttons {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.et-mail-in-action-buttons .button {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
jQuery(document).ready(function($) {
|
||||||
|
$('.et-mail-in-mark-received-single').on('click', function() {
|
||||||
|
var orderId = $(this).data('order-id');
|
||||||
|
var notes = prompt('<?php echo esc_js( __( 'Optional notes about the received check:', 'event-tickets-mail-in' ) ); ?>');
|
||||||
|
|
||||||
|
if (notes !== null) { // User didn't cancel
|
||||||
|
var form = $('<form>', {
|
||||||
|
'method': 'POST',
|
||||||
|
'action': '<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>'
|
||||||
|
});
|
||||||
|
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'action', 'value': 'mark_check_received'}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'order_id', 'value': orderId}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'notes', 'value': notes}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'nonce', 'value': '<?php echo esc_attr( wp_create_nonce( 'et_mail_in_admin' ) ); ?>'}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'redirect_url', 'value': window.location.href}));
|
||||||
|
|
||||||
|
$('body').append(form);
|
||||||
|
form.submit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('.et-mail-in-mark-bounced-single').on('click', function() {
|
||||||
|
var orderId = $(this).data('order-id');
|
||||||
|
var reason = prompt('<?php echo esc_js( __( 'Reason for check bounce (required):', 'event-tickets-mail-in' ) ); ?>');
|
||||||
|
|
||||||
|
if (reason && reason.trim() !== '') {
|
||||||
|
var form = $('<form>', {
|
||||||
|
'method': 'POST',
|
||||||
|
'action': '<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>'
|
||||||
|
});
|
||||||
|
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'action', 'value': 'mark_check_bounced'}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'order_id', 'value': orderId}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'reason', 'value': reason}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'nonce', 'value': '<?php echo esc_attr( wp_create_nonce( 'et_mail_in_admin' ) ); ?>'}));
|
||||||
|
form.append($('<input>', {'type': 'hidden', 'name': 'redirect_url', 'value': window.location.href}));
|
||||||
|
|
||||||
|
$('body').append(form);
|
||||||
|
form.submit();
|
||||||
|
} else if (reason !== null) {
|
||||||
|
alert('<?php echo esc_js( __( 'Please provide a reason for the bounce.', 'event-tickets-mail-in' ) ); ?>');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
151
templates/checkout/mail-in-form.php
Normal file
151
templates/checkout/mail-in-form.php
Normal file
|
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Mail-In Payment checkout form template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var array $args Template arguments
|
||||||
|
* @var \ET_Mail_In_Payment\Gateway $gateway Gateway instance
|
||||||
|
* @var string $instructions Payment instructions
|
||||||
|
* @var string $mailing_address Mailing address
|
||||||
|
* @var string $payable_to Check payable to
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$gateway = $args['gateway'] ?? null;
|
||||||
|
$instructions = $args['instructions'] ?? '';
|
||||||
|
$mailing_address = $args['mailing_address'] ?? '';
|
||||||
|
$payable_to = $args['payable_to'] ?? '';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in">
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__header">
|
||||||
|
<h3><?php echo esc_html( $gateway::get_label() ); ?></h3>
|
||||||
|
<p class="tribe-tickets-commerce-gateway-mail-in__description">
|
||||||
|
<?php echo esc_html( $gateway::get_description() ); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__instructions">
|
||||||
|
<?php if ( $instructions ) : ?>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__instructions-text">
|
||||||
|
<h4><?php esc_html_e( 'Payment Instructions:', 'event-tickets-mail-in' ); ?></h4>
|
||||||
|
<p><?php echo wp_kses_post( nl2br( $instructions ) ); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__details">
|
||||||
|
<?php if ( $payable_to ) : ?>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__payable-to">
|
||||||
|
<h4><?php esc_html_e( 'Make Check Payable To:', 'event-tickets-mail-in' ); ?></h4>
|
||||||
|
<p class="tribe-tickets-commerce-gateway-mail-in__payable-to-name">
|
||||||
|
<strong><?php echo esc_html( $payable_to ); ?></strong>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $mailing_address ) : ?>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__address">
|
||||||
|
<h4><?php esc_html_e( 'Mail Your Check To:', 'event-tickets-mail-in' ); ?></h4>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__address-block">
|
||||||
|
<?php echo wp_kses_post( nl2br( $mailing_address ) ); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__important-note">
|
||||||
|
<h4><?php esc_html_e( 'Important Notes:', 'event-tickets-mail-in' ); ?></h4>
|
||||||
|
<ul>
|
||||||
|
<li><?php esc_html_e( 'Please include your order number in the check memo line.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Your tickets will be reserved while we wait for your payment to arrive.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'You will receive a confirmation email once your payment is processed.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 20px;
|
||||||
|
margin: 15px 0 !important;
|
||||||
|
background: #f9f9f9;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__header h3 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__description {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
font-style: italic;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__instructions {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #e5e5e5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__instructions h4 {
|
||||||
|
margin: 0 0 10px 0;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__details {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__details {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__payable-to-name {
|
||||||
|
font-size: 18px;
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__address-block {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #0073aa;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note {
|
||||||
|
background: #fff3cd;
|
||||||
|
border: 1px solid #ffeaa7;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note h4 {
|
||||||
|
color: #856404;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note ul {
|
||||||
|
margin: 10px 0 0 0;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tribe-tickets-commerce-gateway-mail-in__important-note li {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
color: #856404;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</div>
|
||||||
141
templates/emails/order-cancelled.php
Normal file
141
templates/emails/order-cancelled.php
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Order cancelled email template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php printf( __( 'Order Cancelled: #%s', 'event-tickets-mail-in' ), $order->get_order_number() ); ?></title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background: #f8d7da;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
border-bottom: 3px solid #dc3545;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
background: #fff;
|
||||||
|
padding: 30px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.order-summary {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.cancellation-notice {
|
||||||
|
background: #f8d7da;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #dc3545;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.contact-info {
|
||||||
|
background: #e7f3ff;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #0073aa;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
h1, h2, h3 {
|
||||||
|
color: #dc3545;
|
||||||
|
}
|
||||||
|
.order-number {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #dc3545;
|
||||||
|
}
|
||||||
|
.cancel-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #dc3545;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="email-container">
|
||||||
|
<div class="header">
|
||||||
|
<div class="cancel-icon">✗</div>
|
||||||
|
<h1><?php esc_html_e( 'Order Cancelled', 'event-tickets-mail-in' ); ?></h1>
|
||||||
|
<p><?php printf( __( 'Order #%s', 'event-tickets-mail-in' ), '<span class="order-number">' . esc_html( $order->get_order_number() ) . '</span>' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<h2><?php esc_html_e( 'Your order has been cancelled', 'event-tickets-mail-in' ); ?></h2>
|
||||||
|
|
||||||
|
<p><?php printf(
|
||||||
|
__( 'Hello %s,', 'event-tickets-mail-in' ),
|
||||||
|
esc_html( $order->get_purchaser_name() )
|
||||||
|
); ?></p>
|
||||||
|
|
||||||
|
<div class="cancellation-notice">
|
||||||
|
<h3><?php esc_html_e( 'Order Cancellation Notice', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<p><?php esc_html_e( 'We regret to inform you that your order has been cancelled. This may have occurred for one of the following reasons:', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
<ul>
|
||||||
|
<li><?php esc_html_e( 'Payment was not received within the specified timeframe', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Check payment was returned/bounced', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Manual cancellation by administrator', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Event was cancelled or postponed', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="order-summary">
|
||||||
|
<h3><?php esc_html_e( 'Cancelled Order Details', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<p><strong><?php esc_html_e( 'Order Number:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_order_number() ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Order Total:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_total_value()->get_formatted() ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Cancellation Date:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Status:', 'event-tickets-mail-in' ); ?></strong> <span style="color: #dc3545; font-weight: bold;"><?php esc_html_e( 'Cancelled', 'event-tickets-mail-in' ); ?></span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3><?php esc_html_e( 'What this means:', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<ul>
|
||||||
|
<li><?php esc_html_e( 'Your ticket reservation has been released', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'No payment is required for this cancelled order', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'If you already mailed a check, please contact us for a refund', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'You can place a new order if tickets are still available', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<div class="contact-info">
|
||||||
|
<h3><?php esc_html_e( 'Questions or Concerns?', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<p><?php esc_html_e( 'If you believe this cancellation was made in error, or if you have any questions about this cancellation, please contact us immediately.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
<p><?php esc_html_e( 'We apologize for any inconvenience this may cause.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><?php esc_html_e( 'Thank you for your understanding.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p><?php echo esc_html( get_option( 'blogname' ) ); ?></p>
|
||||||
|
<p><?php echo esc_html( get_option( 'admin_email' ) ); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
122
templates/emails/payment-confirmation.php
Normal file
122
templates/emails/payment-confirmation.php
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Payment confirmation email template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php printf( __( 'Payment Confirmed for Order #%s', 'event-tickets-mail-in' ), $order->get_order_number() ); ?></title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background: #d4edda;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
border-bottom: 3px solid #28a745;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
background: #fff;
|
||||||
|
padding: 30px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.order-summary {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.success-message {
|
||||||
|
background: #d4edda;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #28a745;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
h1, h2, h3 {
|
||||||
|
color: #28a745;
|
||||||
|
}
|
||||||
|
.order-number {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #28a745;
|
||||||
|
}
|
||||||
|
.success-icon {
|
||||||
|
font-size: 48px;
|
||||||
|
color: #28a745;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="email-container">
|
||||||
|
<div class="header">
|
||||||
|
<div class="success-icon">✓</div>
|
||||||
|
<h1><?php esc_html_e( 'Payment Confirmed!', 'event-tickets-mail-in' ); ?></h1>
|
||||||
|
<p><?php printf( __( 'Order #%s', 'event-tickets-mail-in' ), '<span class="order-number">' . esc_html( $order->get_order_number() ) . '</span>' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<h2><?php esc_html_e( 'Your payment has been received!', 'event-tickets-mail-in' ); ?></h2>
|
||||||
|
|
||||||
|
<p><?php printf(
|
||||||
|
__( 'Hello %s,', 'event-tickets-mail-in' ),
|
||||||
|
esc_html( $order->get_purchaser_name() )
|
||||||
|
); ?></p>
|
||||||
|
|
||||||
|
<div class="success-message">
|
||||||
|
<h3><?php esc_html_e( 'Great news!', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<p><?php esc_html_e( 'We have received and processed your check payment. Your order is now complete and your tickets are confirmed!', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="order-summary">
|
||||||
|
<h3><?php esc_html_e( 'Order Summary', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<p><strong><?php esc_html_e( 'Order Number:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_order_number() ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Payment Method:', 'event-tickets-mail-in' ); ?></strong> <?php esc_html_e( 'Check Payment', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Total Amount:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_total_value()->get_formatted() ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Payment Status:', 'event-tickets-mail-in' ); ?></strong> <span style="color: #28a745; font-weight: bold;"><?php esc_html_e( 'Completed', 'event-tickets-mail-in' ); ?></span></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3><?php esc_html_e( 'What happens next?', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<ul>
|
||||||
|
<li><?php esc_html_e( 'Your tickets are now confirmed and active.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'You should receive your tickets in a separate email shortly.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Please keep this confirmation for your records.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'If you have any questions, please contact us.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p><?php esc_html_e( 'Thank you for your payment and we look forward to seeing you at the event!', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p><?php echo esc_html( get_option( 'blogname' ) ); ?></p>
|
||||||
|
<p><?php echo esc_html( get_option( 'admin_email' ) ); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
170
templates/emails/payment-instructions.php
Normal file
170
templates/emails/payment-instructions.php
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Payment instructions email template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var \TEC\Tickets\Commerce\Order $order Order object
|
||||||
|
* @var array $details Mail-in payment details
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?><!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title><?php printf( __( 'Payment Instructions for Order #%s', 'event-tickets-mail-in' ), $order->get_order_number() ); ?></title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #333;
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
border-bottom: 3px solid #0073aa;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
background: #fff;
|
||||||
|
padding: 30px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.order-summary {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.payment-details {
|
||||||
|
background: #e7f3ff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #0073aa;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.important-notes {
|
||||||
|
background: #fff3cd;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
border-left: 4px solid #ffc107;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 0 0 8px 8px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
.mailing-address {
|
||||||
|
background: #f5f5f5;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 10px 0;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
h1, h2, h3 {
|
||||||
|
color: #0073aa;
|
||||||
|
}
|
||||||
|
.order-number {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #0073aa;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
li {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="email-container">
|
||||||
|
<div class="header">
|
||||||
|
<h1><?php esc_html_e( 'Payment Instructions', 'event-tickets-mail-in' ); ?></h1>
|
||||||
|
<p><?php printf( __( 'Order #%s', 'event-tickets-mail-in' ), '<span class="order-number">' . esc_html( $order->get_order_number() ) . '</span>' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<h2><?php esc_html_e( 'Thank you for your order!', 'event-tickets-mail-in' ); ?></h2>
|
||||||
|
|
||||||
|
<p><?php printf(
|
||||||
|
__( 'Hello %s,', 'event-tickets-mail-in' ),
|
||||||
|
esc_html( $order->get_purchaser_name() )
|
||||||
|
); ?></p>
|
||||||
|
|
||||||
|
<p><?php esc_html_e( 'Your order has been received and your tickets have been reserved. To complete your purchase, please mail your check payment using the details below.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
|
||||||
|
<div class="order-summary">
|
||||||
|
<h3><?php esc_html_e( 'Order Summary', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<p><strong><?php esc_html_e( 'Order Number:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_order_number() ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Order Date:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( date_i18n( get_option( 'date_format' ), strtotime( $details['created_date'] ) ) ); ?></p>
|
||||||
|
<p><strong><?php esc_html_e( 'Total Amount:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_total_value()->get_formatted() ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="payment-details">
|
||||||
|
<h3><?php esc_html_e( 'Payment Instructions', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
|
||||||
|
<?php if ( $details['instructions'] ) : ?>
|
||||||
|
<p><?php echo wp_kses_post( nl2br( $details['instructions'] ) ); ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $details['payable_to'] ) : ?>
|
||||||
|
<p><strong><?php esc_html_e( 'Make Check Payable To:', 'event-tickets-mail-in' ); ?></strong></p>
|
||||||
|
<p style="font-size: 18px; font-weight: bold; color: #0073aa;"><?php echo esc_html( $details['payable_to'] ); ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $details['mailing_address'] ) : ?>
|
||||||
|
<p><strong><?php esc_html_e( 'Mail Your Check To:', 'event-tickets-mail-in' ); ?></strong></p>
|
||||||
|
<div class="mailing-address">
|
||||||
|
<?php echo wp_kses_post( nl2br( $details['mailing_address'] ) ); ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<p><strong><?php esc_html_e( 'Check Amount:', 'event-tickets-mail-in' ); ?></strong> <?php echo esc_html( $order->get_total_value()->get_formatted() ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="important-notes">
|
||||||
|
<h3><?php esc_html_e( 'Important Notes', 'event-tickets-mail-in' ); ?></h3>
|
||||||
|
<ul>
|
||||||
|
<li><?php printf( __( 'Please write your order number (%s) in the check memo line.', 'event-tickets-mail-in' ), esc_html( $order->get_order_number() ) ); ?></li>
|
||||||
|
<li><?php
|
||||||
|
$reservation_days = absint( get_option( 'et_mail_in_reservation_days', 7 ) );
|
||||||
|
printf(
|
||||||
|
_n(
|
||||||
|
'Your tickets will be reserved for %d day while we wait for your payment.',
|
||||||
|
'Your tickets will be reserved for %d days while we wait for your payment.',
|
||||||
|
$reservation_days,
|
||||||
|
'event-tickets-mail-in'
|
||||||
|
),
|
||||||
|
$reservation_days
|
||||||
|
);
|
||||||
|
?></li>
|
||||||
|
<li><?php esc_html_e( 'You will receive a confirmation email once your payment is received and processed.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Please keep this email for your records.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p><?php esc_html_e( 'If you have any questions about your order or payment, please contact us.', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
|
||||||
|
<p><?php esc_html_e( 'Thank you for your business!', 'event-tickets-mail-in' ); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p><?php echo esc_html( get_option( 'blogname' ) ); ?></p>
|
||||||
|
<p><?php echo esc_html( get_option( 'admin_email' ) ); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
124
templates/v2/commerce/gateway/mail-in/container.php
Normal file
124
templates/v2/commerce/gateway/mail-in/container.php
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Mail-In Payment checkout container template
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
* @var array $args Template arguments
|
||||||
|
* @var \ET_Mail_In_Payment\Gateway $gateway Gateway instance
|
||||||
|
* @var string $instructions Payment instructions
|
||||||
|
* @var string $mailing_address Mailing address
|
||||||
|
* @var string $payable_to Check payable to
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Variables are extracted from $context in the Gateway class
|
||||||
|
// If not available directly, try to get from $args (fallback)
|
||||||
|
if ( ! isset( $gateway ) ) {
|
||||||
|
$gateway = $args['gateway'] ?? null;
|
||||||
|
}
|
||||||
|
if ( ! isset( $instructions ) ) {
|
||||||
|
$instructions = $args['instructions'] ?? '';
|
||||||
|
}
|
||||||
|
if ( ! isset( $mailing_address ) ) {
|
||||||
|
$mailing_address = $args['mailing_address'] ?? '';
|
||||||
|
}
|
||||||
|
if ( ! isset( $payable_to ) ) {
|
||||||
|
$payable_to = $args['payable_to'] ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get class name for static method calls
|
||||||
|
$gateway_class = $gateway ? get_class( $gateway ) : '';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in">
|
||||||
|
<!-- Toggle Button -->
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__toggle">
|
||||||
|
<button type="button" id="mail-in-toggle-button" class="tribe-tickets-commerce-gateway-mail-in__toggle-button">
|
||||||
|
<span class="toggle-icon">▶</span>
|
||||||
|
<?php esc_html_e( 'Click here to pay by mail (check)', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Hidden Content (Payment Instructions and Form) -->
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__content" id="mail-in-content" style="display: none;">
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__header">
|
||||||
|
<h4><?php echo esc_html( $gateway_class ? $gateway_class::get_label() : __( 'Mail-In Payment', 'event-tickets-mail-in' ) ); ?></h4>
|
||||||
|
<p class="tribe-tickets-commerce-gateway-mail-in__description">
|
||||||
|
<?php echo esc_html( $gateway_class ? $gateway_class::get_description() : __( 'Pay by mailing a check', 'event-tickets-mail-in' ) ); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__instructions">
|
||||||
|
<?php if ( $instructions ) : ?>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__instructions-text">
|
||||||
|
<strong><?php esc_html_e( 'Payment Instructions:', 'event-tickets-mail-in' ); ?></strong>
|
||||||
|
<p><?php echo wp_kses_post( nl2br( $instructions ) ); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__details">
|
||||||
|
<?php if ( $payable_to ) : ?>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__payable-to">
|
||||||
|
<strong><?php esc_html_e( 'Make Check Payable To:', 'event-tickets-mail-in' ); ?></strong>
|
||||||
|
<p class="tribe-tickets-commerce-gateway-mail-in__payable-to-name">
|
||||||
|
<?php echo esc_html( $payable_to ); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( $mailing_address ) : ?>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__address">
|
||||||
|
<strong><?php esc_html_e( 'Mail Your Check To:', 'event-tickets-mail-in' ); ?></strong>
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__address-block">
|
||||||
|
<?php echo wp_kses_post( nl2br( $mailing_address ) ); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tribe-tickets-commerce-gateway-mail-in__important-note">
|
||||||
|
<strong><?php esc_html_e( 'Important Notes:', 'event-tickets-mail-in' ); ?></strong>
|
||||||
|
<ul>
|
||||||
|
<li><?php esc_html_e( 'Please include your order number in the check memo line.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'Your tickets will be reserved while we wait for your payment to arrive.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
<li><?php esc_html_e( 'You will receive a confirmation email once your payment is processed.', 'event-tickets-mail-in' ); ?></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Gateway Selection Form -->
|
||||||
|
<form class="tribe-tickets__commerce-checkout-form tribe-tickets__commerce-checkout-form--mail-in" method="post">
|
||||||
|
<?php wp_nonce_field( 'tec_tickets_commerce_checkout', 'tec_tickets_commerce_checkout_nonce' ); ?>
|
||||||
|
<input type="hidden" name="tec_tc_gateway" value="mail-in" />
|
||||||
|
|
||||||
|
<!-- Purchaser Information -->
|
||||||
|
<div class="tribe-tickets__commerce-checkout-purchaser-info">
|
||||||
|
<h4><?php esc_html_e( 'Contact Information', 'event-tickets-mail-in' ); ?></h4>
|
||||||
|
|
||||||
|
<div class="tribe-tickets__commerce-checkout-form-field">
|
||||||
|
<label for="purchaser_name"><?php esc_html_e( 'Full Name', 'event-tickets-mail-in' ); ?> <span class="required">*</span></label>
|
||||||
|
<input type="text" id="purchaser_name" name="purchaser_name" required class="tribe-common-form-control-text__input" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tribe-tickets__commerce-checkout-form-field">
|
||||||
|
<label for="purchaser_email"><?php esc_html_e( 'Email Address', 'event-tickets-mail-in' ); ?> <span class="required">*</span></label>
|
||||||
|
<input type="email" id="purchaser_email" name="purchaser_email" required class="tribe-common-form-control-text__input" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tribe-tickets__commerce-checkout-form-submit">
|
||||||
|
<button
|
||||||
|
id="tec-tc-gateway-mail-in-checkout-button"
|
||||||
|
type="submit"
|
||||||
|
class="tribe-common-c-btn tribe-tickets__commerce-checkout-form-submit-button"
|
||||||
|
data-gateway="mail-in"
|
||||||
|
>
|
||||||
|
<?php esc_html_e( 'Place Order (Pay by Check)', 'event-tickets-mail-in' ); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div> <!-- End .tribe-tickets-commerce-gateway-mail-in__content -->
|
||||||
|
</div>
|
||||||
Loading…
Add table
Reference in a new issue