REAPI/app/channel/service/ChannelService.php
b3f70a8d30 feat(queue): 新增临时锁卡任务
- 添加 LinSuoKa 类实现临时锁卡功能
- 优化卡密订单关联逻辑,处理状态为 4 的订单- 新增 redis 记录订单详情,用于限单和退款处理
- 修改 Qiling 类中的签名生成逻辑
- 更新 Test 控制器中的 test_ts 方法,增加对不同订单表的处理
2025-06-03 18:55:03 +08:00

559 lines
18 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace app\channel\service;
use app\core\BtWafService;
use app\core\Service;
use think\admin\extend\DataExtend;
use app\merchant\service\MerchantService;
use app\merchant\service\OrderService;
use app\merchant\service\PercentService;
use app\merchant\service\ProjectService;
use app\merchant\service\ProductService as MerchantProductService;
use app\merchant\service\ProjectProductService as MerchantProjectProductService;
use app\setting\service\BlackCardService;
/**
* 渠道服务
* Class ChannelService
* @package app\channel\service
*/
class ChannelService extends Service
{
protected int $isp = 1;
/**
* 设置默认操作表
* @var string
*/
public $table = 'channel_list';
# 加载的类
public $class;
# 获取渠道信息
public function getInfo($key)
{
if (is_numeric($key)) {
$where['id'] = $key;
} else {
$where['key'] = $key;
}
//$where['status'] = 1;
//$where['is_deleted'] = 0;
$data = $this->db()->where($where)->find();
return $data;
}
# 获取缓存
public function get($key, $get = true)
{
if (!$get) {
return false;
}
$cache_key = 'channelv2_' . $key;
$data = !$get ? false : $this->cache($cache_key);
if (!$data) {
$data = $this->getInfo($key);
if ($data) {
$this->cache($cache_key, $data);
}
}
if ($data) {
if ($data['status'] != 1) {
return false;
}
if ($data['is_deleted'] != 0) {
return false;
}
}
return $data;
}
# 获取能使用的服务功能
public function product($key)
{
/*
$config = array
(
# 电话充值 key是对外开放的method是对内使用的
'dhcz' => array
(
'method' => 'dhcz',
),
'zsycz' => array
(
'method' => 'zsycz',
),
'zshcz' => array
(
'method' => 'zshcz',
),
'dfcz' => array
(
'method' => 'dfcz',
),
'qbcz' => array
(
'method' => 'qbcz',
),
'kmcz' => array
(
'method' => 'kmcz',
),
'query' => array
(
'method' => 'query',
),
);
if (isset($config[$key])) {
return $config[$key];
}
*/
if ($key == 'mcz') {
if (isset($this->isp) && $this->isp) {
if ($this->isp == 1) {
$key = 'mydcz';
} elseif ($this->isp == 2) {
$key = 'mltcz';
} elseif ($this->isp == 3) {
$key = 'mdxcz';
}
}
}
return array
(
'method' => $key,
);
}
public function rule($merchant, $key, $value)
{
if ($merchant == 2) {
return true;
}
if ($key == 'dhcz') {
# 验证是否是手机号
$check = "/^1\d{10}$/";
if (!preg_match($check, $value)) {
return false;
}
} elseif ($key == 'zshcz') {
# 验证是否中石化加油卡
$check = "/^1\d{18}$/";
if (!preg_match($check, $value)) {
return false;
}
} elseif ($key == 'zsycz') {
# 验证是否中石油加油卡
$check = "/^(?:7|9)\d{15}$/";
if (!preg_match($check, $value)) {
return false;
}
} elseif ($key == 'xtdc' || $key == 'xtdc') {
# 验证是否中石油、中石化加油卡
$check1 = "/^(?:7|9)\d{15}$/";
$check2 = "/^1\d{18}$/";
if (!preg_match($check1, $value) && !preg_match($check2, $value) ) {
return false;
}
}
return true;
}
# 使用渠道的服务
public function use($merchant, $product, $param = array(), $async = false, $order = '', $use_product = array(),$usequdao = '')
{
if (isset($param['card']) && $param['card']) {
$rule = $this->rule($merchant, $product, $param['card']);
if (!$rule) {
return $param['card'] . '不符合规则';
}
$check = BlackCardService::instance()->check($param['card']);
if (!$check && empty($usequdao)) {
return $param['card'] . '已被列入黑名单';
}elseif (!$check && $usequdao == 'kuaishou'){
$backCard = '1';
}
} elseif (isset($param['mobile']) && $param['mobile']) {
$rule = $this->rule($merchant, $product, $param['mobile']);
if (!$rule) {
return $param['mobile'] . '不符合规则';
}
$check = BlackCardService::instance()->check($param['mobile']);
if (!$check && empty($usequdao)) {
return $param['mobile'] . '已被列入黑名单';
}elseif(!$check && $usequdao == 'kuaishou'){
$backCard = '1';
}
}
# 检测订单号唯一性
if (isset($param['order']) && $param['order'] && !$use_product && !$order) {
$order_info = OrderService::instance()->get(false, $param['order'], $merchant);
if ($order_info) {
if ($async) {
return '订单号重复';
} elseif ($order_info['status'] > 1) {
return '订单已在处理中或者已完成';
}
}
}
if (!$product) {
return '无效的产品';
}
if (is_numeric($product) && $product > 0) {
$product_info = ProductService::instance()->getInfo($product);
} elseif (is_array($product)) {
$product_info = $product;
} else {
# 验证是否有通道id
$project = false;
if (isset($param['project_id']) && $param['project_id'] && $param['project_id'] > 0) {
$project = ProjectService::instance()->getInfo($param['project_id'], $merchant);
if (!$project) {
return '通道已禁用或不存在';
}
}
if ($project) {
# 使用通道
$product_all = MerchantProjectProductService::instance()->getAll($merchant, $param['project_id'], $product);
} else {
# 获取当前商户的所有产品
$product_all = MerchantProductService::instance()->getAll($merchant, $product);
}
if (!$product_all) {
return '未分配产品';
}
$this->isp = $param['isp'] = false;
$param['value'] = false;
if ($product == 'dhcz') {
if (!isset($param['mobile'])) {
return '参数错误';
}
$this->isp = $param['isp'] = $this->isp($param['mobile']);
$isp = PercentService::instance()->getIsp();
if (isset($isp[$param['isp']]) && $isp[$param['isp']]) {
$param['value'] = $isp[$param['isp']];
}
}
# 根据面值做判断
$merchant_info = MerchantService::instance()->get($merchant);
$pid = false;
foreach ($product_all as $k => $v) {
if ($v['cash']) {
$cash = explode(',', $v['cash']);
if ($param['value']) {
if (in_array($param['value'], $cash)) {
$pid = $v['pid'];
if ($this->getNum($pid, $merchant_info)) {
break;
}
}
} else {
if (in_array($param['cash'], $cash)) {
$pid = $v['pid'];
if ($this->getNum($pid, $merchant_info)) {
break;
}
}
}
} else {
$pid = $v['pid'];
if ($this->getNum($pid, $merchant_info)) {
break;
}
}
}
if (!$pid) {
return '产品错误';
}
$product_info = ProductService::instance()->getInfo($pid);
if (!$product_info) {
return '产品无效';
}
if (strstr($product_info['key'], '_cash')) {
$product_info['value'] = $param['value'];
}
# 验证该产品是否符合面值
$state = $this->checkProductValue($product_info, $param, 'value');
if (!$state) {
return '面额无效';
}
# 验证该产品是否符合当前限制的面额
$state = $this->checkProductValue($product_info, $param, 'auto_value');
if (!$state) {
return '面额无效';
}
# 验证该产品是否符合开放时间
if ($product_info['opentime']) {
$state = $this->checkProductOpenTime($product_info);
if (!$state) {
return '产品未开放';
}
}
/*
$merchant_info = MerchantService::instance()->get($merchant);
# 如果自动切换面值
if ($merchant_info && isset($merchant_info['auto']) && $merchant_info['auto'] == 2) {
$product_info = $this->getProductByValue($product_info, $param, $merchant_info['cids']);
if (!$product_info) {
return '产品错误';
}
} else {
# 如果非自动切换,检查当前产品是否符合开放时间
$open_product_info = false;
if ($product_info['opentime']) {
$open_product_info = $this->getProductByOpenTime($product_info, $merchant_info['cids']);
if (!$open_product_info) {
return '产品错误';
} else {
$product_info = $open_product_info;
}
}
}*/
}
$product = $product_info['key'];
$data = array();
$data['merchant'] = $merchant;
$data['product'] = $product_info['id'];
$data['product_key'] = $product;
$data['param'] = $param;
$data['order'] = $order;
if(isset($backCard)){
$data['backCard'] = $backCard;
}
# 如果当前渠道的产品无效是否继续到下一个渠道的产品相同key,此处记录已经用过的产品
$data['use_product'] = $use_product;
# 记录通道id
if (isset($project) && $project && $project['id']) {
$data['project_id'] = $project['id'];
} else {
$data['project_id'] = false;
}
$product = $this->product($product);
if($product['method'] == 'zshcz_wt' && isset($param['is_getMobileCode']) && $param['is_getMobileCode'] == 1){
$product['method'] = 'getMobileCode';
}
return $this->call($product['method'], $product_info['cid'], $param, $async, $data, $product_info);
}
# 获取产品信息
public function getNum($pid, $merchant)
{
# 检测当前的处理单数,如果超过多少单,就自动切换到另外一个渠道
if (isset($merchant['order_handle_num']) && $merchant['order_handle_num'] > 0) {
$total = OrderService::instance()->getNum($pid, 4);
if ($total >= $merchant['order_handle_num']) {
return false;
}
}
return true;
}
# 获取服务
public function call($method, $cid, $param, $async = false, $data = array(), $product = array())
{
$channel = $this->get($cid);
if (!$channel) {
return '渠道错误';
}
if (isset($channel['system_id']) && $channel['system_id'] && $channel['system_id'] > 0) {
$channel['key'] = 'common';
}
$name = ucfirst($channel['key']);
$class = '\\app\\channel\\service\\system\\' . $name;
$this->class = new $class($async, $data, $channel, $product);
if ($channel['key'] == 'common') {
return call_user_func(array($this->class, $method), $param);
} else {
$common = 'common';
if (method_exists($this->class, $method)) {
return call_user_func(array($this->class, $method), $param);
} elseif (method_exists($this->class, $common)) {
return call_user_func(array($this->class, $common), $param);
} else {
return call_user_func_array(array($this->class, 'def'), array($method, $param));
}
}
}
/*
private function getProductByOpenTime($product_info, $cids)
{
$state = $this->checkProductOpenTime($product_info, 'opentime', $cids);
if (!$state) {
$product_data = ProductService::instance()->getByKey($product_info['key'], $product_info['id'], $cids);
if ($product_data) {
foreach ($product_data as $k => $v) {
if ($v['id'] != $product_info['id']) {
$state = $this->checkProductOpenTime($v, 'opentime');
if ($state) {
return $v;
}
}
}
}
}
return $product_info;
}
*/
# 检查面值是否符合当前产品
private function checkProductOpenTime($product_info, $key = 'opentime')
{
if (isset($product_info[$key]) && $product_info[$key]) {
$product_info[$key] = str_replace(':', '', $product_info[$key]);
if (strstr($product_info[$key], '-')) {
$value = explode('-', $product_info[$key]);
$cur = intval(date('Hi'));
if ($cur < intval($value[0]) || $cur > intval($value[1])) {
return false;
}
} else {
$cur = intval(date('Hi'));
$product_info[$key] = intval($product_info[$key]);
if ($cur < $product_info[$key]) {
return false;
}
}
}
return true;
}
/*
private function getProductByValue($product_info, $param, $cids)
{
$state = $this->checkProductValue($product_info, $param, 'auto_value');
if (!$state) {
$product_data = ProductService::instance()->getByKey($product_info['key'], $product_info['id'], $cids);
if ($product_data) {
foreach ($product_data as $k => $v) {
if ($v['id'] != $product_info['id']) {
$state = $this->checkProductValue($v, $param, 'auto_value');
if ($state) {
return $v;
}
}
}
}
return false;
}
return $product_info;
}
*/
# 检查面值是否符合当前产品
private function checkProductValue($product_info, $param, $key = 'value')
{
if (isset($product_info[$key]) && $product_info[$key] && isset($param['cash']) && $param['cash']) {
$value = explode(',', $product_info[$key]);
if (isset($param['value']) && $param['value']) {
if (!in_array($param['value'], $value)) {
return false;
}
} else {
if (!in_array($param['cash'], $value)) {
return false;
}
}
}
return true;
/*
# 符合面值 验证开放时间
$opentime = $this->checkProductOpenTime($product_info);
if ($opentime) {
return true;
} else {
return false;
}
*/
}
public function update_ipWhite($cid,$ip_white_data='')
{
$is_btWaf = sysconf('settingBtWafStatus');
$api_domain = sysconf('api_notify_host') ?: sysconf('BtWaf_domain');
// 提取域名部分
if ($api_domain) {
$api_domain = preg_replace('/^https?:\/\//', '', $api_domain);
$api_domain = explode('/', $api_domain)[0];
}
if(isset($is_btWaf) && $is_btWaf == 1) {
$ip_white_array = $ip_white_data?explode(',', $ip_white_data):[];
$bt = new BtWafService();
$list = $bt->get_customize_list();
$ip_white_id = '';
if($list){
$rule_list = $list['msg']['rules'];
$name = '渠道ip白名单-'.$cid;
foreach ($rule_list as $k=>$v){
if($v['name'] == $name){
$ip_white_id = $k;
break;
}
}
}
if($ip_white_id){
$data = $bt->update_waf_whiteIp($ip_white_id,$name,$api_domain,$ip_white_array);
} else{
$data = $bt->update_waf_whiteIp('', $name, $api_domain, $ip_white_array);
}
if($data && isset($data['status']) && !$data['status']){
return '添加防火墙错误';
}
}
return $this->db()->where(array('id' => $cid))->update(['ip_white'=>$ip_white_data]);
}
}