refactor: rename the theme brand and every identifier from AKSRT to Jio

Full-project rename. `git grep -i aksrt` is now empty apart from the
DBMigrator 3.3.0 changelog note that documents the rename itself.

Code identifiers
- PHP namespace AKSRT\ -> Jio\ (composer PSR-4 + 378 declarations)
- global constants AKSRT_* -> JIO_* (VERSION/DIR/URI, PAY_TYPE_*, CAPTCHA_*)
- procedural functions, hooks, options, meta keys, table names,
  cookies, query vars, ajax actions and nonces: aksrt_ -> jio_
- text domain aksrt -> jio; Theme Name -> Jio
- JS globals: aksrtData/aksrtAdminData/... -> jioData/jioAdminData/...,
  window.AKSRTCaptcha & friends -> window.JioCaptcha, Aksrt* -> Jio*
- Vue components Aks*.vue -> Jio*.vue (15 files renamed + imports)
- CSS classes/data-attrs/custom properties: aksrt- -> jio-
- REST namespace aksrt/v1 -> jio/v1 (incl. payment gateway callbacks)

Storage layer
- DB tables {prefix}aksrt_* -> {prefix}jio_*; SCHEMA_VERSION 3.2.0 -> 3.3.0
  so dbDelta creates the new names on install
- widget id_base aksrt_widget_* -> jio_widget_*
- uninstall.php drop list rebuilt from the actual migrator tables
  (dropped 3 stale entries, added the 17 missing ones)

Removed
- hardcoded https://api.aksrt.com/version.json default update endpoint;
  get_endpoint() now reads the 「更新端点」 setting and do_check() no-ops
  when it is empty

Files renamed: inc/helpers/aksrt-*.php -> jio-*.php (54),
assets/admin/src/components/form/Aks*.vue -> Jio*.vue (15).
Build artifacts regenerated: assets/css/build, assets/js/runtime,
assets/admin/build.

Verified: audit-psr4-paths errors=0, audit-admin-contracts errors=0
(warnings=56, unchanged baseline), 813/813 widget-system tests,
44/44 phpunit, php -l clean across all PHP.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
kate522andClaude Opus 5 committed 2026-11-01 20:05:04 +08:00
1 parent 5b16bc6e15
commit 35bb96e82f
997 files changed
+28216 -28188

No files matched your search

+33 -33
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -45,17 +45,17 @@ class DownloadState {
$is_logged_in = is_user_logged_in();
$user_id = $is_logged_in ? get_current_user_id() : 0;
$meta = function_exists('aksrt_get_download_box_meta')
? aksrt_get_download_box_meta($post_id)
: (function_exists('aksrt_get_resource_meta') ? aksrt_get_resource_meta($post_id) : []);
$meta = function_exists('jio_get_download_box_meta')
? jio_get_download_box_meta($post_id)
: (function_exists('jio_get_resource_meta') ? jio_get_resource_meta($post_id) : []);
$downloads = is_array($meta['downloads'] ?? null) ? $meta['downloads'] : [];
if ($downloads === []) {
return $this->build_result(
self::STATE_NO_PERMISSION,
false,
__('该资源暂未提供下载链接。', 'aksrt'),
__('暂无下载', 'aksrt'),
__('该资源暂未提供下载链接。', 'jio'),
__('暂无下载', 'jio'),
'',
0,
0,
@@ -63,11 +63,11 @@ class DownloadState {
);
}
$access = class_exists('AKSRT\\Content\\Visibility')
$access = class_exists('Jio\\Content\\Visibility')
? Visibility::get_post_access_state($post_id, $user_id)
: [];
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($post_id, $user_id)
$priced = function_exists('jio_get_user_pay_price')
? jio_get_user_pay_price($post_id, $user_id)
: null;
$pay_modo = is_array($priced)
? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0')
@@ -76,23 +76,23 @@ class DownloadState {
? ($priced['amount'] ?? ($pay_modo === 'points' ? 0 : '0.00'))
: ($pay_modo === 'points' ? 0 : '0.00');
$amount_minor = $this->amount_minor($amount, $pay_modo);
$cost = function_exists('aksrt_resource_download_cost')
? (int) aksrt_resource_download_cost($post_id)
$cost = function_exists('jio_resource_download_cost')
? (int) jio_resource_download_cost($post_id)
: 0;
$balance = $user_id > 0 ? \AKSRT\Ledger\LedgerService::get_instance()->balance($user_id, \AKSRT\Ledger\AssetType::POINTS) : 0;
$balance = $user_id > 0 ? \Jio\Ledger\LedgerService::get_instance()->balance($user_id, \Jio\Ledger\AssetType::POINTS) : 0;
$gate = function_exists('aksrt_can_download') ? aksrt_can_download($post_id, $user_id) : true;
$gate = function_exists('jio_can_download') ? jio_can_download($post_id, $user_id) : true;
if (is_wp_error($gate)) {
$code = $gate->get_error_code();
$data = (array) $gate->get_error_data();
$msg = $gate->get_error_message() ?: __('无下载权限。', 'aksrt');
$msg = $gate->get_error_message() ?: __('无下载权限。', 'jio');
if ($code === 'aksrt_need_login') {
if ($code === 'jio_need_login') {
return $this->build_result(
self::STATE_NOT_LOGGED_IN,
false,
__('登录后可下载此资源。', 'aksrt'),
__('登录下载', 'aksrt'),
__('登录后可下载此资源。', 'jio'),
__('登录下载', 'jio'),
(string) ($data['login_url'] ?? $login_url),
$cost,
$balance,
@@ -107,15 +107,15 @@ class DownloadState {
);
}
if ($code === 'aksrt_need_vip') {
$vip_url = function_exists('aksrt_get_user_center_tab_url')
? aksrt_get_user_center_tab_url('credits')
if ($code === 'jio_need_vip') {
$vip_url = function_exists('jio_get_user_center_tab_url')
? jio_get_user_center_tab_url('credits')
: $login_url;
return $this->build_result(
self::STATE_NEED_VIP,
false,
$msg,
__('开通会员', 'aksrt'),
__('开通会员', 'jio'),
$vip_url,
$cost,
$balance,
@@ -131,14 +131,14 @@ class DownloadState {
}
// need_purchase / legacy insufficient credits → cashier.
if (in_array($code, ['aksrt_need_purchase', 'aksrt_points_insufficient'], true)) {
if (in_array($code, ['jio_need_purchase', 'jio_points_insufficient'], true)) {
$label = $pay_modo === 'points'
? sprintf(__('购买(%s 积分)', 'aksrt'), (string) ($amount_minor > 0 ? $amount_minor : $cost))
: __('去购买', 'aksrt');
? sprintf(__('购买(%s 积分)', 'jio'), (string) ($amount_minor > 0 ? $amount_minor : $cost))
: __('去购买', 'jio');
return $this->build_result(
self::STATE_NEED_PURCHASE,
false,
$msg ?: __('请先购买后再下载。', 'aksrt'),
$msg ?: __('请先购买后再下载。', 'jio'),
$label,
'',
$cost,
@@ -158,7 +158,7 @@ class DownloadState {
self::STATE_NO_PERMISSION,
false,
$msg,
__('无权限', 'aksrt'),
__('无权限', 'jio'),
'',
$cost,
$balance,
@@ -181,9 +181,9 @@ class DownloadState {
$owned ? self::STATE_OWNED : self::STATE_AVAILABLE,
true,
$owned
? __('已购买,可下载。', 'aksrt')
: __('此资源可免费下载。', 'aksrt'),
$owned ? __('立即下载', 'aksrt') : __('立即下载', 'aksrt'),
? __('已购买,可下载。', 'jio')
: __('此资源可免费下载。', 'jio'),
$owned ? __('立即下载', 'jio') : __('立即下载', 'jio'),
'',
0,
$balance,
@@ -202,8 +202,8 @@ class DownloadState {
return $this->build_result(
self::STATE_NEED_PURCHASE,
false,
__('请先购买后再下载。', 'aksrt'),
__('去购买', 'aksrt'),
__('请先购买后再下载。', 'jio'),
__('去购买', 'jio'),
'',
$cost,
$balance,
@@ -257,7 +257,7 @@ class DownloadState {
return 0;
}
try {
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
return \Jio\Ledger\AssetAmount::balance_minor($value);
} catch (\InvalidArgumentException $e) {
return 0;
}
+2 -2
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
+91 -91
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -19,18 +19,18 @@ trait PayHelpers {
public function preview(int $post_id, int $user_id = 0, string $coupon_code = '', string $price_type = '') {
$post = get_post($post_id);
if (!($post instanceof \WP_Post) || $post->post_status !== 'publish') {
return new \WP_Error('aksrt_invalid', __('内容不存在', 'aksrt'), ['status' => 404]);
return new \WP_Error('jio_invalid', __('内容不存在', 'jio'), ['status' => 404]);
}
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post) : [];
$pay_type = \AKSRT\Core\DomainModel::normalize_pay_type((string) ($meta['pay_type'] ?? \AKSRT\Core\DomainModel::PAY_TYPE_NO));
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_NO) {
return new \WP_Error('aksrt_not_paid', __('该内容无需购买', 'aksrt'), ['status' => 400]);
$meta = function_exists('jio_get_pay_meta') ? jio_get_pay_meta($post) : [];
$pay_type = \Jio\Core\DomainModel::normalize_pay_type((string) ($meta['pay_type'] ?? \Jio\Core\DomainModel::PAY_TYPE_NO));
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_NO) {
return new \WP_Error('jio_not_paid', __('该内容无需购买', 'jio'), ['status' => 400]);
}
$uid = $user_id > 0 ? $user_id : get_current_user_id();
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($post, $uid)
$priced = function_exists('jio_get_user_pay_price')
? jio_get_user_pay_price($post, $uid)
: ['amount' => '0.00', 'base' => '0.00', 'modo' => '0', 'currency' => '¥', 'is_free' => true, 'pay_limit' => 0, 'vip_level' => 0, 'original' => '0.00', 'vip1' => '0.00', 'vip2' => '0.00'];
$pay_modo = (($priced['modo'] ?? '0') === 'points') ? 'points' : '0';
@@ -65,8 +65,8 @@ trait PayHelpers {
$coupon_desc = '';
if ($coupon_allowed) {
$coupon_desc = trim((string) ($meta['coupon_desc'] ?? ''));
if ($coupon_desc === '' && class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_content_coupon_settings')) {
$coupon_desc = (string) (\AKSRT\Settings\Settings::get_content_coupon_settings()['desc'] ?? '');
if ($coupon_desc === '' && class_exists('\Jio\Settings\Settings') && method_exists('\Jio\Settings\Settings', 'get_content_coupon_settings')) {
$coupon_desc = (string) (\Jio\Settings\Settings::get_content_coupon_settings()['desc'] ?? '');
}
}
@@ -92,18 +92,18 @@ trait PayHelpers {
$has_paid = false;
$paid_order = null;
if ($uid > 0 && class_exists('\AKSRT\Payment\Order')) {
$has_paid = \AKSRT\Payment\Order::get_instance()->has_paid_access(
if ($uid > 0 && class_exists('\Jio\Payment\Order')) {
$has_paid = \Jio\Payment\Order::get_instance()->has_paid_access(
$uid,
\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
\Jio\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
$post_id
);
if ($has_paid && function_exists('aksrt_get_user_content_paid_order')) {
$paid_order = aksrt_get_user_content_paid_order($post_id, $uid);
if ($has_paid && function_exists('jio_get_user_content_paid_order')) {
$paid_order = jio_get_user_content_paid_order($post_id, $uid);
}
}
if (!$has_paid && $uid <= 0 && function_exists('aksrt_get_guest_content_paid_order')) {
$guest_order = aksrt_get_guest_content_paid_order($post_id);
if (!$has_paid && $uid <= 0 && function_exists('jio_get_guest_content_paid_order')) {
$guest_order = jio_get_guest_content_paid_order($post_id);
if ($guest_order) {
$has_paid = true;
$paid_order = $guest_order;
@@ -111,20 +111,20 @@ trait PayHelpers {
}
$pending_order = null;
if ($uid > 0 && !$has_paid && class_exists('\AKSRT\Payment\OrderRepository')) {
if ($uid > 0 && !$has_paid && class_exists('\Jio\Payment\OrderRepository')) {
$pending_order = $this->find_pending_content_order($uid, $post_id);
}
$need_vip = $pay_limit > 0 && $vip_level < $pay_limit;
$allow_guest = function_exists('aksrt_allow_guest_content_pay') && aksrt_allow_guest_content_pay($post);
$allow_guest = function_exists('jio_allow_guest_content_pay') && jio_allow_guest_content_pay($post);
$currency = (string) ($priced['currency'] ?? ($pay_modo === 'points'
? (class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt'))
? (class_exists('\Jio\Settings\Settings') ? \Jio\Settings\Settings::get_currency_name() : __('积分', 'jio'))
: '¥'));
// Points cashier uses Credits; cash cashier uses wallet (元). Keep both for UI.
$points_balance = $uid > 0 ? \AKSRT\Ledger\LedgerService::get_instance()->balance($uid, \AKSRT\Ledger\AssetType::POINTS) : 0;
$wallet_minor = $uid > 0 ? \AKSRT\Ledger\LedgerService::get_instance()->balance($uid, \AKSRT\Ledger\AssetType::BALANCE) : 0;
$wallet_balance = \AKSRT\Ledger\AssetAmount::decimal_from_minor($wallet_minor);
$points_balance = $uid > 0 ? \Jio\Ledger\LedgerService::get_instance()->balance($uid, \Jio\Ledger\AssetType::POINTS) : 0;
$wallet_minor = $uid > 0 ? \Jio\Ledger\LedgerService::get_instance()->balance($uid, \Jio\Ledger\AssetType::BALANCE) : 0;
$wallet_balance = \Jio\Ledger\AssetAmount::decimal_from_minor($wallet_minor);
$balance = $pay_modo === 'points' ? $points_balance : $wallet_balance;
$methods = $this->available_payment_methods($pay_modo, $uid > 0);
@@ -133,16 +133,16 @@ trait PayHelpers {
$list_label = $this->format_amount_label($list_minor, $pay_modo, $currency);
$over_label = $over_minor > 0 ? $this->format_amount_label($over_minor, $pay_modo, $currency) : '';
$vip_page = function_exists('aksrt_get_user_center_tab_url')
? aksrt_get_user_center_tab_url('credits')
: (function_exists('aksrt_get_user_center_url')
? aksrt_get_user_center_url()
$vip_page = function_exists('jio_get_user_center_tab_url')
? jio_get_user_center_tab_url('credits')
: (function_exists('jio_get_user_center_url')
? jio_get_user_center_url()
: home_url('/'));
$free_limit = $uid > 0 && function_exists('aksrt_get_user_free_download_limit')
? aksrt_get_user_free_download_limit($uid) : 0;
$free_used = $uid > 0 && function_exists('aksrt_get_user_free_downloaded_number')
? aksrt_get_user_free_downloaded_number($uid) : 0;
$free_limit = $uid > 0 && function_exists('jio_get_user_free_download_limit')
? jio_get_user_free_download_limit($uid) : 0;
$free_used = $uid > 0 && function_exists('jio_get_user_free_downloaded_number')
? jio_get_user_free_downloaded_number($uid) : 0;
$quota_over = $free_limit > 0 && $free_used >= $free_limit;
$payable_amount = $this->asset_value($payable_minor, $pay_modo);
@@ -155,7 +155,7 @@ trait PayHelpers {
'title' => get_the_title($post),
'permalink' => get_permalink($post),
'pay_type' => $pay_type,
'pay_type_label' => \AKSRT\Core\DomainModel::pay_type_labels()[$pay_type] ?? $pay_type,
'pay_type_label' => \Jio\Core\DomainModel::pay_type_labels()[$pay_type] ?? $pay_type,
'pay_modo' => $pay_modo,
'pay_limit' => $pay_limit,
'vip_level' => $vip_level,
@@ -225,11 +225,11 @@ trait PayHelpers {
'rebate_price' => $this->asset_value($rebate_price_minor, $pay_modo),
],
// legacy: points_deduction runtime hard-off; card_pass not a content payment method.
'points_deduction_allowed' => function_exists('aksrt_is_allow_points_deduction')
? (bool) aksrt_is_allow_points_deduction('content')
'points_deduction_allowed' => function_exists('jio_is_allow_points_deduction')
? (bool) jio_is_allow_points_deduction('content')
: false,
'card_pass_allowed' => function_exists('aksrt_is_content_card_pass_pay_allowed')
? (bool) aksrt_is_content_card_pass_pay_allowed($post)
'card_pass_allowed' => function_exists('jio_is_content_card_pass_pay_allowed')
? (bool) jio_is_content_card_pass_pay_allowed($post)
: false,
'price_type' => $price_type,
];
@@ -244,38 +244,38 @@ trait PayHelpers {
private function assert_purchasable(int $post_id, int $user_id, string $price_type = '') {
$post = get_post($post_id);
if (!($post instanceof \WP_Post) || $post->post_status !== 'publish') {
return new \WP_Error('aksrt_invalid', __('内容不存在', 'aksrt'), ['status' => 404]);
return new \WP_Error('jio_invalid', __('内容不存在', 'jio'), ['status' => 404]);
}
$meta = function_exists('aksrt_get_pay_meta') ? aksrt_get_pay_meta($post) : [];
$pay_type = \AKSRT\Core\DomainModel::normalize_pay_type((string) ($meta['pay_type'] ?? \AKSRT\Core\DomainModel::PAY_TYPE_NO));
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_NO && $price_type !== 'download_limit_over') {
return new \WP_Error('aksrt_not_paid', __('该内容无需购买', 'aksrt'), ['status' => 400]);
$meta = function_exists('jio_get_pay_meta') ? jio_get_pay_meta($post) : [];
$pay_type = \Jio\Core\DomainModel::normalize_pay_type((string) ($meta['pay_type'] ?? \Jio\Core\DomainModel::PAY_TYPE_NO));
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_NO && $price_type !== 'download_limit_over') {
return new \WP_Error('jio_not_paid', __('该内容无需购买', 'jio'), ['status' => 400]);
}
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_VIP) {
return new \WP_Error('aksrt_need_vip', __('该内容为 VIP 专属,请开通会员。', 'aksrt'), ['status' => 403]);
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_VIP) {
return new \WP_Error('jio_need_vip', __('该内容为 VIP 专属,请开通会员。', 'jio'), ['status' => 403]);
}
$pay_modo_meta = (($meta['pay_modo'] ?? '0') === 'points') ? 'points' : '0';
$allow_guest = function_exists('aksrt_allow_guest_content_pay') && aksrt_allow_guest_content_pay($post);
$allow_guest = function_exists('jio_allow_guest_content_pay') && jio_allow_guest_content_pay($post);
if ($user_id <= 0) {
if ($pay_modo_meta === 'points' || !$allow_guest) {
return new \WP_Error('aksrt_need_login', __('请先登录后再购买。', 'aksrt'), [
return new \WP_Error('jio_need_login', __('请先登录后再购买。', 'jio'), [
'status' => 401,
'login_url' => wp_login_url(get_permalink($post)),
]);
}
}
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($post, $user_id)
$priced = function_exists('jio_get_user_pay_price')
? jio_get_user_pay_price($post, $user_id)
: ['amount' => '0.00', 'modo' => '0', 'pay_limit' => 0, 'vip_level' => 0, 'is_free' => true, 'base' => '0.00'];
// Free daily quota overbuy: override amount, ignore VIP discount (legacy).
if ($price_type === 'download_limit_over') {
$over_minor = $this->parse_asset_minor($meta['download_limit_over_price'] ?? ($pay_modo_meta === 'points' ? 0 : '0'), $pay_modo_meta);
if ($over_minor <= 0) {
return new \WP_Error('aksrt_no_overbuy', __('未开放超额下载购买。', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_no_overbuy', __('未开放超额下载购买。', 'jio'), ['status' => 400]);
}
$priced['amount'] = $this->asset_value($over_minor, $pay_modo_meta);
$priced['base'] = $this->asset_value($over_minor, $pay_modo_meta);
@@ -286,9 +286,9 @@ trait PayHelpers {
$pay_limit = (int) ($priced['pay_limit'] ?? 0);
$vip_level = (int) ($priced['vip_level'] ?? 0);
if ($pay_limit > 0 && $vip_level < $pay_limit && $price_type !== 'download_limit_over') {
return new \WP_Error('aksrt_need_vip', sprintf(
return new \WP_Error('jio_need_vip', sprintf(
/* translators: %d: required VIP level */
__('该资源仅限 VIP%s 及以上会员购买/下载。', 'aksrt'),
__('该资源仅限 VIP%s 及以上会员购买/下载。', 'jio'),
max(1, $pay_limit)
), [
'status' => 403,
@@ -296,19 +296,19 @@ trait PayHelpers {
]);
}
if ($user_id > 0 && class_exists('\AKSRT\Payment\Order') && \AKSRT\Payment\Order::get_instance()->has_paid_access(
if ($user_id > 0 && class_exists('\Jio\Payment\Order') && \Jio\Payment\Order::get_instance()->has_paid_access(
$user_id,
\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
\Jio\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
$post_id
)) {
return new \WP_Error('aksrt_already_paid', __('您已购买该内容。', 'aksrt'), [
return new \WP_Error('jio_already_paid', __('您已购买该内容。', 'jio'), [
'status' => 200,
'has_paid_access' => true,
'reload' => true,
]);
}
if ($user_id <= 0 && function_exists('aksrt_guest_has_paid_access') && aksrt_guest_has_paid_access($post_id)) {
return new \WP_Error('aksrt_already_paid', __('您已购买该内容。', 'aksrt'), [
if ($user_id <= 0 && function_exists('jio_guest_has_paid_access') && jio_guest_has_paid_access($post_id)) {
return new \WP_Error('jio_already_paid', __('您已购买该内容。', 'jio'), [
'status' => 200,
'has_paid_access' => true,
'reload' => true,
@@ -330,17 +330,17 @@ trait PayHelpers {
private function available_payment_methods(string $pay_modo, bool $logged_in = true): array {
if ($pay_modo === 'points') {
return [
['id' => 'points', 'name' => __('积分支付', 'aksrt')],
['id' => 'points', 'name' => __('积分支付', 'jio')],
];
}
if (function_exists('aksrt_list_cash_payment_methods')) {
return aksrt_list_cash_payment_methods($logged_in);
if (function_exists('jio_list_cash_payment_methods')) {
return jio_list_cash_payment_methods($logged_in);
}
return $logged_in
? [['id' => 'balance', 'name' => __('站内余额', 'aksrt')]]
: [['id' => 'alipay', 'name' => __('支付宝', 'aksrt')]];
? [['id' => 'balance', 'name' => __('站内余额', 'jio')]]
: [['id' => 'alipay', 'name' => __('支付宝', 'jio')]];
}
@@ -350,14 +350,14 @@ trait PayHelpers {
if (!empty($meta['coupon_s'])) {
return true;
}
if (function_exists('aksrt_is_content_coupon_allowed')) {
return aksrt_is_content_coupon_allowed($post_id);
if (function_exists('jio_is_content_coupon_allowed')) {
return jio_is_content_coupon_allowed($post_id);
}
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_content_coupon_settings')) {
return !empty(\AKSRT\Settings\Settings::get_content_coupon_settings()['enabled']);
if (class_exists('\Jio\Settings\Settings') && method_exists('\Jio\Settings\Settings', 'get_content_coupon_settings')) {
return !empty(\Jio\Settings\Settings::get_content_coupon_settings()['enabled']);
}
if (class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_paid_content_settings')) {
return !empty(\AKSRT\Settings\Settings::get_paid_content_settings()['coupon_post_s']);
if (class_exists('\Jio\Settings\Settings') && method_exists('\Jio\Settings\Settings', 'get_paid_content_settings')) {
return !empty(\Jio\Settings\Settings::get_paid_content_settings()['coupon_post_s']);
}
return false;
}
@@ -369,21 +369,21 @@ trait PayHelpers {
*/
private function resolve_referrer_context(int $user_id): array {
$empty = ['id' => 0, 'ratio' => 0];
if (!class_exists('\AKSRT\Settings\Settings') || !method_exists('\AKSRT\Settings\Settings', 'get_payment_affiliate_settings')) {
if (!class_exists('\Jio\Settings\Settings') || !method_exists('\Jio\Settings\Settings', 'get_payment_affiliate_settings')) {
return $empty;
}
$aff = \AKSRT\Settings\Settings::get_payment_affiliate_settings();
$aff = \Jio\Settings\Settings::get_payment_affiliate_settings();
if (empty($aff['enabled'])) {
return $empty;
}
$referrer_id = class_exists('\AKSRT\Payment\ReferralAttribution')
? \AKSRT\Payment\ReferralAttribution::get_instance()->resolve($user_id)
$referrer_id = class_exists('\Jio\Payment\ReferralAttribution')
? \Jio\Payment\ReferralAttribution::get_instance()->resolve($user_id)
: 0;
if ($referrer_id <= 0) {
return $empty;
}
$ratio = (int) \AKSRT\Settings\Settings::affiliate_ratio_for_user($referrer_id);
$ratio = (int) \Jio\Settings\Settings::affiliate_ratio_for_user($referrer_id);
if ($ratio <= 0) {
return $empty;
}
@@ -421,19 +421,19 @@ trait PayHelpers {
$coupon_code = sanitize_text_field($coupon_code);
if ($coupon_code !== '') {
if (!$this->is_coupon_allowed((int) $post->ID, $meta)) {
$err = new \WP_Error('aksrt_coupon_not_allowed', __('当前内容不支持优惠码。', 'aksrt'), ['status' => 400]);
$err = new \WP_Error('jio_coupon_not_allowed', __('当前内容不支持优惠码。', 'jio'), ['status' => 400]);
if (!$soft_coupon) {
return $err;
}
} elseif (!class_exists('\AKSRT\Payment\Coupon')) {
$err = new \WP_Error('aksrt_coupon_unavailable', __('优惠券系统不可用。', 'aksrt'), ['status' => 500]);
} elseif (!class_exists('\Jio\Payment\Coupon')) {
$err = new \WP_Error('jio_coupon_unavailable', __('优惠券系统不可用。', 'jio'), ['status' => 500]);
if (!$soft_coupon) {
return $err;
}
} else {
$result = \AKSRT\Payment\Coupon::get_instance()->validate(
$result = \Jio\Payment\Coupon::get_instance()->validate(
$coupon_code,
\AKSRT\Ledger\AssetAmount::decimal_from_minor($pay_minor),
\Jio\Ledger\AssetAmount::decimal_from_minor($pay_minor),
[
'user_id' => max(0, $user_id),
'product_ids' => [(int) $post->ID],
@@ -442,8 +442,8 @@ trait PayHelpers {
);
if (empty($result['valid'])) {
$err = new \WP_Error(
'aksrt_coupon_error',
(string) ($result['message'] ?? __('优惠码不可用。', 'aksrt')),
'jio_coupon_error',
(string) ($result['message'] ?? __('优惠码不可用。', 'jio')),
['status' => 400]
);
if (!$soft_coupon) {
@@ -458,7 +458,7 @@ trait PayHelpers {
'code' => (string) ($c['code'] ?? $coupon_code),
'type' => (string) ($c['type'] ?? ''),
'value' => $c['value'] ?? 0,
'discount' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($coupon_discount_minor),
'discount' => \Jio\Ledger\AssetAmount::decimal_from_minor($coupon_discount_minor),
];
}
}
@@ -467,21 +467,21 @@ trait PayHelpers {
$payable_minor = max(0, $pay_minor);
$rebate_price_minor = 0;
if ($referrer_id > 0 && $ratio > 0 && $payable_minor > 0) {
$rebate_price_minor = \AKSRT\Ledger\AssetAmount::percentage($payable_minor, $ratio);
$rebate_price_minor = \Jio\Ledger\AssetAmount::percentage($payable_minor, $ratio);
}
return [
'list_amount' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($list_minor),
'list_amount' => \Jio\Ledger\AssetAmount::decimal_from_minor($list_minor),
'list_minor' => $list_minor,
'rebate_discount' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($rebate_discount_minor),
'rebate_discount' => \Jio\Ledger\AssetAmount::decimal_from_minor($rebate_discount_minor),
'rebate_discount_minor' => $rebate_discount_minor,
'coupon_discount' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($coupon_discount_minor),
'coupon_discount' => \Jio\Ledger\AssetAmount::decimal_from_minor($coupon_discount_minor),
'coupon_discount_minor' => $coupon_discount_minor,
'coupon' => $coupon_meta,
'payable' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($payable_minor),
'payable' => \Jio\Ledger\AssetAmount::decimal_from_minor($payable_minor),
'payable_minor' => $payable_minor,
'referrer_id' => $referrer_id,
'rebate_price' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($rebate_price_minor),
'rebate_price' => \Jio\Ledger\AssetAmount::decimal_from_minor($rebate_price_minor),
'rebate_price_minor' => $rebate_price_minor,
'ratio' => $ratio,
];
@@ -491,10 +491,10 @@ trait PayHelpers {
private function format_amount_label(int $minor, string $pay_modo, string $currency): string {
if ($minor <= 0) {
return (string) __('免费', 'aksrt');
return (string) __('免费', 'jio');
}
$amount = $this->asset_value($minor, $pay_modo);
$n = function_exists('aksrt_format_price') ? aksrt_format_price($amount) : (string) $amount;
$n = function_exists('jio_format_price') ? jio_format_price($amount) : (string) $amount;
if ($pay_modo === 'points') {
return $n . ' ' . $currency;
}
@@ -515,14 +515,14 @@ trait PayHelpers {
) {
return 0;
}
return \AKSRT\Ledger\AssetAmount::points((int) $value)->minor();
return \Jio\Ledger\AssetAmount::points((int) $value)->minor();
}
if (!is_string($value)) {
return 0;
}
try {
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
return \Jio\Ledger\AssetAmount::balance_minor($value);
} catch (\InvalidArgumentException $e) {
return 0;
}
@@ -531,7 +531,7 @@ trait PayHelpers {
private function asset_value(int $minor, string $pay_modo) {
return $pay_modo === 'points'
? $minor
: \AKSRT\Ledger\AssetAmount::decimal_from_minor($minor);
: \Jio\Ledger\AssetAmount::decimal_from_minor($minor);
}
}
+94 -94
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -19,7 +19,7 @@ trait PayOrders {
*/
public function fulfill_paid_order(string $order_number, array $paid_order) {
$product_type = sanitize_key((string) ($paid_order['product_type'] ?? ''));
if (!\AKSRT\Core\DomainModel::is_resource_product_type($product_type)) {
if (!\Jio\Core\DomainModel::is_resource_product_type($product_type)) {
return true;
}
$post_id = (int) ($paid_order['product_id'] ?? 0);
@@ -31,25 +31,25 @@ trait PayOrders {
if (!($post instanceof \WP_Post) || $post->post_type !== 'post') {
return true;
}
if (function_exists('aksrt_bump_content_sales_volume')) {
aksrt_bump_content_sales_volume($post_id, 1);
if (function_exists('jio_bump_content_sales_volume')) {
jio_bump_content_sales_volume($post_id, 1);
} else {
$key = \AKSRT\Core\DomainModel::RESOURCE_SALES_VOLUME_KEY;
$key = \Jio\Core\DomainModel::RESOURCE_SALES_VOLUME_KEY;
$cur = (int) get_post_meta($post_id, $key, true);
update_post_meta($post_id, $key, $cur + 1);
}
// Guest cookie unlock (user_id=0).
$uid = (int) ($paid_order['user_id'] ?? 0);
if ($uid <= 0 && function_exists('aksrt_set_guest_content_pay_cookies')) {
if ($uid <= 0 && function_exists('jio_set_guest_content_pay_cookies')) {
// Ensure full order row for token material.
if (class_exists('\AKSRT\Payment\OrderRepository')) {
$full = \AKSRT\Payment\OrderRepository::get_instance()->get($order_number);
if (class_exists('\Jio\Payment\OrderRepository')) {
$full = \Jio\Payment\OrderRepository::get_instance()->get($order_number);
if (is_array($full)) {
$paid_order = array_merge($full, $paid_order);
}
}
aksrt_set_guest_content_pay_cookies($paid_order);
jio_set_guest_content_pay_cookies($paid_order);
}
// Consume coupon + write affiliate commission (cash content only; idempotent).
@@ -57,14 +57,14 @@ trait PayOrders {
if (is_wp_error($side_effects)) {
return $side_effects;
}
if (class_exists('\AKSRT\Payment\CreatorRevenue')) {
if (class_exists('\Jio\Payment\CreatorRevenue')) {
$revenue_order = array_merge($paid_order, [
'order_number' => $order_number,
'status' => \AKSRT\Payment\Order::STATUS_PAID,
'status' => \Jio\Payment\Order::STATUS_PAID,
]);
$revenue_id = \AKSRT\Payment\CreatorRevenue::get_instance()->create_from_paid_order($revenue_order);
$revenue_id = \Jio\Payment\CreatorRevenue::get_instance()->create_from_paid_order($revenue_order);
if ($revenue_id < 0) {
return new \WP_Error('aksrt_creator_revenue_conflict', __('同一订单的收益载荷不一致。', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_creator_revenue_conflict', __('同一订单的收益载荷不一致。', 'jio'), ['status' => 409]);
}
}
return true;
@@ -88,11 +88,11 @@ trait PayOrders {
$buyer_id = (int) ($order['user_id'] ?? 0);
// Coupon burn (shared helper; idempotent via coupon_usage.order_number).
if (function_exists('aksrt_burn_order_coupon')) {
if (function_exists('jio_burn_order_coupon')) {
$coupon = is_array($meta['coupon'] ?? null) ? $meta['coupon'] : [];
$coupon_code = (string) ($coupon['code'] ?? $meta['coupon_code'] ?? '');
if ($coupon_code !== '' && !aksrt_burn_order_coupon($order_number, $meta, $buyer_id)) {
return new \WP_Error('aksrt_coupon_consume_failed', __('优惠券核销失败。', 'aksrt'), ['status' => 409]);
if ($coupon_code !== '' && !jio_burn_order_coupon($order_number, $meta, $buyer_id)) {
return new \WP_Error('jio_coupon_consume_failed', __('优惠券核销失败。', 'jio'), ['status' => 409]);
}
}
@@ -132,9 +132,9 @@ trait PayOrders {
}
$priced = $assert['priced'];
$content_type = \AKSRT\Core\DomainModel::resolve_order_product_type(\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE, ['pay_type' => $assert['meta']['pay_type'] ?? '']);
$content_type = \Jio\Core\DomainModel::resolve_order_product_type(\Jio\Core\DomainModel::ORDER_PRODUCT_RESOURCE, ['pay_type' => $assert['meta']['pay_type'] ?? '']);
if ((($priced['modo'] ?? '0') !== 'points')) {
return new \WP_Error('aksrt_wrong_modo', __('该内容不支持积分支付。', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_wrong_modo', __('该内容不支持积分支付。', 'jio'), ['status' => 400]);
}
$amount = $this->parse_asset_minor($priced['amount'] ?? 0, 'points');
@@ -143,20 +143,20 @@ trait PayOrders {
'success' => true,
'data' => [
'free' => true,
'message' => __('无需支付,已可访问。', 'aksrt'),
'message' => __('无需支付,已可访问。', 'jio'),
'reload' => true,
],
];
}
if (!class_exists('\AKSRT\Payment\Order')) {
return new \WP_Error('aksrt_pay_unavailable', __('支付系统不可用。', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Order')) {
return new \WP_Error('jio_pay_unavailable', __('支付系统不可用。', 'jio'), ['status' => 500]);
}
$ledger = \AKSRT\Ledger\LedgerService::get_instance();
$balance = $ledger->balance($user_id, \AKSRT\Ledger\AssetType::POINTS);
$ledger = \Jio\Ledger\LedgerService::get_instance();
$balance = $ledger->balance($user_id, \Jio\Ledger\AssetType::POINTS);
if ($balance < $amount) {
return new \WP_Error('aksrt_points_insufficient', __('积分不足,暂时无法支付。', 'aksrt'), [
return new \WP_Error('jio_points_insufficient', __('积分不足,暂时无法支付。', 'jio'), [
'status' => 402,
'balance' => $balance,
'cost' => $amount,
@@ -174,7 +174,7 @@ trait PayOrders {
'amount' => $amount,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$repo = \AKSRT\Payment\OrderRepository::get_instance();
$repo = \Jio\Payment\OrderRepository::get_instance();
$existing = $operation_key !== '' ? $repo->get_by_request_key($operation_key) : null;
$is_new_order = !is_array($existing);
if (is_array($existing)) {
@@ -187,7 +187,7 @@ trait PayOrders {
|| sanitize_key((string) ($existing['payment_method'] ?? '')) !== 'points'
|| (string) ($existing_meta['price_type'] ?? '') !== $price_type
) {
return new \WP_Error('aksrt_ledger_idempotency_conflict', __('相同操作标识已用于其他购买请求。', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_ledger_idempotency_conflict', __('相同操作标识已用于其他购买请求。', 'jio'), ['status' => 409]);
}
$order_number = (string) $existing['order_number'];
} else {
@@ -195,35 +195,35 @@ trait PayOrders {
}
if ($order_number === '') {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败。', 'jio'), ['status' => 500]);
}
$guard = static function () use ($is_new_order, $order_number, $user_id, $post_id, $amount) {
if ($is_new_order) {
return true;
}
global $wpdb;
$table = \AKSRT\Core\DBMigrator::table('order');
$table = \Jio\Core\DBMigrator::table('order');
$current = $wpdb->get_row($wpdb->prepare("SELECT user_id, product_id, amount, currency, status FROM {$table} WHERE order_number = %s FOR UPDATE", $order_number), ARRAY_A);
if (!is_array($current)
|| (int) ($current['user_id'] ?? 0) !== $user_id
|| (int) ($current['product_id'] ?? 0) !== $post_id
|| (int) ($current['amount'] ?? 0) !== $amount
|| (string) ($current['currency'] ?? '') !== 'points'
|| (string) ($current['status'] ?? '') !== \AKSRT\Payment\Order::STATUS_PENDING
|| (string) ($current['status'] ?? '') !== \Jio\Payment\Order::STATUS_PENDING
) {
return new \WP_Error('aksrt_order_confirm_failed', __('订单状态或金额已变化。', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_order_confirm_failed', __('订单状态或金额已变化。', 'jio'), ['status' => 409]);
}
return true;
};
$deducted = $ledger->debit(
$user_id,
\AKSRT\Ledger\AssetType::POINTS,
\Jio\Ledger\AssetType::POINTS,
$amount,
$operation_key,
'content_points_pay',
['type' => 'order', 'key' => $order_number],
sprintf(__('积分购买《%s》', 'aksrt'), get_the_title($post_id)),
sprintf(__('积分购买《%s》', 'jio'), get_the_title($post_id)),
$user_id,
['post_id' => $post_id],
static function () use ($is_new_order, $repo, $order_number, $operation_key, $user_id, $post_id, $amount, $note, $content_type) {
@@ -235,22 +235,22 @@ trait PayOrders {
'product_id' => $post_id,
'amount' => $amount,
'currency' => 'points',
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
'status' => \Jio\Payment\Order::STATUS_PENDING,
'payment_method' => 'points',
'note' => is_string($note) ? $note : '',
'expires_at' => \AKSRT\Settings\PaymentRuntime::get_order_expiry_at(),
'expires_at' => \Jio\Settings\PaymentRuntime::get_order_expiry_at(),
'request_key' => $operation_key,
]);
if ($created !== $order_number) {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败。', 'jio'), ['status' => 500]);
}
}
$paid = \AKSRT\Payment\Order::get_instance()->update_status($order_number, \AKSRT\Payment\Order::STATUS_PAID, [
$paid = \Jio\Payment\Order::get_instance()->update_status($order_number, \Jio\Payment\Order::STATUS_PAID, [
'payment_method' => 'points',
'note' => sprintf(__('积分支付 %d 积分。', 'aksrt'), $amount),
'note' => sprintf(__('积分支付 %d 积分。', 'jio'), $amount),
'require_transition' => true,
]);
return $paid ? true : new \WP_Error('aksrt_order_confirm_failed', __('订单确认失败。', 'aksrt'), ['status' => 500]);
return $paid ? true : new \WP_Error('jio_order_confirm_failed', __('订单确认失败。', 'jio'), ['status' => 500]);
},
$guard
);
@@ -264,9 +264,9 @@ trait PayOrders {
'order_number' => $order_number,
'amount' => $amount,
'pay_modo' => 'points',
'balance' => $ledger->balance($user_id, \AKSRT\Ledger\AssetType::POINTS),
'balance' => $ledger->balance($user_id, \Jio\Ledger\AssetType::POINTS),
'replayed' => $deducted->replayed,
'message' => __('支付成功', 'aksrt'),
'message' => __('支付成功', 'jio'),
'reload' => true,
],
];
@@ -288,18 +288,18 @@ trait PayOrders {
$post = $assert['post'];
$meta = $assert['meta'];
$priced = $assert['priced'];
$content_type = \AKSRT\Core\DomainModel::resolve_order_product_type(\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE, ['pay_type' => $meta['pay_type'] ?? '']);
$content_type = \Jio\Core\DomainModel::resolve_order_product_type(\Jio\Core\DomainModel::ORDER_PRODUCT_RESOURCE, ['pay_type' => $meta['pay_type'] ?? '']);
if ((($priced['modo'] ?? '0') === 'points')) {
return new \WP_Error('aksrt_wrong_modo', __('该内容仅支持积分支付。', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_wrong_modo', __('该内容仅支持积分支付。', 'jio'), ['status' => 400]);
}
// Card pass cannot stack coupon (legacy). Content cashier does not sell via card_pass.
$payment_method = sanitize_key($payment_method);
if ($payment_method === 'card_pass') {
if (!function_exists('aksrt_is_content_card_pass_pay_allowed') || !aksrt_is_content_card_pass_pay_allowed($post)) {
if (!function_exists('jio_is_content_card_pass_pay_allowed') || !jio_is_content_card_pass_pay_allowed($post)) {
return new \WP_Error(
'aksrt_card_pass_not_allowed',
__('内容购买不支持卡密支付,请在用户中心使用卡密兑换余额/会员/积分。', 'aksrt'),
'jio_card_pass_not_allowed',
__('内容购买不支持卡密支付,请在用户中心使用卡密兑换余额/会员/积分。', 'jio'),
['status' => 400]
);
}
@@ -315,19 +315,19 @@ trait PayOrders {
$list_minor = max(0, (int) ($discounted['list_minor'] ?? $amount_minor));
$rebate_discount_minor = max(0, (int) ($discounted['rebate_discount_minor'] ?? 0));
$coupon_discount_minor = max(0, (int) ($discounted['coupon_discount_minor'] ?? 0));
$amount = \AKSRT\Ledger\AssetAmount::decimal_from_minor($amount_minor);
$list_amount = \AKSRT\Ledger\AssetAmount::decimal_from_minor($list_minor);
$rebate_discount = \AKSRT\Ledger\AssetAmount::decimal_from_minor($rebate_discount_minor);
$coupon_discount = \AKSRT\Ledger\AssetAmount::decimal_from_minor($coupon_discount_minor);
$amount = \Jio\Ledger\AssetAmount::decimal_from_minor($amount_minor);
$list_amount = \Jio\Ledger\AssetAmount::decimal_from_minor($list_minor);
$rebate_discount = \Jio\Ledger\AssetAmount::decimal_from_minor($rebate_discount_minor);
$coupon_discount = \Jio\Ledger\AssetAmount::decimal_from_minor($coupon_discount_minor);
$coupon_meta = is_array($discounted['coupon'] ?? null) ? $discounted['coupon'] : [];
$referrer_id = (int) ($discounted['referrer_id'] ?? 0);
$rebate_price_minor = max(0, (int) ($discounted['rebate_price_minor'] ?? 0));
$rebate_price = \AKSRT\Ledger\AssetAmount::decimal_from_minor($rebate_price_minor);
$rebate_price = \Jio\Ledger\AssetAmount::decimal_from_minor($rebate_price_minor);
if ($amount_minor <= 0) {
// Free after discount (or free content): create 0-paid order for access + burn coupon.
if (!class_exists('\AKSRT\Payment\Order') || !class_exists('\AKSRT\Payment\OrderRepository')) {
return new \WP_Error('aksrt_pay_unavailable', __('支付系统不可用。', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Order') || !class_exists('\Jio\Payment\OrderRepository')) {
return new \WP_Error('jio_pay_unavailable', __('支付系统不可用。', 'jio'), ['status' => 500]);
}
$note = wp_json_encode([
'content_pay' => 1,
@@ -347,11 +347,11 @@ trait PayOrders {
'payable' => '0.00',
'referrer_id' => $referrer_id,
'rebate_price' => '0.00',
'ip_address' => function_exists('aksrt_pay_client_ip') ? aksrt_pay_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? ''),
'ip_address' => function_exists('jio_pay_client_ip') ? jio_pay_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? ''),
'guest' => $user_id <= 0 ? 1 : 0,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$repo = \AKSRT\Payment\OrderRepository::get_instance();
$repo = \Jio\Payment\OrderRepository::get_instance();
$existing = $operation_key !== '' ? $repo->get_by_request_key($operation_key) : null;
$replayed = is_array($existing);
if (is_array($existing)) {
@@ -361,7 +361,7 @@ trait PayOrders {
|| sanitize_key((string) ($existing['payment_method'] ?? '')) !== 'free'
|| (string) ($existing['amount'] ?? '') !== '0.00'
) {
return new \WP_Error('aksrt_ledger_idempotency_conflict', __('相同操作标识已用于其他内容请求。', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_ledger_idempotency_conflict', __('相同操作标识已用于其他内容请求。', 'jio'), ['status' => 409]);
}
$order_number = (string) $existing['order_number'];
} else {
@@ -371,25 +371,25 @@ trait PayOrders {
'product_id' => $post_id,
'amount' => '0.00',
'currency' => 'CNY',
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
'status' => \Jio\Payment\Order::STATUS_PENDING,
'payment_method' => 'free',
'note' => is_string($note) ? $note : '',
'expires_at' => \AKSRT\Settings\PaymentRuntime::get_order_expiry_at(),
'expires_at' => \Jio\Settings\PaymentRuntime::get_order_expiry_at(),
'request_key' => $operation_key,
]);
}
if ($order_number === '') {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败。', 'jio'), ['status' => 500]);
}
$status = is_array($existing) ? (string) ($existing['status'] ?? '') : '';
if ($status !== \AKSRT\Payment\Order::STATUS_PAID) {
$paid = \AKSRT\Payment\Order::get_instance()->update_status($order_number, \AKSRT\Payment\Order::STATUS_PAID, [
if ($status !== \Jio\Payment\Order::STATUS_PAID) {
$paid = \Jio\Payment\Order::get_instance()->update_status($order_number, \Jio\Payment\Order::STATUS_PAID, [
'payment_method' => 'free',
'payment_transaction_id' => '',
'note' => __('优惠后无需支付。', 'aksrt'),
'note' => __('优惠后无需支付。', 'jio'),
]);
if (!$paid) {
return new \WP_Error('aksrt_order_confirm_failed', __('订单确认失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_confirm_failed', __('订单确认失败。', 'jio'), ['status' => 500]);
}
}
return [
@@ -401,14 +401,14 @@ trait PayOrders {
'free' => true,
'transaction_id' => '',
'replayed' => $replayed,
'message' => __('无需支付,已可访问。', 'aksrt'),
'message' => __('无需支付,已可访问。', 'jio'),
'reload' => true,
],
];
}
if (!class_exists('\AKSRT\Payment\Order') || !class_exists('\AKSRT\Payment\OrderRepository')) {
return new \WP_Error('aksrt_pay_unavailable', __('支付系统不可用。', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Order') || !class_exists('\Jio\Payment\OrderRepository')) {
return new \WP_Error('jio_pay_unavailable', __('支付系统不可用。', 'jio'), ['status' => 500]);
}
if ($payment_method === '') {
@@ -422,7 +422,7 @@ trait PayOrders {
$coupon_code_norm = (string) ($coupon_meta['code'] ?? $coupon_code);
// A retry resolves only through its request key; a new operation never reuses another pending order.
$pending = $operation_key !== '' ? \AKSRT\Payment\OrderRepository::get_instance()->get_by_request_key($operation_key) : null;
$pending = $operation_key !== '' ? \Jio\Payment\OrderRepository::get_instance()->get_by_request_key($operation_key) : null;
$can_resume = false;
if (is_array($pending)) {
$pending_meta = $this->decode_order_note_meta($pending);
@@ -440,7 +440,7 @@ trait PayOrders {
&& (int) ($pending_meta['post_id'] ?? 0) === $post_id
&& $pending_coupon === $coupon_code_norm;
if (!$can_resume) {
return new \WP_Error('aksrt_ledger_idempotency_conflict', __('相同操作标识已用于其他内容购买请求。', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_ledger_idempotency_conflict', __('相同操作标识已用于其他内容购买请求。', 'jio'), ['status' => 409]);
}
}
if ($can_resume) {
@@ -465,30 +465,30 @@ trait PayOrders {
'payable' => $amount_decimal,
'referrer_id' => $referrer_id,
'rebate_price' => $rebate_price,
'ip_address' => function_exists('aksrt_pay_client_ip') ? aksrt_pay_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? ''),
'ip_address' => function_exists('jio_pay_client_ip') ? jio_pay_client_ip() : (string) ($_SERVER['REMOTE_ADDR'] ?? ''),
'guest' => $user_id <= 0 ? 1 : 0,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$order_number = \AKSRT\Payment\OrderRepository::get_instance()->create([
$order_number = \Jio\Payment\OrderRepository::get_instance()->create([
'user_id' => max(0, $user_id),
'product_type' => $content_type,
'product_id' => $post_id,
'amount' => $amount_decimal,
'currency' => 'CNY',
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
'status' => \Jio\Payment\Order::STATUS_PENDING,
'payment_method' => $payment_method,
'note' => is_string($note) ? $note : '',
'expires_at' => \AKSRT\Settings\PaymentRuntime::get_order_expiry_at(),
'expires_at' => \Jio\Settings\PaymentRuntime::get_order_expiry_at(),
'request_key' => $operation_key,
]);
if ($order_number === '') {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败。', 'jio'), ['status' => 500]);
}
$order = \AKSRT\Payment\OrderRepository::get_instance()->get($order_number);
$order = \Jio\Payment\OrderRepository::get_instance()->get($order_number);
if (!$order) {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败。', 'jio'), ['status' => 500]);
}
}
@@ -496,7 +496,7 @@ trait PayOrders {
if ($payment_method === '') {
$payment_method = $user_id > 0 ? 'balance' : 'alipay';
}
if ($can_resume && (string) ($order['status'] ?? '') === \AKSRT\Payment\Order::STATUS_PAID) {
if ($can_resume && (string) ($order['status'] ?? '') === \Jio\Payment\Order::STATUS_PAID) {
return [
'success' => true,
'data' => [
@@ -504,8 +504,8 @@ trait PayOrders {
'amount' => $amount_decimal,
'pay_modo' => '0',
'replayed' => true,
'balance' => \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => __('支付成功', 'aksrt'),
'balance' => \Jio\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => __('支付成功', 'jio'),
'reload' => true,
],
];
@@ -513,38 +513,38 @@ trait PayOrders {
$order['subject'] = sprintf(
/* translators: %s: post title */
__('购买《%s》', 'aksrt'),
__('购买《%s》', 'jio'),
get_the_title($post_id)
);
$order['payment_method'] = $payment_method;
// Ensure gateway uses discounted amount.
$order['amount'] = $amount_decimal;
if (!class_exists('\AKSRT\Payment\Gateway')) {
return new \WP_Error('aksrt_pay_unavailable', __('支付网关不可用。', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Gateway')) {
return new \WP_Error('jio_pay_unavailable', __('支付网关不可用。', 'jio'), ['status' => 500]);
}
$resolved = \AKSRT\Payment\PaymentOrchestrator::resolve_gateway($payment_method);
$resolved = \Jio\Payment\PaymentOrchestrator::resolve_gateway($payment_method);
if (empty($resolved['gateway'])) {
return new \WP_Error(
(string) ($resolved['error_code'] ?? 'aksrt_gateway_unavailable'),
(string) ($resolved['message'] ?? __('当前支付方式不可用。', 'aksrt')),
(string) ($resolved['error_code'] ?? 'jio_gateway_unavailable'),
(string) ($resolved['message'] ?? __('当前支付方式不可用。', 'jio')),
['status' => 400, 'order_number' => $order_number]
);
}
$payment_result = \AKSRT\Payment\PaymentOrchestrator::pay($resolved['gateway'], $order, [
'paid_note' => __('用户完成内容购买支付。', 'aksrt'),
$payment_result = \Jio\Payment\PaymentOrchestrator::pay($resolved['gateway'], $order, [
'paid_note' => __('用户完成内容购买支付。', 'jio'),
]);
if (empty($payment_result['success'])) {
return new \WP_Error(
(string) ($payment_result['code'] ?? 'aksrt_pay_failed'),
(string) ($payment_result['message'] ?? __('支付失败。', 'aksrt')),
(string) ($payment_result['code'] ?? 'jio_pay_failed'),
(string) ($payment_result['message'] ?? __('支付失败。', 'jio')),
['status' => (int) ($payment_result['status'] ?? 400), 'order_number' => $order_number]
);
}
$cashier = \AKSRT\Payment\PaymentOrchestrator::cashier_payload($payment_result);
$cashier = \Jio\Payment\PaymentOrchestrator::cashier_payload($payment_result);
if ($cashier !== []) {
return [
'success' => true,
@@ -566,7 +566,7 @@ trait PayOrders {
'amount' => $amount_decimal,
'pay_modo' => '0',
'replayed' => !empty($payment_result['replayed']),
'balance' => $user_id > 0 ? \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id) : '0.00',
'balance' => $user_id > 0 ? \Jio\Ledger\LedgerService::get_instance()->balance_decimal($user_id) : '0.00',
'message' => $payment_result['message'],
'reload' => true,
],
@@ -579,16 +579,16 @@ trait PayOrders {
* @return array<string,mixed>|null
*/
private function find_pending_content_order(int $user_id, int $post_id): ?array {
if ($user_id <= 0 || $post_id <= 0 || !class_exists('\AKSRT\Payment\OrderRepository')) {
if ($user_id <= 0 || $post_id <= 0 || !class_exists('\Jio\Payment\OrderRepository')) {
return null;
}
$orders = \AKSRT\Payment\OrderRepository::get_instance()->get_user_orders($user_id, [
'status' => \AKSRT\Core\DomainModel::ORDER_STATUS_PENDING,
$orders = \Jio\Payment\OrderRepository::get_instance()->get_user_orders($user_id, [
'status' => \Jio\Core\DomainModel::ORDER_STATUS_PENDING,
'limit' => 20,
'offset' => 0,
]);
foreach ($orders as $order) {
if ((int) ($order['product_id'] ?? 0) === $post_id && \AKSRT\Core\DomainModel::is_resource_product_type((string) ($order['product_type'] ?? ''))) {
if ((int) ($order['product_id'] ?? 0) === $post_id && \Jio\Core\DomainModel::is_resource_product_type((string) ($order['product_type'] ?? ''))) {
return $order;
}
}
+22 -22
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -12,7 +12,7 @@ trait PayRest {
public function register_routes(): void {
register_rest_route('aksrt/v1', '/pay/content/(?P<id>\d+)', [
register_rest_route('jio/v1', '/pay/content/(?P<id>\d+)', [
[
'methods' => 'GET',
'callback' => [$this, 'rest_preview'],
@@ -37,7 +37,7 @@ trait PayRest {
],
]);
register_rest_route('aksrt/v1', '/pay/order/(?P<order_number>[A-Za-z0-9_-]+)', [
register_rest_route('jio/v1', '/pay/order/(?P<order_number>[A-Za-z0-9_-]+)', [
'methods' => 'GET',
'callback' => [$this, 'rest_order_status'],
'permission_callback' => [$this, 'check_rest_nonce'],
@@ -64,10 +64,10 @@ trait PayRest {
public function check_rest_nonce(\WP_REST_Request $request) {
$nonce = $request->get_header('x-wp-nonce');
if (!$nonce) {
return new \WP_Error('aksrt_rest_no_nonce', __('缺少安全令牌', 'aksrt'), ['status' => 403]);
return new \WP_Error('jio_rest_no_nonce', __('缺少安全令牌', 'jio'), ['status' => 403]);
}
if (!wp_verify_nonce($nonce, 'wp_rest')) {
return new \WP_Error('aksrt_rest_bad_nonce', __('安全令牌已过期,请刷新页面', 'aksrt'), ['status' => 403]);
return new \WP_Error('jio_rest_bad_nonce', __('安全令牌已过期,请刷新页面', 'jio'), ['status' => 403]);
}
return true;
}
@@ -102,7 +102,7 @@ trait PayRest {
public function rest_purchase(\WP_REST_Request $request) {
$post_id = (int) $request['id'];
$uid = get_current_user_id();
$operation_key = \AKSRT\Ledger\OperationKey::from_request($request, 'content-purchase', $uid);
$operation_key = \Jio\Ledger\OperationKey::from_request($request, 'content-purchase', $uid);
if (is_wp_error($operation_key)) {
return $operation_key;
}
@@ -121,9 +121,9 @@ trait PayRest {
// Guest allowed only for cash + pay_limit=0 + setting on.
if ($uid <= 0) {
$post = get_post($post_id);
$allow_guest = function_exists('aksrt_allow_guest_content_pay') && aksrt_allow_guest_content_pay($post);
$allow_guest = function_exists('jio_allow_guest_content_pay') && jio_allow_guest_content_pay($post);
if (!$allow_guest) {
return new \WP_Error('aksrt_need_login', __('请先登录后再购买。', 'aksrt'), [
return new \WP_Error('jio_need_login', __('请先登录后再购买。', 'jio'), [
'status' => 401,
'login_url' => wp_login_url($post ? get_permalink($post) : home_url('/')),
]);
@@ -144,7 +144,7 @@ trait PayRest {
}
if ($mode === 'points' || $pay_modo === 'points') {
if ($uid <= 0) {
return new \WP_Error('aksrt_need_login', __('积分支付请先登录。', 'aksrt'), ['status' => 401]);
return new \WP_Error('jio_need_login', __('积分支付请先登录。', 'jio'), ['status' => 401]);
}
// Point purchases do not support coupons.
return $this->rest_wrap_result($this->create_and_pay_points($post_id, $uid, $price_type, $operation_key));
@@ -169,32 +169,32 @@ trait PayRest {
public function rest_order_status(\WP_REST_Request $request) {
$uid = get_current_user_id();
$order_number = sanitize_text_field((string) $request['order_number']);
if ($order_number === '' || !class_exists('\AKSRT\Payment\OrderRepository')) {
return new \WP_Error('aksrt_invalid', __('订单不存在', 'aksrt'), ['status' => 404]);
if ($order_number === '' || !class_exists('\Jio\Payment\OrderRepository')) {
return new \WP_Error('jio_invalid', __('订单不存在', 'jio'), ['status' => 404]);
}
$repo = \AKSRT\Payment\OrderRepository::get_instance();
$repo = \Jio\Payment\OrderRepository::get_instance();
if ($uid > 0) {
$order = $repo->get_user_order($uid, $order_number);
} else {
$order = $repo->get($order_number);
// Guest may only poll own guest cash orders (user_id=0): content resource.
$ptype = sanitize_key((string) ($order['product_type'] ?? ''));
$guest_types = \AKSRT\Core\DomainModel::resource_order_product_types();
$guest_types = \Jio\Core\DomainModel::resource_order_product_types();
if ($order && ((int) ($order['user_id'] ?? -1) !== 0 || !in_array($ptype, $guest_types, true))) {
$order = null;
}
}
if (!$order) {
return new \WP_Error('aksrt_invalid', __('订单不存在', 'aksrt'), ['status' => 404]);
return new \WP_Error('jio_invalid', __('订单不存在', 'jio'), ['status' => 404]);
}
if (class_exists('\AKSRT\Payment\Gateway')) {
$order = \AKSRT\Payment\Gateway::get_instance()->reconcile_order($order_number, $order) ?: $order;
if (class_exists('\Jio\Payment\Gateway')) {
$order = \Jio\Payment\Gateway::get_instance()->reconcile_order($order_number, $order) ?: $order;
}
$status = (string) ($order['status'] ?? '');
$paid = class_exists('\AKSRT\Core\DomainModel') && \AKSRT\Core\DomainModel::is_paid_order_status($status);
if ($paid && $uid <= 0 && function_exists('aksrt_set_guest_pay_cookies')) {
$paid = class_exists('\Jio\Core\DomainModel') && \Jio\Core\DomainModel::is_paid_order_status($status);
if ($paid && $uid <= 0 && function_exists('jio_set_guest_pay_cookies')) {
// Ensure cookie set even if notify raced ahead of browser cookie.
aksrt_set_guest_pay_cookies($order);
jio_set_guest_pay_cookies($order);
}
return new \WP_REST_Response([
'order_number' => $order_number,
@@ -219,9 +219,9 @@ trait PayRest {
return $result;
}
if (empty($result['success'])) {
$code = sanitize_key((string) ($result['code'] ?? 'aksrt_pay_failed'));
$code = sanitize_key((string) ($result['code'] ?? 'jio_pay_failed'));
$status = (int) ($result['status'] ?? 400);
return new \WP_Error($code !== '' ? $code : 'aksrt_pay_failed', (string) ($result['message'] ?? __('支付失败', 'aksrt')), array_merge(
return new \WP_Error($code !== '' ? $code : 'jio_pay_failed', (string) ($result['message'] ?? __('支付失败', 'jio')), array_merge(
['status' => $status > 0 ? $status : 400],
is_array($result['data'] ?? null) ? $result['data'] : []
));
+5 -5
View File
@@ -2,10 +2,10 @@
/**
* VIP membership event persistence.
*
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -14,14 +14,14 @@ final class VipMembershipEventRepository {
private string $table;
public function __construct() {
$this->table = \AKSRT\Core\DBMigrator::table('vip_membership_event');
$this->table = \Jio\Core\DBMigrator::table('vip_membership_event');
}
/** @param array<string,mixed> $event */
public function begin(array $event): string|\WP_Error {
global $wpdb;
if ($this->table === '') {
return new \WP_Error('aksrt_vip_audit_unavailable', __('会员变更审计表不可用。', 'aksrt'));
return new \WP_Error('jio_vip_audit_unavailable', __('会员变更审计表不可用。', 'jio'));
}
$uuid = wp_generate_uuid4();
$inserted = $wpdb->insert($this->table, [
@@ -37,7 +37,7 @@ final class VipMembershipEventRepository {
'status' => 'pending',
'created_at' => current_time('mysql', true),
]);
return $inserted === 1 ? $uuid : new \WP_Error('aksrt_vip_audit_begin_failed', __('无法创建会员变更审计记录。', 'aksrt'));
return $inserted === 1 ? $uuid : new \WP_Error('jio_vip_audit_begin_failed', __('无法创建会员变更审计记录。', 'jio'));
}
/** @param array<string,mixed> $after */
+22 -22
View File
@@ -2,16 +2,16 @@
/**
* VIP layered membership expiry and recovery service.
*
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
final class VipMembershipExpiry {
public const CRON_HOOK = 'aksrt_vip_membership_expiry';
public const CRON_HOOK = 'jio_vip_membership_expiry';
private const BATCH_SIZE = 100;
public static function init(): void {
@@ -30,12 +30,12 @@ final class VipMembershipExpiry {
$now = time();
$rows = $wpdb->get_col($wpdb->prepare(
"SELECT DISTINCT um.user_id FROM {$wpdb->usermeta} um
WHERE um.meta_key = 'aksrt_vip_level'
WHERE um.meta_key = 'jio_vip_level'
AND CAST(um.meta_value AS UNSIGNED) > 0
AND EXISTS (
SELECT 1 FROM {$wpdb->usermeta} expiry
WHERE expiry.user_id = um.user_id
AND expiry.meta_key = 'aksrt_vip_expires'
AND expiry.meta_key = 'jio_vip_expires'
AND CAST(expiry.meta_value AS UNSIGNED) > 0
AND CAST(expiry.meta_value AS UNSIGNED) <= %d
)
@@ -55,7 +55,7 @@ final class VipMembershipExpiry {
*/
public static function process_user(int $user_id, string $source = 'resolver', string $reason = ''): array|\WP_Error {
if ($user_id <= 0 || !get_userdata($user_id)) {
return new \WP_Error('aksrt_vip_user_missing', __('用户不存在。', 'aksrt'));
return new \WP_Error('jio_vip_user_missing', __('用户不存在。', 'jio'));
}
$before = self::snapshot($user_id);
if ($before['level'] <= 0 || $before['expires'] <= 0 || $before['expires'] > time()) {
@@ -68,7 +68,7 @@ final class VipMembershipExpiry {
'actor_user_id' => 0,
'operation' => 'expire_recover',
'source' => $source,
'reason' => $reason !== '' ? $reason : __('会员当前层到期处理', 'aksrt'),
'reason' => $reason !== '' ? $reason : __('会员当前层到期处理', 'jio'),
'request' => ['now' => time()],
'before' => $before,
]);
@@ -79,15 +79,15 @@ final class VipMembershipExpiry {
$fallback_valid = $before['base_level'] > 0
&& ($before['base_expires'] === 0 || $before['base_expires'] > time());
if ($fallback_valid) {
update_user_meta($user_id, 'aksrt_vip_level', $before['base_level']);
update_user_meta($user_id, 'aksrt_vip_expires', $before['base_expires']);
update_user_meta($user_id, 'jio_vip_level', $before['base_level']);
update_user_meta($user_id, 'jio_vip_expires', $before['base_expires']);
} else {
update_user_meta($user_id, 'aksrt_vip_level_expired', max($before['expired_level'], $before['level']));
update_user_meta($user_id, 'aksrt_vip_level', 0);
update_user_meta($user_id, 'aksrt_vip_expires', 0);
update_user_meta($user_id, 'jio_vip_level_expired', max($before['expired_level'], $before['level']));
update_user_meta($user_id, 'jio_vip_level', 0);
update_user_meta($user_id, 'jio_vip_expires', 0);
}
delete_user_meta($user_id, 'aksrt_vip_base_level');
delete_user_meta($user_id, 'aksrt_vip_base_expires');
delete_user_meta($user_id, 'jio_vip_base_level');
delete_user_meta($user_id, 'jio_vip_base_expires');
$after = self::snapshot($user_id);
$expected_level = $fallback_valid ? $before['base_level'] : 0;
@@ -95,30 +95,30 @@ final class VipMembershipExpiry {
if ($after['level'] !== $expected_level || $after['expires'] !== $expected_expires || $after['base_level'] !== 0 || $after['base_expires'] !== 0) {
self::restore($user_id, $before);
$after = self::snapshot($user_id);
$error = new \WP_Error('aksrt_vip_expiry_write_failed', __('会员到期状态保存失败。', 'aksrt'));
$error = new \WP_Error('jio_vip_expiry_write_failed', __('会员到期状态保存失败。', 'jio'));
$repository->complete($event_uuid, 'failed', $after, $error->get_error_code(), $error->get_error_message());
return $error;
}
$repository->complete($event_uuid, 'succeeded', $after);
do_action('aksrt_vip_membership_expired', $user_id, $before, $after, $source, $event_uuid);
do_action('jio_vip_membership_expired', $user_id, $before, $after, $source, $event_uuid);
return ['changed' => true, 'before' => $before, 'after' => $after];
}
/** @return array{level:int,expires:int,base_level:int,base_expires:int,expired_level:int} */
public static function snapshot(int $user_id): array {
return [
'level' => max(0, min(2, (int) get_user_meta($user_id, 'aksrt_vip_level', true))),
'expires' => max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true)),
'base_level' => max(0, min(2, (int) get_user_meta($user_id, 'aksrt_vip_base_level', true))),
'base_expires' => max(0, (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true)),
'expired_level' => max(0, min(2, (int) get_user_meta($user_id, 'aksrt_vip_level_expired', true))),
'level' => max(0, min(2, (int) get_user_meta($user_id, 'jio_vip_level', true))),
'expires' => max(0, (int) get_user_meta($user_id, 'jio_vip_expires', true)),
'base_level' => max(0, min(2, (int) get_user_meta($user_id, 'jio_vip_base_level', true))),
'base_expires' => max(0, (int) get_user_meta($user_id, 'jio_vip_base_expires', true)),
'expired_level' => max(0, min(2, (int) get_user_meta($user_id, 'jio_vip_level_expired', true))),
];
}
/** @param array<string,int> $snapshot */
private static function restore(int $user_id, array $snapshot): void {
foreach (['level' => 'aksrt_vip_level', 'expires' => 'aksrt_vip_expires', 'base_level' => 'aksrt_vip_base_level', 'base_expires' => 'aksrt_vip_base_expires', 'expired_level' => 'aksrt_vip_level_expired'] as $key => $meta_key) {
foreach (['level' => 'jio_vip_level', 'expires' => 'jio_vip_expires', 'base_level' => 'jio_vip_base_level', 'base_expires' => 'jio_vip_base_expires', 'expired_level' => 'jio_vip_level_expired'] as $key => $meta_key) {
$value = (int) ($snapshot[$key] ?? 0);
if ($value > 0 || in_array($key, ['level', 'expires'], true)) {
update_user_meta($user_id, $meta_key, $value);
+2 -2
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
+30 -30
View File
@@ -2,10 +2,10 @@
/**
* Administrator membership mutations.
*
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -14,25 +14,25 @@ trait VipServiceMembership {
/** @return array{level:int,expires:int,base_level:int,base_expires:int,expired_level:int} */
public function get_membership_snapshot(int $user_id): array {
return [
'level' => max(0, min(2, (int) get_user_meta($user_id, 'aksrt_vip_level', true))),
'expires' => max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true)),
'base_level' => max(0, min(2, (int) get_user_meta($user_id, 'aksrt_vip_base_level', true))),
'base_expires' => max(0, (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true)),
'expired_level' => max(0, min(2, (int) get_user_meta($user_id, 'aksrt_vip_level_expired', true))),
'level' => max(0, min(2, (int) get_user_meta($user_id, 'jio_vip_level', true))),
'expires' => max(0, (int) get_user_meta($user_id, 'jio_vip_expires', true)),
'base_level' => max(0, min(2, (int) get_user_meta($user_id, 'jio_vip_base_level', true))),
'base_expires' => max(0, (int) get_user_meta($user_id, 'jio_vip_base_expires', true)),
'expired_level' => max(0, min(2, (int) get_user_meta($user_id, 'jio_vip_level_expired', true))),
];
}
/** @param array<string,mixed> $payload @param array<string,mixed> $context */
public function mutate_membership(int $user_id, string $operation, array $payload, array $context = []): array|\WP_Error {
if ($user_id <= 0 || !get_userdata($user_id)) {
return new \WP_Error('aksrt_vip_user_missing', __('用户不存在。', 'aksrt'));
return new \WP_Error('jio_vip_user_missing', __('用户不存在。', 'jio'));
}
if (!in_array($operation, ['set', 'extend', 'disable', 'restore'], true)) {
return new \WP_Error('aksrt_vip_operation_invalid', __('会员操作无效。', 'aksrt'));
return new \WP_Error('jio_vip_operation_invalid', __('会员操作无效。', 'jio'));
}
$reason = sanitize_text_field((string) ($context['reason'] ?? ''));
if ($reason === '') {
return new \WP_Error('aksrt_vip_reason_required', __('请填写变更原因。', 'aksrt'));
return new \WP_Error('jio_vip_reason_required', __('请填写变更原因。', 'jio'));
}
$before = $this->get_membership_snapshot($user_id);
@@ -57,37 +57,37 @@ trait VipServiceMembership {
return $target;
}
delete_user_meta($user_id, 'aksrt_vip_base_level');
delete_user_meta($user_id, 'aksrt_vip_base_expires');
delete_user_meta($user_id, 'aksrt_vip_level_expired');
update_user_meta($user_id, 'aksrt_vip_level', $target['level']);
update_user_meta($user_id, 'aksrt_vip_expires', $target['expires']);
delete_user_meta($user_id, 'jio_vip_base_level');
delete_user_meta($user_id, 'jio_vip_base_expires');
delete_user_meta($user_id, 'jio_vip_level_expired');
update_user_meta($user_id, 'jio_vip_level', $target['level']);
update_user_meta($user_id, 'jio_vip_expires', $target['expires']);
$after = $this->get_membership_snapshot($user_id);
if ($after['level'] !== $target['level'] || $after['expires'] !== $target['expires'] || $after['base_level'] !== 0 || $after['base_expires'] !== 0 || $after['expired_level'] !== 0) {
$this->restore_membership_snapshot($user_id, $before);
$after = $this->get_membership_snapshot($user_id);
$error = new \WP_Error('aksrt_vip_write_failed', __('会员状态保存失败。', 'aksrt'));
$error = new \WP_Error('jio_vip_write_failed', __('会员状态保存失败。', 'jio'));
$repository->complete($event_uuid, 'failed', $after, $error->get_error_code(), $error->get_error_message());
return $error;
}
unset($this->vip_member_cache[$user_id], $this->vip_catalog_cache[$user_id]);
$repository->complete($event_uuid, 'succeeded', $after);
do_action('aksrt_vip_membership_mutated', $user_id, $operation, $before, $after, $context, $event_uuid);
do_action('jio_vip_membership_mutated', $user_id, $operation, $before, $after, $context, $event_uuid);
return ['event_uuid' => $event_uuid, 'before' => $before, 'after' => $after];
}
/** @param array<string,mixed> $snapshot */
private function restore_membership_snapshot(int $user_id, array $snapshot): void {
foreach ([
'aksrt_vip_level' => 'level',
'aksrt_vip_expires' => 'expires',
'aksrt_vip_base_level' => 'base_level',
'aksrt_vip_base_expires' => 'base_expires',
'aksrt_vip_level_expired' => 'expired_level',
'jio_vip_level' => 'level',
'jio_vip_expires' => 'expires',
'jio_vip_base_level' => 'base_level',
'jio_vip_base_expires' => 'base_expires',
'jio_vip_level_expired' => 'expired_level',
] as $meta_key => $snapshot_key) {
$value = (int) ($snapshot[$snapshot_key] ?? 0);
if ($value > 0 || $meta_key === 'aksrt_vip_level' || ($meta_key === 'aksrt_vip_expires' && (int) ($snapshot['level'] ?? 0) > 0)) {
if ($value > 0 || $meta_key === 'jio_vip_level' || ($meta_key === 'jio_vip_expires' && (int) ($snapshot['level'] ?? 0) > 0)) {
update_user_meta($user_id, $meta_key, $value);
} else {
delete_user_meta($user_id, $meta_key);
@@ -101,7 +101,7 @@ trait VipServiceMembership {
$level = max(0, min(2, (int) $before['base_level']));
$expires = max(0, (int) $before['base_expires']);
if ($level <= 0 || ($expires > 0 && $expires <= time())) {
return new \WP_Error('aksrt_vip_restore_unavailable', __('没有有效的回退会员可恢复。', 'aksrt'));
return new \WP_Error('jio_vip_restore_unavailable', __('没有有效的回退会员可恢复。', 'jio'));
}
return ['level' => $level, 'expires' => $expires];
}
@@ -111,30 +111,30 @@ trait VipServiceMembership {
if ($operation === 'set') {
$level = (int) ($payload['level'] ?? 0);
if (!in_array($level, [1, 2], true)) {
return new \WP_Error('aksrt_vip_level_invalid', __('会员档位无效。', 'aksrt'));
return new \WP_Error('jio_vip_level_invalid', __('会员档位无效。', 'jio'));
}
$expires = (int) ($payload['expires'] ?? -1);
if ($expires < 0 || ($expires > 0 && $expires < time())) {
return new \WP_Error('aksrt_vip_expiry_invalid', __('到期时间无效或已过期。', 'aksrt'));
return new \WP_Error('jio_vip_expiry_invalid', __('到期时间无效或已过期。', 'jio'));
}
return ['level' => $level, 'expires' => $expires];
}
$amount = (int) ($payload['amount'] ?? 0);
$unit = sanitize_key((string) ($payload['unit'] ?? 'day'));
if ($before['level'] < 1) {
return new \WP_Error('aksrt_vip_extend_unavailable', __('无有效会员,无法延长。', 'aksrt'));
return new \WP_Error('jio_vip_extend_unavailable', __('无有效会员,无法延长。', 'jio'));
}
if ($before['expires'] <= 0) {
return new \WP_Error('aksrt_vip_extend_permanent', __('永久会员无需延长。', 'aksrt'));
return new \WP_Error('jio_vip_extend_permanent', __('永久会员无需延长。', 'jio'));
}
if ($amount < 1 || $amount > 3650 || !in_array($unit, ['day', 'month'], true)) {
return new \WP_Error('aksrt_vip_duration_invalid', __('延长时长无效。', 'aksrt'));
return new \WP_Error('jio_vip_duration_invalid', __('延长时长无效。', 'jio'));
}
$base = max(time(), $before['expires']);
$date = (new \DateTimeImmutable('@' . $base))->setTimezone(wp_timezone());
$next = $date->modify('+' . $amount . ' ' . ($unit === 'month' ? 'months' : 'days'));
if (!$next) {
return new \WP_Error('aksrt_vip_duration_invalid', __('无法计算新的到期时间。', 'aksrt'));
return new \WP_Error('jio_vip_duration_invalid', __('无法计算新的到期时间。', 'jio'));
}
return ['level' => $before['level'], 'expires' => $next->getTimestamp()];
}
+31 -31
View File
@@ -2,10 +2,10 @@
/**
* VIP modal view model + card HTML (legacy pay-vip modal / vip-card parity).
*
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -33,8 +33,8 @@ trait VipServiceModal {
continue;
}
$equity = (string) ($levels[$level]['equity'] ?? '');
$equity = function_exists('aksrt_format_vip_equity_html')
? (string) aksrt_format_vip_equity_html($equity)
$equity = function_exists('jio_format_vip_equity_html')
? (string) jio_format_vip_equity_html($equity)
: wp_kses_post($equity);
$level_view[] = [
'level' => $level,
@@ -136,7 +136,7 @@ trait VipServiceModal {
'levels' => $level_view,
'payment_methods' => $methods,
'card_pass' => $card_pass,
'currency_mark' => (string) (\AKSRT\Settings\Settings::get_payment_gateway_settings()['currency']['mark'] ?? '¥'),
'currency_mark' => (string) (\Jio\Settings\Settings::get_payment_gateway_settings()['currency']['mark'] ?? '¥'),
'allowed_actions' => [
'purchase' => $package_ids !== [] && $methods !== [],
'renew' => $has_renew && $methods !== [],
@@ -164,23 +164,23 @@ trait VipServiceModal {
* 与余额充值/购买积分弹窗同构(静止态由 vip-modal.css 显式隐藏,打开态由
* pay-vip.js 的自包含开关以内联 display:flex 驱动)。
*
* 入口有两处(均带 data-aksrt-vip-points-open,pay-vip.js 文档级委托开合):
* 入口有两处(均带 data-jio-vip-points-open,pay-vip.js 文档级委托开合):
* 会员购买弹窗内的「积分兑换会员」按钮,以及 /user/vip/ 档位购买卡下方的
* 入口横条(aksrt_get_vip_points_exchange_entry_html)。.pay-vip 触发点
* 全站可见,因此由 aksrt_render_vip_points_exchange_modal() 在 wp_footer
* 入口横条(jio_get_vip_points_exchange_entry_html)。.pay-vip 触发点
* 全站可见,因此由 jio_render_vip_points_exchange_modal() 在 wp_footer
* 全局输出一次。
*
* @return string 空串表示积分兑换不可用(不输出弹窗壳)。
*/
public function get_points_exchange_modal_html(int $user_id = 0): string {
$user_id = max(0, $user_id);
if ($user_id <= 0 || !class_exists('\AKSRT\Settings\Settings')) {
if ($user_id <= 0 || !class_exists('\Jio\Settings\Settings')) {
return '';
}
// 先做零成本门控,避免每次页面渲染都去查积分余额。
$vip = $this->get_vip_settings_context();
if (empty($vip['enabled']) || empty($vip['points_exchange']['enabled']) || !\AKSRT\Settings\Settings::credits_enabled()) {
if (empty($vip['enabled']) || empty($vip['points_exchange']['enabled']) || !\Jio\Settings\Settings::credits_enabled()) {
return '';
}
@@ -193,9 +193,9 @@ trait VipServiceModal {
$levels = is_array($vip['levels'] ?? null) ? $vip['levels'] : [];
$user_points = max(0, (int) ($catalog['user_points'] ?? 0));
$currency = (string) ($catalog['currency_name'] ?? __('积分', 'aksrt'));
$points_center_url = function_exists('aksrt_get_user_center_tab_url')
? aksrt_get_user_center_tab_url('credits')
$currency = (string) ($catalog['currency_name'] ?? __('积分', 'jio'));
$points_center_url = function_exists('jio_get_user_center_tab_url')
? jio_get_user_center_tab_url('credits')
: home_url('/');
// 会员卡片(参考主题 data-for/data-value 选中模型;data-value 为本主题的套餐 ID)。
@@ -220,8 +220,8 @@ trait VipServiceModal {
$pkg_time = max(0, (int) ($package['time'] ?? 0));
$pkg_unit = ((string) ($package['unit'] ?? 'day')) === 'month' ? 'month' : 'day';
$duration = ($is_permanent || $pkg_time <= 0)
? esc_html__('永久', 'aksrt')
: (string) $pkg_time . '<span class="px12">' . esc_html($pkg_unit === 'month' ? __('个月', 'aksrt') : __('天', 'aksrt')) . '</span>';
? esc_html__('永久', 'jio')
: (string) $pkg_time . '<span class="px12">' . esc_html($pkg_unit === 'month' ? __('个月', 'jio') : __('天', 'jio')) . '</span>';
$level_name = (string) ($levels[$level]['name_html'] ?? $levels[$level]['name'] ?? ('VIP' . $level));
$cards .= '<div class="vip-card vip-theme' . $level . ($index === 0 ? ' active' : '') . ' " data-for="product_id" data-value="' . $package_id . '">'
@@ -243,7 +243,7 @@ trait VipServiceModal {
$desc = $desc_text !== ''
// 管理员编辑的富文本说明:保存端已 wp_kses_post,这里同级别输出
// (参考主题 zibpay_get_vip_points_exchange_modal 原样拼接)。
? '<div class="muted-box muted-2-color padding-10 em09 mt20 aksrt-vip-points-desc">' . wp_kses_post($desc_text) . '</div>'
? '<div class="muted-box muted-2-color padding-10 em09 mt20 jio-vip-points-desc">' . wp_kses_post($desc_text) . '</div>'
: '';
// 最低价套餐仍超出用户积分 → 参考主题的 badg c-red btn-block 提示。
@@ -251,41 +251,41 @@ trait VipServiceModal {
// 此处按其原意取真实比较,保证提示分支可达。)
if ($min_points > $user_points) {
$form = '<div class="mt20"><div class="badg c-red btn-block">'
. esc_html(sprintf(__('%s不足,暂时无法兑换', 'aksrt'), $currency))
. esc_html(sprintf(__('%s不足,暂时无法兑换', 'jio'), $currency))
. '</div></div>';
} else {
$form = '<div class="mt20">'
. '<input type="hidden" name="product_id" value="' . $first_package_id . '">'
. '<input type="hidden" name="order_type" value="4">'
. '<input type="hidden" name="action" value="points_initiate_pay">'
. '<button type="submit" class="mt6 but jb-yellow btn-block radius padding-lg" data-aksrt-vip-points-submit>'
. '<i class="fa fas fa-check" aria-hidden="true"></i>' . esc_html__('立即兑换', 'aksrt')
. '<button type="submit" class="mt6 but jb-yellow btn-block radius padding-lg" data-jio-vip-points-submit>'
. '<i class="fa fas fa-check" aria-hidden="true"></i>' . esc_html__('立即兑换', 'jio')
. '</button></div>';
}
$header = '<div class="mb10 touch">'
. '<button type="button" class="close" data-dismiss="modal" aria-label="' . esc_attr__('关闭', 'aksrt') . '">'
. '<button type="button" class="close" data-dismiss="modal" aria-label="' . esc_attr__('关闭', 'jio') . '">'
. '<svg class="ic-close" aria-hidden="true"><use xlink:href="#icon-close"></use></svg></button>'
. '<b class="modal-title flex ac"><span class="mr6 em14">'
. '<svg class="icon" aria-hidden="true"><use xlink:href="#icon-vip_1"></use></svg></span>'
. esc_html(sprintf(__('%s兑换会员', 'aksrt'), $currency)) . '</b></div>';
. esc_html(sprintf(__('%s兑换会员', 'jio'), $currency)) . '</b></div>';
$user_box = '<div class="muted-box padding-h10 mb20">'
. '<a rel="nofollow" class="flex jsb ac" href="' . esc_url($points_center_url) . '">'
. '<span class="muted-2-color">'
. '<svg class="icon" aria-hidden="true"><use xlink:href="#icon-points"></use></svg> '
. esc_html(sprintf(__('我的%s', 'aksrt'), $currency)) . '</span>'
. esc_html(sprintf(__('我的%s', 'jio'), $currency)) . '</span>'
. '<span class="font-bold ml6 em14"><span class="c-green mr10">' . $user_points . '</span>'
. '<i class="fa fas fa-angle-right" aria-hidden="true"></i></span></a></div>';
$lists = '<div class="muted-2-color mb6 em09">' . esc_html__('请选择需兑换的会员', 'aksrt') . '</div>'
$lists = '<div class="muted-2-color mb6 em09">' . esc_html__('请选择需兑换的会员', 'jio') . '</div>'
. '<div class="flex hh exchange-card-box">' . $cards . '</div>';
return '<div class="modal flex jc fade" id="aksrt-vip-points-modal" tabindex="-1" role="dialog" aria-hidden="false" data-aksrt-vip-points-modal>'
return '<div class="modal flex jc fade" id="jio-vip-points-modal" tabindex="-1" role="dialog" aria-hidden="false" data-jio-vip-points-modal>'
. '<div class="modal-dialog modal-mini full-sm" role="document">'
. '<div class="modal-content"><div class="modal-body">'
. $header
. '<form class="" data-aksrt-vip-points-form>' . $user_box . $lists . $desc . $form . '</form>'
. '<form class="" data-jio-vip-points-form>' . $user_box . $lists . $desc . $form . '</form>'
. '</div></div></div></div>';
}
@@ -301,7 +301,7 @@ trait VipServiceModal {
return '<i class="fa fas fa-certificate mr3" aria-hidden="true"></i>';
}
return '<img' . aksrt_get_lazy_attr('lazy_other', $icon_url, 'img-icon mr3')
return '<img' . jio_get_lazy_attr('lazy_other', $icon_url, 'img-icon mr3')
. ' title="' . esc_attr($name_text) . '" alt="' . esc_attr($name_text) . '">';
}
@@ -324,7 +324,7 @@ trait VipServiceModal {
}
/**
* Mini hover card for header (legacy aksrtpay_get_vip_card).
* Mini hover card for header (legacy jiopay_get_vip_card).
*/
public function render_vip_card(int $level, int $user_id = 0): string {
$level = max(1, min(2, $level));
@@ -338,13 +338,13 @@ trait VipServiceModal {
$equity = (string) ($levels[$level]['equity'] ?? '');
$cls = $user_id > 0 ? ' pay-vip' : ' signin-loader';
$equity_html = $equity !== '' && function_exists('aksrt_format_vip_equity_html')
? aksrt_format_vip_equity_html($equity, 'mb10 relative')
$equity_html = $equity !== '' && function_exists('jio_format_vip_equity_html')
? jio_format_vip_equity_html($equity, 'mb10 relative')
: ($equity !== '' ? '<div class="v-equity mb10 relative">' . wp_kses_post($equity) . '</div>' : '');
$icon_url = esc_url((string) ($levels[$level]['img_icon'] ?? ''));
$icon = $icon_url !== ''
? '<img' . aksrt_get_lazy_attr('lazy_other', $icon_url, 'img-icon') . ' title="' . esc_attr($name_text) . '" alt="' . esc_attr($name_text) . '" decoding="async">'
? '<img' . jio_get_lazy_attr('lazy_other', $icon_url, 'img-icon') . ' title="' . esc_attr($name_text) . '" alt="' . esc_attr($name_text) . '" decoding="async">'
: '<i class="fa fas fa-gem" aria-hidden="true"></i>';
$html = '<div class="vip-card pointer level-' . $level . ' vip-theme' . $level . $cls . '" vip-level="' . $level . '">';
$html .= '<div class="abs-center vip-baicon" aria-hidden="true">' . $icon . '</div>';
@@ -353,7 +353,7 @@ trait VipServiceModal {
$html .= '<div class="vip-name mb10"><span class="mr6">' . $icon . '</span>' . wp_kses_post($name) . '</div>';
$html .= $equity_html;
$html .= '<a class="but jb-blue radius payvip-button" href="javascript:;">'
. wp_kses_post(sprintf(__('开通%s', 'aksrt'), $name))
. wp_kses_post(sprintf(__('开通%s', 'jio'), $name))
. '<span class="ml6"><i class="fa fas fa-chevron-circle-right" aria-hidden="true"></i></span></a>';
$html .= '</div></div>';
return $html;
+47 -47
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -47,7 +47,7 @@ trait VipServicePackages {
if ($daily_minor > 0) {
$remaining = (int) ceil(max(1, ($expires - $now) / DAY_IN_SECONDS));
if ($daily_minor <= intdiv(PHP_INT_MAX, $remaining)) {
$price = \AKSRT\Ledger\AssetAmount::decimal_from_minor($remaining * $daily_minor);
$price = \Jio\Ledger\AssetAmount::decimal_from_minor($remaining * $daily_minor);
$items[] = [
'package_id' => $this->encode_package_id(2, 902),
'level' => 2,
@@ -59,11 +59,11 @@ trait VipServicePackages {
'discount_tag' => (string) ($config['unit_tag'] ?? ''),
'tag_class' => (string) ($config['unit_tag_class'] ?? ''),
'days' => $remaining,
'title' => sprintf(__('按剩余 %d 天升级', 'aksrt'), $remaining),
'title' => sprintf(__('按剩余 %d 天升级', 'jio'), $remaining),
'price_label' => $this->format_cash_label($price),
'show_price_label' => '',
'days_label' => sprintf(__('%d 天', 'aksrt'), $remaining),
'cta_label' => __('立即升级', 'aksrt'),
'days_label' => sprintf(__('%d 天', 'jio'), $remaining),
'cta_label' => __('立即升级', 'jio'),
'is_upgrade_product' => true,
'upgrade_mode' => 'unit',
];
@@ -75,9 +75,9 @@ trait VipServicePackages {
if (!$is_permanent && !empty($config['jump_s'])) {
$price_minor = $this->parse_vip_money_minor((string) ($config['jump_price'] ?? ''));
if ($price_minor > 0) {
$price = \AKSRT\Ledger\AssetAmount::decimal_from_minor($price_minor);
$price = \Jio\Ledger\AssetAmount::decimal_from_minor($price_minor);
$show_minor = $this->parse_vip_money_minor((string) ($config['jump_show_price'] ?? ''));
$show = \AKSRT\Ledger\AssetAmount::decimal_from_minor($show_minor);
$show = \Jio\Ledger\AssetAmount::decimal_from_minor($show_minor);
$items[] = [
'package_id' => $this->encode_package_id(2, 903),
'level' => 2,
@@ -89,11 +89,11 @@ trait VipServicePackages {
'discount_tag' => (string) ($config['jump_tag'] ?? ''),
'tag_class' => (string) ($config['jump_tag_class'] ?? ''),
'days' => 0,
'title' => __('升级为永久会员', 'aksrt'),
'title' => __('升级为永久会员', 'jio'),
'price_label' => $this->format_cash_label($price),
'show_price_label' => $show_minor > 0 ? $this->format_cash_label($show) : '',
'days_label' => __('永久', 'aksrt'),
'cta_label' => __('立即升级', 'aksrt'),
'days_label' => __('永久', 'jio'),
'cta_label' => __('立即升级', 'jio'),
'is_upgrade_product' => true,
'upgrade_mode' => 'jump',
];
@@ -104,9 +104,9 @@ trait VipServicePackages {
if ($is_permanent) {
$price_minor = $this->parse_vip_money_minor((string) ($config['permanent_price'] ?? ''));
if ($price_minor > 0) {
$price = \AKSRT\Ledger\AssetAmount::decimal_from_minor($price_minor);
$price = \Jio\Ledger\AssetAmount::decimal_from_minor($price_minor);
$show_minor = $this->parse_vip_money_minor((string) ($config['permanent_show_price'] ?? ''));
$show = \AKSRT\Ledger\AssetAmount::decimal_from_minor($show_minor);
$show = \Jio\Ledger\AssetAmount::decimal_from_minor($show_minor);
$items[] = [
'package_id' => $this->encode_package_id(2, 901),
'level' => 2,
@@ -118,11 +118,11 @@ trait VipServicePackages {
'discount_tag' => (string) ($config['permanent_tag'] ?? ''),
'tag_class' => (string) ($config['permanent_tag_class'] ?? ''),
'days' => 0,
'title' => __('永久会员升级', 'aksrt'),
'title' => __('永久会员升级', 'jio'),
'price_label' => $this->format_cash_label($price),
'show_price_label' => $show_minor > 0 ? $this->format_cash_label($show) : '',
'days_label' => __('永久', 'aksrt'),
'cta_label' => __('立即升级', 'aksrt'),
'days_label' => __('永久', 'jio'),
'cta_label' => __('立即升级', 'jio'),
'is_upgrade_product' => true,
'upgrade_mode' => 'permanent',
];
@@ -147,7 +147,7 @@ trait VipServicePackages {
public function get_points_exchange_packages(array $vip, array $levels): array {
$points_ex = is_array($vip['points_exchange'] ?? null) ? $vip['points_exchange'] : [];
$rows = isset($points_ex['packages']) && is_array($points_ex['packages']) ? $points_ex['packages'] : [];
$currency = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
$currency = class_exists('\Jio\Settings\Settings') ? \Jio\Settings\Settings::get_currency_name() : __('积分', 'jio');
$out = [];
$i = 0;
foreach ($rows as $row) {
@@ -181,14 +181,14 @@ trait VipServicePackages {
'unit' => $unit,
'is_permanent' => $is_permanent,
'title' => $is_permanent
? sprintf(__('%s · 永久', 'aksrt'), $lv_name)
: sprintf(__('%1$s · %2$d%3$s', 'aksrt'), $lv_name, $time, $unit === 'month' ? __('个月', 'aksrt') : __('天', 'aksrt')),
? sprintf(__('%s · 永久', 'jio'), $lv_name)
: sprintf(__('%1$s · %2$d%3$s', 'jio'), $lv_name, $time, $unit === 'month' ? __('个月', 'jio') : __('天', 'jio')),
'price_label' => $pts . ' ' . $currency,
'days_label' => $is_permanent
? __('永久', 'aksrt')
: ($unit === 'month' ? sprintf(__('%d 个月', 'aksrt'), $time) : sprintf(__('%d 天', 'aksrt'), $time)),
'duration_label' => $is_permanent ? __('永久', 'aksrt') : ($unit === 'month' ? sprintf(__('%d 个月', 'aksrt'), $time) : sprintf(__('%d 天', 'aksrt'), $time)),
'cta_label' => __('立即兑换', 'aksrt'),
? __('永久', 'jio')
: ($unit === 'month' ? sprintf(__('%d 个月', 'jio'), $time) : sprintf(__('%d 天', 'jio'), $time)),
'duration_label' => $is_permanent ? __('永久', 'jio') : ($unit === 'month' ? sprintf(__('%d 个月', 'jio'), $time) : sprintf(__('%d 天', 'jio'), $time)),
'cta_label' => __('立即兑换', 'jio'),
];
}
return $out;
@@ -229,7 +229,7 @@ trait VipServicePackages {
if ($action !== 'renew') {
return [
'price' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($base_minor),
'price' => \Jio\Ledger\AssetAmount::decimal_from_minor($base_minor),
'show_price' => '0.00',
'tag' => '',
'tag_class' => '',
@@ -251,10 +251,10 @@ trait VipServicePackages {
}
// 折值:8 = 八折(参考主题 slider 0.1–9.9 语义)。
$discount = max(0.1, min(9.9, $discount));
$price_minor = \AKSRT\Ledger\AssetAmount::percentage($base_minor, $discount * 10);
$price_minor = \Jio\Ledger\AssetAmount::percentage($base_minor, $discount * 10);
$tag = sprintf(
/* translators: %s: discount like 8 */
__('%s折优惠', 'aksrt'),
__('%s折优惠', 'jio'),
rtrim(rtrim(number_format($discount, 1, '.', ''), '0'), '.') ?: '0'
);
} elseif ($type === 'reduce') {
@@ -262,8 +262,8 @@ trait VipServicePackages {
$price_minor = max(1, $base_minor - $reduce_minor);
$tag = sprintf(
/* translators: %s: amount */
__('续费立减%s', 'aksrt'),
$this->format_cash_label(\AKSRT\Ledger\AssetAmount::decimal_from_minor($reduce_minor))
__('续费立减%s', 'jio'),
$this->format_cash_label(\Jio\Ledger\AssetAmount::decimal_from_minor($reduce_minor))
);
} elseif ($type === 'customize') {
// 自定义商品:沿用商品自身的原价、促销标签与标签颜色。
@@ -272,7 +272,7 @@ trait VipServicePackages {
$tag_class = (string) ($pkg['tag_class'] ?? '');
} else {
$show_minor = 0;
$tag = __('续费同价', 'aksrt');
$tag = __('续费同价', 'jio');
}
if ($price_minor < 1) {
@@ -282,13 +282,13 @@ trait VipServicePackages {
// 参考主题契约:原价仅在低于执行价时展示。
$show_minor = 0;
if ($computed_tag) {
$tag = __('续费', 'aksrt');
$tag = __('续费', 'jio');
}
}
return [
'price' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($price_minor),
'show_price' => \AKSRT\Ledger\AssetAmount::decimal_from_minor($show_minor > $price_minor ? $show_minor : 0),
'price' => \Jio\Ledger\AssetAmount::decimal_from_minor($price_minor),
'show_price' => \Jio\Ledger\AssetAmount::decimal_from_minor($show_minor > $price_minor ? $show_minor : 0),
'tag' => $tag,
'tag_class' => $tag_class,
];
@@ -323,19 +323,19 @@ trait VipServicePackages {
* @return array<int, array{id:string,name:string}>
*/
private function available_payment_methods(): array {
$methods = function_exists('aksrt_list_cash_payment_methods')
? aksrt_list_cash_payment_methods(true)
$methods = function_exists('jio_list_cash_payment_methods')
? jio_list_cash_payment_methods(true)
: [];
// 卡密兑换会员渠道(后台 会员购买 → 启用卡密兑换会员功能):
// 提交走 /pay/card-pass/redeem type=vip,不创建支付订单。
$card_pass = $this->vip_card_pass_context();
if (!empty($card_pass['enabled'])) {
$methods[] = ['id' => 'card_pass', 'name' => __('卡密', 'aksrt')];
$methods[] = ['id' => 'card_pass', 'name' => __('卡密', 'jio')];
}
// 卡密渠道追加后需按「收款接口显示顺序」重新定位(含 card_pass 槽位)。
return function_exists('aksrt_sort_payment_methods')
? aksrt_sort_payment_methods($methods)
return function_exists('jio_sort_payment_methods')
? jio_sort_payment_methods($methods)
: $methods;
}
@@ -346,10 +346,10 @@ trait VipServicePackages {
*/
private function vip_card_pass_context(): array {
$empty = ['enabled' => false, 'desc' => '', 'only_password' => false];
if (!class_exists('\AKSRT\Payment\ChargeCard')) {
if (!class_exists('\Jio\Payment\ChargeCard')) {
return $empty;
}
$opts = \AKSRT\Payment\ChargeCard::get_instance()->get_public_options();
$opts = \Jio\Payment\ChargeCard::get_instance()->get_public_options();
return is_array($opts['vip'] ?? null) ? array_merge($empty, $opts['vip']) : $empty;
}
@@ -360,11 +360,11 @@ trait VipServicePackages {
if (method_exists($this, 'get_paid_display_context')) {
$paid = $this->get_paid_display_context();
$symbol = (string) ($paid['display']['currency_symbol'] ?? '¥');
} elseif (class_exists('\AKSRT\Settings\Settings')) {
$paid = \AKSRT\Settings\Settings::get_paid_content_settings();
} elseif (class_exists('\Jio\Settings\Settings')) {
$paid = \Jio\Settings\Settings::get_paid_content_settings();
$symbol = (string) ($paid['display']['currency_symbol'] ?? '¥');
}
$n = function_exists('aksrt_format_price') ? aksrt_format_price($amount) : (string) $amount;
$n = function_exists('jio_format_price') ? jio_format_price($amount) : (string) $amount;
return $symbol . $n;
}
@@ -373,7 +373,7 @@ trait VipServicePackages {
return 0;
}
try {
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
return \Jio\Ledger\AssetAmount::balance_minor($value);
} catch (\InvalidArgumentException $e) {
return 0;
}
@@ -383,17 +383,17 @@ trait VipServicePackages {
private function format_expires_label(int $expires, int $level): string {
if ($level <= 0) {
return __('未开通', 'aksrt');
return __('未开通', 'jio');
}
if ($expires <= 0) {
return __('永久有效', 'aksrt');
return __('永久有效', 'jio');
}
if ($expires < time()) {
return __('已过期', 'aksrt');
return __('已过期', 'jio');
}
return sprintf(
/* translators: %s: date */
__('到期时间:%s', 'aksrt'),
__('到期时间:%s', 'jio'),
wp_date('Y-m-d H:i', $expires)
);
}
+128 -128
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -32,8 +32,8 @@ trait VipServicePurchase {
return $this->vip_settings_cache;
}
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_payment_vip_settings()
$settings = class_exists('\Jio\Settings\Settings')
? \Jio\Settings\Settings::get_payment_vip_settings()
: [];
$this->vip_settings_cache = is_array($settings)
? $settings
@@ -52,8 +52,8 @@ trait VipServicePurchase {
return $this->vip_member_cache[$user_id];
}
$vip_state = $user_id > 0 && function_exists('aksrt_get_user_vip_state')
? aksrt_get_user_vip_state($user_id)
$vip_state = $user_id > 0 && function_exists('jio_get_user_vip_state')
? jio_get_user_vip_state($user_id)
: ['level' => 0, 'expires' => 0, 'state' => 'unopened', 'source' => 'none'];
$level = (int) ($vip_state['level'] ?? 0);
$expires = max(0, (int) ($vip_state['expires'] ?? 0));
@@ -63,7 +63,7 @@ trait VipServicePurchase {
? 'permanent'
: ($expires < time() ? 'expired' : 'active');
} elseif ($expires > 0 && $expires < time()) {
// aksrt_get_user_vip_level() lazily clears expired levels; retain
// jio_get_user_vip_level() lazily clears expired levels; retain
// the observable expired state for this response without reviving it.
$member_state = 'expired';
}
@@ -74,7 +74,7 @@ trait VipServicePurchase {
'state' => $member_state,
'source' => (string) ($vip_state['source'] ?? 'none'),
'expires_label' => $member_state === 'expired'
? __('已过期', 'aksrt')
? __('已过期', 'jio')
: $this->format_expires_label($expires, $level),
];
$this->vip_member_cache[$user_id] = $state;
@@ -90,8 +90,8 @@ trait VipServicePurchase {
if (is_array($this->vip_paid_display_cache)) {
return $this->vip_paid_display_cache;
}
$settings = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_paid_content_settings()
$settings = class_exists('\Jio\Settings\Settings')
? \Jio\Settings\Settings::get_paid_content_settings()
: [];
$this->vip_paid_display_cache = is_array($settings) ? $settings : [];
return $this->vip_paid_display_cache;
@@ -117,7 +117,7 @@ trait VipServicePurchase {
$points_ex = is_array($vip['points_exchange'] ?? null) ? $vip['points_exchange'] : [];
$renew_enabled = !isset($renew['enabled']) || !empty($renew['enabled']);
$upgrade_enabled = !isset($upgrade['enabled']) || !empty($upgrade['enabled']);
$credits_enabled = !class_exists('\AKSRT\Settings\Settings') || \AKSRT\Settings\Settings::credits_enabled();
$credits_enabled = !class_exists('\Jio\Settings\Settings') || \Jio\Settings\Settings::credits_enabled();
$points_enabled = !empty($points_ex['enabled']) && $credits_enabled;
$level_packages = [];
@@ -182,11 +182,11 @@ trait VipServicePurchase {
$tag_class = (string) $pkg['tag_class'];
}
$days_label = __('永久', 'aksrt');
$days_label = __('永久', 'jio');
if ((int) $pkg['time'] > 0) {
$days_label = ((string) ($pkg['unit'] ?? 'day') === 'month')
? sprintf(__('%d 个月', 'aksrt'), (int) $pkg['time'])
: sprintf(__('%d 天', 'aksrt'), (int) $pkg['time']);
? sprintf(__('%d 个月', 'jio'), (int) $pkg['time'])
: sprintf(__('%d 天', 'jio'), (int) $pkg['time']);
}
$items[] = [
@@ -208,8 +208,8 @@ trait VipServicePurchase {
: '',
'days_label' => $days_label,
'cta_label' => $action === 'renew'
? __('立即续费', 'aksrt')
: ($action === 'upgrade' ? __('立即升级', 'aksrt') : __('立即开通', 'aksrt')),
? __('立即续费', 'jio')
: ($action === 'upgrade' ? __('立即升级', 'jio') : __('立即开通', 'jio')),
];
}
@@ -246,9 +246,9 @@ trait VipServicePurchase {
}
}
$balances = \AKSRT\Ledger\LedgerService::get_instance()->points_and_balance($user_id);
$balances = \Jio\Ledger\LedgerService::get_instance()->points_and_balance($user_id);
$methods = $this->available_payment_methods();
$currency_name = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_currency_name() : __('积分', 'aksrt');
$currency_name = class_exists('\Jio\Settings\Settings') ? \Jio\Settings\Settings::get_currency_name() : __('积分', 'jio');
$catalog = [
'enabled' => !empty($vip['enabled']),
@@ -314,17 +314,17 @@ trait VipServicePurchase {
*/
public function purchase(int $user_id, int $package_id, string $payment_method = 'balance', string $operation_key = '') {
if ($user_id <= 0) {
return new \WP_Error('aksrt_need_login', __('请先登录后再开通会员。', 'aksrt'), ['status' => 401]);
return new \WP_Error('jio_need_login', __('请先登录后再开通会员。', 'jio'), ['status' => 401]);
}
$catalog = $this->get_catalog($user_id);
if (empty($catalog['enabled'])) {
return new \WP_Error('aksrt_vip_disabled', __('会员功能未启用', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_vip_disabled', __('会员功能未启用', 'jio'), ['status' => 400]);
}
$pkg = $this->find_catalog_package($catalog, $package_id);
if (!$pkg) {
return new \WP_Error('aksrt_invalid_package', __('套餐不存在或当前不可购买', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_invalid_package', __('套餐不存在或当前不可购买', 'jio'), ['status' => 400]);
}
$level = (int) ($pkg['level'] ?? 0);
@@ -347,16 +347,16 @@ trait VipServicePurchase {
}
if ($level < 1 || $level > 2 || $index < 1 || $action === '') {
return new \WP_Error('aksrt_invalid_package', __('套餐无效', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_invalid_package', __('套餐无效', 'jio'), ['status' => 400]);
}
if ($amount_minor <= 0) {
return new \WP_Error('aksrt_invalid_price', __('套餐价格无效', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_invalid_price', __('套餐价格无效', 'jio'), ['status' => 400]);
}
$amount_decimal = \AKSRT\Ledger\AssetAmount::decimal_from_minor($amount_minor);
$amount_decimal = \Jio\Ledger\AssetAmount::decimal_from_minor($amount_minor);
if (!class_exists('\AKSRT\Payment\Order') || !class_exists('\AKSRT\Payment\OrderRepository')) {
return new \WP_Error('aksrt_pay_unavailable', __('支付系统不可用', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Order') || !class_exists('\Jio\Payment\OrderRepository')) {
return new \WP_Error('jio_pay_unavailable', __('支付系统不可用', 'jio'), ['status' => 500]);
}
$payment_method = sanitize_key($payment_method);
@@ -365,7 +365,7 @@ trait VipServicePurchase {
}
// 卡密兑换会员走 /pay/card-pass/redeem(type=vip)直兑,不创建支付订单。
if ($payment_method === 'card_pass') {
return new \WP_Error('aksrt_card_pass_redeem_required', __('卡密兑换会员请直接输入卡密提交', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_card_pass_redeem_required', __('卡密兑换会员请直接输入卡密提交', 'jio'), ['status' => 400]);
}
$note = wp_json_encode([
@@ -383,15 +383,15 @@ trait VipServicePurchase {
'discount_tag' => $discount_tag,
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$expires_at = \AKSRT\Settings\PaymentRuntime::get_order_expiry_at();
$repo = \AKSRT\Payment\OrderRepository::get_instance();
$expires_at = \Jio\Settings\PaymentRuntime::get_order_expiry_at();
$repo = \Jio\Payment\OrderRepository::get_instance();
$existing = $operation_key !== '' ? $repo->get_by_request_key($operation_key) : null;
$is_new_order = !is_array($existing);
if (is_array($existing)) {
$existing_meta = json_decode((string) ($existing['note'] ?? ''), true);
$existing_meta = is_array($existing_meta) ? $existing_meta : [];
if ((int) ($existing['user_id'] ?? 0) !== $user_id
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== \Jio\Core\DomainModel::ORDER_PRODUCT_VIP
|| (int) ($existing['product_id'] ?? 0) !== $package_id
|| (string) ($existing['amount'] ?? '') !== $amount_decimal
|| strtoupper((string) ($existing['currency'] ?? '')) !== 'CNY'
@@ -402,17 +402,17 @@ trait VipServicePurchase {
|| sanitize_key((string) ($existing_meta['unit'] ?? '')) !== $pkg_unit
|| sanitize_key((string) ($existing_meta['action'] ?? '')) !== $action
) {
return new \WP_Error('aksrt_ledger_idempotency_conflict', __('相同操作标识已用于其他会员购买请求', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_ledger_idempotency_conflict', __('相同操作标识已用于其他会员购买请求', 'jio'), ['status' => 409]);
}
$order_number = (string) $existing['order_number'];
} else {
$order_number = $repo->create([
'user_id' => $user_id,
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP,
'product_type' => \Jio\Core\DomainModel::ORDER_PRODUCT_VIP,
'product_id' => $package_id,
'amount' => $amount_decimal,
'currency' => 'CNY',
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
'status' => \Jio\Payment\Order::STATUS_PENDING,
'payment_method' => $payment_method,
'note' => is_string($note) ? $note : '',
'expires_at' => $expires_at,
@@ -420,9 +420,9 @@ trait VipServicePurchase {
]);
}
if ($order_number === '') {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败', 'jio'), ['status' => 500]);
}
if (is_array($existing) && (string) ($existing['status'] ?? '') === \AKSRT\Payment\Order::STATUS_PAID) {
if (is_array($existing) && (string) ($existing['status'] ?? '') === \Jio\Payment\Order::STATUS_PAID) {
return [
'success' => true,
'data' => [
@@ -432,8 +432,8 @@ trait VipServicePurchase {
'days' => $days,
'action' => $action,
'replayed' => true,
'balance' => \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => __('会员购买已完成', 'aksrt'),
'balance' => \Jio\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => __('会员购买已完成', 'jio'),
'reload' => true,
],
];
@@ -442,21 +442,21 @@ trait VipServicePurchase {
// package used for validation. PaymentOrchestrator still reloads the
// persisted row under its attempt lock before touching the gateway.
$level_name = (string) ($pkg['_level_name'] ?? ('VIP' . $level));
$action_label = $action === 'renew' ? __('续费', 'aksrt') : ($action === 'upgrade' ? __('升级', 'aksrt') : __('开通', 'aksrt'));
$action_label = $action === 'renew' ? __('续费', 'jio') : ($action === 'upgrade' ? __('升级', 'jio') : __('开通', 'jio'));
$order = [
'order_number' => $order_number,
'user_id' => $user_id,
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP,
'product_type' => \Jio\Core\DomainModel::ORDER_PRODUCT_VIP,
'product_id' => $package_id,
'amount' => $amount_decimal,
'currency' => 'CNY',
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
'status' => \Jio\Payment\Order::STATUS_PENDING,
'payment_method' => $payment_method,
'note' => is_string($note) ? $note : '',
'expires_at' => $expires_at,
'subject' => sprintf(
/* translators: 1: action 2: vip name 3: price label 4: duration label */
__('%1$s%2$s · %3$s / %4$s', 'aksrt'),
__('%1$s%2$s · %3$s / %4$s', 'jio'),
$action_label,
$level_name,
(string) ($pkg['price_label'] ?? ''),
@@ -464,31 +464,31 @@ trait VipServicePurchase {
),
];
if (!class_exists('\AKSRT\Payment\Gateway')) {
return new \WP_Error('aksrt_pay_unavailable', __('支付网关不可用', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Gateway')) {
return new \WP_Error('jio_pay_unavailable', __('支付网关不可用', 'jio'), ['status' => 500]);
}
$resolved = \AKSRT\Payment\PaymentOrchestrator::resolve_gateway($payment_method);
$resolved = \Jio\Payment\PaymentOrchestrator::resolve_gateway($payment_method);
if (empty($resolved['gateway'])) {
return new \WP_Error(
(string) ($resolved['error_code'] ?? 'aksrt_gateway_unavailable'),
(string) ($resolved['message'] ?? __('当前支付方式不可用', 'aksrt')),
(string) ($resolved['error_code'] ?? 'jio_gateway_unavailable'),
(string) ($resolved['message'] ?? __('当前支付方式不可用', 'jio')),
['status' => 400, 'order_number' => $order_number]
);
}
$payment_result = \AKSRT\Payment\PaymentOrchestrator::pay($resolved['gateway'], $order, [
'paid_note' => __('用户完成会员开通支付。', 'aksrt'),
$payment_result = \Jio\Payment\PaymentOrchestrator::pay($resolved['gateway'], $order, [
'paid_note' => __('用户完成会员开通支付。', 'jio'),
'order_context' => $order,
]);
if (empty($payment_result['success'])) {
return new \WP_Error(
(string) ($payment_result['code'] ?? 'aksrt_pay_failed'),
(string) ($payment_result['message'] ?? __('支付失败', 'aksrt')),
(string) ($payment_result['code'] ?? 'jio_pay_failed'),
(string) ($payment_result['message'] ?? __('支付失败', 'jio')),
['status' => (int) ($payment_result['status'] ?? 400), 'order_number' => $order_number]
);
}
$cashier = \AKSRT\Payment\PaymentOrchestrator::cashier_payload($payment_result);
$cashier = \Jio\Payment\PaymentOrchestrator::cashier_payload($payment_result);
if ($cashier !== []) {
return [
'success' => true,
@@ -511,10 +511,10 @@ trait VipServicePurchase {
'days' => $days,
'action' => $action,
'replayed' => !empty($payment_result['replayed']),
'balance' => \AKSRT\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'balance' => \Jio\Ledger\LedgerService::get_instance()->balance_decimal($user_id),
'message' => $action === 'renew'
? __('会员续费成功', 'aksrt')
: ($action === 'upgrade' ? __('会员升级成功', 'aksrt') : __('会员开通成功', 'aksrt')),
? __('会员续费成功', 'jio')
: ($action === 'upgrade' ? __('会员升级成功', 'jio') : __('会员开通成功', 'jio')),
'reload' => true,
],
];
@@ -529,7 +529,7 @@ trait VipServicePurchase {
* @param array $paid_order
*/
public function fulfill_paid_order(string $order_number, array $paid_order) {
if (sanitize_key((string) ($paid_order['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP) {
if (sanitize_key((string) ($paid_order['product_type'] ?? '')) !== \Jio\Core\DomainModel::ORDER_PRODUCT_VIP) {
return true;
}
if (sanitize_key((string) ($paid_order['payment_method'] ?? '')) === 'card_pass') {
@@ -576,31 +576,31 @@ trait VipServicePurchase {
$level = 2;
}
$previous_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
$previous_expiry = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
$previous_base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
$previous_base_expiry = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
$previous_level = (int) get_user_meta($user_id, 'jio_vip_level', true);
$previous_expiry = (int) get_user_meta($user_id, 'jio_vip_expires', true);
$previous_base_level = (int) get_user_meta($user_id, 'jio_vip_base_level', true);
$previous_base_expiry = (int) get_user_meta($user_id, 'jio_vip_base_expires', true);
$finite_duration = $time > 0 || $days > 0;
if ($previous_level > 0 && $level > $previous_level && $finite_duration) {
// Preserve the original lower tier while a finite higher-tier upgrade is active.
if ($previous_base_level <= 0 || ($previous_base_expiry > 0 && $previous_base_expiry < time())) {
update_user_meta($user_id, 'aksrt_vip_base_level', $previous_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', max(0, $previous_expiry));
update_user_meta($user_id, 'jio_vip_base_level', $previous_level);
update_user_meta($user_id, 'jio_vip_base_expires', max(0, $previous_expiry));
}
} elseif (!$finite_duration || $level < $previous_level) {
// Permanent grants and lower-tier grants do not retain a temporary overlay.
delete_user_meta($user_id, 'aksrt_vip_base_level');
delete_user_meta($user_id, 'aksrt_vip_base_expires');
delete_user_meta($user_id, 'jio_vip_base_level');
delete_user_meta($user_id, 'jio_vip_base_expires');
}
$fulfilled = false;
// unit upgrade: raise level only, keep current expiry (legacy).
if ($upgrade_mode === 'unit') {
$this->activate_vip($user_id, $level, 0, true);
$fulfilled = (int) get_user_meta($user_id, 'aksrt_vip_level', true) >= $level;
$fulfilled = (int) get_user_meta($user_id, 'jio_vip_level', true) >= $level;
} elseif ($time > 0 || (isset($meta['time']) && (int) $meta['time'] === 0 && $days === 0)) {
// Prefer calendar time+unit when present (including permanent time=0).
$this->activate_vip_duration($user_id, $level, $time, $unit);
$new_expiry = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
$new_expiry = (int) get_user_meta($user_id, 'jio_vip_expires', true);
$expected_base = max($previous_expiry, time());
$expected_expiry = $time <= 0
? 0
@@ -608,23 +608,23 @@ trait VipServicePurchase {
if ($expected_expiry === false) {
$expected_expiry = $expected_base + ($this->duration_to_days($time, $unit) * DAY_IN_SECONDS);
}
$fulfilled = (int) get_user_meta($user_id, 'aksrt_vip_level', true) >= max($previous_level, $level)
$fulfilled = (int) get_user_meta($user_id, 'jio_vip_level', true) >= max($previous_level, $level)
&& ($new_expiry === 0 || ($time <= 0 ? $new_expiry === 0 : $new_expiry >= $expected_expiry));
} else {
$this->activate_vip($user_id, $level, $days, false);
$new_expiry = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
$fulfilled = (int) get_user_meta($user_id, 'aksrt_vip_level', true) >= max($previous_level, $level)
$new_expiry = (int) get_user_meta($user_id, 'jio_vip_expires', true);
$fulfilled = (int) get_user_meta($user_id, 'jio_vip_level', true) >= max($previous_level, $level)
&& ($new_expiry === 0 || $days <= 0 || $new_expiry >= max($previous_expiry, time()) + ($days * DAY_IN_SECONDS));
}
if (!$fulfilled) {
return new \WP_Error('aksrt_vip_fulfillment_failed', __('会员权益发放失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_vip_fulfillment_failed', __('会员权益发放失败。', 'jio'), ['status' => 500]);
}
$vip_after = $this->get_membership_snapshot($user_id);
if (!\AKSRT\Payment\OrderRepository::get_instance()->merge_meta($order_number, [
if (!\Jio\Payment\OrderRepository::get_instance()->merge_meta($order_number, [
'vip_before' => $vip_before,
'vip_after' => $vip_after,
])) {
return new \WP_Error('aksrt_vip_snapshot_failed', __('会员订单快照保存失败。', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_vip_snapshot_failed', __('会员订单快照保存失败。', 'jio'), ['status' => 500]);
}
return true;
}
@@ -642,20 +642,20 @@ trait VipServicePurchase {
return;
}
$level = max(1, min(2, $level));
$current_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
$current_expiry = max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true));
$current_level = (int) get_user_meta($user_id, 'jio_vip_level', true);
$current_expiry = max(0, (int) get_user_meta($user_id, 'jio_vip_expires', true));
if (!$keep_expiry && $days > 0 && $current_level > 0 && $level > $current_level) {
$base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
$base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
$base_level = (int) get_user_meta($user_id, 'jio_vip_base_level', true);
$base_expires = (int) get_user_meta($user_id, 'jio_vip_base_expires', true);
if ($base_level <= 0 || ($base_expires > 0 && $base_expires < time())) {
update_user_meta($user_id, 'aksrt_vip_base_level', $current_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', $current_expiry);
update_user_meta($user_id, 'jio_vip_base_level', $current_level);
update_user_meta($user_id, 'jio_vip_base_expires', $current_expiry);
}
}
$new_level = max($current_level, $level);
update_user_meta($user_id, 'aksrt_vip_level', $new_level);
update_user_meta($user_id, 'jio_vip_level', $new_level);
// Clear expired memory when re-granting.
delete_user_meta($user_id, 'aksrt_vip_level_expired');
delete_user_meta($user_id, 'jio_vip_level_expired');
// Unit upgrade (legacy): keep vip_exp_date, only raise level.
if ($keep_expiry) {
@@ -664,18 +664,18 @@ trait VipServicePurchase {
if ($days <= 0) {
// Permanent.
delete_user_meta($user_id, 'aksrt_vip_base_level');
delete_user_meta($user_id, 'aksrt_vip_base_expires');
update_user_meta($user_id, 'aksrt_vip_expires', 0);
delete_user_meta($user_id, 'jio_vip_base_level');
delete_user_meta($user_id, 'jio_vip_base_expires');
update_user_meta($user_id, 'jio_vip_expires', 0);
return;
}
$current_exp = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
$current_exp = (int) get_user_meta($user_id, 'jio_vip_expires', true);
if ($current_exp === 0 && $current_level > 0 && $level <= $current_level) {
return; // keep an existing permanent level when not upgrading it
}
$base = max($current_exp, time());
update_user_meta($user_id, 'aksrt_vip_expires', $base + ($days * DAY_IN_SECONDS));
update_user_meta($user_id, 'jio_vip_expires', $base + ($days * DAY_IN_SECONDS));
}
/**
@@ -688,28 +688,28 @@ trait VipServicePurchase {
}
$level = max(1, min(2, $level));
$unit = $unit === 'month' ? 'month' : 'day';
$current_level = (int) get_user_meta($user_id, 'aksrt_vip_level', true);
$current_expiry = max(0, (int) get_user_meta($user_id, 'aksrt_vip_expires', true));
$current_level = (int) get_user_meta($user_id, 'jio_vip_level', true);
$current_expiry = max(0, (int) get_user_meta($user_id, 'jio_vip_expires', true));
if ($time > 0 && $current_level > 0 && $level > $current_level) {
$base_level = (int) get_user_meta($user_id, 'aksrt_vip_base_level', true);
$base_expires = (int) get_user_meta($user_id, 'aksrt_vip_base_expires', true);
$base_level = (int) get_user_meta($user_id, 'jio_vip_base_level', true);
$base_expires = (int) get_user_meta($user_id, 'jio_vip_base_expires', true);
if ($base_level <= 0 || ($base_expires > 0 && $base_expires < time())) {
update_user_meta($user_id, 'aksrt_vip_base_level', $current_level);
update_user_meta($user_id, 'aksrt_vip_base_expires', $current_expiry);
update_user_meta($user_id, 'jio_vip_base_level', $current_level);
update_user_meta($user_id, 'jio_vip_base_expires', $current_expiry);
}
}
$new_level = max($current_level, $level);
update_user_meta($user_id, 'aksrt_vip_level', $new_level);
delete_user_meta($user_id, 'aksrt_vip_level_expired');
update_user_meta($user_id, 'jio_vip_level', $new_level);
delete_user_meta($user_id, 'jio_vip_level_expired');
if ($time <= 0) {
delete_user_meta($user_id, 'aksrt_vip_base_level');
delete_user_meta($user_id, 'aksrt_vip_base_expires');
update_user_meta($user_id, 'aksrt_vip_expires', 0);
delete_user_meta($user_id, 'jio_vip_base_level');
delete_user_meta($user_id, 'jio_vip_base_expires');
update_user_meta($user_id, 'jio_vip_expires', 0);
return;
}
$current_exp = (int) get_user_meta($user_id, 'aksrt_vip_expires', true);
$current_exp = (int) get_user_meta($user_id, 'jio_vip_expires', true);
if ($current_exp === 0 && $current_level > 0 && $level <= $current_level) {
return; // keep an existing permanent level when not upgrading it
}
@@ -721,7 +721,7 @@ trait VipServicePurchase {
if ($new_exp === false) {
$new_exp = $base + ($this->duration_to_days($time, $unit) * DAY_IN_SECONDS);
}
update_user_meta($user_id, 'aksrt_vip_expires', (int) $new_exp);
update_user_meta($user_id, 'jio_vip_expires', (int) $new_exp);
}
@@ -734,23 +734,23 @@ trait VipServicePurchase {
*/
public function exchange_with_points(int $user_id, int $package_id, string $operation_key = '') {
if ($user_id <= 0) {
return new \WP_Error('aksrt_need_login', __('请先登录后再兑换。', 'aksrt'), ['status' => 401]);
return new \WP_Error('jio_need_login', __('请先登录后再兑换。', 'jio'), ['status' => 401]);
}
$catalog = $this->get_catalog($user_id);
// 兑换相关文案(错误提示 / 订单备注 / 流水说明)统一跟随自定义货币名称
// (后台「积分配置 → 自定义货币名称」),catalog 已带出 currency_name。
$currency_name = (string) ($catalog['currency_name'] ?? '');
if ($currency_name === '') {
$currency_name = class_exists('\AKSRT\Settings\Settings')
? \AKSRT\Settings\Settings::get_currency_name()
: __('积分', 'aksrt');
$currency_name = class_exists('\Jio\Settings\Settings')
? \Jio\Settings\Settings::get_currency_name()
: __('积分', 'jio');
}
if (array_key_exists('credits_enabled', $catalog) && empty($catalog['credits_enabled'])) {
return new \WP_Error('aksrt_points_disabled', __('积分功能未启用', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_points_disabled', __('积分功能未启用', 'jio'), ['status' => 400]);
}
$points_ex = is_array($catalog['points_exchange'] ?? null) ? $catalog['points_exchange'] : [];
if (empty($points_ex['enabled'])) {
return new \WP_Error('aksrt_points_exchange_disabled', sprintf(__('%s兑换会员未启用', 'aksrt'), $currency_name), ['status' => 400]);
return new \WP_Error('jio_points_exchange_disabled', sprintf(__('%s兑换会员未启用', 'jio'), $currency_name), ['status' => 400]);
}
$match = null;
@@ -762,7 +762,7 @@ trait VipServicePurchase {
}
}
if (!$match) {
return new \WP_Error('aksrt_invalid_package', __('兑换套餐不存在', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_invalid_package', __('兑换套餐不存在', 'jio'), ['status' => 400]);
}
if ((int) ($catalog['user_level'] ?? 0) > 0) {
@@ -770,7 +770,7 @@ trait VipServicePurchase {
$target_level = (int) ($match['level'] ?? 0);
$is_permanent = !empty($catalog['user_is_permanent']);
if ($target_level < $current_level || ($target_level === $current_level && $is_permanent)) {
return new \WP_Error('aksrt_vip_package_unavailable', __('当前会员状态无法兑换该套餐。', 'aksrt'), ['status' => 400]);
return new \WP_Error('jio_vip_package_unavailable', __('当前会员状态无法兑换该套餐。', 'jio'), ['status' => 400]);
}
}
@@ -783,20 +783,20 @@ trait VipServicePurchase {
$pkg_unit = 'day';
}
if ($cost <= 0) {
return new \WP_Error('aksrt_invalid_price', sprintf(__('兑换%s无效', 'aksrt'), $currency_name), ['status' => 400]);
return new \WP_Error('jio_invalid_price', sprintf(__('兑换%s无效', 'jio'), $currency_name), ['status' => 400]);
}
$balance = (int) ($catalog['user_points'] ?? 0);
if ($balance < $cost) {
return new \WP_Error('aksrt_points_insufficient', sprintf(__('%s不足,暂时无法兑换', 'aksrt'), $currency_name), [
return new \WP_Error('jio_points_insufficient', sprintf(__('%s不足,暂时无法兑换', 'jio'), $currency_name), [
'status' => 402,
'balance' => $balance,
'cost' => $cost,
]);
}
if (!class_exists('\AKSRT\Payment\Order') || !class_exists('\AKSRT\Payment\OrderRepository')) {
return new \WP_Error('aksrt_pay_unavailable', __('订单系统不可用', 'aksrt'), ['status' => 500]);
if (!class_exists('\Jio\Payment\Order') || !class_exists('\Jio\Payment\OrderRepository')) {
return new \WP_Error('jio_pay_unavailable', __('订单系统不可用', 'jio'), ['status' => 500]);
}
$note = wp_json_encode([
@@ -812,14 +812,14 @@ trait VipServicePurchase {
'action' => 'points_exchange',
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$repo = \AKSRT\Payment\OrderRepository::get_instance();
$repo = \Jio\Payment\OrderRepository::get_instance();
$existing = $operation_key !== '' ? $repo->get_by_request_key($operation_key) : null;
$is_new_order = !is_array($existing);
if (is_array($existing)) {
$existing_meta = json_decode((string) ($existing['note'] ?? ''), true);
$existing_meta = is_array($existing_meta) ? $existing_meta : [];
if ((int) ($existing['user_id'] ?? 0) !== $user_id
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP
|| sanitize_key((string) ($existing['product_type'] ?? '')) !== \Jio\Core\DomainModel::ORDER_PRODUCT_VIP
|| (int) ($existing['product_id'] ?? 0) !== $package_id
|| (string) ($existing['currency'] ?? '') !== 'points'
|| (int) ($existing['amount'] ?? 0) !== $cost
@@ -827,43 +827,43 @@ trait VipServicePurchase {
|| (int) ($existing_meta['level'] ?? 0) !== $level
|| (int) ($existing_meta['days'] ?? 0) !== $days
) {
return new \WP_Error('aksrt_ledger_idempotency_conflict', __('相同操作标识已用于其他会员兑换请求', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_ledger_idempotency_conflict', __('相同操作标识已用于其他会员兑换请求', 'jio'), ['status' => 409]);
}
$order_number = (string) $existing['order_number'];
} else {
$order_number = $repo->allocate_order_number();
}
if ($order_number === '') {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败', 'jio'), ['status' => 500]);
}
$guard = static function () use ($is_new_order, $order_number, $user_id, $package_id, $cost) {
if ($is_new_order) {
return true;
}
global $wpdb;
$table = \AKSRT\Core\DBMigrator::table('order');
$table = \Jio\Core\DBMigrator::table('order');
$current = $wpdb->get_row($wpdb->prepare("SELECT user_id, product_id, amount, currency, status FROM {$table} WHERE order_number = %s FOR UPDATE", $order_number), ARRAY_A);
if (!is_array($current)
|| (int) ($current['user_id'] ?? 0) !== $user_id
|| (int) ($current['product_id'] ?? 0) !== $package_id
|| (int) ($current['amount'] ?? 0) !== $cost
|| (string) ($current['currency'] ?? '') !== 'points'
|| (string) ($current['status'] ?? '') !== \AKSRT\Payment\Order::STATUS_PENDING
|| (string) ($current['status'] ?? '') !== \Jio\Payment\Order::STATUS_PENDING
) {
return new \WP_Error('aksrt_order_confirm_failed', __('订单状态或金额已变化', 'aksrt'), ['status' => 409]);
return new \WP_Error('jio_order_confirm_failed', __('订单状态或金额已变化', 'jio'), ['status' => 409]);
}
return true;
};
$ledger = \AKSRT\Ledger\LedgerService::get_instance();
$ledger = \Jio\Ledger\LedgerService::get_instance();
$deducted = $ledger->debit(
$user_id,
\AKSRT\Ledger\AssetType::POINTS,
\Jio\Ledger\AssetType::POINTS,
$cost,
$operation_key,
'vip_points_exchange',
['type' => 'order', 'key' => $order_number],
sprintf(__('%s兑换会员 · %s', 'aksrt'), $currency_name, (string) ($match['title'] ?? '')),
sprintf(__('%s兑换会员 · %s', 'jio'), $currency_name, (string) ($match['title'] ?? '')),
$user_id,
['level' => $level, 'days' => $days, 'package_id' => $package_id],
static function () use ($is_new_order, $repo, $order_number, $operation_key, $user_id, $package_id, $cost, $note) {
@@ -871,27 +871,27 @@ trait VipServicePurchase {
$created = $repo->create([
'order_number' => $order_number,
'user_id' => $user_id,
'product_type' => \AKSRT\Core\DomainModel::ORDER_PRODUCT_VIP,
'product_type' => \Jio\Core\DomainModel::ORDER_PRODUCT_VIP,
'product_id' => $package_id,
'amount' => $cost,
'currency' => 'points',
'status' => \AKSRT\Payment\Order::STATUS_PENDING,
'status' => \Jio\Payment\Order::STATUS_PENDING,
'payment_method' => 'points',
'note' => is_string($note) ? $note : '',
'expires_at' => \AKSRT\Settings\PaymentRuntime::get_order_expiry_at(),
'expires_at' => \Jio\Settings\PaymentRuntime::get_order_expiry_at(),
'request_key' => $operation_key,
]);
if ($created !== $order_number) {
return new \WP_Error('aksrt_order_create_failed', __('创建订单失败', 'aksrt'), ['status' => 500]);
return new \WP_Error('jio_order_create_failed', __('创建订单失败', 'jio'), ['status' => 500]);
}
}
$paid = \AKSRT\Payment\Order::get_instance()->update_status($order_number, \AKSRT\Payment\Order::STATUS_PAID, [
$paid = \Jio\Payment\Order::get_instance()->update_status($order_number, \Jio\Payment\Order::STATUS_PAID, [
'payment_method' => 'points',
// 订单备注同样跟随自定义货币名称(后台「积分配置 → 自定义货币名称」)。
'note' => sprintf(__('%1$s兑换会员 %2$d %1$s。', 'aksrt'), $currency_name, $cost),
'note' => sprintf(__('%1$s兑换会员 %2$d %1$s。', 'jio'), $currency_name, $cost),
'require_transition' => true,
]);
return $paid ? true : new \WP_Error('aksrt_order_confirm_failed', __('兑换确认失败', 'aksrt'), ['status' => 500]);
return $paid ? true : new \WP_Error('jio_order_confirm_failed', __('兑换确认失败', 'jio'), ['status' => 500]);
},
$guard
);
@@ -906,9 +906,9 @@ trait VipServicePurchase {
'points' => $cost,
'level' => $level,
'days' => $days,
'balance' => $ledger->balance($user_id, \AKSRT\Ledger\AssetType::POINTS),
'balance' => $ledger->balance($user_id, \Jio\Ledger\AssetType::POINTS),
'replayed' => $deducted->replayed,
'message' => __('兑换成功', 'aksrt'),
'message' => __('兑换成功', 'jio'),
'reload' => true,
],
];
+16 -16
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -12,7 +12,7 @@ trait VipServiceRest {
public function register_routes(): void {
register_rest_route('aksrt/v1', '/pay/vip', [
register_rest_route('jio/v1', '/pay/vip', [
[
'methods' => 'GET',
'callback' => [$this, 'rest_catalog'],
@@ -29,14 +29,14 @@ trait VipServiceRest {
],
]);
register_rest_route('aksrt/v1', '/pay/vip/points-exchange', [
register_rest_route('jio/v1', '/pay/vip/points-exchange', [
'methods' => 'POST',
'callback' => [$this, 'rest_points_exchange'],
'permission_callback' => [$this, 'check_rest_nonce'],
'args' => ['package_id' => ['type' => 'integer', 'required' => true, 'minimum' => 1]],
]);
register_rest_route('aksrt/v1', '/pay/vip/modal', [
register_rest_route('jio/v1', '/pay/vip/modal', [
'methods' => 'GET',
'callback' => [$this, 'rest_modal'],
'permission_callback' => [$this, 'check_rest_nonce'],
@@ -55,9 +55,9 @@ trait VipServiceRest {
public function rest_modal(\WP_REST_Request $request) {
$uid = get_current_user_id();
if ($uid <= 0) {
return new \WP_Error('aksrt_need_login', __('请先登录后再开通会员。', 'aksrt'), [
return new \WP_Error('jio_need_login', __('请先登录后再开通会员。', 'jio'), [
'status' => 401,
'login_url' => function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(),
'login_url' => function_exists('jio_get_login_url') ? jio_get_login_url() : wp_login_url(),
]);
}
$level = (int) $request->get_param('vip_level');
@@ -79,10 +79,10 @@ trait VipServiceRest {
public function check_rest_nonce(\WP_REST_Request $request) {
$nonce = $request->get_header('x-wp-nonce');
if (!$nonce) {
return new \WP_Error('aksrt_rest_no_nonce', __('缺少安全令牌', 'aksrt'), ['status' => 403]);
return new \WP_Error('jio_rest_no_nonce', __('缺少安全令牌', 'jio'), ['status' => 403]);
}
if (!wp_verify_nonce($nonce, 'wp_rest')) {
return new \WP_Error('aksrt_rest_bad_nonce', __('安全令牌已过期,请刷新页面', 'aksrt'), ['status' => 403]);
return new \WP_Error('jio_rest_bad_nonce', __('安全令牌已过期,请刷新页面', 'jio'), ['status' => 403]);
}
return true;
}
@@ -106,9 +106,9 @@ trait VipServiceRest {
public function rest_purchase(\WP_REST_Request $request) {
$uid = get_current_user_id();
if ($uid <= 0) {
return new \WP_Error('aksrt_need_login', __('请先登录后再开通会员。', 'aksrt'), [
return new \WP_Error('jio_need_login', __('请先登录后再开通会员。', 'jio'), [
'status' => 401,
'login_url' => function_exists('aksrt_get_login_url') ? aksrt_get_login_url() : wp_login_url(),
'login_url' => function_exists('jio_get_login_url') ? jio_get_login_url() : wp_login_url(),
]);
}
@@ -117,7 +117,7 @@ trait VipServiceRest {
$params = $request->get_params();
}
$package_id = (int) ($params['package_id'] ?? 0);
$operation_key = \AKSRT\Ledger\OperationKey::from_request($request, 'vip-purchase', $uid);
$operation_key = \Jio\Ledger\OperationKey::from_request($request, 'vip-purchase', $uid);
if (is_wp_error($operation_key)) {
return $operation_key;
}
@@ -132,8 +132,8 @@ trait VipServiceRest {
}
if (empty($result['success'])) {
return new \WP_Error(
sanitize_key((string) ($result['code'] ?? 'aksrt_vip_pay_failed')),
(string) ($result['message'] ?? __('开通失败', 'aksrt')),
sanitize_key((string) ($result['code'] ?? 'jio_vip_pay_failed')),
(string) ($result['message'] ?? __('开通失败', 'jio')),
['status' => (int) ($result['status'] ?? 400)]
);
}
@@ -149,14 +149,14 @@ trait VipServiceRest {
public function rest_points_exchange(\WP_REST_Request $request) {
$uid = get_current_user_id();
if ($uid <= 0) {
return new \WP_Error('aksrt_need_login', __('请先登录后再兑换。', 'aksrt'), ['status' => 401]);
return new \WP_Error('jio_need_login', __('请先登录后再兑换。', 'jio'), ['status' => 401]);
}
$params = $request->get_json_params();
if (!is_array($params)) {
$params = $request->get_params();
}
$package_id = (int) ($params['package_id'] ?? 0);
$operation_key = \AKSRT\Ledger\OperationKey::from_request($request, 'vip-points-purchase', $uid);
$operation_key = \Jio\Ledger\OperationKey::from_request($request, 'vip-points-purchase', $uid);
if (is_wp_error($operation_key)) {
return $operation_key;
}
+67 -67
View File
@@ -1,9 +1,9 @@
<?php
/**
* @package AKSRT
* @package Jio
*/
namespace AKSRT\Content;
namespace Jio\Content;
defined('ABSPATH') || exit;
@@ -20,9 +20,9 @@ class Visibility {
}
public function init(): void {
// 短代码注册统一在 \AKSRT\Core\Shortcodes(registry);本类只提供渲染实现。
add_action('wp_ajax_aksrt_check_visibility', [$this, 'ajax_check_visibility']);
add_action('wp_ajax_nopriv_aksrt_check_visibility', [$this, 'ajax_check_visibility']);
// 短代码注册统一在 \Jio\Core\Shortcodes(registry);本类只提供渲染实现。
add_action('wp_ajax_jio_check_visibility', [$this, 'ajax_check_visibility']);
add_action('wp_ajax_nopriv_jio_check_visibility', [$this, 'ajax_check_visibility']);
}
/**
@@ -32,12 +32,12 @@ class Visibility {
public static function get_post_access_state($post = null, int $user_id = 0): array {
$resource_post = get_post($post);
$uid = $user_id > 0 ? $user_id : get_current_user_id();
$pay_meta = function_exists('aksrt_get_pay_meta')
? aksrt_get_pay_meta($resource_post)
: \AKSRT\Core\DomainModel::default_pay_meta();
$pay_type = \AKSRT\Core\DomainModel::normalize_pay_type((string) ($pay_meta['pay_type'] ?? \AKSRT\Core\DomainModel::PAY_TYPE_NO));
$priced = function_exists('aksrt_get_user_pay_price')
? aksrt_get_user_pay_price($resource_post, $uid)
$pay_meta = function_exists('jio_get_pay_meta')
? jio_get_pay_meta($resource_post)
: \Jio\Core\DomainModel::default_pay_meta();
$pay_type = \Jio\Core\DomainModel::normalize_pay_type((string) ($pay_meta['pay_type'] ?? \Jio\Core\DomainModel::PAY_TYPE_NO));
$priced = function_exists('jio_get_user_pay_price')
? jio_get_user_pay_price($resource_post, $uid)
: null;
$pay_modo = is_array($priced)
? ((($priced['modo'] ?? '0') === 'points') ? 'points' : '0')
@@ -71,12 +71,12 @@ class Visibility {
return $state;
}
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_NO) {
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_NO) {
$state['has_paid_access'] = true;
return $state;
}
$has_free_access = $price_minor <= 0 && $pay_type !== \AKSRT\Core\DomainModel::PAY_TYPE_VIP;
$has_free_access = $price_minor <= 0 && $pay_type !== \Jio\Core\DomainModel::PAY_TYPE_VIP;
$pay_limit = (int) ($pay_meta['pay_limit'] ?? 0);
if (!in_array($pay_limit, [0, 1, 2], true)) {
$pay_limit = 0;
@@ -84,28 +84,28 @@ class Visibility {
$state['pay_limit'] = $pay_limit;
$has_paid_order = false;
if ($uid > 0 && class_exists('\AKSRT\Payment\Order')) {
$has_paid_order = \AKSRT\Payment\Order::get_instance()->has_paid_access(
if ($uid > 0 && class_exists('\Jio\Payment\Order')) {
$has_paid_order = \Jio\Payment\Order::get_instance()->has_paid_access(
$uid,
\AKSRT\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
\Jio\Core\DomainModel::ORDER_PRODUCT_RESOURCE,
(int) $resource_post->ID
);
}
// Guest cookie paid unlock (legacy pay_no_logged_in).
if (!$has_paid_order && $uid <= 0 && function_exists('aksrt_guest_has_paid_access')) {
$has_paid_order = aksrt_guest_has_paid_access((int) $resource_post->ID);
if (!$has_paid_order && $uid <= 0 && function_exists('jio_guest_has_paid_access')) {
$has_paid_order = jio_guest_has_paid_access((int) $resource_post->ID);
}
$has_vip_access = false;
$user_vip_level = is_array($priced) ? (int) ($priced['vip_level'] ?? 0) : 0;
if ($uid > 0) {
if ($user_vip_level <= 0 && function_exists('aksrt_get_user_vip_level')) {
$user_vip_level = aksrt_get_user_vip_level($uid);
if ($user_vip_level <= 0 && function_exists('jio_get_user_vip_level')) {
$user_vip_level = jio_get_user_vip_level($uid);
}
if (function_exists('aksrt_is_vip_exempt') && aksrt_is_vip_exempt($uid)) {
if (function_exists('jio_is_vip_exempt') && jio_is_vip_exempt($uid)) {
$has_vip_access = true;
$user_vip_level = max($user_vip_level, 2);
} elseif ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_VIP || $pay_limit > 0) {
} elseif ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_VIP || $pay_limit > 0) {
$has_vip_access = $user_vip_level >= max(1, $pay_limit);
} elseif ($user_vip_level > 0) {
// VIP tier pricing may zero cost; still track membership.
@@ -115,10 +115,10 @@ class Visibility {
$state['user_vip_level'] = $user_vip_level;
// Member-only purchase restriction (legacy pay_limit).
if ($pay_limit > 0 && $pay_type !== \AKSRT\Core\DomainModel::PAY_TYPE_NO) {
if ($pay_limit > 0 && $pay_type !== \Jio\Core\DomainModel::PAY_TYPE_NO) {
$state['need_vip'] = $uid <= 0 || $user_vip_level < $pay_limit;
$allowed_member = $uid > 0 && $user_vip_level >= $pay_limit;
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_DOWNLOAD) {
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_DOWNLOAD) {
// Cash: order gate only. Points: cashier once → paid order zeros cost.
$download_cost = 0;
if ($pay_modo === 'points' && $price_minor > 0 && !$has_paid_order) {
@@ -127,7 +127,7 @@ class Visibility {
if ($allowed_member && $price_minor <= 0) {
$download_cost = 0;
}
$can_download = function_exists('aksrt_user_can') && aksrt_user_can('resource_download', $uid, (int) $resource_post->ID);
$can_download = function_exists('jio_user_can') && jio_user_can('resource_download', $uid, (int) $resource_post->ID);
$state['download_cost'] = max(0, $download_cost);
$state['need_login'] = !$can_download && $uid <= 0;
$state['need_purchase'] = $allowed_member && $price_minor > 0 && !$has_paid_order;
@@ -158,7 +158,7 @@ class Visibility {
return $state;
}
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_DOWNLOAD) {
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_DOWNLOAD) {
// legacy: cash = order unlock; points = one-shot cashier order (not per-download deduct).
$download_cost = 0;
if ($pay_modo === 'points' && $price_minor > 0 && !$has_paid_order) {
@@ -166,9 +166,9 @@ class Visibility {
}
$state['download_cost'] = max(0, $download_cost);
$can_download = function_exists('aksrt_user_can') && aksrt_user_can('resource_download', $uid, (int) $resource_post->ID);
$can_download = function_exists('jio_user_can') && jio_user_can('resource_download', $uid, (int) $resource_post->ID);
$state['need_login'] = !$can_download && $uid <= 0;
$state['require_captcha'] = function_exists('aksrt_is_captcha_enabled_for') && aksrt_is_captcha_enabled_for('download');
$state['require_captcha'] = function_exists('jio_is_captcha_enabled_for') && jio_is_captcha_enabled_for('download');
$state['need_purchase'] = !$has_paid_order && $price_minor > 0;
$state['has_paid_access'] = $has_paid_order || $price_minor <= 0 || $has_free_access;
@@ -178,7 +178,7 @@ class Visibility {
return $state;
}
if ($pay_type === \AKSRT\Core\DomainModel::PAY_TYPE_VIP) {
if ($pay_type === \Jio\Core\DomainModel::PAY_TYPE_VIP) {
$state['need_vip'] = true;
$state['has_paid_access'] = $has_vip_access;
$state['can_view'] = $has_vip_access;
@@ -191,7 +191,7 @@ class Visibility {
$state['need_purchase'] = !$has_free_access && !$has_paid_order;
$state['has_paid_access'] = $has_free_access || $has_paid_order;
// VIP free tier for reading etc. via amount.
if (!$state['has_paid_access'] && $price_minor <= 0 && $pay_type !== \AKSRT\Core\DomainModel::PAY_TYPE_VIP) {
if (!$state['has_paid_access'] && $price_minor <= 0 && $pay_type !== \Jio\Core\DomainModel::PAY_TYPE_VIP) {
$state['has_paid_access'] = true;
$state['need_purchase'] = false;
}
@@ -212,26 +212,26 @@ class Visibility {
*/
public static function can_download_resource($post = null, int $user_id = 0) {
$resource_post = get_post($post);
if (!($resource_post instanceof \WP_Post) || !function_exists('aksrt_is_downloadable_content') || !aksrt_is_downloadable_content($resource_post)) {
return new \WP_Error('aksrt_not_downloadable', __('该内容未启用下载能力。', 'aksrt'));
if (!($resource_post instanceof \WP_Post) || !function_exists('jio_is_downloadable_content') || !jio_is_downloadable_content($resource_post)) {
return new \WP_Error('jio_not_downloadable', __('该内容未启用下载能力。', 'jio'));
}
$state = self::get_post_access_state($resource_post, $user_id);
$uid = $user_id > 0 ? $user_id : get_current_user_id();
if (!function_exists('aksrt_user_can') || !aksrt_user_can('resource_download', $uid, (int) $resource_post->ID)) {
return new \WP_Error('aksrt_download_forbidden', __('当前账号没有下载资源的权限。', 'aksrt'), [
if (!function_exists('jio_user_can') || !jio_user_can('resource_download', $uid, (int) $resource_post->ID)) {
return new \WP_Error('jio_download_forbidden', __('当前账号没有下载资源的权限。', 'jio'), [
'status' => $uid > 0 ? 403 : 401,
'login_url' => wp_login_url(get_permalink($resource_post)),
]);
}
if (($state['pay_type'] ?? '') !== \AKSRT\Core\DomainModel::PAY_TYPE_DOWNLOAD) {
return new \WP_Error('aksrt_not_downloadable', __('该内容未启用下载能力。', 'aksrt'));
if (($state['pay_type'] ?? '') !== \Jio\Core\DomainModel::PAY_TYPE_DOWNLOAD) {
return new \WP_Error('jio_not_downloadable', __('该内容未启用下载能力。', 'jio'));
}
if (!empty($state['need_login']) && $uid <= 0) {
return new \WP_Error('aksrt_need_login', __('请先登录后再下载。', 'aksrt'), [
return new \WP_Error('jio_need_login', __('请先登录后再下载。', 'jio'), [
'status' => 401,
'login_url' => wp_login_url(get_permalink($resource_post)),
]);
@@ -241,9 +241,9 @@ class Visibility {
// Member-only (pay_limit).
if (!empty($state['need_vip']) && empty($state['has_paid_access']) && empty($state['can_download'])) {
$need_level = (int) ($state['pay_limit'] ?? 1);
return new \WP_Error('aksrt_need_vip', sprintf(
return new \WP_Error('jio_need_vip', sprintf(
/* translators: %d: required VIP level */
__('该资源仅限 VIP%s 及以上会员购买/下载。', 'aksrt'),
__('该资源仅限 VIP%s 及以上会员购买/下载。', 'jio'),
max(1, $need_level)
), [
'status' => 403,
@@ -254,7 +254,7 @@ class Visibility {
// Cash or points: require cashier purchase (resource order) before download token.
if (!empty($state['need_purchase']) && empty($state['has_paid_access'])) {
$pay_modo = (string) ($state['pay_modo'] ?? '0');
return new \WP_Error('aksrt_need_purchase', __('请先购买后再下载。', 'aksrt'), [
return new \WP_Error('jio_need_purchase', __('请先购买后再下载。', 'jio'), [
'status' => 402,
'pay_modo' => $pay_modo,
'amount' => $state['price'] ?? ($pay_modo === 'points' ? 0 : '0.00'),
@@ -263,18 +263,18 @@ class Visibility {
}
// legacy daily free-download quota (only when free / already unlocked).
if ($cost <= 0 && function_exists('aksrt_check_free_download_quota')) {
if ($cost <= 0 && function_exists('jio_check_free_download_quota')) {
// Provide per-post overbuy price to quota error.
$over_cb = static function ($over, $uid) use ($resource_post) {
if (!($resource_post instanceof \WP_Post) || !function_exists('aksrt_get_pay_meta')) {
if (!($resource_post instanceof \WP_Post) || !function_exists('jio_get_pay_meta')) {
return $over;
}
$m = aksrt_get_pay_meta($resource_post);
$m = jio_get_pay_meta($resource_post);
return $m['download_limit_over_price'] ?? 0;
};
add_filter('aksrt_download_limit_over_price', $over_cb, 10, 2);
$quota = aksrt_check_free_download_quota($uid, $cost);
remove_filter('aksrt_download_limit_over_price', $over_cb, 10);
add_filter('jio_download_limit_over_price', $over_cb, 10, 2);
$quota = jio_check_free_download_quota($uid, $cost);
remove_filter('jio_download_limit_over_price', $over_cb, 10);
if (is_wp_error($quota)) {
$data = (array) $quota->get_error_data();
$data['post_id'] = (int) ($state['post_id'] ?? 0);
@@ -291,7 +291,7 @@ class Visibility {
'mode' => 'comment',
'message' => '',
'pid' => get_the_ID(),
], $atts, 'aksrt_hide');
], $atts, 'jio_hide');
$mode = sanitize_key((string) $atts['mode']);
$pid = (int) $atts['pid'];
@@ -302,36 +302,36 @@ class Visibility {
}
if ($this->is_unlocked($mode, $pid)) {
return '<div class="aksrt-hidden-content aksrt-hidden-content--unlocked">' . do_shortcode($content) . '</div>';
return '<div class="jio-hidden-content jio-hidden-content--unlocked">' . do_shortcode($content) . '</div>';
}
if ($message === '') {
switch ($mode) {
case 'comment':
$message = __('评论后查看隐藏内容', 'aksrt');
$message = __('评论后查看隐藏内容', 'jio');
break;
case 'login':
$message = __('登录后查看隐藏内容', 'aksrt');
$message = __('登录后查看隐藏内容', 'jio');
break;
case 'password':
$message = __('输入密码后查看隐藏内容', 'aksrt');
$message = __('输入密码后查看隐藏内容', 'jio');
break;
default:
$message = __('此内容已隐藏', 'aksrt');
$message = __('此内容已隐藏', 'jio');
}
}
$wrapper_class = 'aksrt-hidden-content aksrt-hidden-content--locked aksrt-hidden-content--' . esc_attr($mode);
$html = '<div class="' . $wrapper_class . '" data-aksrt-visibility-mode="' . esc_attr($mode) . '" data-aksrt-visibility-pid="' . esc_attr((string) $pid) . '">';
$html .= '<div class="aksrt-hidden-content__message">';
$wrapper_class = 'jio-hidden-content jio-hidden-content--locked jio-hidden-content--' . esc_attr($mode);
$html = '<div class="' . $wrapper_class . '" data-jio-visibility-mode="' . esc_attr($mode) . '" data-jio-visibility-pid="' . esc_attr((string) $pid) . '">';
$html .= '<div class="jio-hidden-content__message">';
$html .= '<i class="fa fas fa-lock" aria-hidden="true"></i> ';
$html .= '<span>' . esc_html($message) . '</span>';
$html .= '</div>';
if ($mode === 'password') {
$html .= '<div class="aksrt-hidden-content__form">';
$html .= '<input type="password" class="aksrt-hidden-content__password-input" placeholder="' . esc_attr__('请输入密码', 'aksrt') . '">';
$html .= '<button type="button" class="aksrt-hidden-content__submit-btn btn-primary btn-sm">' . esc_html__('验证', 'aksrt') . '</button>';
$html .= '<div class="jio-hidden-content__form">';
$html .= '<input type="password" class="jio-hidden-content__password-input" placeholder="' . esc_attr__('请输入密码', 'jio') . '">';
$html .= '<button type="button" class="jio-hidden-content__submit-btn btn-primary btn-sm">' . esc_html__('验证', 'jio') . '</button>';
$html .= '</div>';
}
@@ -348,7 +348,7 @@ class Visibility {
return 0;
}
try {
return \AKSRT\Ledger\AssetAmount::balance_minor($value);
return \Jio\Ledger\AssetAmount::balance_minor($value);
} catch (\InvalidArgumentException $e) {
return 0;
}
@@ -372,7 +372,7 @@ class Visibility {
return is_user_logged_in();
case 'password':
return !empty($_COOKIE['aksrt_hide_pwd_' . $pid]);
return !empty($_COOKIE['jio_hide_pwd_' . $pid]);
default:
return false;
@@ -380,30 +380,30 @@ class Visibility {
}
public function ajax_check_visibility(): void {
check_ajax_referer('aksrt_visibility', '_nonce');
check_ajax_referer('jio_visibility', '_nonce');
$mode = sanitize_key((string) ($_POST['mode'] ?? ''));
$pid = (int) ($_POST['pid'] ?? 0);
if ($pid <= 0 || !in_array($mode, ['comment', 'login', 'password'], true)) {
wp_send_json_error(['message' => __('参数无效', 'aksrt')]);
wp_send_json_error(['message' => __('参数无效', 'jio')]);
}
if ($mode === 'password') {
$password = sanitize_text_field((string) ($_POST['password'] ?? ''));
$post_password = get_post_password($pid);
if ($post_password === '' || $password !== $post_password) {
wp_send_json_error(['message' => __('密码错误', 'aksrt')]);
wp_send_json_error(['message' => __('密码错误', 'jio')]);
}
setcookie('aksrt_hide_pwd_' . $pid, '1', time() + HOUR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
wp_send_json_success(['message' => __('验证成功', 'aksrt')]);
setcookie('jio_hide_pwd_' . $pid, '1', time() + HOUR_IN_SECONDS, COOKIEPATH, COOKIE_DOMAIN, is_ssl(), true);
wp_send_json_success(['message' => __('验证成功', 'jio')]);
}
if ($this->is_unlocked($mode, $pid)) {
wp_send_json_success(['message' => __('已解锁', 'aksrt')]);
wp_send_json_success(['message' => __('已解锁', 'jio')]);
}
wp_send_json_error(['message' => __('未满足条件', 'aksrt')]);
wp_send_json_error(['message' => __('未满足条件', 'jio')]);
}
}