Files
wordpress-theme-aksrt/inc/helpers/user-center-renderers/credits-wallet.php
T
kate522 3481620ed0 feat(payment): 通用卡密兑换弹窗并修正核销订单实付与订单名称
- /user/balance/ 余额卡片入口改为通用「卡密兑换」弹窗:请求不带类型,
  后端按卡密自动识别余额/会员/积分;卡号输入恒展示且选填
- 后台「余额充值 → 卡密充值」语义更新为「卡密兑换」,开关更名
  「启用卡密兑换功能」(设置键不变),双源 schema 同步并重建 SPA
- 删除死代码:credits-vip.php 死文件、credits-balance.php 内联积分
  兑换块、/pay/card-pass/options 路由与 rest_options、labels 数组、
  asset_points_card_description/password_only 死字段及内联块专属 CSS
- 卡密核销订单实付恒 0:create_redeem_order 源头写 0,UserOrders
  对 card_pass 订单视图层归零覆盖历史行(不迁移数据)
- 订单名称按 note.meta 生成:卡密兑换-余额充值X / 卡密兑换-积分充值X /
  购入[会员档位名]X天(永久)
- 新增契约 card-pass-universal-redeem.test.cjs,收紧 user-assets-layout
  契约(禁 .uc-card-pass 根类回潮)
2026-09-17 19:04:47 +08:00

214 lines
11 KiB
PHP

<?php
/**
* User center: cash wallet (站内余额) — legacy-like asset card.
*
* Expects extracted $context vars.
*
* @package AKSRT
*/
defined('ABSPATH') || exit;
if (empty($balance_enabled)) {
return;
}
$normalize_balance = static function ($value): \AKSRT\Ledger\AssetAmount {
try {
return \AKSRT\Ledger\AssetAmount::balance(is_string($value) ? $value : '');
} catch (\InvalidArgumentException $e) {
return \AKSRT\Ledger\AssetAmount::balance('0');
}
};
$wallet = $normalize_balance($wallet_balance ?? '0');
$wallet_fmt = $wallet->formatted();
$recharge = class_exists('\AKSRT\Settings\Settings') && method_exists('\AKSRT\Settings\Settings', 'get_payment_recharge_settings')
? \AKSRT\Settings\Settings::get_payment_recharge_settings()
: [];
$uid = (int) ($user_id ?? get_current_user_id());
$transfer_on = !empty($recharge['transfer']['enabled']);
if ($transfer_on && class_exists('\AKSRT\Settings\Capabilities') && !\AKSRT\Settings\Capabilities::user_can('balance_transfer', $uid)) {
$transfer_on = false;
}
$all_settings = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_all() : [];
$withdraw_on = !empty($all_settings['pay_balance_withdraw_s']);
if ($withdraw_on && class_exists('\AKSRT\Settings\Capabilities') && !\AKSRT\Settings\Capabilities::user_can('balance_withdraw', $uid)) {
$withdraw_on = false;
}
$withdraw_settings = class_exists('\\AKSRT\\Settings\\Settings') ? \AKSRT\Settings\Settings::get_withdrawal_settings() : [];
$withdraw_min = $normalize_balance($withdraw_settings['min_amount'] ?? '50')->decimal();
$withdraw_usage = ['remaining_count' => 0, 'remaining_amount' => '0.00'];
$withdraw_pending_hold = '0.00';
if ($withdraw_on && class_exists('\AKSRT\Payment\Withdrawal')) {
$wd_svc = \AKSRT\Payment\Withdrawal::get_instance();
$withdraw_pending_hold = $wd_svc->sum_pending_hold((int) ($user_id ?? 0));
$withdraw_usage = $wd_svc->daily_usage((int) ($user_id ?? 0), $withdraw_settings);
}
// 卡密兑换总开关(后台 余额充值 → 卡密兑换 → 启用卡密兑换功能),
// 通用弹窗支持余额 / 会员 / 积分三类卡密,类型由后端按卡密自动识别。
$card_pass_redeem = ['enabled' => false, 'desc' => ''];
if (class_exists('\AKSRT\Payment\ChargeCard')) {
$opts = \AKSRT\Payment\ChargeCard::get_instance()->get_public_options();
$card_pass_redeem = is_array($opts['balance'] ?? null) ? $opts['balance'] : $card_pass_redeem;
}
$charge_view = [];
if (class_exists('\AKSRT\Credits\BalanceService')) {
$charge_view = \AKSRT\Credits\BalanceService::get_instance()->get_charge_view((int) $user_id);
}
$packages = is_array($charge_view['packages'] ?? null) ? $charge_view['packages'] : [];
$methods = is_array($charge_view['payment_methods'] ?? null) ? $charge_view['payment_methods'] : [];
$custom_s = !empty($charge_view['custom_s']);
$custom_limit = (int) ($charge_view['custom_limit'] ?? 9999);
$mark = (string) ($charge_view['currency_mark'] ?? '元');
?>
<div class="uc-asset-card uc-asset-card--wallet">
<div class="uc-asset-card__head flex jsb ac">
<div class="uc-asset-card__title">
<i class="fa fas fa-money-bill em12 mr6" aria-hidden="true"></i><?php esc_html_e('余额', 'aksrt'); ?>
</div>
<?php if ($withdraw_on) : ?>
<button type="button" class="uc-asset-card__head-action muted-color px12" data-aksrt-withdraw-history-open>
<?php esc_html_e('提现记录', 'aksrt'); ?>
<i class="fa fas fa-angle-right em12 ml3" aria-hidden="true"></i>
</button>
<?php endif; ?>
</div>
<div class="uc-asset-card__body flex jsb ac">
<div class="uc-asset-card__amount c-blue-2">
<?php if (!in_array($mark, ['', '元', '¥'], true)) : ?>
<span class="uc-asset-card__mark px12"><?php echo esc_html($mark); ?></span>
<?php endif; ?>
<span class="uc-asset-card__value font-bold" data-aksrt-wallet-value title="<?php echo esc_attr($wallet_fmt); ?>"><?php echo esc_html($wallet_fmt); ?></span>
</div>
<div class="uc-asset-card__actions flex0">
<?php if ($transfer_on) : ?>
<button type="button" class="but c-blue-2 mr6 hollow" data-aksrt-transfer-open="balance"><?php esc_html_e('转账', 'aksrt'); ?></button>
<?php endif; ?>
<?php if ($withdraw_on) : ?>
<button type="button" class="but c-blue-2 mr6 hollow" data-aksrt-withdraw-open><?php esc_html_e('提现', 'aksrt'); ?></button>
<?php endif; ?>
<button type="button" class="but b-blue-2" data-aksrt-charge-open><?php esc_html_e('充值', 'aksrt'); ?></button>
</div>
</div>
<?php if ($withdraw_on || !empty($card_pass_redeem['enabled'])) : ?>
<div class="uc-asset-card__foot muted-2-color em09 mt6 flex jsb ac">
<?php if ($withdraw_on) : ?>
<span><?php printf(esc_html__('冻结中 %s', 'aksrt'), esc_html($normalize_balance($withdraw_pending_hold)->formatted())); ?></span>
<?php else : ?>
<span></span>
<?php endif; ?>
<?php if (!empty($card_pass_redeem['enabled'])) : ?>
<button type="button" class="uc-asset-card__head-action muted-color px12" data-aksrt-card-pass-open>
<?php esc_html_e('卡密兑换', 'aksrt'); ?>
<i class="fa fas fa-angle-right em12 ml3" aria-hidden="true"></i>
</button>
<?php endif; ?>
</div>
<?php endif; ?>
</div>
<?php if (!empty($card_pass_redeem['enabled'])) : ?>
<div class="uc-modal" id="aksrt-card-pass-modal" hidden data-aksrt-card-pass-modal data-aksrt-card-pass="">
<div class="uc-modal__overlay" data-aksrt-card-pass-close></div>
<div class="uc-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="aksrt-card-pass-title">
<button type="button" class="uc-modal__close" data-aksrt-card-pass-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fa fas fa-times" aria-hidden="true"></i></button>
<h3 id="aksrt-card-pass-title" class="uc-modal__title"><i class="fa fas fa-ticket-alt mr6" aria-hidden="true"></i><?php esc_html_e('卡密兑换', 'aksrt'); ?></h3>
<?php if (!empty($card_pass_redeem['desc'])) : ?>
<div class="uc-modal__desc muted-box em09"><?php echo esc_html((string) $card_pass_redeem['desc']); ?></div>
<?php endif; ?>
<input type="text" class="uc-card-pass__input" name="aksrt_card_no" data-aksrt-card-no autocomplete="off" placeholder="<?php esc_attr_e('请输入卡号(选填)', 'aksrt'); ?>">
<input type="text" class="uc-card-pass__input" name="aksrt_card_password" data-aksrt-card-password autocomplete="off" placeholder="<?php esc_attr_e('请输入卡密', 'aksrt'); ?>">
<div class="uc-card-pass-actions">
<button type="button" class="uc-card-pass__btn" data-aksrt-card-redeem>
<?php esc_html_e('立即兑换', 'aksrt'); ?>
</button>
</div>
<p class="uc-card-pass__tip" data-aksrt-card-tip></p>
</div>
</div>
<?php endif; ?>
<!-- Charge modal -->
<div class="uc-modal" id="aksrt-charge-modal" hidden data-aksrt-charge-modal>
<div class="uc-modal__overlay" data-aksrt-charge-close></div>
<div class="uc-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="aksrt-charge-title">
<button type="button" class="uc-modal__close" data-aksrt-charge-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fa fas fa-times" aria-hidden="true"></i></button>
<h3 id="aksrt-charge-title" class="uc-modal__title"><i class="fa fas fa-money-bill mr6" aria-hidden="true"></i><?php esc_html_e('余额充值', 'aksrt'); ?></h3>
<?php if (!empty($charge_view['desc'])) : ?>
<div class="uc-modal__desc muted-box em09"><?php echo esc_html((string) $charge_view['desc']); ?></div>
<?php endif; ?>
<form class="uc-charge-form" data-aksrt-charge-form>
<?php if ($packages) : ?>
<div class="muted-color mb6"><?php esc_html_e('请选择充值金额', 'aksrt'); ?></div>
<div class="uc-charge-packages">
<?php foreach ($packages as $idx => $pkg) :
$package_credit = $normalize_balance($pkg['price'] ?? '');
$package_pay = $normalize_balance($pkg['pay_price'] ?? '');
$package_saving_minor = max(0, $package_credit->minor() - $package_pay->minor());
?>
<label class="uc-charge-package<?php echo $idx === 0 ? ' is-active' : ''; ?>">
<input type="radio" name="balance_package" value="<?php echo esc_attr((string) $pkg['key']); ?>" <?php checked($idx === 0); ?>>
<div class="uc-charge-package__credit"><?php echo esc_html((string) $pkg['price']); ?></div>
<div class="uc-charge-package__pay c-red"><?php echo esc_html((string) $pkg['pay_price']); ?>
<?php if ($package_saving_minor > 0) : ?>
<span class="ml6 c-yellow smail"><?php printf(esc_html__('省%s', 'aksrt'), esc_html(\AKSRT\Ledger\AssetAmount::decimal_from_minor($package_saving_minor))); ?></span>
<?php endif; ?>
</div>
<?php if (!empty($pkg['tag'])) : ?>
<span class="uc-charge-package__tag"><?php echo esc_html((string) $pkg['tag']); ?></span>
<?php endif; ?>
</label>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php if ($custom_s) : ?>
<div class="muted-color mt16 mb6"><?php echo $packages ? esc_html__('自定义充值金额', 'aksrt') : esc_html__('请输入充值金额', 'aksrt'); ?></div>
<div class="uc-charge-custom flex ac">
<input type="number" class="uc-charge-custom__input" name="custom_price" min="1" max="<?php echo esc_attr((string) $custom_limit); ?>" step="0.01" placeholder="1 ~ <?php echo esc_attr((string) $custom_limit); ?>">
</div>
<?php if (!$packages) : ?>
<input type="hidden" name="balance_package" value="custom">
<?php endif; ?>
<?php endif; ?>
<?php if ($methods) : ?>
<div class="muted-color mt16 mb6"><?php esc_html_e('支付方式', 'aksrt'); ?></div>
<div class="uc-charge-methods">
<?php foreach ($methods as $mi => $m) : ?>
<label class="uc-charge-method">
<input type="radio" name="payment_method" value="<?php echo esc_attr((string) ($m['id'] ?? '')); ?>" <?php checked($mi === 0); ?>>
<span><?php echo esc_html((string) ($m['name'] ?? $m['id'] ?? '')); ?></span>
</label>
<?php endforeach; ?>
</div>
<?php endif; ?>
<button type="submit" class="but jb-blue btn-block mt10" data-aksrt-charge-submit><?php esc_html_e('立即充值', 'aksrt'); ?></button>
</form>
</div>
</div>
<?php if ($withdraw_on) :
$withdraw_modal_rendered = !empty($GLOBALS['aksrt_withdraw_modal_rendered']);
if (!$withdraw_modal_rendered) {
require __DIR__ . '/withdraw-modal.php';
}
endif; ?>
<?php if ($withdraw_on) : ?>
<div class="uc-modal" id="aksrt-withdraw-history-modal" hidden data-aksrt-withdraw-history-modal>
<div class="uc-modal__overlay" data-aksrt-withdraw-history-close></div>
<div class="uc-modal__dialog uc-withdraw-history-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="aksrt-withdraw-history-title">
<button type="button" class="uc-modal__close" data-aksrt-withdraw-history-close aria-label="<?php esc_attr_e('关闭', 'aksrt'); ?>"><i class="fa fas fa-times" aria-hidden="true"></i></button>
<h3 id="aksrt-withdraw-history-title" class="uc-modal__title"><i class="fa fas fa-file-alt mr6" aria-hidden="true"></i><?php esc_html_e('提现记录', 'aksrt'); ?></h3>
<div class="uc-withdraw-history" data-aksrt-withdraw-history-list aria-live="polite"></div>
<nav class="uc-withdraw-history__pagination" data-aksrt-withdraw-history-pagination aria-label="<?php esc_attr_e('提现记录分页', 'aksrt'); ?>"></nav>
</div>
</div>
<?php endif; ?>
<?php if (empty($skip_wallet_ledger)) : ?>
<?php require __DIR__ . '/credits-wallet-ledger.php'; ?>
<?php endif; ?>