534 lines
14 KiB
PHP
534 lines
14 KiB
PHP
<?php
|
|
/**
|
|
* 支付令牌类
|
|
*
|
|
* 管理客户的支付令牌,用于订阅续费和重复支付
|
|
*/
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* 支付令牌类
|
|
*/
|
|
class Yoone_Payment_Token extends Abstract_Yoone_Data {
|
|
|
|
/**
|
|
* 对象类型
|
|
*/
|
|
protected $object_type = 'yoone_payment_token';
|
|
|
|
/**
|
|
* 数据结构
|
|
*/
|
|
protected $data = array(
|
|
'customer_id' => 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;
|
|
}
|
|
} |