<?php
if (!class_exists('PPO_Pay')) {
    class PPO_Pay {

        public function __construct(){
        
            add_action('wp_ajax_push_ppo_pay', array($this, 'push_ppo_pay'));
            add_action('wp_ajax_pay_interval', array($this, 'pay_interval'));
                   
        }

        public static function pay_btn_base($mode='post'){
            $alipay_enabled = get_op('alipay_type', '0') !== '0';
            $wepay_enabled = get_op('wepay_type', '0') !== '0';
            $cash_data = PPO_Down::pay_icon('cash');

            $html = '<div class="pay-type-inner">';
            if ($alipay_enabled) {
                $html .= '<div class="pay-type-btn" type-data="alipay"><i class="ri-alipay-fill"></i>支付宝</div>';
            }
            if ($wepay_enabled) {
                $html .= '<div class="pay-type-btn" type-data="wepay"><i class="ri-wechat-pay-fill"></i>微信</div>';
            }
            if($mode !== 'yecz'){
                $html .= '<div class="pay-type-btn" type-data="balance"><i class="ri-wallet-3-fill"></i>'.esc_html($cash_data['name']).'</div>';
            }
            $html .= '</div>';

            return $html;
        }

        public static function pay_type_btn(){
            $html = '<div class="pay-type-box">';
            $html .= self::pay_btn_base();
            $html .= '<div class="pay-push-btn"><div class="agree-price">同意并支付：<span></span></div><a class="pay-sure-btn" mode="vip" data="" pay_type="">立即支付</a></div>';
            $html .= '</div>';

            return $html;
        }

        public static function dd_pay_btn($pay_type,$uid,$mode='post'){
            $type = 'credit';
            //$mode = $mode ?? 'post';
            $balance = get_user_balance($uid);
            $icon = PPO_Down::pay_icon($pay_type);
            $html = '<div class="pay-type-box dd-pay">';
            if($pay_type == 'cash'){
                $html .= '<div class="balance-left"><div class="value">您当前的'.$icon['name'].'为'.$icon['icon'].$balance.'</div><a class="charge">前往充值</a></div>';
                $html .= self::pay_btn_base($mode);
                $type = '';
            }
            $html .= '<div class="pay-push-btn"><a class="pay-sure-btn" mode="'.$mode.'" data="" pay_type="'.$type.'">确认支付</a></div>';
            $html .= '</div>';

            return $html;
        }

        // 支付协议
        public static function vip_protocol(){
            $html = '';
        }

        // 支付回调页面
        public static function pay_notify_page($type){
            $url = home_url('/'.$type);
            return $url;
        }

        private static function trim_config_value($value){
            return trim((string)$value, " \t\n\r\0\x0B\xC2\xA0");
        }

        private static function pay_config_value($key, $default = ''){
            $config = get_op('pay_config');
            if (!is_array($config) || !array_key_exists($key, $config)) {
                return $default;
            }

            return $config[$key];
        }

        private static function yipay_config(){
            return array(
                'pid' => self::trim_config_value(self::pay_config_value('yipay_appid')),
                'secret' => self::trim_config_value(self::pay_config_value('yipay_secret')),
                'url' => rtrim(self::trim_config_value(self::pay_config_value('yipay_url')), '/'),
            );
        }

        private static function xunhu_channel_settings($pay_type_info){
            if ($pay_type_info === 'wepay_hupijiao') {
                return array(
                    'appid' => self::trim_config_value(self::pay_config_value('wepay_hupijiao_appid')),
                    'appsecret' => self::pay_config_value('wepay_hupijiao_appsecret'),
                    'geteway' => self::trim_config_value(self::pay_config_value('hupijiao_gateway')),
                    'payment' => 'wechat',
                );
            }

            if ($pay_type_info === 'alipay_hupijiao') {
                return array(
                    'appid' => self::trim_config_value(self::pay_config_value('alipay_hupijiao_appid')),
                    'appsecret' => self::pay_config_value('alipay_hupijiao_appsecret'),
                    'geteway' => self::trim_config_value(self::pay_config_value('hupijiao_geteway')),
                    'payment' => 'alipay',
                );
            }

            return array(
                'appid' => '',
                'appsecret' => '',
                'geteway' => '',
                'payment' => '',
            );
        }
	

        // 获取当前使用的支付平台
        public static function pay_type($type){

            if($type == 'alipay'){
                $alipay_type = get_op('alipay_type');
                return array(
                    'use' => 'alipay',
                    'type' => $alipay_type
                );			
            } else if($type == 'wepay'){
                $wepay_type = get_op('wepay_type');
                return array(
                    'use' => 'wepay',
                    'type' => $wepay_type
                );	
            }else if($type == 'balance'){
                return array(
                    'use' => 'balance',
                    'type' => 'balance'
                );
            } else if($type == 'credit'){
                return array(
                    'use' => 'credit',
                    'type' => 'credit'
                );
            } else {
                return array(
                    'error' => '未知的支付类型'
                );
            }
        }

        // 判断扫码还是跳转
        public static function pay_jump($type){
            $type = self::pay_type($type);
            $pay_api = get_op('pay_config');
            $is_mobile = wp_is_mobile();
            switch ($type['type']) {
                case 'alipay_normal':
                    $alipay_type = $pay_api['alipay_normal_type'];
                    if($alipay_type === 'alipay_normal'){
                        $pay_type = 'jump';
                    }else if(!$is_mobile){
                        $pay_type = 'scan';
                    }else{
                        $pay_type = 'jump';
                    }
                    break;
                case 'yipay':
                    $pay_type = 'jump';
                    break;
                case 'alipay_hupijiao':
                case 'wepay_hupijiao':
                    if($is_mobile){
                        $pay_type = 'jump';
                    }else{
                        $pay_type = 'scan';
                    }
                    break;
                case 'balance':
                    $pay_type = 'balance';
                    break;	
                case 'credit':
                    $pay_type = 'credit';
                    break;			
            }

            $data = array(
                'jump' => $pay_type,
            );
    
            return $data;
        }

        // 调用支付接口
        public static function ppo_pay($data){
            $pay_type = self::pay_type($data['pay_type']);
            if(isset($pay_type['error'])) return $data;

            if(isset($data['pay_type'])){
                $type = $pay_type['type'];
                return self::$type($data);
            
            }
        }

        // 检查支付接口类型 防止篡改
        public static function check_pay_type($data){
            $pay_type = $data['pay_type'];
            $_pay_type = PPO_Down::dd_pay_type($data['data_id']);
            $mode = $data['mode'];
            $arr = array('alipay','wepay','balance');
            if (in_array($mode, array('jfcz', 'yecz'), true)) {
                $charge_allowed = $mode === 'yecz' ? array('alipay', 'wepay') : array('alipay', 'wepay', 'balance');
                if (!in_array($pay_type, $charge_allowed, true)) {
                    return array('error' => '未知的支付类型');
                }
                if ($pay_type === 'alipay' && get_op('alipay_type', '0') === '0') {
                    return array('error' => '支付宝支付已关闭');
                }
                if ($pay_type === 'wepay' && get_op('wepay_type', '0') === '0') {
                    return array('error' => '微信支付已关闭');
                }
                return;
            }
            if($mode == 'vip' || $_pay_type == 'cash') {
                if(!in_array($pay_type,$arr)){
                    return array('error' => '未知的支付类型');
                }
                if ($pay_type === 'alipay' && get_op('alipay_type', '0') === '0') {
                    return array('error' => '支付宝支付已关闭');
                }
                if ($pay_type === 'wepay' && get_op('wepay_type', '0') === '0') {
                    return array('error' => '微信支付已关闭');
                }
            } else if($_pay_type == 'credit'){
                if($pay_type != $_pay_type){
                    return array('error' => '未知的支付类型');
                }
            }
        }

        // 拉起支付
        public static function push_ppo_pay(){
            if (!is_user_logged_in()) {
                wp_send_json(array('error' => '请先登录'));
            }

            check_ajax_referer('ppo_pay_action', 'nonce');

            $current_user = wp_get_current_user();
            $user_id = $current_user->ID;
            $rate_limit = self::check_order_create_rate_limit($user_id);
            if (is_wp_error($rate_limit)) {
                wp_send_json(array('error' => $rate_limit->get_error_message()));
            }

            $mode = isset($_POST['mode']) ? sanitize_key($_POST['mode']) : ''; //付费类型 文章购买 VIP 充值
            $data_id = isset($_POST['data_id']) ? intval($_POST['data_id']) : 0;  // vip_id,post_id 
            $data_id = isset($_POST['data_id']) ? intval($_POST['data_id']) : 0;
            $pay_type = isset($_POST['pay_type']) ? sanitize_key($_POST['pay_type']) : ''; // 支付类型 alipay wepay balance credit
            //$order_id = $_POST['order_id'] ? $_POST['order_id'] : ''; //支付订单

            //$_pay_type = PPO_Down::dd_pay_type($data_id);
            $pay_type_info = self::pay_type($pay_type);
            if (isset($pay_type_info['error'])) {
                wp_send_json(array('error' => $pay_type_info['error']));
            }
            // 订单数据
            $order_data = array(
                'mode' => $mode,
                'data_id' => $data_id,
                'pay_type' => $pay_type,
                'order_id' => '',
                'user_id'      => $user_id,
                'pay_type_info' => $pay_type_info['type'],
                'order_address' => isset($_POST['order_email']) ? sanitize_email($_POST['order_email']) : '',
                'return' => '',
            );

            $check = self::check_pay_type($order_data);
            if(isset($check['error'])){
                wp_send_json(array('error' => $check['error']));
            }

            if($mode == 'vip'){
                $order_data['order_extra'] = isset($_POST['vip_item']) ? sanitize_text_field(wp_unslash($_POST['vip_item'])) : ''; //vip项目
                $pay_rurl = home_url('/user/'.$user_id);
                $vip_arr = self::vip_pay_data($order_data);
                $order_data = array_merge($order_data,$vip_arr);
            } else if($mode == 'post') {
                $post_arr = PPO_Down::dd_pay_data($data_id);
                $pay_rurl = get_the_permalink( $data_id );
                $order_data = array_merge($order_data,$post_arr);
            } else if($mode == 'mj'){
                $mj_item = isset($_POST['mj_item']) ? sanitize_text_field(wp_unslash($_POST['mj_item'])) : ''; 
                $order_data['order_extra'] = $mj_item;
                $mj_data = get_mj_data($data_id,$mj_item);
                $pay_rurl = get_term_link( (int)$data_id , 'moments');
                $order_data = array_merge($order_data,$mj_data);
            } else if($mode == 'jfcz' || $mode == 'yecz'){
                $pay_value = isset($_POST['pay_value']) ? floatval($_POST['pay_value']) : 0;
                $charge_check = pix_validate_charge_amount($mode, $pay_value, $user_id);
                if (is_wp_error($charge_check)) {
                    wp_send_json(array('error' => $charge_check->get_error_message()));
                }
                $pay_value = $charge_check['amount'];
                $pay_rurl = home_url('/dashboard/wallet');
                $charge_data = get_charge_pay_data($mode,$pay_value);
                $order_data = array_merge($order_data,$charge_data);
            } else {
                wp_send_json(array('error' => '未知的支付场景'));
            }

            $order_data = array_merge($order_data, self::build_order_snapshot($order_data, $current_user));

            setcookie("pay_rurl", $pay_rurl, time()+3600*24*1,"/");

            $jump = self::pay_jump($pay_type);
		    $order_data['jump'] = $jump['jump'];

            $res = self::create_pay_order($order_data);
            $order_data['order_id'] = $res['order_id'];

            $_data = self::ppo_pay($order_data);
            if(isset($_data['error'])){
                wp_send_json(array('error' => $_data['error']));
            }
            $order_data['url'] = $_data['url'];

            wp_send_json($order_data);

        }

        private static function check_order_create_rate_limit($user_id){
            global $wpdb;
            $table_name = $wpdb->prefix . 'ppo_pay_order';
            $minute_limit = max(1, intval(apply_filters('ppo_pay_order_minute_limit', 6, $user_id)));
            $hour_limit = max($minute_limit, intval(apply_filters('ppo_pay_order_hour_limit', 30, $user_id)));
            $now = current_time('timestamp');
            $minute_start = date('Y-m-d H:i:s', $now - 60);
            $hour_start = date('Y-m-d H:i:s', $now - 3600);

            $minute_count = intval($wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM $table_name WHERE user_id = %d AND create_time >= %s",
                $user_id,
                $minute_start
            )));
            if ($minute_count >= $minute_limit) {
                return new WP_Error('order_rate_limited', '订单创建过于频繁，请稍后再试');
            }

            $hour_count = intval($wpdb->get_var($wpdb->prepare(
                "SELECT COUNT(*) FROM $table_name WHERE user_id = %d AND create_time >= %s",
                $user_id,
                $hour_start
            )));
            if ($hour_count >= $hour_limit) {
                return new WP_Error('order_rate_limited', '订单创建次数过多，请稍后再试');
            }

            return true;
        }
        

        //创建支付订单
        public static function create_pay_order($data){
            $PixOrder = new PixOrder();
            //创建订单
            $_data = array(
                "data_id" => $data['data_id'], 
                "order_title"=> $data['subject'], 
                "order_id" => isset($data['order_id']) ? $data['order_id'] : '',
                "pay_trade_no" => isset($data['pay_trade_no']) ? $data['pay_trade_no'] : '',
                "user_id" => $data['user_id'],  
                "order_type" => $data['mode'], 
                "pay_type" => $data['pay_type'],
                "pay_type_info" => $data['pay_type_info'],
                "total_price" =>$data['total_amount'], 
                "pay_count" => '1',
                "status" => '0',
                "order_address" => isset($data['order_address']) ? $data['order_address'] : '',
                "order_content" => isset($data['order_content']) ? $data['order_content'] : '',
                "order_license" => isset($data['order_license']) ? $data['order_license'] : '',
                'order_extra' => isset($data['order_extra']) ? $data['order_extra'] : '',
                'product_type' => isset($data['product_type']) ? $data['product_type'] : '',
                'product_subtype' => isset($data['product_subtype']) ? $data['product_subtype'] : '',
                'product_id' => isset($data['product_id']) ? intval($data['product_id']) : 0,
                'product_title' => isset($data['product_title']) ? $data['product_title'] : '',
                'buyer_name' => isset($data['buyer_name']) ? $data['buyer_name'] : '',
                'buyer_email' => isset($data['buyer_email']) ? $data['buyer_email'] : '',
                'shipping_status' => isset($data['shipping_status']) ? $data['shipping_status'] : '',
                'tracking_no' => isset($data['tracking_no']) ? $data['tracking_no'] : '',
                'shipping_company' => isset($data['shipping_company']) ? $data['shipping_company'] : '',
                'shipping_meta' => isset($data['shipping_meta']) ? $data['shipping_meta'] : '',
                'order_meta' => isset($data['order_meta']) ? $data['order_meta'] : '',
                'admin_note' => isset($data['admin_note']) ? $data['admin_note'] : '',
                'deleted_at' => isset($data['deleted_at']) ? $data['deleted_at'] : null
            );

            // 新建订单号
            $order_id = $PixOrder->build_order_no();
            $_data['order_id'] = $order_id;
            $PixOrder->create($_data);

            return array(
                'order_id' => $order_id
            );
            
        }

        private static function build_order_snapshot($data, $user){
            $mode = isset($data['mode']) ? sanitize_key($data['mode']) : '';
            $data_id = isset($data['data_id']) ? intval($data['data_id']) : 0;
            $product_type = $mode;
            $product_subtype = '';
            $product_id = $data_id;
            $product_title = isset($data['subject']) ? preg_replace('/^(文章购买|余额充值|积分充值)[:：]/u', '', $data['subject']) : '';
            $order_meta = array();

            if ($mode === 'post' && $data_id > 0) {
                $product_type = get_post_type($data_id) ?: 'post';
                $product_title = get_the_title($data_id);
                $post_meta = get_post_meta($data_id, '_ppo_post_options', true);
                if (is_array($post_meta)) {
                    $product_subtype = isset($post_meta['dd_type']) ? sanitize_key($post_meta['dd_type']) : '';
                    $order_meta['post_type'] = $product_type;
                    $order_meta['pay_content_type'] = $product_subtype;
                }
            } else if ($mode === 'vip') {
                $product_type = 'vip';
                $product_subtype = isset($data['order_extra']) ? sanitize_key($data['order_extra']) : '';
                $product_title = isset($data['subject']) ? $data['subject'] : '会员购买';
            } else if ($mode === 'mj') {
                $product_type = 'moment';
                $product_subtype = isset($data['order_extra']) ? sanitize_key($data['order_extra']) : '';
                $term = $data_id > 0 ? get_term($data_id, 'moments') : null;
                $product_title = ($term && !is_wp_error($term)) ? $term->name : (isset($data['subject']) ? $data['subject'] : '圈子订阅');
            } else if ($mode === 'jfcz' || $mode === 'yecz') {
                $product_type = 'charge';
                $product_subtype = $mode;
                $product_id = 0;
                $product_title = isset($data['subject']) ? $data['subject'] : ($mode === 'jfcz' ? '积分充值' : '余额充值');
            }

            $order_meta = apply_filters('ppo_order_snapshot_meta', $order_meta, $data, $user);

            return array(
                'product_type' => sanitize_key($product_type),
                'product_subtype' => sanitize_key($product_subtype),
                'product_id' => intval($product_id),
                'product_title' => sanitize_text_field($product_title),
                'buyer_name' => sanitize_text_field($user->display_name),
                'buyer_email' => sanitize_email($user->user_email),
                'shipping_status' => '',
                'tracking_no' => '',
                'shipping_company' => '',
                'shipping_meta' => '',
                'order_meta' => wp_json_encode($order_meta, JSON_UNESCAPED_UNICODE),
                'admin_note' => '',
                'deleted_at' => null,
            );
        }

        //轮询订单状态
        public function pay_interval(){
            if (!is_user_logged_in()) {
                wp_send_json(array('state' => '0' , 'msg' => 'unauthorized'));
            }

            check_ajax_referer('ppo_pay_action', 'nonce');

            $PixOrder = new PixOrder();
            $order_id = !empty($_POST['order_id']) ? sanitize_text_field(wp_unslash($_POST['order_id'])) : '';

            $order = $PixOrder->get_order_info($order_id);
            if (!$order || intval($order->user_id) !== get_current_user_id()) {
                wp_send_json(array('state' => '0' , 'msg' => 'forbidden'));
            }

            $res = $PixOrder->check($order_id);

            if(!$res){
                $data = array('state' => '0' , 'msg' => 'waiting');
            } else {
                $data = array('state' => '1' , 'msg' => 'success');
            }
            wp_send_json($data);

        }

        //统一回调链接接口
        public static function handle_pay_notify(){
            $method = strtolower($_SERVER['REQUEST_METHOD']);
            if($method === 'post'){
                $data = empty($_POST) ? $_GET : $_POST;
            }else{
                $data = $_GET;
            }

            $res = self::pay_notify($method, $data);
            $res = self::normalize_pay_result($res);

            self::log_notify($method, $data, $res, 'notify');

            if(empty($res['success'])){
                echo 'fail';
            }else{
                echo 'success';
            }
            exit;
        }

        //统一同步回调接口
        public static function handle_pay_return(){
            $res = self::pay_notify('get', $_GET);
            $res = self::normalize_pay_result($res);
            self::log_notify('get', $_GET, $res, 'return');
            $success = !empty($res['success']);
            $pay_rurl = isset($_COOKIE['pay_rurl']) ? $_COOKIE['pay_rurl'] : home_url();
            $current_user = wp_get_current_user();
            $user_id = $current_user->ID;

            get_header();
            ?>
            <div id="pay-return-page" class="pay-return pix-content home-classic" uk-height-viewport="expand: true">
                <?php if($success) { ?>
                    <div class="pay-return-icon success"><i class="ri-check-line"></i></div>
                    <div class="success-title"><?php echo __('恭喜，支付成功','ppo'); ?></div>
                <?php } else { ?>
                    <div class="pay-return-icon fail"><i class="ri-close-line"></i></div>
                    <div class="fail-title"><?php echo __('抱歉，支付失败','ppo'); ?></div>
                <?php } ?>
                <div class="btn-group">
                    <a class="close-page" href="javascript:window.location.href='about:blank';window.close();"><?php echo __('关闭此页面','ppo'); ?></a>
                    <a class="jump-order-page" href="<?php echo get_author_posts_url($user_id); ?>"><?php echo __('查看订单页','ppo'); ?></a>
                    <a class="back-page" href="<?php echo esc_url($pay_rurl); ?>"><?php echo __('返回商品页','ppo'); ?></a>
                </div>
            </div>
            <?php
            get_footer();
            exit;
        }

        //回调日志记录
        private static function log_notify($method, $data, $result, $request_type = 'notify'){
            global $wpdb;
            $table_name = $wpdb->prefix . 'ppo_pay_notify_log';

            if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name && function_exists('ppo_pay_notify_log_install')) {
                ppo_pay_notify_log_install();
            }

            if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
                return false;
            }

            $result = self::normalize_pay_result($result);
            $summary = self::extract_notify_summary($data, $result);
            if (function_exists('get_real_ip') && (!empty($_SERVER['HTTP_CLIENT_IP']) || !empty($_SERVER['HTTP_X_FORWARDED_FOR']) || !empty($_SERVER['REMOTE_ADDR']))) {
                $ip = get_real_ip();
            } else {
                $ip = $_SERVER['REMOTE_ADDR'] ?? '';
            }

            return $wpdb->insert($table_name, array(
                'channel' => $summary['channel'],
                'method' => strtoupper(sanitize_text_field($method)),
                'request_type' => sanitize_key($request_type),
                'order_id' => $summary['order_id'],
                'trade_no' => $summary['trade_no'],
                'amount' => $summary['amount'],
                'success' => empty($result['success']) ? 0 : 1,
                'error_code' => empty($result['code']) ? '' : sanitize_key($result['code']),
                'message' => $summary['message'],
                'ip_address' => sanitize_text_field($ip),
                'payload' => wp_json_encode($data, JSON_UNESCAPED_UNICODE),
                'result' => wp_json_encode($result, JSON_UNESCAPED_UNICODE),
                'created_at' => current_time('mysql'),
            ), array('%s','%s','%s','%s','%s','%f','%d','%s','%s','%s','%s','%s','%s'));
        }

        private static function extract_notify_summary($data, $result){
            $result_data = isset($result['data']) && is_array($result['data']) ? $result['data'] : array();
            $raw = isset($result_data['raw']) && is_array($result_data['raw']) ? $result_data['raw'] : array();
            $source = array_merge(is_array($data) ? $data : array(), $raw, $result_data);

            $order_id = $source['order_id'] ?? ($source['out_trade_no'] ?? ($source['trade_order_id'] ?? ($source['pay_id'] ?? '')));
            $trade_no = $source['trade_no'] ?? ($source['transaction_id'] ?? ($source['pay_trade_no'] ?? ($source['open_order_id'] ?? '')));
            $amount = $source['amount'] ?? ($source['total_fee'] ?? ($source['money'] ?? ($source['total_amount'] ?? 0)));

            $channel = $result_data['channel'] ?? '';
            if (empty($channel)) {
                if (isset($source['hash']) && isset($source['trade_order_id'])) {
                    $channel = 'xunhu';
                } else if (isset($source['pid']) || isset($source['trade_status'])) {
                    $channel = 'yipay';
                } else if (isset($source['app_id']) || isset($source['notify_id'])) {
                    $channel = 'alipay';
                }
            }

            $message = !empty($result['success'])
                ? ($result['msg'] ?? 'success')
                : ($result['error'] ?? '支付处理失败');

            return array(
                'channel' => sanitize_key($channel),
                'order_id' => sanitize_text_field($order_id),
                'trade_no' => sanitize_text_field($trade_no),
                'amount' => round(floatval($amount), 4),
                'message' => mb_substr(sanitize_text_field($message), 0, 255),
            );
        }

        private static function pay_success($message = 'success', $data = array()){
            return array(
                'success' => true,
                'msg' => $message,
                'data' => $data,
            );
        }

        private static function pay_error($message = '支付处理失败', $code = 'payment_error'){
            return array(
                'success' => false,
                'error' => $message,
                'code' => $code,
            );
        }

        private static function normalize_pay_result($result){
            if (is_array($result)) {
                if (isset($result['success'])) {
                    return $result;
                }
                if (isset($result['error'])) {
                    return self::pay_error($result['error']);
                }
                return self::pay_success($result['msg'] ?? 'success', $result);
            }

            if ($result === true || $result === 'success') {
                return self::pay_success();
            }

            return self::pay_error(is_string($result) ? $result : '支付处理失败');
        }

        private static function build_paid_result($channel, $order_id, $trade_no, $amount, $raw = array()){
            return array(
                'success' => true,
                'channel' => sanitize_key($channel),
                'order_id' => sanitize_text_field($order_id),
                'trade_no' => sanitize_text_field($trade_no),
                'amount' => round(floatval($amount), 2),
                'raw' => is_array($raw) ? $raw : array(),
            );
        }

        private static function complete_paid_order($paid_result){
            $paid_result = self::normalize_pay_result($paid_result);
            if (empty($paid_result['success'])) {
                return $paid_result;
            }

            $order_id = $paid_result['order_id'] ?? '';
            $trade_no = $paid_result['trade_no'] ?? '';
            $amount = $paid_result['amount'] ?? null;

            $PixOrder = new PixOrder();
            $order = $PixOrder->get_order_info($order_id);
            if (!$order) {
                return self::pay_error('订单不存在', 'order_not_found');
            }

            if (!self::verify_notify_amount($order, $amount)) {
                return self::pay_error('支付金额校验失败', 'amount_mismatch');
            }

            $result = $PixOrder->update_success_trade($order_id, $trade_no);
            return self::normalize_pay_result($result);
        }

        //订单回调
        public static function pay_notify($method,$post){
            $order_id = '';
            
            if(isset($post['fund_bill_list'])){
                //if(get_magic_quotes_gpc()){
                $post['fund_bill_list'] = stripslashes($post['fund_bill_list']);
                //}
            }

            if(isset($post['out_trade_no'])){
                $order_id = $post['out_trade_no'];
            }
            
            $xunhu = isset($post['hash']) && isset($post['trade_order_id']);
            if($xunhu){
                $order_id = $post['trade_order_id'];
            }

            if(isset($post['userID']) && isset($post['trueID'])){
                $order_id = $post['pay_id'];
            }

            if(!$order_id) return array('error'=>__('订单获取失败'));
            
            global $wpdb;
            $table_name = $wpdb->prefix . 'ppo_pay_order';
            $order = $wpdb->get_row(
                $wpdb->prepare("
                    SELECT * FROM $table_name
                    WHERE order_id = %s
                    ",
                    $order_id
                )
            ,ARRAY_A);

            if(empty($order)) return array('error'=>$order);
            //$content = var_export($order, true);
            
            if($xunhu){
                return self::xunhu_notify($post,$order);
            }
               
            $type = $order['pay_type_info']; 
            $type = $type.'_notify';
            //file_put_contents(__DIR__ . '/notify_result.txt', $type);
            $_POST = $post;
            $_GET = $post;
            
            return self::$type($method,$post);
            //return array('order_id' => $type);
        }

        // vip购买支付参数
        public static function vip_pay_data($data){
            $arr = get_op('vip_item');
            $res = $arr[$data['data_id']];
            $vip_item = $data['order_extra'];
            $off = 'price_'.$vip_item.'';

            switch ($vip_item) {
                case 'm':
                    $price = $res[$off] * $res['price_n'] * 0.1;
                    $time = '月费';
                    break;
                
                case 'q':
                    $price = $res[$off] * $res['price_n'] * 0.1 * 3;
                    $time = '季费';
                    break;

                case 'y':
                    $price = $res[$off] * $res['price_n'] * 0.1 * 12;
                    $time = '年费';
                    break;    
            }
  
            return array(
                'total_amount' => round($price,2),
                'subject' => ''.$res['title'].'购买-'.$time.'',
            );
        }

        private static function asset_pay_lock_name($order_id){
            return 'ppo_asset_pay_' . md5((string)$order_id);
        }

        private static function acquire_asset_pay_lock($order_id){
            global $wpdb;
            $lock_name = self::asset_pay_lock_name($order_id);
            $locked = $wpdb->get_var($wpdb->prepare('SELECT GET_LOCK(%s, 5)', $lock_name));
            return $locked === '1' || $locked === 1;
        }

        private static function release_asset_pay_lock($order_id){
            global $wpdb;
            $lock_name = self::asset_pay_lock_name($order_id);
            $wpdb->get_var($wpdb->prepare('SELECT RELEASE_LOCK(%s)', $lock_name));
        }

        private static function asset_pay($order_data, $asset_type){
            $PixOrder = new PixOrder();
            $order_id = isset($order_data['order_id']) ? sanitize_text_field($order_data['order_id']) : '';
            $is_credit = $asset_type === 'credit';
            $asset_name = $is_credit ? get_op('credit_name','积分') : get_op('cash_name','余额');

            if(empty($order_id)) return array('error'=>'支付信息错误');

            if(!self::acquire_asset_pay_lock($order_id)){
                return array('error'=>'订单正在处理中，请稍后重试');
            }

            try {
                $order = $PixOrder->validate_payable_order($order_id, $asset_type);
                if(is_array($order) && isset($order['error'])){
                    return $order;
                }

                if(intval($order->user_id) !== intval($order_data['user_id'])){
                    return array('error'=>'订单用户不匹配');
                }

                $amount = floatval($order->total_price);
                if($amount <= 0){
                    return array('error'=>'订单金额错误');
                }

                if($is_credit){
                    $res = Credit::credit_change(intval($order->user_id), -$amount, array(
                        'change_type' => 'pay_credit',
                        'order_id' => $order_id,
                        'note' => '积分支付',
                    ));
                } else {
                    $res = Credit::cash_change(intval($order->user_id), -$amount, array(
                        'change_type' => 'pay_cash',
                        'order_id' => $order_id,
                        'note' => '余额支付',
                    ));
                }

                if($res === false){
                    return array('error' => $asset_name . ($is_credit ? '余额不足' : '不足'));
                }

                $paid = $PixOrder->update_success_trade($order_id,'');
                if(is_array($paid) && isset($paid['error'])){
                    return $paid;
                }

                return array('msg' => '支付成功,正在跳转');
            } finally {
                self::release_asset_pay_lock($order_id);
            }
        }

        // 积分支付
        public static function credit($order_data){
            return self::asset_pay($order_data, 'credit');
        }

        // 余额支付
        public static function balance($order_data){
            return self::asset_pay($order_data, 'balance');
        }

        // 虎皮椒微信
        public static function wepay_hupijiao($data){
            $settings = self::xunhu_channel_settings('wepay_hupijiao');
            return self::xunhu_action($data,$settings);
        }	

        // 虎皮椒支付宝
        public static function alipay_hupijiao($data){
            $settings = self::xunhu_channel_settings('alipay_hupijiao');
            return self::xunhu_action($data,$settings);
        }

        // 虎皮椒V3支付
        public static function xunhu_action($data,$settings){
            $home_url = home_url();
            $is_mobile = wp_is_mobile();

            $settings['trade_order_id'] = $data['order_id'];
            $settings['total_fee'] = $data['total_amount'];
            $settings['title']     = $data['subject'];
            $settings['version']   = '1.1';
            $settings['lang']       = 'zh-cn'; 
            $settings['time']      = time();
            $settings['notify_url']=  home_url('/notify');
            $settings['return_url']= home_url('/return');
            $settings['callback_url']= $home_url;
            $settings['nonce_str'] = str_shuffle(time());

            if($is_mobile && $settings['payment'] == 'wechat'){
                $settings['type'] = 'WAP';
                $settings['wap_url'] = $home_url;
                $settings['wap_name'] = $home_url;
            }

            

            require THEME_DIR . '/inc/payment/xunhupay/api.php';

            $settings['hash']     = \XH_Payment_Api::generate_xh_hash($settings,$settings['appsecret']);

            $url = 'https://api.xunhupay.com/payment/do.html';
            if (!empty($settings['geteway'])) {
                $url = $settings['geteway'];
            }

            try {
                $response     = \XH_Payment_Api::http_post($url, json_encode($settings));
    
                $result       = $response ? json_decode($response,true) : null;
                if(!$result){
                    return array('error'=>'Internal server error');
                }
    
                $hash         = \XH_Payment_Api::generate_xh_hash($result,$settings['appsecret']);
                if(!isset( $result['hash'])|| $hash!=$result['hash']){
                    return array('error'=>__('Invalid sign!','ppo'));
                }
    
                if($result['errcode']!=0){
                    return array('error'=>$result['errmsg']);
                }
    
                if($is_mobile){
                    return array(
                        'order_id'=>$data['order_id'],
                        'url'=>$result['url']
                    );
                }

                return array(
                    'order_id'=>$data['order_id'],
                    'url'=>$result['url_qrcode']
                );
    
            } catch (\Exception $e) {
                return array('error' => 1, 'errcode' => $e->getCode(), 'msg' => $e->getMessage());
            }
            
            
        }

        public static function xunhu_notify($data, $order){
            if (!isset($data['status']) || $data['status'] !== 'OD') {
                return self::pay_error('虎皮椒订单未支付', 'xunhu_unpaid');
            }

            $settings = self::xunhu_channel_settings($order['pay_type_info']);
            $expected_appid = $settings['appid'];
            $appsecret = $settings['appsecret'];

            if (empty($expected_appid) || empty($appsecret)) {
                return self::pay_error('虎皮椒支付配置缺失', 'xunhu_config_missing');
            }

            if (empty($data['appid']) || strval($data['appid']) !== strval($expected_appid)) {
                return self::pay_error('虎皮椒 AppID 校验失败', 'xunhu_appid_mismatch');
            }

            require_once THEME_DIR . '/inc/payment/xunhupay/api.php';
            $expected_hash = \XH_Payment_Api::generate_xh_hash($data, $appsecret);
            if (empty($data['hash']) || !hash_equals($expected_hash, $data['hash'])) {
                return self::pay_error('虎皮椒签名校验失败', 'xunhu_invalid_sign');
            }

            $paid_result = self::build_paid_result(
                'xunhu',
                $data['trade_order_id'] ?? '',
                $data['transaction_id'] ?? ($data['open_order_id'] ?? ''),
                $data['total_fee'] ?? 0,
                $data
            );

            return self::complete_paid_order($paid_result);
        }

        // 易支付
        public static function yipay($data){
            $config = self::yipay_config();
            $settings = array(
                'pid'=>$config['pid'],
                'type'=>$data['pay_type'] == 'alipay' ? 'alipay' : 'wxpay',
                'sitename'=>PPO_BLOG_NAME,
                'out_trade_no'=>$data['order_id'],
                'notify_url'=>home_url('/notify'),
                'return_url'=>home_url('/return'),
                'name'=>$data['subject'],
                'money'=>$data['total_amount'],
                'sign_type'=>'MD5'
            );

            ksort($settings);
            reset($settings);

            $sign = '';
            $urls = '';
    
            foreach ($settings AS $key => $val) {
                if ($val == '' || $key == 'sign' || $key == 'sign_type') continue;
                if ($sign != '') {
                    $sign .= "&";
                    $urls .= "&";
                }
                $sign .= "$key=$val";
                $urls .= "$key=" . urlencode($val);
            }
    
            $query = $urls . '&sign=' . md5($sign.$config['secret']).'&sign_type=MD5';
            $url = $config['url'];
            $url = $url.'/submit.php?'.$query;
    
            return array(
                'id'=>$data['order_id'],
                'url'=>$url
            );

        }

        //易支付回调
	public static function yipay_notify($method,$data){
		$config = self::yipay_config();
		if(isset($data['trade_status']) && $data['trade_status'] === 'TRADE_SUCCESS'){
            $expected_pid = $config['pid'];
            if (!empty($expected_pid) && isset($data['pid']) && strval($data['pid']) !== strval($expected_pid)) {
                return array('error'=>'商户号校验失败');
            }
            ksort($data);
            reset($data);
    
            $sign = '';
    
            foreach ($data AS $key => $val) {
                if ($val == '' || $key == 'sign' || $key == 'sign_type') continue;
                if ($sign != '') {
                    $sign .= "&";
                }
                $sign .= "$key=$val";
            }

            $sign = md5($sign .$config['secret']);

            if(!$sign) return array('error'=>__('支付回调错误','ppo'));

            if($sign === $data['sign']){
                if($method == 'get'){
                    return self::pay_success();
                }else{
                    $paid_result = self::build_paid_result(
                        'yipay',
                        $data['out_trade_no'] ?? '',
                        $data['trade_no'] ?? '',
                        $data['money'] ?? 0,
                        $data
                    );
                    return self::complete_paid_order($paid_result);
                }
            }
        }

        return self::pay_error('支付回调错误');
	}	

        // 支付宝接口参数
        public static function alipay_config(){
            $config = get_op('pay_config');
            if(is_array($config)){
                return [
                    // 沙箱模式
                    'debug'       => true,
                    'sign_type'   => "RSA2",
                    'appid'       => $config['alipay_appid'],
                    'public_key'  => $config['alipay_public_key'],
                    'private_key' => $config['alipay_private_key'],
                    'notify_url'  => home_url('/notify'),
                    'return_url'  => home_url('/return'),
                    'normal_type'        => $config['alipay_normal_type']
                ];
            }
        }

        // 支付宝官方发起支付
        public static function alipay_normal($order_data){
            $config = self::alipay_config();
            //$config['return_url'] = $order_data['return'];

                try {

                if(empty($config['appid']) || empty($config['private_key'])){
                    return array('error' => 1, 'msg' => '缺少APPID或应用私钥');
                }

                // 判断跳转支付还是扫码
                if($config['normal_type'] == 'alipay_normal'){

                    if (empty($config['public_key'])) {
                        return array('error' => 1, 'msg' => '缺少支付宝公钥参数');
                    }

                    // 手机支付
                    if(wp_is_mobile()){
    
                        $pay = \We::AliPayWap($config);

                    } else {
                        
                        $pay = \We::AliPayWeb($config);
                    }

                } else {
                
                    if (empty($config['public_key'])) {
                        return array('error' => 1, 'msg' => '缺少支付宝公钥参数');
                    }
                    $pay = \We::AliPayScan($config);


                }

                $result = $pay->apply([
                    'out_trade_no' => $order_data['order_id'], // 商户订单号
                    'total_amount' => $order_data['total_amount'], // 支付金额
                    'subject'      => $order_data['subject'] // 支付订单描述
                ]);

                if($config['normal_type'] == 'alipay_normal' && $order_data['jump'] === 'jump'){
                    return array('url' => $result);
                } else {
                    $pay_url = $result['qr_code'];
                    $qrcode = create_qrcode($pay_url);
                    return array('url' => $qrcode);
                }

            } catch (\Exception $e) {
                return array('error'=>$e->getMessage());
            }

        }

        //支付宝官方回调
        public static function alipay_normal_notify($method , $post){
            
            $config = self::alipay_config();
            
                $pay = \AliPay\App::instance($config);
                $data = $pay->notify();
                      
                try {
                    if($method == 'get'){
                        if($post['sign'] === $data['sign']){
                            return self::pay_success();
                        }else{
                            return self::pay_error('支付回调错误');
                        }
                    }else{
                        
                        if (in_array($data['trade_status'], ['TRADE_SUCCESS', 'TRADE_FINISHED'])) {
                            if (!empty($config['appid']) && isset($data['app_id']) && strval($data['app_id']) !== strval($config['appid'])) {
                                return self::pay_error('支付宝 AppID 校验失败', 'appid_mismatch');
                            }
                            $paid_result = self::build_paid_result(
                                'alipay_normal',
                                $data['out_trade_no'] ?? '',
                                $data['trade_no'] ?? '',
                                $data['total_amount'] ?? 0,
                                $data
                            );
                            return self::complete_paid_order($paid_result);
                        } else {
                           
                        } 
                    }
                } catch (\Exception $e) {
                    //file_put_contents('notify.txt', 'alipay_normal::'.$e->getMessage(), FILE_APPEND);
                    return self::pay_error($e->getMessage());
                }
        
        }	

        private static function verify_notify_amount($order, $paid_amount){
            if ($paid_amount === null || $paid_amount === '') {
                return false;
            }

            $expected = round(floatval($order->total_price), 2);
            $actual = round(floatval($paid_amount), 2);

            return abs($expected - $actual) < 0.01;
        }



    //end
    
    }
}

new PPO_Pay;
