'GET', 'callback' => array($this, 'get_subscriptions'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/subscriptions/(?P\d+)', array( 'methods' => 'GET', 'callback' => array($this, 'get_subscription'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/subscriptions/(?P\d+)', array( 'methods' => 'PUT', 'callback' => array($this, 'update_subscription'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/subscriptions/(?P\d+)/pause', array( 'methods' => 'POST', 'callback' => array($this, 'pause_subscription'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/subscriptions/(?P\d+)/resume', array( 'methods' => 'POST', 'callback' => array($this, 'resume_subscription'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/subscriptions/(?P\d+)/cancel', array( 'methods' => 'POST', 'callback' => array($this, 'cancel_subscription'), 'permission_callback' => array($this, 'check_permissions'), )); // 混装产品相关端点 register_rest_route(self::API_NAMESPACE, '/bundles', array( 'methods' => 'GET', 'callback' => array($this, 'get_bundles'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/bundles/(?P\d+)', array( 'methods' => 'GET', 'callback' => array($this, 'get_bundle'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/bundles/(?P\d+)/price', array( 'methods' => 'POST', 'callback' => array($this, 'calculate_bundle_price'), 'permission_callback' => '__return_true', )); // 支付相关端点 register_rest_route(self::API_NAMESPACE, '/payment/tokens', array( 'methods' => 'GET', 'callback' => array($this, 'get_payment_tokens'), 'permission_callback' => array($this, 'check_permissions'), )); register_rest_route(self::API_NAMESPACE, '/payment/tokens/(?P\d+)', array( 'methods' => 'DELETE', 'callback' => array($this, 'delete_payment_token'), 'permission_callback' => array($this, 'check_permissions'), )); // Webhook端点 register_rest_route(self::API_NAMESPACE, '/webhook/moneris', array( 'methods' => 'POST', 'callback' => array($this, 'handle_moneris_webhook'), 'permission_callback' => '__return_true', )); } /** * 检查权限 */ public function check_permissions($request) { return current_user_can('manage_woocommerce') || current_user_can('edit_shop_orders'); } /** * 获取订阅列表 */ public function get_subscriptions($request) { $customer_id = $request->get_param('customer_id'); $status = $request->get_param('status'); $page = $request->get_param('page') ?: 1; $per_page = $request->get_param('per_page') ?: 10; global $wpdb; $where_conditions = array('1=1'); $params = array(); if ($customer_id) { $where_conditions[] = 'customer_id = %d'; $params[] = $customer_id; } if ($status) { $where_conditions[] = 'status = %s'; $params[] = $status; } $where_clause = implode(' AND ', $where_conditions); $offset = ($page - 1) * $per_page; $query = $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE {$where_clause} ORDER BY created_at DESC LIMIT %d OFFSET %d", array_merge($params, array($per_page, $offset)) ); $subscriptions = $wpdb->get_results($query); return rest_ensure_response($subscriptions); } /** * 获取单个订阅 */ public function get_subscription($request) { $id = $request->get_param('id'); global $wpdb; $subscription = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscriptions WHERE id = %d", $id )); if (!$subscription) { return new WP_Error('subscription_not_found', '订阅不存在', array('status' => 404)); } // 获取订阅项目 $items = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_subscription_items WHERE subscription_id = %d", $id )); $subscription->items = $items; return rest_ensure_response($subscription); } /** * 更新订阅 */ public function update_subscription($request) { $id = $request->get_param('id'); $data = $request->get_json_params(); global $wpdb; $allowed_fields = array('status', 'next_payment_date', 'billing_period', 'billing_interval'); $update_data = array(); foreach ($allowed_fields as $field) { if (isset($data[$field])) { $update_data[$field] = $data[$field]; } } if (empty($update_data)) { return new WP_Error('no_data', '没有提供更新数据', array('status' => 400)); } $update_data['updated_at'] = current_time('mysql'); $result = $wpdb->update( $wpdb->prefix . 'yoone_subscriptions', $update_data, array('id' => $id), array('%s'), array('%d') ); if ($result === false) { return new WP_Error('update_failed', '更新失败', array('status' => 500)); } return rest_ensure_response(array('success' => true, 'message' => '订阅更新成功')); } /** * 暂停订阅 */ public function pause_subscription($request) { $id = $request->get_param('id'); global $wpdb; $result = $wpdb->update( $wpdb->prefix . 'yoone_subscriptions', array( 'status' => 'paused', 'updated_at' => current_time('mysql') ), array('id' => $id), array('%s', '%s'), array('%d') ); if ($result === false) { return new WP_Error('pause_failed', '暂停失败', array('status' => 500)); } // 记录日志 Yoone_Logger::info("订阅 {$id} 已暂停", array('subscription_id' => $id)); return rest_ensure_response(array('success' => true, 'message' => '订阅已暂停')); } /** * 恢复订阅 */ public function resume_subscription($request) { $id = $request->get_param('id'); global $wpdb; $result = $wpdb->update( $wpdb->prefix . 'yoone_subscriptions', array( 'status' => 'active', 'updated_at' => current_time('mysql') ), array('id' => $id), array('%s', '%s'), array('%d') ); if ($result === false) { return new WP_Error('resume_failed', '恢复失败', array('status' => 500)); } // 记录日志 Yoone_Logger::info("订阅 {$id} 已恢复", array('subscription_id' => $id)); return rest_ensure_response(array('success' => true, 'message' => '订阅已恢复')); } /** * 取消订阅 */ public function cancel_subscription($request) { $id = $request->get_param('id'); global $wpdb; $result = $wpdb->update( $wpdb->prefix . 'yoone_subscriptions', array( 'status' => 'cancelled', 'end_date' => current_time('mysql'), 'updated_at' => current_time('mysql') ), array('id' => $id), array('%s', '%s', '%s'), array('%d') ); if ($result === false) { return new WP_Error('cancel_failed', '取消失败', array('status' => 500)); } // 记录日志 Yoone_Logger::info("订阅 {$id} 已取消", array('subscription_id' => $id)); return rest_ensure_response(array('success' => true, 'message' => '订阅已取消')); } /** * 获取混装产品列表 */ public function get_bundles($request) { global $wpdb; $bundles = $wpdb->get_results( "SELECT * FROM {$wpdb->prefix}yoone_bundles WHERE status = 'active' ORDER BY created_at DESC" ); return rest_ensure_response($bundles); } /** * 获取单个混装产品 */ public function get_bundle($request) { $id = $request->get_param('id'); global $wpdb; $bundle = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_bundles WHERE id = %d", $id )); if (!$bundle) { return new WP_Error('bundle_not_found', '混装产品不存在', array('status' => 404)); } // 获取混装项目 $items = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_bundle_items WHERE bundle_id = %d ORDER BY sort_order", $id )); $bundle->items = $items; return rest_ensure_response($bundle); } /** * 计算混装产品价格 */ public function calculate_bundle_price($request) { $bundle_id = $request->get_param('id'); $quantities = $request->get_param('quantities') ?: array(); global $wpdb; // 获取混装产品信息 $bundle = $wpdb->get_row($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_bundles WHERE id = %d AND status = 'active'", $bundle_id )); if (!$bundle) { return new WP_Error('bundle_not_found', '混装产品不存在', array('status' => 404)); } // 获取混装项目 $items = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_bundle_items WHERE bundle_id = %d", $bundle_id )); $total_price = 0; $item_details = array(); foreach ($items as $item) { $product = wc_get_product($item->product_id); if (!$product) { continue; } $quantity = isset($quantities[$item->product_id]) ? intval($quantities[$item->product_id]) : $item->quantity; $price = $product->get_price(); $subtotal = $price * $quantity; $total_price += $subtotal; $item_details[] = array( 'product_id' => $item->product_id, 'name' => $product->get_name(), 'price' => $price, 'quantity' => $quantity, 'subtotal' => $subtotal ); } // 应用折扣 $discount_amount = 0; if ($bundle->discount_type === 'percentage') { $discount_amount = $total_price * ($bundle->discount_value / 100); } elseif ($bundle->discount_type === 'fixed') { $discount_amount = $bundle->discount_value; } $final_price = max(0, $total_price - $discount_amount); return rest_ensure_response(array( 'bundle_id' => $bundle_id, 'original_price' => $total_price, 'discount_amount' => $discount_amount, 'final_price' => $final_price, 'items' => $item_details )); } /** * 获取支付令牌 */ public function get_payment_tokens($request) { $customer_id = $request->get_param('customer_id') ?: get_current_user_id(); global $wpdb; $tokens = $wpdb->get_results($wpdb->prepare( "SELECT * FROM {$wpdb->prefix}yoone_payment_tokens WHERE customer_id = %d AND (expires_at IS NULL OR expires_at > NOW()) ORDER BY is_default DESC, created_at DESC", $customer_id )); return rest_ensure_response($tokens); } /** * 删除支付令牌 */ public function delete_payment_token($request) { $id = $request->get_param('id'); global $wpdb; $result = $wpdb->delete( $wpdb->prefix . 'yoone_payment_tokens', array('id' => $id), array('%d') ); if ($result === false) { return new WP_Error('delete_failed', '删除失败', array('status' => 500)); } return rest_ensure_response(array('success' => true, 'message' => '支付令牌已删除')); } /** * 处理Moneris Webhook */ public function handle_moneris_webhook($request) { $body = $request->get_body(); $headers = $request->get_headers(); // 验证webhook签名 if (!$this->verify_webhook_signature($body, $headers)) { return new WP_Error('invalid_signature', '无效的签名', array('status' => 401)); } $data = json_decode($body, true); if (!$data) { return new WP_Error('invalid_data', '无效的数据', array('status' => 400)); } // 处理不同类型的webhook事件 switch ($data['event_type']) { case 'payment_success': $this->handle_payment_success($data); break; case 'payment_failed': $this->handle_payment_failed($data); break; case 'subscription_cancelled': $this->handle_subscription_cancelled($data); break; default: Yoone_Logger::warning('未知的webhook事件类型: ' . $data['event_type']); } return rest_ensure_response(array('success' => true)); } /** * 验证webhook签名 */ private function verify_webhook_signature($body, $headers) { // 这里应该实现Moneris的签名验证逻辑 // 暂时返回true,实际使用时需要根据Moneris文档实现 return true; } /** * 处理支付成功 */ private function handle_payment_success($data) { // 实现支付成功处理逻辑 Yoone_Logger::info('收到支付成功webhook', $data); } /** * 处理支付失败 */ private function handle_payment_failed($data) { // 实现支付失败处理逻辑 Yoone_Logger::warning('收到支付失败webhook', $data); } /** * 处理订阅取消 */ private function handle_subscription_cancelled($data) { // 实现订阅取消处理逻辑 Yoone_Logger::info('收到订阅取消webhook', $data); } }