feat: adjust affiliate commissions and withdrawal strategy
This commit is contained in:
1 parent
8fc6fe5312
commit
929603b9e2
13 files changed
+93
-111
No files matched your search
@@ -12,6 +12,7 @@ final class CommissionLedger {
|
||||
public function init(): void {
|
||||
add_action('aksrt_order_paid', [$this, 'on_order_paid'], 20, 2);
|
||||
add_action('aksrt_order_status_changed', [$this, 'on_order_status_changed'], 20, 3);
|
||||
add_action('aksrt_points_exchange_completed', [$this, 'on_points_exchange_completed'], 20, 4);
|
||||
add_action('aksrt_affiliate_settle_due', [$this, 'settle_due']);
|
||||
add_action('rest_api_init', [$this, 'register_routes']);
|
||||
if (!wp_next_scheduled('aksrt_affiliate_settle_due')) {
|
||||
@@ -23,6 +24,16 @@ final class CommissionLedger {
|
||||
public function on_order_status_changed(string $order_number, string $status, array $order = []): void {
|
||||
if (in_array($status, ['refunding', 'refunded'], true)) { $this->reverse($order_number, (float) ($order['amount'] ?? 0), 'refund'); }
|
||||
}
|
||||
public function on_points_exchange_completed(int $user_id, float $amount, int $points, string $exchange_ref): void {
|
||||
$this->record_paid_order([
|
||||
'order_number' => 'points-exchange-' . sanitize_key($exchange_ref),
|
||||
'product_type' => 'credits',
|
||||
'user_id' => $user_id,
|
||||
'amount' => $amount,
|
||||
'exchange_ref' => $exchange_ref,
|
||||
'points' => $points,
|
||||
]);
|
||||
}
|
||||
public function record_paid_order(array $order): int {
|
||||
if (!\AKSRT\Settings\Settings::affiliate_enabled()) return 0;
|
||||
$type = sanitize_key((string) ($order['product_type'] ?? ''));
|
||||
@@ -35,14 +46,16 @@ final class CommissionLedger {
|
||||
$amount = round((float) ($order['amount'] ?? 0), 2);
|
||||
if ($order_no === '' || $buyer <= 0 || $amount <= 0) return 0;
|
||||
$promoter = ReferralAttribution::get_instance()->resolve($buyer);
|
||||
if ($promoter <= 0 || $promoter === $buyer) return 0;
|
||||
if (!$settings['allow_self_purchase'] && $promoter === $buyer) return 0;
|
||||
$ratio = (float) $settings['ratio'];
|
||||
if ($promoter <= 0) return 0;
|
||||
$ratio = (float) \AKSRT\Settings\PaymentRuntime::affiliate_ratio_for_user($promoter);
|
||||
$commission = round($amount * $ratio / 100, 2);
|
||||
if ($commission <= 0) return 0;
|
||||
global $wpdb;
|
||||
$table = $this->table('commission_ledger');
|
||||
$key = hash('sha256', 'affiliate:' . $order_no . ':' . $order_type);
|
||||
$identity = $order_type === 'credits' && !empty($order['exchange_ref'])
|
||||
? 'credits:' . sanitize_key((string) $order['exchange_ref'])
|
||||
: $order_no . ':' . $order_type;
|
||||
$key = hash('sha256', 'affiliate:' . $identity);
|
||||
$now = current_time('mysql', true);
|
||||
$available = gmdate('Y-m-d H:i:s', time() + ((int) $settings['settlement_days'] * DAY_IN_SECONDS));
|
||||
$ok = $wpdb->insert($table, ['promoter_id'=>$promoter,'source_user_id'=>$buyer,'order_number'=>$order_no,'order_type'=>$order_type,'eligible_base'=>$amount,'ratio'=>$ratio,'original_amount'=>$commission,'adjustment_total'=>0,'status'=>'pending','idempotency_key'=>$key,'available_at'=>$available,'created_at'=>$now], ['%d','%d','%s','%s','%f','%f','%f','%f','%s','%s','%s','%s']);
|
||||
@@ -123,9 +136,9 @@ final class CommissionLedger {
|
||||
$user_id=get_current_user_id(); $amount=(int)round((float)$request->get_param('amount')); $method=sanitize_key((string)$request->get_param('method')); $account=sanitize_text_field((string)$request->get_param('account')); $settings=\AKSRT\Settings\Settings::get_withdrawal_settings(); $affiliate=\AKSRT\Settings\Settings::get_affiliate_settings();
|
||||
if (empty($affiliate['enabled'])) return new \WP_Error('affiliate_disabled',__('推广返佣未启用。','aksrt'),['status'=>403]);
|
||||
if (\AKSRT\Payment\Withdrawal::get_instance()->has_open_withdrawal($user_id)) return new \WP_Error('affiliate_withdraw_pending',__('已有待处理提现申请。','aksrt'),['status'=>409]);
|
||||
if ($amount < (int)ceil((float)$affiliate['min_withdrawal'])) return new \WP_Error('affiliate_withdraw_min',__('未达到最低提现金额。','aksrt'),['status'=>400]);
|
||||
if ($amount < (int)ceil((float)$settings['min_amount'])) return new \WP_Error('affiliate_withdraw_min',__('未达到最低提现金额。','aksrt'),['status'=>400]);
|
||||
if ((float)get_user_meta($user_id,self::DEBT_META,true)>0) return new \WP_Error('affiliate_withdraw_debt',__('存在待偿还的佣金欠款,暂不可提现。','aksrt'),['status'=>409]);
|
||||
if (!in_array($method,(array)$affiliate['payout_channels'],true) || $account==='') return new \WP_Error('affiliate_withdraw_account',__('请提供有效的收款渠道和收款码。','aksrt'),['status'=>400]);
|
||||
if (!in_array($method,(array)$settings['payout_channels'],true) || $account==='') return new \WP_Error('affiliate_withdraw_account',__('请提供有效的收款渠道和收款码。','aksrt'),['status'=>400]);
|
||||
$result=\AKSRT\Payment\Withdrawal::get_instance()->create_balance_request($user_id,$amount,$method,$account,$settings); if(is_wp_error($result)) return $result; return new \WP_REST_Response(['success'=>true,'data'=>$result],201);
|
||||
}
|
||||
public function admin_withdrawals(array $args): array { $service=\AKSRT\Payment\Withdrawal::get_instance(); return ['items'=>$service->get_all(['status'=>sanitize_key((string)($args['status']??'')),'limit'=>max(1,min(100,(int)($args['per_page']??20))),'offset'=>max(0,((int)($args['page']??1)-1)*max(1,(int)($args['per_page']??20)))]),'stats'=>$service->get_stats()]; }
|
||||
|
||||
Reference in new issue
Block a user