woo-alipay/inc/class-wc-alipay-order-timeout.php
feibisi 7d99b65289 Add Alipay FaceToPay and Huabei gateways
Introduces new WooCommerce payment gateways for Alipay FaceToPay (QR code) and Alipay Installment (Huabei), including frontend styles, JS, PHP gateway classes, Blocks support, and SDK helpers. Enables QR code payments, installment selection, order status polling, and admin configuration for both gateways.
2025-10-04 06:42:11 +08:00

235 lines
5.7 KiB
PHP

<?php
/**
* Alipay Order Timeout Class
*
* Handles automatic cancellation of unpaid orders
*
* @package Woo_Alipay
* @since 3.3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
class WC_Alipay_Order_Timeout {
/**
* Default timeout duration in minutes
*/
const DEFAULT_TIMEOUT = 30;
/**
* Constructor
*/
public function __construct() {
$this->init_hooks();
}
/**
* Initialize hooks
*/
private function init_hooks() {
// Schedule cron job for checking timeout orders
add_action( 'wp', array( $this, 'schedule_timeout_check' ) );
add_action( 'woo_alipay_check_timeout_orders', array( $this, 'check_timeout_orders' ) );
// Add timeout info to order
add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_timeout_meta' ), 10, 3 );
}
/**
* Schedule cron job
*/
public function schedule_timeout_check() {
$gateway = $this->get_gateway();
// Check if feature is enabled
if ( ! $gateway || 'yes' !== $gateway->get_option( 'enable_order_timeout', 'yes' ) ) {
// Unschedule if disabled
$timestamp = wp_next_scheduled( 'woo_alipay_check_timeout_orders' );
if ( $timestamp ) {
wp_unschedule_event( $timestamp, 'woo_alipay_check_timeout_orders' );
}
return;
}
if ( ! wp_next_scheduled( 'woo_alipay_check_timeout_orders' ) ) {
// Check every 10 minutes
wp_schedule_event( time(), 'woo_alipay_10min', 'woo_alipay_check_timeout_orders' );
}
}
/**
* Check timeout orders
*/
public function check_timeout_orders() {
$gateway = $this->get_gateway();
// Check if feature is enabled
if ( ! $gateway || 'yes' !== $gateway->get_option( 'enable_order_timeout', 'yes' ) ) {
return;
}
$timeout = $this->get_timeout_duration();
// Get pending/on-hold Alipay orders
$args = array(
'status' => array( 'pending', 'on-hold' ),
'payment_method' => 'alipay',
'limit' => 100,
'orderby' => 'date',
'order' => 'ASC',
'date_created' => '<' . ( time() - $timeout * 60 ), // Orders older than timeout duration
);
$orders = wc_get_orders( $args );
foreach ( $orders as $order ) {
$this->cancel_timeout_order( $order );
}
}
/**
* Cancel timeout order
*
* @param WC_Order $order
* @return bool
*/
private function cancel_timeout_order( $order ) {
if ( ! $order || $order->is_paid() ) {
return false;
}
// Check if order has timeout meta
$timeout_time = $order->get_meta( '_alipay_timeout_time' );
if ( $timeout_time && time() < $timeout_time ) {
// Not timeout yet
return false;
}
// Check if order was sent to Alipay
$out_trade_no = $order->get_meta( 'alipay_initalRequest' );
if ( empty( $out_trade_no ) ) {
// Order wasn't sent to Alipay, safe to cancel
$order->update_status(
'cancelled',
__( 'Order cancelled due to payment timeout (not sent to Alipay)', 'woo-alipay' )
);
$this->log( 'Order #' . $order->get_id() . ' cancelled due to timeout (not sent to Alipay)' );
return true;
}
// Order was sent to Alipay, query status first before cancelling
if ( class_exists( 'WC_Alipay_Order_Query' ) ) {
$query = new WC_Alipay_Order_Query();
$result = $query->query_single_order_status( $order );
// Reload order after query
$order = wc_get_order( $order->get_id() );
if ( $order->is_paid() ) {
// Payment was completed
$this->log( 'Order #' . $order->get_id() . ' was paid, not cancelling' );
return false;
}
}
// Cancel the order
$order->update_status(
'cancelled',
sprintf(
__( 'Order cancelled due to payment timeout (%d minutes)', 'woo-alipay' ),
$this->get_timeout_duration()
)
);
$this->log( 'Order #' . $order->get_id() . ' cancelled due to timeout' );
// Trigger action for other plugins
do_action( 'woo_alipay_order_timeout_cancelled', $order );
return true;
}
/**
* Add timeout meta to order
*
* @param int $order_id
* @param array $posted_data
* @param WC_Order $order
*/
public function add_timeout_meta( $order_id, $posted_data, $order ) {
if ( $order->get_payment_method() !== 'alipay' ) {
return;
}
$gateway = $this->get_gateway();
// Check if feature is enabled
if ( ! $gateway || 'yes' !== $gateway->get_option( 'enable_order_timeout', 'yes' ) ) {
return;
}
$timeout = $this->get_timeout_duration();
$timeout_time = time() + ( $timeout * 60 );
$order->update_meta_data( '_alipay_timeout_time', $timeout_time );
$order->update_meta_data( '_alipay_timeout_duration', $timeout );
$order->save();
}
/**
* Get timeout duration from settings
*
* @return int Timeout duration in minutes
*/
private function get_timeout_duration() {
$gateway = $this->get_gateway();
if ( ! $gateway ) {
return self::DEFAULT_TIMEOUT;
}
$timeout = $gateway->get_option( 'order_timeout', self::DEFAULT_TIMEOUT );
return absint( $timeout ) > 0 ? absint( $timeout ) : self::DEFAULT_TIMEOUT;
}
/**
* Get gateway instance
*
* @return WC_Alipay|null
*/
private function get_gateway() {
$gateways = WC()->payment_gateways->payment_gateways();
return isset( $gateways['alipay'] ) ? $gateways['alipay'] : null;
}
/**
* Log message
*
* @param string $message
* @param string $level
*/
private function log( $message, $level = 'info' ) {
$gateway = $this->get_gateway();
if ( $gateway && method_exists( $gateway, 'get_option' ) ) {
$log_enabled = ( 'yes' === $gateway->get_option( 'debug', 'no' ) );
if ( $log_enabled ) {
$logger = wc_get_logger();
$logger->log( $level, $message, array( 'source' => 'alipay-timeout' ) );
}
}
}
}
// Initialize the class
new WC_Alipay_Order_Timeout();