HEX
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/7.4.30
System: Linux iZj6c1151k3ad370bosnmsZ 3.10.0-1160.76.1.el7.x86_64 #1 SMP Wed Aug 10 16:21:17 UTC 2022 x86_64
User: root (0)
PHP: 7.4.30
Disabled: NONE
Upload Files
File: /var/www/html/breadsecret.com/wp-content/plugins/wc-ionlinepay-alipayhk/wc-ionlinepay-alipayhk.php
<?php
/*
 * Plugin Name: iOnlinePay AlipayHK Payment Gateway for WooCommerce
 * Description: Receive Payment from Hong Kong Buyers via AlipayHK Payment Gateway
 * Author: iOnline Pay
 * Author URI: https://www.ionline.com.hk
 * Version: 1.0.0
 */

defined( 'ABSPATH' ) || exit;

/**
 * Add the gateway to iOnlinePay Available Gateways
 */
function wc_ionlinepay_alipayhk_add_to_gateways( $gateways ) {
	$gateways[] = 'WC_Gateway_Ionlinepay_AlipayHK';
	return $gateways;
}
add_filter( 'woocommerce_payment_gateways', 'wc_ionlinepay_alipayhk_add_to_gateways' );



function plugin_row_meta_ionlinepay_alipayhk( $links, $plugin_file_name ) {

	if( strpos( $plugin_file_name, basename(__FILE__) ) ) {	
		$row_meta = array(
			'docs'    => '<a href="' . esc_url( apply_filters( 'ionlinepay_merchant_registration_url', 'https://www.ionlinepay.com/registration?source=wc_plugin' ) ) . '" aria-label="' . esc_attr__( 'Register a Merchant Account', 'ionlinepay' ) . '">' . esc_html__( 'Register a Merchant Account', 'ionlinepay' ) . '</a>',
			'apidocs' => '<a href="' . esc_url( apply_filters( 'ionlinepay_api_doc_url', 'https://www.ionlinepay.com/doc?source=wc_plugin' ) ) . '" aria-label="' . esc_attr__( 'View iOnlinePay API docs', 'ionlinepay' ) . '">' . esc_html__( 'API docs', 'ionlinepay' ) . '</a>',
			'support' => '<a href="' . esc_url( apply_filters( 'ionlinepay_support_url', 'mailto:info@o2opayment.com?subject=Enquiry: WooCommerce iOnlinePay AlipayHK Plugin' ) ) . '" aria-label="' . esc_attr__( 'Contact Us', 'ionlinepay' ) . '">' . esc_html__( 'Contact Us', 'ionlinepay' ) . '</a>',
		);

		return array_merge( $links, $row_meta );
	}

	return (array) $links;
}
add_filter( 'plugin_row_meta', 'plugin_row_meta_ionlinepay_alipayhk', 10, 2 );


/**
 * Adds plugin page links
 * 
 * @since 1.0.0
 * @param array $links all plugin links
 * @return array $links all plugin links + our custom links (i.e., "Settings")
 */
function wc_ionlinepay_alipayhk_gateway_plugin_links( $links ) {
	$plugin_links = array(
		'<a href="' . admin_url( 'admin.php?page=wc-settings&tab=checkout&section=ionlinepay_alipayhk' ) . '">' . __( 'Configure', 'ionlinepay' ) . '</a>'
	);
	return array_merge( $plugin_links, $links );
}
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), 'wc_ionlinepay_alipayhk_gateway_plugin_links' );

add_action( 'plugins_loaded', 'wc_ionlinepay_alipayhk_gateway_init', 11 );
function wc_ionlinepay_alipayhk_gateway_init() {
	
	if(!class_exists('WC_Payment_Gateway')) return;
	/**
	 * WC_Gateway_Ionlinepay_AlipayHK Class.
	 */
	class WC_Gateway_Ionlinepay_AlipayHK extends WC_Payment_Gateway {

		/**
		 * Payment Mode: Auto, PC or WAP
		 *
		 * @var bool
		 */
		public static $payment_mode = 'auto';

		/**
		 * Whether or not logging is enabled
		 *
		 * @var bool
		 */
		public static $log_enabled = false;

		/**
		 * Logger instance
		 *
		 * @var WC_Logger
		 */
		public static $log = false;


		/**
		 * Constructor for the gateway.
		 */
		public function __construct() {
			$this->id                = 'ionlinepay_alipayhk';
			$this->has_fields        = false;
			$this->order_button_text = __( 'Proceed to AlipayHK', 'ionlinepay' );
			$this->method_title      = __( 'AlipayHK (powered by iOnlinePay)', 'ionlinepay' );
			/* translators: %s: Link to WC system status page */
			$this->method_description = __( 'AlipayHK WAP Payment redirects customers to AlipayHK checkout page to enter their payment information.', 'ionlinepay' );
			$this->supports           = array(
				// 'products',
				// 'refunds',
			);

			// Load the settings.
			$this->init_form_fields();
			$this->init_settings();

			// Define user set variables.
			$this->title          = $this->get_option( 'title' );
			$this->description    = $this->get_option( 'description' );
			$this->testmode       = 'yes' === $this->get_option( 'testmode', 'no' );
			$this->debug          = 'yes' === $this->get_option( 'debug', 'no' );

			self::$log_enabled    = $this->debug;
			self::$payment_mode    = $this->get_option( 'paymentmode', 'auto' );
			if ( $this->testmode ) {
				$this->description .= ' ' . __( 'SANDBOX ENABLED. You can use sandbox testing account only.', 'ionlinepay' );
				$this->description  = trim( $this->description );
			}

			
			add_action( 'admin_enqueue_scripts', array( $this, 'admin_scripts' ) );
			add_action( 'woocommerce_update_options_payment_gateways_' . $this->id, array( $this, 'process_admin_options' ) );
			add_action( 'woocommerce_api_ionlinepay-alipayhk-notify-callback', array( $this, 'notify_callback' ) );
		}

		/**
		 * Logging method.
		 *
		 * @param string $message Log message.
		 * @param string $level Optional. Default 'info'. Possible values:
		 *                      emergency|alert|critical|error|warning|notice|info|debug.
		 */
		public static function log( $message, $level = 'info' ) {
			if ( self::$log_enabled ) {
				if ( empty( self::$log ) ) {
					self::$log = wc_get_logger();
				}
				self::$log->log( $level, $message, array( 'source' => 'ionlinepay_alipayhk' ) );
			}
		}

		/**
		 * Processes and saves options.
		 * If there is an error thrown, will continue to save and validate fields, but will leave the erroring field out.
		 *
		 * @return bool was anything saved?
		 */
		public function process_admin_options() {
			$saved = parent::process_admin_options();

			// Maybe clear logs.
			if ( 'yes' !== $this->get_option( 'debug', 'no' ) ) {
				if ( empty( self::$log ) ) {
					self::$log = wc_get_logger();
				}
				self::$log->clear( 'ionlinepay_alipayhk' );
			}

			return $saved;
		}

		/**
		 * Get gateway icon.
		 *
		 * @return string
		 */
		public function get_icon() {
			$icon_html = '<img src="https://www.ionlinepay.com/doc/images/alipayhk.png" />';
			return apply_filters( 'woocommerce_gateway_icon', $icon_html, $this->id );
		}

		/**
		 * Check if this gateway is enabled and available in the user's country.
		 *
		 * @return bool
		 */
		public function is_valid_for_use() {
			return in_array(
				get_woocommerce_currency(),
				apply_filters(
					'woocommerce_ionlinepay_alipayhk_supported_currencies',
					array( 'HKD')
				),
				true
			);
		}




		/**
		 * Admin Panel Options.
		 * - Options for bits like 'title' and availability on a country-by-country basis.
		 *
		 * @since 1.0.0
		 */
		public function admin_options() {
			if ( $this->is_valid_for_use() ) {
				parent::admin_options();
			} else {
				?>
				<div class="inline error">
					<p>
						<strong><?php esc_html_e( 'Gateway disabled', 'ionlinepay' ); ?></strong>: <?php esc_html_e( 'iOnline Pay AlipayHK does not support your store currency.', 'ionlinepay' ); ?>
					</p>
				</div>
				<?php
			}
		}



		/**
		 * Initialise Gateway Settings Form Fields.
		 */
		public function init_form_fields() {
			$this->form_fields = include 'includes/settings-wc-ionlinepay-alipayhk.php';
		}


		/**
		 * Load admin scripts.
		 *
		 * @since 3.3.0
		 */
		public function admin_scripts() {
			$screen    = get_current_screen();
			$screen_id = $screen ? $screen->id : '';

			if ( 'woocommerce_page_wc-settings' !== $screen_id ) {
				return;
			}

			// $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
			$suffix = '';
			wp_enqueue_script( 'woocommerce_ionlinepay_alipayhk_admin', plugins_url('wc-ionlinepay-alipayhk') .'/assets/js/ionlinepay-admin' . $suffix . '.js', array(), WC_VERSION, true );
		}




		/**
		 * Init the API class and set the username/password etc.
		 */
		protected function init_api() {
			include_once dirname( __FILE__ ) . '/includes/class-wc-gateway-ionlinepay-alipayhk-api-handler.php';

			WC_Gateway_Ionlinepay_AlipayHK_API_Handler::$api_username  = $this->testmode ? $this->get_option( 'sandbox_api_username' ) : $this->get_option( 'api_username' );
			WC_Gateway_Ionlinepay_AlipayHK_API_Handler::$api_signature = $this->testmode ? $this->get_option( 'sandbox_api_signature' ) : $this->get_option( 'api_signature' );
			WC_Gateway_Ionlinepay_AlipayHK_API_Handler::$sandbox       = $this->testmode;
		}		


		/**
		 * Process the payment and return the result.
		 *
		 * @param  int $order_id Order ID.
		 * @return array
		 */
		public function process_payment( $order_id ) {
			

			$this->init_api();
			$order          = wc_get_order( $order_id ); 
			$api_result = WC_Gateway_Ionlinepay_AlipayHK_API_Handler::get_alipayhk_pay_url( $order, $this );

			if( !isset($api_result['pay_url']) || $api_result['pay_url']=='' || !isset($api_result['out_trade_no']) || $api_result['out_trade_no']=='' ) {
				return array(
					'result'   => 'failure',
				);
			} 
			else {

				add_post_meta( $order_id, 'ionlinepay_out_trade_no', $api_result['out_trade_no']);

				return array(
					'result'   => 'success',
					'redirect' => $api_result['pay_url'],
				);
			}
		}


		public function notify_callback() {

			$raw_post_data = file_get_contents("php://input"); 
			$xmlObject = simplexml_load_string($raw_post_data, 'SimpleXMLElement', LIBXML_NOCDATA, '', false);
			$jsonArray = json_decode(json_encode($xmlObject), true);
			$this->init_api();

			$this->log($raw_post_data);
			$this->log(json_encode($xmlObject, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));

			//TODO: verify json data
			if( WC_Gateway_Ionlinepay_AlipayHK_API_Handler::verify_sign( $jsonArray ) != true ) {

				die('invalid_sign');
			}
			else {
				if($jsonArray['status']=='0' && $jsonArray['result_code']=='0' && $jsonArray['pay_result']=='0') {

					//TODO: update WC order status
					//Merchant system should check if this record has been processed before in order to avoid duplicate payment
					//After processing, merchant system acknowledges to the payment gateway system by returning the plain text "success"
					$out_trade_no = $jsonArray['out_trade_no'];
					$fee_type = $jsonArray['fee_type'];
					$total_fee = $jsonArray['total_fee'];
					$out_transaction_id = $jsonArray['out_transaction_id'];

					$args = array( 
					  'meta_key' => 'ionlinepay_out_trade_no', 
					  'meta_value' => $out_trade_no, 
					  'meta_compare' => '=' 
					);
					$wc_orders = wc_get_orders($args);
					//`out_trade_no` must be an unique id to identify a WC Order. If two or more WC Orders have the same `out_trade_no` value, there should be some errors.
					$order = ($wc_orders && sizeof($wc_orders)==1) ? $wc_orders[0]: false; 

					if ( $order ) {

						if($order->is_paid() == false ) {

							if( $fee_type==$order->get_currency() && $total_fee==($order->get_total()*100) ) {
								update_post_meta( $order->get_id(), 'ionlinepay_notify_time', date('Y-m-d h:i:s') );
								update_post_meta( $order->get_id(), 'ionlinepay_notify_out_trade_no', wc_clean($out_trade_no) );
								update_post_meta( $order->get_id(), 'ionlinepay_notify_out_transaction_id', wc_clean($out_transaction_id) );
								$order->add_order_note( __( 'AlipayHK Payment completed (iOnlinePay)', 'ionlinepay' ) );
								$order->payment_complete( $out_transaction_id );

								$this->log( 'Receive Notification of Order #' . $order->get_id() );

								die('success');

							}
							else {
								$this->log( 'Found order #' . $order->get_id() 
									.' ; but currency/total_fee not match: '. $order->get_currency().' vs '. $fee_type
									.' ; '. ($order->get_total()*100) .' vs '. $total_fee
									);
								die('fail_order_amount_not_match');	
							}
						}
						else {
							$this->log( 'Found order #' . $order->get_id() .' already paid.');

							die('fail_already_paid');	
						}
											
					}				
					else {

						$this->log( 'Order Not Found by out_trade_no: ' . $out_trade_no );
						die('fail_order_not_found');	
					}	
					
				}
				else {
					//for other reasons that couldn't process the order information, your system should return the plain text "fail" or other text except "success"
					die('fail');
				}
			}
		}
	}
}