0, 'gateway_id' => '', 'token' => '', 'token_type' => 'credit_card', 'card_type' => '', 'last_four' => '', 'expiry_month' => '', 'expiry_year' => '', 'is_default' => false, 'expires_at' => null, 'created_at' => null, 'updated_at' => null ); /** * 构造函数 */ public function __construct($id = 0) { parent::__construct($id); } /* |-------------------------------------------------------------------------- | Getters |-------------------------------------------------------------------------- */ /** * 获取客户ID */ public function get_customer_id($context = 'view') { return $this->get_prop('customer_id', $context); } /** * 获取网关ID */ public function get_gateway_id($context = 'view') { return $this->get_prop('gateway_id', $context); } /** * 获取令牌 */ public function get_token($context = 'view') { return $this->get_prop('token', $context); } /** * 获取令牌类型 */ public function get_token_type($context = 'view') { return $this->get_prop('token_type', $context); } /** * 获取卡片类型 */ public function get_card_type($context = 'view') { return $this->get_prop('card_type', $context); } /** * 获取卡片后四位 */ public function get_last_four($context = 'view') { return $this->get_prop('last_four', $context); } /** * 获取过期月份 */ public function get_expiry_month($context = 'view') { return $this->get_prop('expiry_month', $context); } /** * 获取过期年份 */ public function get_expiry_year($context = 'view') { return $this->get_prop('expiry_year', $context); } /** * 是否为默认令牌 */ public function is_default($context = 'view') { return $this->get_prop('is_default', $context); } /** * 获取过期时间 */ public function get_expires_at($context = 'view') { return $this->get_prop('expires_at', $context); } /** * 获取创建时间 */ public function get_created_at($context = 'view') { return $this->get_prop('created_at', $context); } /** * 获取更新时间 */ public function get_updated_at($context = 'view') { return $this->get_prop('updated_at', $context); } /* |-------------------------------------------------------------------------- | Setters |-------------------------------------------------------------------------- */ /** * 设置客户ID */ public function set_customer_id($customer_id) { $this->set_prop('customer_id', absint($customer_id)); } /** * 设置网关ID */ public function set_gateway_id($gateway_id) { $this->set_prop('gateway_id', sanitize_text_field($gateway_id)); } /** * 设置令牌 */ public function set_token($token) { $this->set_prop('token', sanitize_text_field($token)); } /** * 设置令牌类型 */ public function set_token_type($type) { $valid_types = array('credit_card', 'debit_card', 'bank_account'); if (in_array($type, $valid_types)) { $this->set_prop('token_type', $type); } } /** * 设置卡片类型 */ public function set_card_type($type) { $this->set_prop('card_type', sanitize_text_field($type)); } /** * 设置卡片后四位 */ public function set_last_four($last_four) { $this->set_prop('last_four', sanitize_text_field($last_four)); } /** * 设置过期月份 */ public function set_expiry_month($month) { $this->set_prop('expiry_month', str_pad(absint($month), 2, '0', STR_PAD_LEFT)); } /** * 设置过期年份 */ public function set_expiry_year($year) { $this->set_prop('expiry_year', absint($year)); } /** * 设置为默认令牌 */ public function set_default($is_default) { $this->set_prop('is_default', (bool) $is_default); // 如果设置为默认,需要取消其他令牌的默认状态 if ($is_default && $this->get_customer_id()) { $this->unset_other_defaults(); } } /** * 设置过期时间 */ public function set_expires_at($expires_at) { $this->set_prop('expires_at', $this->format_date($expires_at)); } /* |-------------------------------------------------------------------------- | 验证方法 |-------------------------------------------------------------------------- */ /** * 检查令牌是否有效 */ public function is_valid() { // 检查基本信息 if (empty($this->get_token()) || empty($this->get_gateway_id()) || !$this->get_customer_id()) { return false; } // 检查是否过期 if ($this->is_expired()) { return false; } return true; } /** * 检查令牌是否过期 */ public function is_expired() { $expires_at = $this->get_expires_at(); if (!$expires_at) { return false; } return strtotime($expires_at) < time(); } /** * 检查卡片是否过期 */ public function is_card_expired() { $month = $this->get_expiry_month(); $year = $this->get_expiry_year(); if (!$month || !$year) { return false; } $expiry_date = mktime(23, 59, 59, $month, date('t', mktime(0, 0, 0, $month, 1, $year)), $year); return $expiry_date < time(); } /* |-------------------------------------------------------------------------- | 辅助方法 |-------------------------------------------------------------------------- */ /** * 获取显示名称 */ public function get_display_name() { $card_type = $this->get_card_type(); $last_four = $this->get_last_four(); if ($card_type && $last_four) { return sprintf('%s ending in %s', ucfirst($card_type), $last_four); } return __('支付方式', 'yoone-subscriptions'); } /** * 取消其他令牌的默认状态 */ protected function unset_other_defaults() { global $wpdb; $wpdb->update( $wpdb->prefix . 'yoone_payment_tokens', array('is_default' => 0), array( 'customer_id' => $this->get_customer_id(), 'gateway_id' => $this->get_gateway_id() ), array('%d'), array('%d', '%s') ); } /** * 格式化日期 */ protected function format_date($date) { if (empty($date)) { return null; } if (is_numeric($date)) { return date('Y-m-d H:i:s', $date); } return date('Y-m-d H:i:s', strtotime($date)); } /* |-------------------------------------------------------------------------- | 数据库操作 |-------------------------------------------------------------------------- */ /** * 从数据库读取 */ protected function read() { global $wpdb; $data = $wpdb->get_row($wpdb->prepare(" SELECT * FROM {$wpdb->prefix}yoone_payment_tokens WHERE id = %d ", $this->get_id())); if ($data) { $this->set_props(array( 'customer_id' => $data->customer_id, 'gateway_id' => $data->gateway_id, 'token' => $data->token, 'token_type' => $data->token_type, 'card_type' => $data->card_type, 'last_four' => $data->last_four, 'expiry_month' => $data->expiry_month, 'expiry_year' => $data->expiry_year, 'is_default' => (bool) $data->is_default, 'expires_at' => $data->expires_at, 'created_at' => $data->created_at, 'updated_at' => $data->updated_at )); } } /** * 创建记录 */ protected function create() { global $wpdb; $data = array( 'customer_id' => $this->get_customer_id('edit'), 'gateway_id' => $this->get_gateway_id('edit'), 'token' => $this->get_token('edit'), 'token_type' => $this->get_token_type('edit'), 'card_type' => $this->get_card_type('edit'), 'last_four' => $this->get_last_four('edit'), 'expiry_month' => $this->get_expiry_month('edit'), 'expiry_year' => $this->get_expiry_year('edit'), 'is_default' => $this->is_default('edit') ? 1 : 0, 'expires_at' => $this->get_expires_at('edit'), 'created_at' => current_time('mysql'), 'updated_at' => current_time('mysql') ); $result = $wpdb->insert( $wpdb->prefix . 'yoone_payment_tokens', $data, array('%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%d', '%s', '%s', '%s') ); if ($result) { $this->set_id($wpdb->insert_id); do_action('yoone_payment_token_created', $this->get_id(), $this); } return $result; } /** * 更新记录 */ protected function update() { global $wpdb; $changes = $this->get_changes(); if (empty($changes)) { return true; } $changes['updated_at'] = current_time('mysql'); $result = $wpdb->update( $wpdb->prefix . 'yoone_payment_tokens', $changes, array('id' => $this->get_id()), null, array('%d') ); if ($result !== false) { do_action('yoone_payment_token_updated', $this->get_id(), $this); } return $result !== false; } /** * 从数据库删除 */ protected function delete_from_database($force_delete = false) { global $wpdb; $result = $wpdb->delete( $wpdb->prefix . 'yoone_payment_tokens', array('id' => $this->get_id()), array('%d') ); if ($result) { do_action('yoone_payment_token_deleted', $this->get_id()); } return $result !== false; } /** * 设置多个属性 */ protected function set_props($props) { foreach ($props as $prop => $value) { if (array_key_exists($prop, $this->data)) { $this->data[$prop] = $value; } } } /* |-------------------------------------------------------------------------- | 静态方法 |-------------------------------------------------------------------------- */ /** * 根据客户ID获取令牌 */ public static function get_customer_tokens($customer_id, $gateway_id = '') { global $wpdb; $where = $wpdb->prepare("customer_id = %d", $customer_id); if ($gateway_id) { $where .= $wpdb->prepare(" AND gateway_id = %s", $gateway_id); } $where .= " AND (expires_at IS NULL OR expires_at > NOW())"; $results = $wpdb->get_results(" SELECT id FROM {$wpdb->prefix}yoone_payment_tokens WHERE {$where} ORDER BY is_default DESC, created_at DESC "); $tokens = array(); foreach ($results as $result) { $tokens[] = new self($result->id); } return $tokens; } /** * 根据令牌字符串获取令牌对象 */ public static function get_by_token($token, $gateway_id) { global $wpdb; $id = $wpdb->get_var($wpdb->prepare(" SELECT id FROM {$wpdb->prefix}yoone_payment_tokens WHERE token = %s AND gateway_id = %s ", $token, $gateway_id)); return $id ? new self($id) : null; } /** * 获取客户的默认令牌 */ public static function get_default_token($customer_id, $gateway_id) { global $wpdb; $id = $wpdb->get_var($wpdb->prepare(" SELECT id FROM {$wpdb->prefix}yoone_payment_tokens WHERE customer_id = %d AND gateway_id = %s AND is_default = 1 AND (expires_at IS NULL OR expires_at > NOW()) ", $customer_id, $gateway_id)); return $id ? new self($id) : null; } /** * 清理过期令牌 */ public static function cleanup_expired_tokens() { global $wpdb; $count = $wpdb->query(" DELETE FROM {$wpdb->prefix}yoone_payment_tokens WHERE expires_at IS NOT NULL AND expires_at < NOW() "); if ($count > 0) { Yoone_Logger::info("清理了 {$count} 个过期的支付令牌"); } return $count; } }