144 lines
7.3 KiB
PHP
144 lines
7.3 KiB
PHP
<?php
|
||
/**
|
||
* Plugin Name: Yoone Moneris Payments
|
||
* Description: 自定义 Moneris 支付网关,支持 WooCommerce Subscriptions 的令牌化与自动续费(占位实现,待接入 Moneris 实际 API)。
|
||
* Version: 0.1.0
|
||
* Author: Yoone
|
||
* Requires at least: 5.0
|
||
* Requires PHP: 7.4
|
||
* Requires Plugins: woocommerce
|
||
* WC requires at least: 6.0
|
||
* WC tested up to: 10.1.0
|
||
*/
|
||
// 以上为 WordPress 插件头部信息:
|
||
// - Plugin Name/Description/Version/Author 等会在后台插件列表展示;
|
||
// - Requires at least/Requires PHP 指定最低 WordPress/PHP 版本要求;
|
||
// - Requires Plugins: woocommerce 表示此插件依赖 WooCommerce;
|
||
// - WC requires at least / WC tested up to 提供与 WooCommerce 版本兼容性提示。
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
// 说明:这是 WordPress 的常量 ABSPATH(WP 根目录路径),未定义通常表示非 WP 环境直接访问 PHP 文件;
|
||
// 为安全起见,若未定义则退出,避免被直接访问执行。
|
||
}
|
||
|
||
/**
|
||
* 初始化插件
|
||
*/
|
||
function yoone_moneris_payments_init() {
|
||
if ( ! class_exists( 'WooCommerce' ) ) {
|
||
// add_action 是 WordPress 的动作钩子 API:在 'admin_notices' 钩子上注册一个回调,
|
||
// 该钩子用于在后台页面顶部显示提示信息;这里我们输出一条错误提示,提醒需要启用 WooCommerce。
|
||
add_action( 'admin_notices', function() {
|
||
echo '<div class="error"><p><strong>Yoone Moneris Payments 需要 WooCommerce 插件已启用。</strong></p></div>';
|
||
} );
|
||
// 由于 Woo 未启用,直接返回,不再继续初始化插件逻辑。
|
||
return;
|
||
}
|
||
|
||
// 加载常量/接口/工具与类:require_once 是 PHP 语句,确保文件仅加载一次;
|
||
// __DIR__ 是当前文件所在目录,拼接 includes 路径以找到类定义文件。
|
||
require_once __DIR__ . '/includes/constants/moneris.php';
|
||
require_once __DIR__ . '/includes/interfaces/class-yoone-moneris-api-interface.php';
|
||
require_once __DIR__ . '/includes/utils/logger.php';
|
||
require_once __DIR__ . '/includes/class-yoone-moneris-api.php';
|
||
require_once __DIR__ . '/includes/class-yoone-gateway-moneris.php';
|
||
|
||
// 注册到 WooCommerce 支付网关列表:add_filter 是 WordPress 的过滤器钩子 API,
|
||
// 'woocommerce_payment_gateways' 钩子在 Woo 初始化网关列表时触发,回调接收现有网关类名数组 $methods;
|
||
// 我们把自定义网关类名 'Yoone_Gateway_Moneris' 追加进去并返回。
|
||
add_filter( 'woocommerce_payment_gateways', function( $methods ) {
|
||
$methods[] = 'Yoone_Gateway_Moneris';
|
||
return $methods;
|
||
} );
|
||
}
|
||
// 在 WordPress 的 'plugins_loaded' 钩子上注册初始化函数:
|
||
// 'plugins_loaded' 在所有插件加载完成后触发,优先级 0 表示尽早执行;
|
||
// 这样可以保证 WooCommerce 已加载,从而我们的初始化逻辑能正确检测与注册网关。
|
||
add_action( 'plugins_loaded', 'yoone_moneris_payments_init', 0 );
|
||
|
||
/**
|
||
* 声明 HPOS 兼容(如启用)
|
||
*/
|
||
// 说明:HPOS(High-Performance Order Storage)是 WooCommerce 的高性能订单存储机制;
|
||
// 若站点启用该特性,插件需要声明兼容,避免因订单数据结构变化导致不兼容问题。
|
||
function yoone_moneris_declare_hpos_compat() {
|
||
if ( class_exists( '\\Automattic\\WooCommerce\\Utilities\\FeaturesUtil' ) ) {
|
||
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
|
||
}
|
||
}
|
||
// 在 WooCommerce 初始化前('before_woocommerce_init' 钩子)注册兼容性声明函数:
|
||
// 该钩子在 Woo 启动早期触发,确保 Woo 在初始化过程中已经知道本插件对 HPOS 的兼容性。
|
||
add_action( 'before_woocommerce_init', 'yoone_moneris_declare_hpos_compat' );
|
||
|
||
/**
|
||
* 检测是否使用了 WooCommerce Blocks 结账但当前网关未提供 Blocks 集成,提示管理员。
|
||
*/
|
||
function yoone_moneris_blocks_checkout_admin_notice() {
|
||
if ( ! class_exists( 'WooCommerce' ) ) {
|
||
return;
|
||
}
|
||
// 仅在后台提示
|
||
if ( ! is_admin() ) {
|
||
return;
|
||
}
|
||
|
||
// 网关是否启用
|
||
$settings = get_option( 'woocommerce_yoone_moneris_settings', array() );
|
||
$enabled = isset( $settings['enabled'] ) ? $settings['enabled'] : 'no';
|
||
if ( 'yes' !== $enabled ) {
|
||
return;
|
||
}
|
||
|
||
// 检查结账页是否为 Blocks 结账
|
||
$checkout_id = function_exists( 'wc_get_page_id' ) ? wc_get_page_id( 'checkout' ) : 0;
|
||
if ( $checkout_id && function_exists( 'has_block' ) ) {
|
||
$post = get_post( $checkout_id );
|
||
if ( $post && has_block( 'woocommerce/checkout', $post ) ) {
|
||
// 当前插件未提供 Blocks 前端集成,因此 Blocks 结账不会显示本网关
|
||
add_action( 'admin_notices', function() {
|
||
echo '<div class="notice notice-warning"><p>Yoone Moneris Payments 当前未集成 WooCommerce Blocks 结账。如果你的结账页使用了 Blocks,请改用经典结账(在结账页添加短代码 [woocommerce_checkout] 并在 WooCommerce → 设置 → 高级 中设置该页面为结账页),或联系开发者添加 Blocks 集成。</p></div>';
|
||
} );
|
||
}
|
||
}
|
||
}
|
||
add_action( 'admin_init', 'yoone_moneris_blocks_checkout_admin_notice' );
|
||
|
||
/**
|
||
* Blocks 结账支付方式集成:注册脚本、向前端暴露设置、注册支付方式类型。
|
||
*/
|
||
function yoone_moneris_blocks_bootstrap() {
|
||
// 仅当 WooCommerce Blocks 环境可用时进行注册
|
||
if ( ! class_exists( '\\Automattic\\WooCommerce\\Blocks\\Payments\\PaymentMethodRegistry' ) ) {
|
||
return;
|
||
}
|
||
|
||
// 注册前端脚本(不打包版本,依赖 Blocks 与 WP 提供的全局模块)
|
||
$asset_deps = array( 'wc-blocks-registry', 'wc-settings', 'wp-element', 'wp-i18n' );
|
||
wp_register_script(
|
||
'yoone-moneris-blocks',
|
||
plugins_url( 'yoone-moneris-payments/assets/js/blocks/moneris.js', dirname(__FILE__) ),
|
||
$asset_deps,
|
||
'1.0.0',
|
||
true
|
||
);
|
||
|
||
// 暴露网关基础设置到前端 wcSettings
|
||
$settings = get_option( 'woocommerce_yoone_moneris_settings', array() );
|
||
$data = array(
|
||
'title' => isset( $settings['title'] ) ? (string) $settings['title'] : __( 'Credit Card (Moneris)', 'yoone-moneris' ),
|
||
'enabled' => isset( $settings['enabled'] ) && 'yes' === strtolower( (string) $settings['enabled'] ),
|
||
'sandbox' => isset( $settings['sandbox'] ) ? (string) $settings['sandbox'] : 'yes',
|
||
'currency' => function_exists( 'get_woocommerce_currency' ) ? get_woocommerce_currency() : 'CAD',
|
||
);
|
||
wp_add_inline_script( 'yoone-moneris-blocks', 'window.wcSettings = window.wcSettings || {}; window.wcSettings.yooneMonerisData = ' . wp_json_encode( $data ) . ';', 'before' );
|
||
|
||
// 注册 Blocks 支付方式类型(在 Blocks 类型存在时才注册,避免类未定义导致致命错误)
|
||
require_once __DIR__ . '/includes/blocks/class-yoone-blocks-moneris.php';
|
||
add_action( 'woocommerce_blocks_payment_method_type_registration', function( $payment_method_registry ) {
|
||
if ( class_exists( 'Yoone_Moneris_Blocks_Payment_Method' ) ) {
|
||
$payment_method_registry->register( new Yoone_Moneris_Blocks_Payment_Method() );
|
||
}
|
||
} );
|
||
}
|
||
add_action( 'woocommerce_blocks_loaded', 'yoone_moneris_blocks_bootstrap' ); |