event-tickets-mail-in-payment/src/Hooks.php
Ruben Ramirez 8fd8d9708c 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
2025-06-30 21:56:49 -04:00

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' ) . '>',
];
}
}