积分与余额账务系统硬切重构
This commit is contained in:
1 parent
ca12226b39
commit
5cae5b5c93
159 files changed
+7275
-4718
No files matched your search
@@ -44,6 +44,17 @@ if (!function_exists('aksrt_render_rewards_modal_for_user')) {
|
||||
$done[$key] = true;
|
||||
$settings = \AKSRT\Settings\Settings::get_post_page_settings();
|
||||
$amounts = (array) ($settings['rewards_amounts'] ?? [5, 10, 20, 50, 100]);
|
||||
$render_amounts = [];
|
||||
foreach ($amounts as $amount) {
|
||||
try {
|
||||
$parsed = \AKSRT\Ledger\AssetAmount::balance(is_string($amount) ? $amount : '');
|
||||
if ($parsed->minor() > 0) {
|
||||
$render_amounts[] = $parsed->decimal();
|
||||
}
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$recipient = get_userdata($user_id);
|
||||
?>
|
||||
<div class="reward-modal" id="reward-modal-<?php echo (int) $user_id; ?>" data-user-id="<?php echo (int) $user_id; ?>" data-post-id="<?php echo (int) $post_id; ?>" aria-hidden="true">
|
||||
@@ -54,8 +65,8 @@ if (!function_exists('aksrt_render_rewards_modal_for_user')) {
|
||||
<h3 id="reward-title-<?php echo (int) $user_id; ?>"><?php echo esc_html((string) ($settings['rewards_text'] ?? __('赞赏', 'aksrt'))); ?></h3>
|
||||
<p class="muted-2-color em09"><?php printf(esc_html__('赞赏将直接进入 %s 的站内余额', 'aksrt'), esc_html($recipient ? $recipient->display_name : __('作者', 'aksrt'))); ?></p>
|
||||
<div class="reward-amounts" data-aksrt-reward-amounts>
|
||||
<?php foreach ($amounts as $index => $amount) : ?>
|
||||
<button type="button" class="reward-amount<?php echo $index === 0 ? ' is-active' : ''; ?>" data-reward-amount="<?php echo esc_attr(number_format((float) $amount, 2, '.', '')); ?>">¥<?php echo esc_html(number_format_i18n((float) $amount, 2)); ?></button>
|
||||
<?php foreach ($render_amounts as $index => $amount) : ?>
|
||||
<button type="button" class="reward-amount<?php echo $index === 0 ? ' is-active' : ''; ?>" data-reward-amount="<?php echo esc_attr($amount); ?>">¥<?php echo esc_html($amount); ?></button>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php if (!empty($settings['rewards_custom'])) : ?>
|
||||
@@ -75,7 +86,8 @@ add_action('wp_ajax_aksrt_submit_tip', function (): void {
|
||||
if (!is_user_logged_in()) {
|
||||
wp_send_json_error(['message' => __('请先登录后赞赏', 'aksrt')], 401);
|
||||
}
|
||||
if (!aksrt_rewards_enabled() || !class_exists('\AKSRT\Credits\Balance') || !\AKSRT\Credits\Balance::enabled()) {
|
||||
$recharge = class_exists('\AKSRT\Settings\Settings') ? \AKSRT\Settings\Settings::get_payment_recharge_settings() : [];
|
||||
if (!aksrt_rewards_enabled() || empty($recharge['enabled'])) {
|
||||
wp_send_json_error(['message' => __('赞赏功能当前不可用', 'aksrt')], 400);
|
||||
}
|
||||
|
||||
@@ -94,40 +106,63 @@ add_action('wp_ajax_aksrt_submit_tip', function (): void {
|
||||
}
|
||||
|
||||
$settings = \AKSRT\Settings\Settings::get_post_page_settings();
|
||||
$amount = isset($_POST['amount']) ? round((float) wp_unslash($_POST['amount']), 2) : 0.0;
|
||||
$minimum = (float) ($settings['rewards_min'] ?? 1);
|
||||
$maximum = (float) ($settings['rewards_max'] ?? 1000);
|
||||
if (!is_finite($amount) || $amount < $minimum || $amount > $maximum) {
|
||||
wp_send_json_error(['message' => sprintf(__('赞赏金额需在 ¥%1$s 至 ¥%2$s 之间', 'aksrt'), number_format_i18n($minimum, 2), number_format_i18n($maximum, 2))], 400);
|
||||
$raw_amount = isset($_POST['amount']) ? (string) wp_unslash($_POST['amount']) : '';
|
||||
try {
|
||||
$amount = \AKSRT\Ledger\AssetAmount::balance($raw_amount);
|
||||
$minimum = \AKSRT\Ledger\AssetAmount::balance(is_string($settings['rewards_min'] ?? null) ? $settings['rewards_min'] : '');
|
||||
$maximum = \AKSRT\Ledger\AssetAmount::balance(is_string($settings['rewards_max'] ?? null) ? $settings['rewards_max'] : '');
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
wp_send_json_error(['message' => __('赞赏金额格式无效', 'aksrt')], 400);
|
||||
}
|
||||
if ($amount->minor() < $minimum->minor() || $amount->minor() > $maximum->minor()) {
|
||||
wp_send_json_error(['message' => sprintf(__('赞赏金额需在 ¥%1$s 至 ¥%2$s 之间', 'aksrt'), $minimum->formatted(), $maximum->formatted())], 400);
|
||||
}
|
||||
if (empty($settings['rewards_custom'])) {
|
||||
$allowed_amounts = array_map(static fn($value): float => round((float) $value, 2), (array) ($settings['rewards_amounts'] ?? []));
|
||||
if (!in_array($amount, $allowed_amounts, true)) {
|
||||
$allowed_amounts = [];
|
||||
foreach ((array) ($settings['rewards_amounts'] ?? []) as $allowed) {
|
||||
try {
|
||||
$allowed_amounts[] = \AKSRT\Ledger\AssetAmount::balance(is_string($allowed) ? $allowed : '')->minor();
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!in_array($amount->minor(), $allowed_amounts, true)) {
|
||||
wp_send_json_error(['message' => __('请选择预设的赞赏金额', 'aksrt')], 400);
|
||||
}
|
||||
}
|
||||
$request_key = sanitize_text_field(wp_unslash((string) ($_SERVER['HTTP_IDEMPOTENCY_KEY'] ?? '')));
|
||||
if (!wp_is_uuid($request_key)) {
|
||||
wp_send_json_error(['message' => __('缺少或无效的 Idempotency-Key 请求头', 'aksrt')], 400);
|
||||
}
|
||||
$operation_key = \AKSRT\Ledger\OperationKey::deterministic('client-tip', [$sender_id, strtolower($request_key)]);
|
||||
|
||||
$rate_key = 'aksrt_tip_rate_' . $sender_id;
|
||||
if (get_transient($rate_key)) {
|
||||
$recent_operation = (string) get_transient($rate_key);
|
||||
if ($recent_operation !== '' && !hash_equals($recent_operation, $operation_key)) {
|
||||
wp_send_json_error(['message' => __('操作太频繁,请稍后再试', 'aksrt')], 429);
|
||||
}
|
||||
set_transient($rate_key, 1, 3);
|
||||
set_transient($rate_key, $operation_key, 3);
|
||||
|
||||
$result = \AKSRT\Credits\Balance::transfer(
|
||||
$result = \AKSRT\Ledger\LedgerService::get_instance()->transfer(
|
||||
$sender_id,
|
||||
$recipient_id,
|
||||
$amount,
|
||||
'tip_sent',
|
||||
'tip_received',
|
||||
\AKSRT\Ledger\AssetType::BALANCE,
|
||||
$amount->minor(),
|
||||
0,
|
||||
$operation_key,
|
||||
'tip',
|
||||
['type' => 'tip', 'id' => $post_id],
|
||||
$post_id > 0 ? sprintf(__('赞赏文章 #%d', 'aksrt'), $post_id) : __('用户赞赏', 'aksrt')
|
||||
$post_id > 0 ? sprintf(__('赞赏文章 #%d', 'aksrt'), $post_id) : __('用户赞赏', 'aksrt'),
|
||||
__('收到用户赞赏', 'aksrt')
|
||||
);
|
||||
if (is_wp_error($result)) {
|
||||
wp_send_json_error(['message' => $result->get_error_message()], 400);
|
||||
wp_send_json_error(['message' => $result->get_error_message()], (int) ($result->get_error_data()['status'] ?? 400));
|
||||
}
|
||||
|
||||
wp_send_json_success([
|
||||
'message' => __('赞赏成功,金额已进入对方余额', 'aksrt'),
|
||||
'balance' => \AKSRT\Credits\Balance::format((float) $result['sender_balance']),
|
||||
'transaction_id' => $result->transaction_id,
|
||||
'replayed' => $result->replayed,
|
||||
'balance' => \AKSRT\Ledger\AssetAmount::from_minor(\AKSRT\Ledger\AssetType::BALANCE, $result->balance($sender_id, \AKSRT\Ledger\AssetType::BALANCE))->decimal(),
|
||||
]);
|
||||
});
|
||||
Reference in new issue
Block a user