|
@@ -6,6 +6,8 @@ use Log;
|
|
|
|
|
|
class mratio_controlex
|
|
|
{
|
|
|
+ const delta = 0.0000001;
|
|
|
+
|
|
|
private $mTimesConfig; //对应refill.ini 配置文件数据
|
|
|
private $mInterceptConfig;
|
|
|
|
|
@@ -76,11 +78,13 @@ class mratio_controlex
|
|
|
|
|
|
private function load_intercept()
|
|
|
{
|
|
|
- $mch_configs = function () {
|
|
|
+ $mch_configs = function ()
|
|
|
+ {
|
|
|
$result = [];
|
|
|
|
|
|
$i = 0;
|
|
|
- while (true) {
|
|
|
+ while (true)
|
|
|
+ {
|
|
|
$start = $i * 100;
|
|
|
$items = Model()->table('merchant')->where(['mchid' => ['gt', 0], 'merchant_state' => 1])->field('mchid,intercept_cfg')->order('mchid asc')->limit("{$start},100")->select();
|
|
|
if (empty($items)) {
|
|
@@ -88,19 +92,22 @@ class mratio_controlex
|
|
|
}
|
|
|
$i++;
|
|
|
|
|
|
- foreach ($items as $item) {
|
|
|
+ foreach ($items as $item)
|
|
|
+ {
|
|
|
$mchid = intval($item['mchid']);
|
|
|
if ($mchid <= 0) continue;
|
|
|
|
|
|
$cfg = unserialize($item['intercept_cfg']);
|
|
|
if (empty($cfg)) continue;
|
|
|
|
|
|
- if (!empty($cfg['segment'])) {
|
|
|
+ if (!empty($cfg['segment']))
|
|
|
+ {
|
|
|
$segment = $cfg['segment'];
|
|
|
$sitems = explode(',', $segment);
|
|
|
|
|
|
$tmp = [];
|
|
|
- foreach ($sitems as $sitem) {
|
|
|
+ foreach ($sitems as $sitem)
|
|
|
+ {
|
|
|
$sitem = trim($sitem);
|
|
|
if (!empty($sitem)) {
|
|
|
$tmp[] = $sitem;
|
|
@@ -158,7 +165,8 @@ class mratio_controlex
|
|
|
|
|
|
$times = 0;
|
|
|
$secs = 0;
|
|
|
- foreach ($items as $quality => $val) {
|
|
|
+ foreach ($items as $quality => $val)
|
|
|
+ {
|
|
|
if (!in_array($quality, $qualities, true)) {
|
|
|
continue;
|
|
|
}
|
|
@@ -187,7 +195,8 @@ class mratio_controlex
|
|
|
|
|
|
public function seconds($mchid, $quality)
|
|
|
{
|
|
|
- if (array_key_exists($mchid, $this->mTimesConfig)) {
|
|
|
+ if (array_key_exists($mchid, $this->mTimesConfig))
|
|
|
+ {
|
|
|
$items = $this->mTimesConfig[$mchid]['qualities'] ?? [];
|
|
|
if (array_key_exists($quality, $items)) {
|
|
|
return $items[$quality]['secs'];
|
|
@@ -206,31 +215,17 @@ class mratio_controlex
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- //{\"10202\":{\"ratio\":0.65,\"period\":86400,\"profit_ratio\":0.002,\"profit_formula\":\"all\"}
|
|
|
- //to-do for test
|
|
|
-// private function lowest_ratio($mchid)
|
|
|
-// {
|
|
|
-// $lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
|
|
|
-// if (empty($lower_ratio)) {
|
|
|
-// return [0.30, 86400];
|
|
|
-// } else {
|
|
|
-// return [$lower_ratio['ratio'], $lower_ratio['period']];
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// private function profit_ratio($mchid) {
|
|
|
-// $profit_ratio = $this->mTimesConfig[$mchid]['profit_ratio'] ?? 0.002;
|
|
|
-// return $profit_ratio;
|
|
|
-// }
|
|
|
-
|
|
|
+ private function profit_formula($mchid) {
|
|
|
+ return $this->mTimesConfig[$mchid]['profit_formula'] ?? 'qts';
|
|
|
+ }
|
|
|
|
|
|
private function lowest_ratio($mchid)
|
|
|
{
|
|
|
$lower_ratio = $this->mTimesConfig[$mchid]['lower_ratio'] ?? [];
|
|
|
if (empty($lower_ratio)) {
|
|
|
- return [0.0, 3600];
|
|
|
+ return 0.0;
|
|
|
} else {
|
|
|
- return [$lower_ratio['ratio'], $lower_ratio['period']];
|
|
|
+ return $lower_ratio['ratio'];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -262,94 +257,131 @@ class mratio_controlex
|
|
|
return [0, 0, 0, 0, 0, 0];
|
|
|
}
|
|
|
|
|
|
- //return true 表示当前质量满足条件。
|
|
|
- public function ratio_match($mchid, $org_quality, $card_type, $spec, $qualities)
|
|
|
+ //match: true 表示当前质量满足条件,可以不走溢价,false,表示可以走溢价
|
|
|
+ //can_last: true,能补充,false 表示不能走溢价
|
|
|
+ public function ratio_matchex($mchid, $org_quality, $card_type, $spec, $qualities)
|
|
|
{
|
|
|
if (count($qualities) <= 1) {
|
|
|
return [true, true];
|
|
|
}
|
|
|
|
|
|
+ $lowest_ratio = $this->lowest_ratio($mchid);
|
|
|
+ $lowest_pratio = $this->profit_ratio($mchid);
|
|
|
+ $profit_formula = $this->profit_formula($mchid);
|
|
|
$header = __METHOD__ . " mchid={$mchid} card_type={$card_type} spec={$spec}";
|
|
|
- [$lowest_ratio, $period] = $this->lowest_ratio($mchid);
|
|
|
|
|
|
- $lowest_pratio = $this->profit_ratio($mchid);
|
|
|
- [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
|
|
|
- Log::record("{$header} gross_ratio={$gross_ratio}, lower_ratio={$lowest_ratio}", Log::DEBUG);
|
|
|
+ Log::record("{$header} formula={$profit_formula}, lowest_ratio={$lowest_ratio} lowest_pratio={$lowest_pratio}", Log::DEBUG);
|
|
|
|
|
|
- if ($gross_pratio > $lowest_pratio) {
|
|
|
- $can_last = true;
|
|
|
- } else {
|
|
|
- $can_last = false;
|
|
|
- }
|
|
|
+ $formula = $this->profit_formula($mchid);
|
|
|
+ Log::record("{$header} formula = {$formula}",Log::DEBUG);
|
|
|
|
|
|
- if (!PolicyUtil::mixed_quality($org_quality))
|
|
|
+ if($formula === 'all')
|
|
|
{
|
|
|
- if ($gross_ratio >= $lowest_ratio) {
|
|
|
- return [true,true];
|
|
|
+ [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
|
|
|
+ Log::record("{$header} gross_ratio={$gross_ratio}, gross_pratio={$gross_pratio}", Log::DEBUG);
|
|
|
+
|
|
|
+ if ($gross_pratio > $lowest_pratio) {
|
|
|
+ $can_last = true;
|
|
|
+ } else {
|
|
|
+ $can_last = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!PolicyUtil::mixed_quality($org_quality))
|
|
|
+ {
|
|
|
+ if ($gross_ratio >= $lowest_ratio) {
|
|
|
+ return [true,true];
|
|
|
+ } else {
|
|
|
+ return [false,true];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ elseif ($gross_ratio >= $lowest_ratio) {
|
|
|
+ $match = $this->pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
|
|
|
+ return [$match,$can_last];
|
|
|
} else {
|
|
|
- return [false,true];
|
|
|
+ $match = $this->all_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
|
|
|
+ return [$match,$can_last];
|
|
|
}
|
|
|
}
|
|
|
- elseif ($gross_ratio >= $lowest_ratio) {
|
|
|
- $match = $this->pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
|
|
|
- return [$match,$can_last];
|
|
|
- } else {
|
|
|
- $match = $this->all_checker($mchid, $card_type, $spec, $header, $lowest_ratio);
|
|
|
- return [$match,$can_last];
|
|
|
+ elseif($formula === 'qt') {
|
|
|
+ return $this->qts_checker($mchid, $org_quality,$cur_quality, $card_type, $spec, $qualities,$period,$header,$ratio);
|
|
|
}
|
|
|
+ else {
|
|
|
+ return $this->qts_checker($mchid, $org_quality,$cur_quality, $card_type, $spec, $qualities,$period,$header,$ratio);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ [$submit_count, $succ_count, $fail_count, $gross_ratio, $profit, $gross_pratio] = $this->gross_ratio($mchid);
|
|
|
+ Log::record("{$header} gross_ratio={$gross_ratio}, lower_ratio={$lowest_ratio}", Log::DEBUG);
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private function pre_checker($mchid, $card_type, $spec, $header, $lowest_ratio)
|
|
|
{
|
|
|
- $ts_ratios = function ($mchid, $type_specs, $all_submit)
|
|
|
+ //计算各个card_type,spec 提交订单的占比情况,及所有面额
|
|
|
+ $spec_ratios = function ($mchid, $type_specs, $all_submit)
|
|
|
{
|
|
|
- $result = [];
|
|
|
+ $specs = [];
|
|
|
+ $spec_details = [];
|
|
|
+ foreach ($type_specs as $item)
|
|
|
+ {
|
|
|
+ [$card_type, $spec] = $item;
|
|
|
+ if(!in_array($spec,$spec_details)) {
|
|
|
+ $spec_details[] = $spec;
|
|
|
+ $specs[] = $spec;
|
|
|
+ }
|
|
|
|
|
|
- if ($all_submit == 0) {
|
|
|
- $all_submit += 0.00001;
|
|
|
+ [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio] = $this->detail_ratio($mchid, $card_type, $spec);
|
|
|
+ $spec_details[$spec][] = [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio];
|
|
|
}
|
|
|
|
|
|
- foreach ($type_specs as $item) {
|
|
|
- [$card_type, $spec] = $item;
|
|
|
- [$submit_count, $succ_count, $fail_count, $cur_ratio, $profit, $cur_pratio] = $this->detail_ratio($mchid, $card_type, $spec);
|
|
|
- $submit_ratio = $submit_count / $all_submit;
|
|
|
+ $ratios = [];
|
|
|
+ foreach ($spec_details as $spec => $details)
|
|
|
+ {
|
|
|
+ [$submit_count, $succ_count, $fail_count] = [0, 0, 0];
|
|
|
+ foreach ($details as $item) {
|
|
|
+ [$_submit_count, $_succ_count, $_fail_count, $_cur_ratio, $_profit, $_cur_pratio] = $item;
|
|
|
+ $submit_count += $_submit_count;
|
|
|
+ $succ_count += $_succ_count;
|
|
|
+ $fail_count += $_fail_count;
|
|
|
+ }
|
|
|
+ $submit_ratio = $submit_count / ($all_submit + self::delta);
|
|
|
+ $cur_ratio = $succ_count / ($succ_count + $fail_count + self::delta);
|
|
|
|
|
|
- $result[] = [$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio];
|
|
|
+ $ratios[$spec] = [$submit_count, $succ_count, $fail_count, $submit_ratio, $cur_ratio];
|
|
|
}
|
|
|
|
|
|
- return $result;
|
|
|
+ return [$specs, $ratios];
|
|
|
};
|
|
|
|
|
|
- $spec_extract = function ($item) {
|
|
|
- [$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio] = $item;
|
|
|
- return $spec;
|
|
|
- };
|
|
|
+ $split_array
|
|
|
|
|
|
- $ts_sorter_spec = function ($left, $right) use ($spec_extract)
|
|
|
+ //找出最佳补充面额
|
|
|
+ $ts_filter = function ($all_submit, $specs, $spec_details, $ratio, $lowest_ratio)
|
|
|
{
|
|
|
- $l = $spec_extract($left);
|
|
|
- $r = $spec_extract($right);
|
|
|
-
|
|
|
- if ($l > $r)
|
|
|
- return 1;
|
|
|
- elseif ($l < $r)
|
|
|
- return -1;
|
|
|
- else
|
|
|
- return 0;
|
|
|
- };
|
|
|
+ $count = count($specs);
|
|
|
+ if ($count === 1) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
|
|
|
- $ts_filter = function ($ts_ratios, $ratio, $lowest_ratio)
|
|
|
- {
|
|
|
+
|
|
|
+ for ($i = 1; $i < $count; $i++)
|
|
|
+ {
|
|
|
+ end()
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ $mast_succs = intval($all_submit * $lowest_ratio);
|
|
|
$result = [];
|
|
|
|
|
|
$all = 0.00;
|
|
|
- foreach ($ts_ratios as $item)
|
|
|
+ foreach ($spec_details as $item)
|
|
|
{
|
|
|
[$card_type, $spec, $submit_ratio, $cur_ratio, $cur_pratio] = $item;
|
|
|
$all += $submit_ratio * $cur_ratio;
|
|
|
|
|
|
- $r = $all / ($lowest_ratio + 0.00001);
|
|
|
- if ($r > $ratio)
|
|
|
+ $r = $all / ($lowest_ratio + self::delta);
|
|
|
+ if ($r > 1)
|
|
|
break;
|
|
|
else {
|
|
|
$result[] = "{$card_type}-{$spec}";
|
|
@@ -358,6 +390,7 @@ class mratio_controlex
|
|
|
return $result;
|
|
|
};
|
|
|
|
|
|
+
|
|
|
$lowest_pratio = $this->profit_ratio($mchid);
|
|
|
[$all_submit, $succ_count, $fail_count, $gross_ratio, $profit, $cur_pratio] = $this->gross_ratio($mchid);
|
|
|
|
|
@@ -365,16 +398,30 @@ class mratio_controlex
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- $type_specs = $this->mMchQTS[$mchid];
|
|
|
- $ts_ratios = $ts_ratios($mchid, $type_specs, $all_submit);
|
|
|
- usort($ts_ratios, $ts_sorter_spec);
|
|
|
-
|
|
|
- $ratio = $gross_ratio / ($lowest_ratio + 0.00001);
|
|
|
+ $ratio = $gross_ratio / ($lowest_ratio + self::delta);
|
|
|
+ if ($lowest_pratio >= 0.95) {
|
|
|
+ $max_ratio = 1.0;
|
|
|
+ }
|
|
|
+ elseif($lowest_pratio >= 0.90) {
|
|
|
+ $max_ratio = 1.02;
|
|
|
+ }
|
|
|
+ elseif ($lowest_pratio >= 0.5) {
|
|
|
+ $max_ratio = 1.05;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $max_ratio = 1.07;
|
|
|
+ }
|
|
|
|
|
|
- if ($ratio > 1.1) {
|
|
|
+ if($ratio >= $max_ratio) {
|
|
|
return true;
|
|
|
- } else {
|
|
|
- $meet = $ts_filter($ts_ratios, $ratio, $lowest_ratio);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ $type_specs = $this->mMchQTS[$mchid];
|
|
|
+ [$specs, $spec_ratios] = $spec_ratios($mchid, $type_specs, $all_submit);
|
|
|
+ sort($specs);
|
|
|
+
|
|
|
+ $meet = $ts_filter($all_submit, $spec_ratios, $ratio, $lowest_ratio);
|
|
|
$exist = array_key_exists("{$card_type}-{$spec}", $meet);
|
|
|
return !$exist;
|
|
|
}
|
|
@@ -392,6 +439,7 @@ class mratio_controlex
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ //机构订单拦截
|
|
|
public function need_intercept($mchid, $card_type, $card_state, $is_transfer, $card_no): bool
|
|
|
{
|
|
|
$start_with = function ($card_no, $segment) {
|