|
@@ -0,0 +1,314 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace App\Service\Callback;
|
|
|
+
|
|
|
+use App\Service\Callback\Tiktok\TiktokEventReportService;
|
|
|
+use App\Service\Util\Support\Trace\TraceContext;
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
+
|
|
|
+class JuliangAccountReportChargeService
|
|
|
+{
|
|
|
+ private $uid;
|
|
|
+ private $orderId;
|
|
|
+ /**
|
|
|
+ * @var TraceContext
|
|
|
+ */
|
|
|
+ private $traceContext;
|
|
|
+ private $order;
|
|
|
+ private $result;
|
|
|
+ private $trackRecord;
|
|
|
+ private $ranseInfo;
|
|
|
+ private $callbackConfig;
|
|
|
+ private $promotion;
|
|
|
+ private $rateConfig;
|
|
|
+ public function __construct($uid, $orderId, $traceInfo)
|
|
|
+ {
|
|
|
+ $this->uid = $uid;
|
|
|
+ $this->orderId = $orderId;
|
|
|
+ $this->traceContext = TraceContext::newFromParent($traceInfo);
|
|
|
+ $this->result = [
|
|
|
+ 'need_report' => true,
|
|
|
+ 'config_rate' => 0,
|
|
|
+ 'current_rate' => 0,
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ public function report() {
|
|
|
+ $this->order = DB::table('orders')->where('id', $this->orderId)->first();
|
|
|
+ $this->fillRanseInfo();
|
|
|
+ $this->fillTrackInfo();
|
|
|
+ $this->judgeOrderAlreadyDeal();
|
|
|
+ $this->judgeIsFirstCharge();
|
|
|
+ $this->judgeChargeMoney();
|
|
|
+ $this->judgePromotionProtect();
|
|
|
+ $this->judgeCallbackRate();
|
|
|
+
|
|
|
+ dump($this->result);
|
|
|
+ $this->reportJuliang();
|
|
|
+
|
|
|
+ $this->saveRecord();
|
|
|
+ }
|
|
|
+
|
|
|
+ private function saveRecord() {
|
|
|
+ if($this->result['save_record'] ?? true) {
|
|
|
+ $now = date('Y-m-d H:i:s');
|
|
|
+ if($this->result['info_type'] == 'promotion_protect') {
|
|
|
+ if($this->result['report_success']) {
|
|
|
+ $protectedRecord = DB::table('juliang_account_promotion_protect_record')
|
|
|
+ ->where(['adv_promotion_id' => $this->trackRecord->adv_promotion_id,
|
|
|
+ 'optimizer_uid' => $this->promotion->uid, 'is_enabeld' => 1])
|
|
|
+ ->first();
|
|
|
+ if($protectedRecord) {
|
|
|
+ DB::table('juliang_account_promotion_protect_record')
|
|
|
+ ->where(['id' => $protectedRecord->id])
|
|
|
+ ->where('protected_num', '<', $this->callbackConfig->protect_num)
|
|
|
+ ->increment('protected_num', 1, ['updated_at' => $now]);
|
|
|
+ } else {
|
|
|
+ DB::table('juliang_account_promotion_protect_record')
|
|
|
+ ->insert([
|
|
|
+ 'adv_promotion_id' => $this->trackRecord->adv_promotion_id,
|
|
|
+ 'optimizer_uid' => $this->promotion->uid,
|
|
|
+ 'advertiser_id' => $this->callbackConfig->adv_account_id,
|
|
|
+ 'protected_num' => 1,
|
|
|
+ 'is_enabled' => 1,
|
|
|
+ 'created_at' => $now,
|
|
|
+ 'updated_at' => $now,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $chargeRecord = DB::table('callback_report_charge_record')->where([
|
|
|
+ 'order_no' => $this->order->trade_no
|
|
|
+ ])->first();
|
|
|
+ if(!$chargeRecord) {
|
|
|
+ DB::table('callback_report_charge_record')
|
|
|
+ ->insert([
|
|
|
+ 'uid' => $this->uid,
|
|
|
+ 'order_id' => $this->orderId,
|
|
|
+ 'order_no' => $this->order->trade_no,
|
|
|
+ 'optimizer_uid' => $this->promotion->uid,
|
|
|
+ 'filter_type' => $this->result['info_type'] ?? 'ok',
|
|
|
+ 'filter_reason' => $this->result['info_str'] ?? '允许回传',
|
|
|
+ 'report_success' => intval($this->result['report_success'] ?? false),
|
|
|
+ 'report_result' => \json_encode($this->result['report_result'] ?? []),
|
|
|
+ 'created_at' => $now,
|
|
|
+ 'updated_at' => $now,
|
|
|
+ 'advertiser_id' => $this->trackRecord->advertiser_id,
|
|
|
+ 'adv_promotion_id' => $this->trackRecord->adv_promotion_id,
|
|
|
+ 'config_rate' => $this->result['config_rate'],
|
|
|
+ 'current_rate' => $this->result['current_rate'],
|
|
|
+ ]);
|
|
|
+ } else {
|
|
|
+ DB::table('callback_report_charge_record')
|
|
|
+ ->where(['id' => $chargeRecord->id])
|
|
|
+ ->update([
|
|
|
+ 'uid' => $this->uid,
|
|
|
+ 'order_id' => $this->orderId,
|
|
|
+ 'order_no' => $this->order->trade_no,
|
|
|
+ 'optimizer_uid' => $this->promotion->uid,
|
|
|
+ 'filter_type' => $this->result['info_type'] ?? 'ok',
|
|
|
+ 'filter_reason' => $this->result['info_str'] ?? '允许回传',
|
|
|
+ 'report_success' => intval($this->result['report_success'] ?? false),
|
|
|
+ 'report_result' => \json_encode($this->result['report_result'] ?? []),
|
|
|
+ 'updated_at' => $now,
|
|
|
+ 'advertiser_id' => $this->trackRecord->advertiser_id,
|
|
|
+ 'adv_promotion_id' => $this->trackRecord->adv_promotion_id,
|
|
|
+ 'config_rate' => $this->result['config_rate'],
|
|
|
+ 'current_rate' => $this->result['current_rate'],
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+
|
|
|
+ DB::table('juliang_account_rate_config_log')
|
|
|
+ ->where(['id' => $this->rateConfig->id])
|
|
|
+ ->update([
|
|
|
+ 'report_count' => $this->rateConfig->report_count + intval($this->result['report_success']),
|
|
|
+ 'unreport_count' => $this->rateConfig->report_count + intval(!$this->result['report_success']),
|
|
|
+ 'total_count' => $this->rateConfig->total_count + 1,
|
|
|
+ 'updated_at' => $now,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private function judgeCallbackRate(){
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ $this->rateConfig = DB::table('juliang_account_rate_config_log')
|
|
|
+ ->where(['company_uid' => $this->promotion->uid,
|
|
|
+ 'account_id' => $this->trackRecord->advertiser_id, 'is_enabled' => 1])
|
|
|
+ ->first();
|
|
|
+ if(!$this->rateConfig) {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'no_rate_config';
|
|
|
+ $this->result['info_str'] = '没有可用的回传比率设置';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $configRate = $this->rateConfig->config_per;
|
|
|
+ if(0 == $configRate) {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'rate_eq_0';
|
|
|
+ $this->result['info_str'] = '设定比例为0不执行回传';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $currentTotalCount = $this->rateConfig->total_count;
|
|
|
+ $currentReportCount = $this->rateConfig->report_count;
|
|
|
+ if(0 == $currentTotalCount) {
|
|
|
+ $currentRate = 0;
|
|
|
+ } else {
|
|
|
+ $currentRate = min(1, round($currentReportCount / $currentTotalCount, 4)) * 100;
|
|
|
+ }
|
|
|
+ if($currentRate <= $configRate) {
|
|
|
+ $this->result['need_report'] = true;
|
|
|
+ $this->result['config_rate'] = $configRate;
|
|
|
+ $this->result['current_rate'] = $currentRate;
|
|
|
+ } else {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'rate_filter';
|
|
|
+ $this->result['info_type'] = '比率过滤';
|
|
|
+ $this->result['config_rate'] = $configRate;
|
|
|
+ $this->result['current_rate'] = $currentRate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private function judgePromotionProtect() {
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(0 == $this->callbackConfig->protect_num) {
|
|
|
+ $this->result['need_report'] = true;
|
|
|
+ } else {
|
|
|
+ $advPromotionId = $this->trackRecord->adv_promotion_id;
|
|
|
+ $protectedRecord = DB::table('juliang_account_promotion_protect_record')
|
|
|
+ ->where(['adv_promotion_id' => $advPromotionId, 'optimizer_uid' => $this->promotion->uid, 'is_enabled' => 1])
|
|
|
+ ->first();
|
|
|
+ if(!$protectedRecord || $protectedRecord->protected_num < $this->callbackConfig->protect_num) {
|
|
|
+ $this->result['need_report'] = true;
|
|
|
+ $this->result['save_record'] = true;
|
|
|
+ $this->result['save_record_type'] = 'protect_promotion';
|
|
|
+ $this->result['info_type'] = 'promotion_protect';
|
|
|
+ $this->result['info_str'] = '计划被保护';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private function judgeOrderAlreadyDeal() {
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(DB::table('callback_report_charge_record')
|
|
|
+ ->where(['order_id' => $this->order->id])
|
|
|
+ ->exists()) {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['save_record'] = false;
|
|
|
+ $this->result['info_type'] = 'order_exists';
|
|
|
+ $this->result['info_str'] = '订单已经处理';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private function judgeChargeMoney() {
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $moneyRange = $this->callbackConfig->moneyRange;
|
|
|
+ if($this->order->price >= $moneyRange->min && $this->order->price <= $moneyRange->max) {
|
|
|
+ $this->result['need_report'] = true;
|
|
|
+ } else {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'money_filter';
|
|
|
+ $this->result['info_str'] = sprintf('充值金额[%s元]不在回传区间范围内[%s - %s]', $this->order->price,
|
|
|
+ $moneyRange->minStr, $moneyRange->maxStr);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private function judgeIsFirstCharge() {
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $isFirstCharge = DB::table('orders')
|
|
|
+ ->where([
|
|
|
+ 'uid' => $this->uid,
|
|
|
+ 'status' => 'paid',
|
|
|
+ 'promotion_id' => $this->trackRecord->ranse_id,
|
|
|
+ ])->where('created_at', '>=', $this->trackRecord->ranse_start_at)
|
|
|
+ ->where('created_at', '<=', $this->trackRecord->ranse_end_at)
|
|
|
+ ->where('id', '<', $this->orderId)
|
|
|
+ ->count() == 0;
|
|
|
+ if($isFirstCharge) {
|
|
|
+ $this->result['need_report'] = true;
|
|
|
+ } else {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'neq_first_charge';
|
|
|
+ $this->result['info_str'] = '非首充';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private function fillRanseInfo() {
|
|
|
+ $ranseId = $this->order->promotion_id;
|
|
|
+ $this->promotion = DB::table('promotions')->where('id', $ranseId)->first();
|
|
|
+ $this->callbackConfig = DB::table('juliang_account_callback_config')
|
|
|
+ ->where(['id' => $this->promotion->callback_config_id])
|
|
|
+ ->first();
|
|
|
+ if(!$this->callbackConfig) {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'no_callback_config';
|
|
|
+ $this->result['info_str'] = '没有回传配置';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(0 == $this->callbackConfig->state) {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'callback_close';
|
|
|
+ $this->result['info_str'] = '回传配置关闭';
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ $min = max(0, $this->callbackConfig->min_money);
|
|
|
+ if (0 >= $this->callbackConfig->max_money) {
|
|
|
+ $max = PHP_INT_MAX;
|
|
|
+ $maxStr = '不限';
|
|
|
+ } else {
|
|
|
+ $max = $this->callbackConfig->max_money;
|
|
|
+ $maxStr = $max . '元';
|
|
|
+ }
|
|
|
+
|
|
|
+ $minStr = $min . '元';
|
|
|
+ $this->callbackConfig->moneyRange = (object)compact('min', 'max', 'minStr', 'maxStr');
|
|
|
+ }
|
|
|
+ private function reportJuliang() {
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $service = new TiktokEventReportService;
|
|
|
+ $reportResult = $service->reportCharge((object)[
|
|
|
+ 'callback' => $this->trackRecord->callback
|
|
|
+ ]);
|
|
|
+ $reportContent = \json_decode($reportResult->content, true);
|
|
|
+ if($reportResult['result'] && 0 == $reportContent['code']) {
|
|
|
+ $this->result['report_success'] = true;
|
|
|
+ } else {
|
|
|
+ $this->result['report_success'] = false;
|
|
|
+ }
|
|
|
+ $this->result['report_result'] = $reportResult;
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ }
|
|
|
+ private function fillTrackInfo() {
|
|
|
+ if(!$this->result['need_report']) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ $this->trackRecord = DB::table('callback_report_ranse_record')
|
|
|
+ ->where(['uid' => $this->uid, 'ranse_id' => $this->order->promotion_id])
|
|
|
+ ->where('ranse_start_at', '<=', $this->order->created_at)
|
|
|
+ ->where('ranse_end_at', '>=', $this->order->created_at)
|
|
|
+ ->orderBy('id', 'desc')
|
|
|
+ ->first();
|
|
|
+ if(!$this->trackRecord) {
|
|
|
+ $this->result['need_report'] = false;
|
|
|
+ $this->result['info_type'] = 'no_track_info';
|
|
|
+ $this->result['info_str'] = '无匹配用户';
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|