积分与余额账务系统硬切重构
This commit is contained in:
@@ -175,81 +175,71 @@ final class ReferralAttribution {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!class_exists('\AKSRT\Credits\Credits')) {
|
||||
return;
|
||||
}
|
||||
if (!empty($settings['require_verify']) && !$this->is_verified($invitee_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$wpdb->query('START TRANSACTION');
|
||||
try {
|
||||
$row = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$table} WHERE invitee_id = %d AND status = 'bound' FOR UPDATE",
|
||||
$invitee_id
|
||||
), ARRAY_A);
|
||||
if (!is_array($row) || (string) ($row['reward_status'] ?? 'pending') !== 'pending') {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return;
|
||||
$row = $wpdb->get_row($wpdb->prepare(
|
||||
"SELECT * FROM {$table} WHERE invitee_id = %d AND status = 'bound'",
|
||||
$invitee_id
|
||||
), ARRAY_A);
|
||||
if (!is_array($row) || (string) ($row['reward_status'] ?? 'pending') !== 'pending') {
|
||||
return;
|
||||
}
|
||||
$relation_id = (int) $row['id'];
|
||||
$promoter_id = (int) $row['promoter_id'];
|
||||
if ($promoter_id <= 0) {
|
||||
$wpdb->update($table, ['reward_status' => 'skipped'], ['id' => $relation_id, 'reward_status' => 'pending'], ['%s'], ['%d', '%s']);
|
||||
return;
|
||||
}
|
||||
$promoter_amount = max(0, (int) ($settings['promoter_amount'] ?? 0));
|
||||
$referred_amount = max(0, (int) ($settings['referred_amount'] ?? 0));
|
||||
$entries = [];
|
||||
if ($promoter_amount > 0) {
|
||||
$entries[] = ['user_id' => $promoter_id, 'asset' => \AKSRT\Ledger\AssetType::POINTS->value, 'delta_minor' => $promoter_amount, 'entry_type' => 'credit', 'counterparty_user_id' => $invitee_id, 'remark' => __('推广注册奖励', 'aksrt')];
|
||||
}
|
||||
if ($referred_amount > 0) {
|
||||
$entries[] = ['user_id' => $invitee_id, 'asset' => \AKSRT\Ledger\AssetType::POINTS->value, 'delta_minor' => $referred_amount, 'entry_type' => 'credit', 'counterparty_user_id' => $promoter_id, 'remark' => __('推广注册新用户奖励', 'aksrt')];
|
||||
}
|
||||
if ($entries === []) {
|
||||
$wpdb->update($table, ['reward_status' => 'rewarded', 'rewarded_at' => current_time('mysql', true)], ['id' => $relation_id, 'reward_status' => 'pending'], ['%s', '%s'], ['%d', '%s']);
|
||||
return;
|
||||
}
|
||||
$level_points = max(0, (int) ($settings['level_points'] ?? 0));
|
||||
$command = new \AKSRT\Ledger\LedgerCommand(
|
||||
\AKSRT\Ledger\OperationKey::deterministic('referral-reward', [$relation_id]),
|
||||
'referral',
|
||||
$entries,
|
||||
'referral',
|
||||
(string) $relation_id,
|
||||
0,
|
||||
['invitee_id' => $invitee_id, 'promoter_id' => $promoter_id]
|
||||
);
|
||||
$guard = function () use ($wpdb, $table, $relation_id, $settings, $row) {
|
||||
$locked = $wpdb->get_row($wpdb->prepare("SELECT reward_status FROM {$table} WHERE id = %d FOR UPDATE", $relation_id), ARRAY_A);
|
||||
if (!is_array($locked) || (string) $locked['reward_status'] !== 'pending') {
|
||||
return new \WP_Error('aksrt_referral_state', __('推广奖励状态已变化', 'aksrt'), ['status' => 409]);
|
||||
}
|
||||
|
||||
$relation_id = (int) $row['id'];
|
||||
$promoter_id = (int) $row['promoter_id'];
|
||||
if ($promoter_id <= 0 || !$this->ip_daily_check($row, $settings)) {
|
||||
$wpdb->update($table, ['reward_status' => 'skipped'], ['id' => $relation_id], ['%s'], ['%d']);
|
||||
$wpdb->query('COMMIT');
|
||||
return;
|
||||
}
|
||||
|
||||
$claimed = $wpdb->update(
|
||||
$table,
|
||||
['reward_status' => 'rewarding'],
|
||||
['id' => $relation_id, 'reward_status' => 'pending'],
|
||||
['%s'],
|
||||
['%d', '%s']
|
||||
);
|
||||
if ($claimed !== 1) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
return;
|
||||
}
|
||||
|
||||
$ref = ['type' => 'referral', 'id' => $relation_id];
|
||||
$promoter_amount = max(0, (int) ($settings['promoter_amount'] ?? 0));
|
||||
$referred_amount = max(0, (int) ($settings['referred_amount'] ?? 0));
|
||||
if ($promoter_amount > 0) {
|
||||
$result = \AKSRT\Credits\Credits::add($promoter_id, $promoter_amount, 'referral', $ref, __('推广注册奖励', 'aksrt'), false);
|
||||
if (is_wp_error($result)) {
|
||||
throw new \RuntimeException($result->get_error_message());
|
||||
}
|
||||
}
|
||||
if ($referred_amount > 0) {
|
||||
$result = \AKSRT\Credits\Credits::add($invitee_id, $referred_amount, 'referral_new_user', $ref, __('推广注册新用户奖励', 'aksrt'), false);
|
||||
if (is_wp_error($result)) {
|
||||
throw new \RuntimeException($result->get_error_message());
|
||||
}
|
||||
}
|
||||
|
||||
$level_points = max(0, (int) ($settings['level_points'] ?? 0));
|
||||
return $this->ip_daily_check($row, $settings)
|
||||
? true
|
||||
: new \WP_Error('aksrt_referral_daily_limit', __('当前网络今日推广奖励次数已达上限', 'aksrt'), ['status' => 409]);
|
||||
};
|
||||
$mutation = function () use ($wpdb, $table, $relation_id, $level_points, $promoter_id) {
|
||||
if ($level_points > 0 && class_exists('\AKSRT\User\Level')) {
|
||||
\AKSRT\User\Level::add($promoter_id, 'referral', $level_points, true);
|
||||
}
|
||||
|
||||
$rewarded_at = current_time('mysql', true);
|
||||
$updated = $wpdb->update(
|
||||
$table,
|
||||
['reward_status' => 'rewarded', 'rewarded_at' => $rewarded_at],
|
||||
['id' => $relation_id, 'reward_status' => 'rewarding'],
|
||||
['reward_status' => 'rewarded', 'rewarded_at' => current_time('mysql', true)],
|
||||
['id' => $relation_id, 'reward_status' => 'pending'],
|
||||
['%s', '%s'],
|
||||
['%d', '%s']
|
||||
);
|
||||
if ($updated !== 1) {
|
||||
throw new \RuntimeException('Unable to finalize referral reward.');
|
||||
}
|
||||
|
||||
$wpdb->query('COMMIT');
|
||||
return $updated === 1 ? true : new \WP_Error('aksrt_referral_update', __('推广奖励状态更新失败', 'aksrt'), ['status' => 500]);
|
||||
};
|
||||
$result = \AKSRT\Ledger\LedgerService::get_instance()->post($command, $guard, $mutation);
|
||||
if (!is_wp_error($result) && !$result->replayed) {
|
||||
do_action('aksrt_referral_rewarded', $relation_id, $promoter_id, $invitee_id);
|
||||
} catch (\Throwable $e) {
|
||||
$wpdb->query('ROLLBACK');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -408,7 +398,7 @@ final class ReferralAttribution {
|
||||
'points_reward' => !empty($reward['enabled']),
|
||||
'affiliate' => !empty($affiliate['enabled']),
|
||||
],
|
||||
'current_ratio' => (float) \AKSRT\Settings\Settings::affiliate_ratio_for_user($user_id),
|
||||
'current_ratio' => (int) \AKSRT\Settings\Settings::affiliate_ratio_for_user($user_id),
|
||||
'ratios' => (array) ($affiliate['ratios'] ?? []),
|
||||
'order_types' => (array) ($affiliate['order_types'] ?? ['membership', 'content']),
|
||||
'rules' => [
|
||||
@@ -655,12 +645,12 @@ final class ReferralAttribution {
|
||||
$today_utc = (new \DateTimeImmutable('today', wp_timezone()))
|
||||
->setTimezone(new \DateTimeZone('UTC'))
|
||||
->format('Y-m-d H:i:s');
|
||||
$count = (int) $wpdb->get_var($wpdb->prepare(
|
||||
"SELECT COUNT(*) FROM {$table} WHERE registration_ip = %s AND reward_status = 'rewarded' AND rewarded_at >= %s FOR UPDATE",
|
||||
$ids = $wpdb->get_col($wpdb->prepare(
|
||||
"SELECT id FROM {$table} WHERE registration_ip = %s AND reward_status = 'rewarded' AND rewarded_at >= %s ORDER BY id ASC FOR UPDATE",
|
||||
$ip,
|
||||
$today_utc
|
||||
));
|
||||
return $count < $cap;
|
||||
return count($ids) < $cap;
|
||||
}
|
||||
|
||||
private function client_ip(): string {
|
||||
|
||||
Reference in New Issue
Block a user