764 lines
26 KiB
PHP
Raw Normal View History

2024-09-29 15:43:18 +08:00
<?php
namespace app\channel\service\system;
use app\gateway\service\CurlService;
use app\gateway\service\AuthService;
use app\gateway\service\RedisService;
use app\channel\service\ProductService;
use app\channel\service\ChannelService;
use app\channel\service\ShopService;
use app\merchant\service\OrderService;
use app\merchant\service\OrderAutoService;
use app\merchant\service\MerchantService;
use app\merchant\service\ProductService as MerchantProductService;
use dever\Log;
/**
* 系统核心
* Class Core
* @package app\channel\service
*/
class Core
{
protected $async = false;
protected $data = array();
protected $channel = array();
protected $product = array();
protected $host = '';
protected $mid = '';
protected $token = '';
protected $card_id = '';
public function __construct($async = false, $data = array(), $channel = array(), $product = array())
{
$this->async = $async;
$this->data = $data;
$this->channel = $channel;
$this->product = $product;
if ($this->channel) {
if (isset($this->channel['host']) && $this->channel['host']) {
$this->host = $this->channel['host'];
}
if (isset($this->channel['mid']) && $this->channel['mid']) {
$this->mid = $this->channel['mid'];
}
if (isset($this->channel['token']) && $this->channel['token']) {
$this->token = $this->channel['token'];
}
}
}
# 通用的充值
public function def($method, $param)
{
if (strstr($method, '_')) {
$temp = explode('_', $method);
$method = $temp[1];
return $this->$method($param);
} else {
return false;
}
}
# 检测传入数据
protected function param($param, $check)
{
if (empty($param['order'])) {
return 'order';
}
if (!isset($param['cash'])) {
$param['cash'] = 0;
}
$detail = array();
if ($check) {
foreach ($check as $k => $v) {
if (!isset($param[$k])) {
return $k;
} elseif (empty($param[$k]) && $param[$k] != 0) {
return $k;
} else {
$detail[$v] = $param[$k];
}
}
}
# 获取订单号
$merchant_order = $param['order'];
$param['order'] = $this->createOrder($param['order']);
$account = '';
if (isset($param['card']) && $param['card']) {
$account = $param['card'];
} elseif (isset($param['mobile']) && $param['mobile']) {
$account = $param['mobile'];
} elseif (isset($param['qq']) && $param['qq']) {
$account = $param['qq'];
} elseif (isset($param['account']) && $param['account']) {
$account = $param['account'];
}
$parent_order_id = '';
if (isset($param['parent_order_id']) && $param['parent_order_id']) {
$parent_order_id = $param['parent_order_id'];
}
$response = array();
if ($this->async) {
$this->data['order'] = $param['order'];
$log['type'] = 'merchant_request';
$log['config'] = $this->data;
$this->log($log);
# 下单
$status = 1;
if (isset($this->data['product_key']) && ($this->data['product_key'] != 'zshcz1')) {
} elseif ($account) {
$account_state = OrderService::instance()->countByAccount($account);
if (!$account_state) {
return '已达到最大下单次数';
}
# 检测该账号是否最近5分钟之内下单如果有就延迟下单
$account_order = OrderService::instance()->getByAccount($account, $param['cash']);
if ($account_order) {
$this->data['time'] = time() + 900;
$status = -1;
} else {
/*
# 检测汇天下当前石化渠道是否同时有80个处理中
if ($this->product && isset($this->product['limit_order']) && $this->product['limit_order'] > 0) {
$total = OrderService::instance()->getNum($this->data['product']);
if ($total >= $this->product['limit_order']) {
$status = -3;
}
}
*/
}
}
if (isset($param['s']) && $param['s']) {
$this->channel['order_limit'] = 0;
unset($param['s']);
}
if (isset($this->channel['order_limit']) && $this->channel['order_limit'] > 0) {
$status = -3;
}
$state = $this->create($param['order'], '', $merchant_order, $param['cash'], '', $this->data, $response, $status, $account, $parent_order_id, $this->card_id, false);
if (!$state) {
return '余额不足下单失败';
}
if ($status == 1) {
$this->queue('submit', $this->data);
}
return array('order' => $param['order'], 'account' => $account, 'status' => 1);
} elseif ($this->data['merchant'] == 6000 && $account) {
# 检测该账号是否最近5分钟之内下单如果有就延迟下单
$account_order = OrderService::instance()->getByAccount($account, $param['cash']);
if ($account_order) {
$this->data['order'] = $param['order'];
$this->data['time'] = time() + 300;
$status = -1;
$this->create($param['order'], '', $merchant_order, $param['cash'], '', $this->data, $response, $status, $account, $parent_order_id, $this->card_id, false);
return 'order';
}
} elseif (!$this->data['use_product']) {
$order = OrderService::instance()->get($param['order']);
if ($order && $order['status'] > 1 && $order['status'] != 5) {
return 'order';
}
}
/*
if (!$this->async) {
$merchant_info = MerchantService::instance()->get($this->data['merchant']);
if ($merchant_info['account_surplus'] < $param['cash'] && $merchant_info['credit_surplus'] < $param['cash']) {
$response['msg'] = 'error';
$response['data'] = '余额不足下单失败';
$this->create($param['order'], '', $merchant_order, $param['cash'], '', $this->data, $response, 3, $account);
return $response['data'];
}
}
*/
return array
(
'order' => $param['order'],
'merchant_order' => $merchant_order,
'cash' => $param['cash'],
'detail' => $detail,
'account' => $account,
'status' => -1
);
}
# 获取店铺id
protected function shop()
{
if ($this->data) {
$product = $this->product ? $this->product : ProductService::instance()->get($this->data['merchant'], $this->data['product']);
if ($product && $product['shop_id'] > 0) {
$shop = ShopService::instance()->get($product['shop_id']);
if ($shop && $shop['shop_id']) {
return $shop['shop_id'];
}
}
}
return 0;
}
protected function getUrl($url,$version = 3)
{
$host = sysconf('system_host');
$api_host = sysconf('api_host');
if($api_host && $version == 4){
$host = $api_host;
}
if (!$host) {
if (isset($_SERVER['SERVER_PORT']) && isset($_SERVER['HTTP_HOST'])) {
$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
$host = $protocol.$_SERVER['HTTP_HOST'];
} else {
$host = 'https://reapi.gcdat.com';
}
}
return $host . $url;
}
# 通知回调地址
protected function getNotify($order, $type, $api_id = false)
{
if ($api_id) {
$type .= '&s_api_id=' . $api_id;
}
$api_host = sysconf('api_host');
if($api_host){
$url = $this->getUrl('/notify/call?s_order=' . $order . '&s_type=' . $type.'&version=v4',4);
}else{
$url = $this->getUrl('/gateway/api.notify/call?s_order=' . $order . '&s_type=' . $type);#修改原为v3.0之前版本
}
return $url;
}
# 创建订单
protected function create($order_id, $channel_order_id, $merchant_order_id, $cash, $url, $request, &$response, $status = 1, $account = '', $parent_order_id = '', $card_id = false, $kou = true)
{
$response_data = '';
if ($response) {
if ($response['msg'] == 'success') {
# 直接成功
$status = 2;
} elseif ($response['msg'] == 'ok') {
$status = 4;
} elseif ($response['msg'] == 'yescard') {
$status = 7;
} else {
$status = 3;
}
$response_data = $response['data'];
}
if ($this->data) {
$product = $this->product ? $this->product : ProductService::instance()->get($this->data['merchant'], $this->data['product']);
if ($product) {
if ($card_id == -1) {
$status = 3;
}
$channel = ChannelService::instance()->get($product['cid']);
if ($channel && $product['cid'] == $channel['id']) {
if (isset($this->data['project_id']) && $this->data['project_id']) {
$project_id = $this->data['project_id'];
} else {
$project_id = false;
}
$order = OrderService::instance()->up($this->data['merchant'], $channel['id'], $product['id'], $product['key'], $order_id, $channel_order_id, $merchant_order_id, $cash, $url, $request, $response_data, $status, $account, $parent_order_id, $project_id, $card_id, $this->data['param'], $kou);
if (!$order) {
return false;
}
# 商户后续操作
$merchant = MerchantService::instance()->get($this->data['merchant']);
#TODO 山东电信换渠道处理TODO未处理万
if ($status == 3 && $merchant['id'] == 2 && isset($this->data['product_key']) && $channel['id'] == '2' && isset($request['szProductId']) && strstr($request['szProductId'], '3000')) {
# 如果直接下单失败就获取另外一个相同key的商品吧
$use_product = array();
if (empty($this->data['use_product'])) {
$this->data['use_product'] = array();
}
$this->data['use_product'][] = $product['id'];
$isp = false;
if (isset($order['isp']) && $order['isp']) {
$isp_config = \app\merchant\service\PercentService::instance()->getIsp();
$isp = $isp_config[$order['isp']];
}
$new_product = $this->getProduct($this->data['merchant'], $this->data['product_key'], $this->data['use_product'], $cash, $isp);
if ($new_product) {
# 记录失败的订单信息
OrderAutoService::instance()->up($order['id']);
$response['msg'] = ChannelService::instance()->use($this->data['merchant'], $new_product, $this->data['param'], false, $order_id, $this->data['use_product']);
return true;
}
}
if ($status == 3 && isset($merchant['stop']) && ($merchant['stop'] == 2 || $merchant['stop'] == 4)) {
# 是否暂停
$num = 1;
$order_id = $order['order_id'] . '_' . $num;
# 该渠道下单失败,重新下单,并暂停,等待手动启动
# 记录失败的订单信息
OrderAutoService::instance()->up($order['id']);
# 修改状态
OrderService::instance()->upStatus($order['order_id'], -5, '', false, $num);
return true;
} elseif ($status == 3 && $merchant['order_auto'] == 2 && isset($this->data['product_key'])) {
# 如果直接下单失败就获取另外一个相同key的商品吧
$use_product = array();
if (empty($this->data['use_product'])) {
$this->data['use_product'] = array();
}
$this->data['use_product'][] = $product['id'];
$isp = false;
if (isset($order['isp']) && $order['isp']) {
$isp_config = \app\merchant\service\PercentService::instance()->getIsp();
$isp = $isp_config[$order['isp']];
}
$new_product = $this->getProduct($this->data['merchant'], $this->data['product_key'], $this->data['use_product'], $cash, $isp);
if ($new_product) {
# 记录失败的订单信息
OrderAutoService::instance()->up($order['id']);
$response['msg'] = ChannelService::instance()->use($this->data['merchant'], $new_product, $this->data['param'], false, $order_id, $this->data['use_product']);
return true;
}
}
/*
if ($status == 3 && $product['id'] == 13 && isset($response['array']['status_code']) && $response['array']['status_code'] == '40000' && isset($response['array']['status_msg']) && strstr($response['array']['status_msg'], '账户余额')) {
# 如果是八达通失败,并且账户余额不足,就不通知用户失败,直接延迟到失败表中
$this->data['order'] = $order_id;
OrderService::instance()->upStatus($order_id, -2, $this->data);
return true;
}
*/
$result = array();
$result['project_id'] = $project_id;
$result['order_id'] = $order_id;
$result['merchant_order_id'] = $order['merchant_order_id'];
$result['status'] = $order['status'];
$result['notify_num'] = $order['merchant_callback_num'];
$result['cash'] = $order['cash'];
$result['account'] = $order['account'];
if (isset($order['isp']) && $order['isp']) {
$result['isp'] = $order['isp'];
}
$result['order'] = $order;
if (isset($this->data['param']['notify']) && $this->data['param']['notify']) {
$result['notify'] = $this->data['param']['notify'];
}
MerchantService::instance()->up($order['id'], $merchant, $product['id'], $product['key'], $result);
return true;
}
}
}
return false;
}
private function getProduct($mid, $product, $use_product, $cash, $isp = false)
{
$product_data = MerchantProductService::instance()->getAll($mid, $product);
if ($product_data) {
foreach ($product_data as $k => $v) {
if ($v['cash']) {
if ($isp && (strstr($v['cash'], '联通') || strstr($v['cash'], '移动') || strstr($v['cash'], '电信'))) {
$cash = $isp;
}
$temp = explode(',', $v['cash']);
if (!in_array($cash, $temp)) {
continue;
}
}
if (!in_array($v['pid'], $use_product)) {
return $v['pid'];
}
}
}
return false;
}
# 创建订单号
protected function createOrder($order)
{
if (isset($this->data['order']) && $this->data['order']) {
return $this->data['order'];
}
$order = $this->createOrderId();
$info = OrderService::instance()->get($order);
if (!$info) {
return $order;
} else {
return $this->createOrder($order);
}
//return sha1($this->data['merchant'] . '_' . $this->data['product'] . '_' . $this->createOrderId() . '_' . $order);
}
# 生成订单号
protected function createOrderId()
{
$prefix = sysconf('system_order_perfix');
if (!$prefix) {
$prefix = 'Q';
}
return $prefix . date('Ymd').substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', mt_rand(100000, 999999));
// if (function_exists('session_create_id')) {
// return strtoupper(session_create_id());
// } else {
// $charid = strtoupper(md5(uniqid(mt_rand(), true)));
// return substr($charid, 0, 8) . substr($charid, 8, 4) . substr($charid, 12, 4) . substr($charid, 16, 4) . substr($charid, 20, 12);
// }
}
# 队列
protected function queue($key, $value = false)
{
$redis = RedisService::getInstance();
if (!$value) {
return $redis->pop($key);
} else {
return $redis->push($key, $value);
}
}
# 请求数据
protected function curl($method, $url, $param = array(), $json = false, $header = false)
{
$log['type'] = 'request';
$log['url'] = $url;
$log['param'] = $param;
$log['config'] = $this->data;
$this->log($log);
$data = CurlService::getInstance($url, $param, $method, $json, $header)->result();
if (!$data) {
$data = CurlService::getInstance($url, $param, $method, $json, $header)->result();
}
return $data;
}
public function http_send($type,$url,$data,$json = false)
{
$header = 'Content-type: application/x-www-form-urlencoded';
$payload = $data;
if($json){
$payload = json_encode($data); // 将数据编码为JSON
$header = 'Content-type: application/json';
}
$options = array(
'http' => array(
'header' => $header,
'method' => $type,
'content' => $payload,
),
);
// var_dump($options);die;
$context = stream_context_create($options); // 创建流上下文
$result = file_get_contents($url, false, $context); // 发送请求
if ($result === FALSE) {
return 'Error';
}
return $result; // 解码JSON响应
// return $this->async;
}
# 通用签名方法,如果有渠道不同的签名方式,需要单独实现
protected function sign($request, $type = 'sha1', $suffix = '', $empty = true)
{
return AuthService::signature($request, $type, $suffix, $empty);
}
protected function getParam($param, $token, $sign_type = 1)
{
return AuthService::get($param, $token, $sign_type);
}
protected function timestamp()
{
return AuthService::timestamp();
}
# 记录日志
protected function log($data)
{
Log::write('gateway', 'log', $data);
}
protected function json_decode($data)
{
$array = json_decode($data, true);
if (!is_array($array) || is_null($array) || json_last_error() != JSON_ERROR_NONE) {
return false;
}
return $array;
}
# 获取手机号
protected function getMobile($card, $n = 1)
{
$info = \app\merchant\service\MobileService::instance()->get($card);
if ($info && $info['mobile']) {
return $info['mobile'];
}
$tel_arr = array(
'130','131','132','133','134','135','136','137','138','139','144','147','150','151','152','153','155','156','157','158','159','176','177','178','180','181','182','183','184','185','186','187','188','189','199',
);
for($i = 0; $i < $n; $i++) {
$tmp[] = $tel_arr[array_rand($tel_arr)].mt_rand(1000,9999).mt_rand(1000,9999);
// $tmp[] = $tel_arr[array_rand($tel_arr)].'xxxx'.mt_rand(1000,9999);
}
$tem = array_unique($tmp);
if (isset($tem[0])) {
$mobile = $tem[0];
\app\merchant\service\MobileService::instance()->up($card, $mobile);
} else {
$mobile = '13800138000';
}
return $mobile;
}
# 获取手机运营商
protected function isp($mobile)
{
return ChannelService::instance()->isp($mobile);
}
# 获取产品id
protected function getGid($cash)
{
$info = $this->product;
if ($info) {
if (isset($info['gid_rule']) && $info['gid_rule']) {
$rule = json_decode($info['gid_rule'], true);
if (isset($rule[$cash]) && $rule[$cash]) {
$gid = $rule[$cash];
return $gid;
}
}
if (isset($info['gid']) && $info['gid']) {
return $info['gid'];
}
}
return -1;
}
//随机生成n条手机号
protected function randomMobile($n = 1)
{
$tel_arr = array(
'130','131','132','133','134','135','136','137','138','139','144','147','150','151','152','153','155','156','157','158','159','176','177','178','180','181','182','183','184','185','186','187','188','189',
);
for($i = 0; $i < $n; $i++) {
$tmp[] = $tel_arr[array_rand($tel_arr)].$this->rands().$this->rands();
}
return array_unique($tmp);
}
//随机生成身份证号
protected function randomShenfen()
{
$city = array(11,12,13,14,15,21,22,23,31,32,33,34,35,36,37,41,42,43,44,45,46,50,51,52,53,54,61,62,63,64,65,71,81,82,91);
//校验位
$parity = array('1','0','X','9','8','7','6','5','4','3','2');
// $a = array('a','b','c');
$arr = array(0,1,2,3,4,5);
$str = '';
// echo $city[array_rand($city)];
//前两位
$str .=$city[array_rand($city)];
//地区位后四位
for($i=0;$i<4;$i++){
$str .=$arr[array_rand($arr)];
}
//出生年 随机20世纪
$str .= '19'.mt_rand(0,9).mt_rand(0,9);
//月份
$month = array('01','02','03','04','05','06','07','08','09','10','11','12');
$str .=$month[array_rand($month)];
//天
$day = mt_rand(0,3);
if($day==3){
$str .=$day.mt_rand(0,1);
}else{
$str .=$day.mt_rand(0,9);
}
//顺序码
for($i=0;$i<3;$i++){
$str .=mt_rand(0,9);
}
//计算加权因子
for($i=18;$i>1;$i--){
$factor[] = fmod(pow(2,$i-1),11);
}
//将加权因子和身份证号对应相乘,再求和
$sum = 0;
for($i=0;$i<count($factor);$i++){
$sum +=$factor[$i]*$str[$i];
}
//将sum对11求余
$mod = fmod($sum,11);
$str .=$parity[$mod];
return $str;
}
# 随机生成姓名
protected function randomName()
{
$name=new rndChinaName();
return $name->getName();
}
protected function rands()
{
$s = mt_rand(1000,9999);
if ($s == '1234') {
return $this->rands();
} elseif ($s == '2345') {
return $this->rands();
} elseif ($s == '3456') {
return $this->rands();
} elseif ($s == '4567') {
return $this->rands();
} elseif ($s == '5678') {
return $this->rands();
} elseif ($s == '6789') {
return $this->rands();
}
return $s;
}
protected function maketime($v)
{
if (!$v) {
return '';
}
if (is_numeric($v)) {
return $v;
}
if (is_array($v)) {
$v = $v[1];
}
if (strstr($v, ' ')) {
$t = explode(' ', $v);
$v = $t[0];
$s = explode(':', $t[1]);
} else {
$s = array(0, 0, 0);
}
if (!isset($s[1])) {
$s[1] = 0;
}
if (!isset($s[2])) {
$s[2] = 0;
}
if (strstr($v, '-')) {
$t = explode('-', $v);
} elseif (strstr($v, '/')) {
$u = explode('/', $v);
$t[0] = $u[2];
$t[1] = $u[0];
$t[2] = $u[1];
}
if (!isset($t)) {
$t = array(0, 0, 0);
}
if (!isset($t[1])) {
$t[1] = 0;
}
if (!isset($t[2])) {
$t[2] = 0;
}
$v = mktime($s[0], $s[1], $s[2], $t[1], $t[2], $t[0]);
return $v;
}
# 获取手机运营商
protected function getMobileInfo($mobile)
{
//git clone https://github.com/shitoudev/phone-location /www/wwwroot/api/extend/phone
// TODO 此处不同服务器需改动的绝对路径
include '/www/wwwroot/bao111/extend/phone/src/PhoneLocation.php';
$pl = new \Shitoudev\Phone\PhoneLocation();
$info = $pl->find($mobile);
return $info;
}
public function diy_send_post($notify_url, $post_data, $type): mixed
{
$postdate = http_build_query($post_data);
$options = array(
'http' => array(
'method' => $type,
'header' => 'Content-type:application/x-www-form-urlencoded',
'content' => $postdate,
'timeout' => 15 * 60 // 超时时间(单位:s
)
);
$context = stream_context_create($options);
return file_get_contents($notify_url, false, $context);
}
}