- 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
405 lines
No EOL
10 KiB
PHP
405 lines
No EOL
10 KiB
PHP
<?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' ) . '>',
|
|
];
|
|
}
|
|
} |