2024-12-04 12:33:47 +08:00

628 lines
20 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\gateway\controller\api;
use app\merchant\service\OrderLastHistoryService;
use app\merchant\service\OrderLastweekHistoryService;
use app\merchant\service\OrderTwoHistoryService;
use think\admin\Controller;
use app\gateway\service\AuthService;
use app\gateway\service\RedisService;
use app\merchant\service\MerchantService;
use app\merchant\service\OrderService;
use app\order\service\OrderService as OrderBase;
use app\merchant\service\OrderHistoryService;
use app\merchant\service\OrderAutoService;
use app\channel\service\ChannelService;
use app\merchant\service\ProductService as MerchantProductService;
use dever\Log;
use think\facade\Db;
/**
* 接口核心控制器
* Class Core
* @package app\gateway\service
*/
class Core extends Controller
{
# 是否检测数据
protected $check = true;
# 商户appid
protected $appid = '';
# 商户id
protected $mid = 0;
# 商户信息
protected $merchant = array();
# token key
protected $key = '';
# product key
protected $product = 'query';
# proid
protected $proid = 0;
# input
protected $input = array();
# use_product
protected $use_product = array();
# sign_type
protected $sign_type = 1;
protected $request_ip= '';
# code码定义
protected $code = array
(
# 成功
1 => 'ok',
# 小于0为失败
-1 => 'appid为空',
-2 => '产品错误',
-3 => 'appid无效',
-4 => '余额不足或者没有传入价格',
-5 => 'signature不能为空',
-6 => 'nonce不能为空',
-7 => 'time不能为空',
-8 => 'signature已失效',
-9 => 'signature验证失败',
-100 => '请求错误',
-101 => '订单不存在',
-102 => '订单号重复',
-104 => '回调渠道订单号不匹配,请核对',
-601 => '该商户已经超过日限额,下单失败',
-602 => '充值失败,请核对上游',
-801 => 'ip: 请求错误,不在白名单',
-1000 => '系统维护中',
);
#找不到方法错误响应
public function __call($name, $arguments){
$this->error('请求'.$name.'错误', '{-null-}', -802);
}
public function initialize()
{
parent::initialize();
$this->sign_type = sysconf('sign_type');
if ($this->check) {
$this->check();
}
}
# 获取输入的信息
public function input()
{
$this->input = input();
if (!$this->input) {
$this->no(-100);
}
$this->appid = input('appid');
if (!$this->appid) {
$this->no(-1);
}
$this->proid = input('proid');
if ($this->proid) {
# 根据产品id 获取信息
$pinfo = \app\channel\service\ProductBaseService::instance()->getOne($this->proid);
if (!$pinfo) {
$this->no(-2);
}
$this->input['proid'] = $this->proid;
$this->product = $pinfo['key'];
if ($this->product != 'dhcz') {
if (!strstr($this->product, '_cash')) {
$this->input['cash'] = $pinfo['value'];
}
} else {
$this->proid = false;
}
} else {
$product = input('api_product');
if ($product) {
$this->product = $product;
}
}
if (!$this->product) {
$this->no(-2);
}
# 从数据库中或者缓存中取出商户的信息,并验证是否有效
$this->getMerchant();
}
public function getRealIp()
{
$forwardedFor = $this->request->header('x-forwarded-for');
if ($forwardedFor) {
// 可能有多个IP第一个通常是真实的
$ips = explode(',', $forwardedFor);
return trim($ips[0]);
}
return $this->request->ip(); // 如果没有X-Forwarded-For头则返回当前请求的IP
}
/**
* 检测输入信息是否合法
*/
protected function check()
{
$this->input();
$input = $this->input;
$ip_white_data = $this->merchant['ip_white'];
$request_ip = $this->getRealIp();
// if()
$ip_white_array = $ip_white_data?explode(',', $ip_white_data):[];
if(!$ip_white_array || !in_array($request_ip, $ip_white_array)){
$this->no(-801,'ip:'.$request_ip.',请求错误,不在白名单内。');
}
// var_dump(1);die;
if ($this->proid && !strstr($this->product, '_cash')) {
unset($input['cash']);
}
if($input['appid'] != 'app574223018568' && $input['appid'] != 'app438960763961' && $input['appid'] != 'app176018250661' && $input['appid'] != 'app302655444830' ){#测试验签
$signature = AuthService::check($input, $this->key, $this->sign_type);
if (is_numeric($signature)) {
$this->no($signature);
}
}
unset($this->input['signature']);
if (isset($this->input['nonce'])) {
unset($this->input['nonce']);
}
if (isset($this->input['time'])) {
unset($this->input['time']);
}
}
# 检测开放或者维护时间
protected function checkOpenTime($opentime)
{
if ($opentime && strstr($opentime, ':')) {
$opentime = str_replace(':', '', $opentime);
if (strstr($opentime, '-')) {
$value = explode('-', $opentime);
$cur = intval(date('Hi'));
$value[0] = intval($value[0]);
$value[1] = intval($value[1]);
if ($value[1] < $value[0]) {
if ($cur >= $value[0] || $cur < $value[1]) {
$this->no(-1000);
}
} else {
if ($cur >= $value[0] && $cur < $value[1]) {
$this->no(-1000);
}
}
}
}
}
/**
* 对输入的信息进行加密
*/
protected function getSignature()
{
$this->input();
$input = $this->input;
if ($this->proid && !strstr($this->product, '_cash')) {
unset($input['cash']);
}
return AuthService::get($input, $this->key, $this->sign_type);
}
# 获取商户信息
protected function getMerchant()
{
$this->merchant = MerchantService::instance()->get($this->appid);
if (!$this->merchant) {
$this->no(-3);
}
if ($this->product != 'query') {
if (empty($this->input['cash'])) {
$this->no(-4);
}
if ($this->product == 'dxdc') {
$cash = 0.23;//这里后续处理
if ($this->merchant['credit_surplus'] < $cash && $this->merchant['account_surplus'] < $cash) {
$this->no(-4);
}
} else {
if ($this->merchant['credit_surplus'] < $this->input['cash'] && $this->merchant['account_surplus'] < $this->input['cash']) {
$this->no(-4);
}
}
if(isset($this->merchant['limit_amount']) && $this->merchant['limit_amount'] > 0){
$count_cash = OrderBase::instance()->countMerchantCash($this->merchant['id']);
if($this->merchant['limit_amount'] < ($count_cash+$this->input['cash'])){
$this->no(-601);
}
}
}
$this->mid = $this->merchant['id'];
if ($this->sign_type == 2) {
$this->key = $this->merchant['appsecret'];
} else {
$this->key = $this->appid . '|' . $this->merchant['appsecret'];
}
}
# 查找订单
protected function getOrder($order_id, $merchant_order_id = false)
{
$orderService = OrderService::instance();
$order = $orderService->get($order_id, $merchant_order_id, $this->mid);
if (!$order) {
$orderLastweekHistoryService = OrderLastweekHistoryService::instance();
$order = $orderLastweekHistoryService->get($order_id, $merchant_order_id, $this->mid);
}
if (!$order) {
$orderLastHistoryService = OrderLastHistoryService::instance();
$order = $orderLastHistoryService->get($order_id, $merchant_order_id, $this->mid);
}
if (!$order) {
$orderTwoHistoryService = OrderTwoHistoryService::instance();
$order = $orderTwoHistoryService->get($order_id, $merchant_order_id, $this->mid);
}
if (!$order) {
$orderHistoryService = OrderHistoryService::instance();
$order = $orderHistoryService->get($order_id, $merchant_order_id, $this->mid);
}
return $order;
}
# 发送通知
protected function notify($order_id, $request, $status = false, $die = true)
{
$orderService = OrderService::instance();
$order = $orderService->get($order_id);
if (!$order) {
$oldorder = OrderHistoryService::instance()->get($order_id);
if ($oldorder) {
$channelService = ChannelService::instance();
$oldupdate = $channelService->call('notify', $oldorder['cid'], $request, false, $oldorder);
$merchant = MerchantService::instance()->get($oldorder['mid']);
if ($oldupdate['status'] == 3 && $oldorder['status'] == 2 && isset($merchant['callback_repeat']) && $merchant['callback_repeat'] > 2) {
if ($oldorder['cid'] == '2') {
OrderHistoryService::instance()->db()->where(array('order_id' => $order_id))->update(['status' => '3', 'buy_back' => '1']);
if (isset($oldupdate['yes']) && $oldupdate['yes']) {
return $oldupdate['yes'];
// die;
}
return 'success';
// die;
}
}
}
}
if ($order) {
$up = $nup = false;
if ($order['status'] != 2 && $order['status'] != 3 && $order['status'] != 5 && $order['status'] != -6) {
$up = true;
}
if(isset($order['channel_order_id']) && $order['channel_order_id'] && isset($request['channel_order_id']) && $request['channel_order_id'] && $order['channel_order_id'] != $request['channel_order_id']) {
$this->no(-104);
}
// var_dump($order);die;
#识别是否重复回调
// $repeated
// if ($order[''])
if (!$status && $request) {
$channelService = ChannelService::instance();
$update = $channelService->call('notify', $order['cid'], $request, false, $order);
$merchant = MerchantService::instance()->get($order['mid']);
if (isset($order['param']) && $order['param']) {
$order['param'] = json_decode($order['param'], true);
} else {
$order['param'] = false;
}
#渠道返销
if ($update['status'] == 3 && $order['status'] == 2 && isset($merchant['callback_repeat']) && $merchant['callback_repeat'] >= 2) {
// # TODO 暂时写死渠道,后续需修改为可以自主选择
if ($order['cid'] == '2') {
$order->db()->where(array('order_id' => $order_id))->update(['status' => '3', 'buy_back' => '1']);
if (isset($update['yes']) && $update['yes']) {
return $update['yes'];
}
return 'success';
}
}
if (isset($order['merchant_callback_at']) && $order['merchant_callback_at']) {
return 'fail';
}
$where[] = [
'order_id', 'like', $order_id
];
// $is_lj_order = Db::name('merchant_order_lj')->where($where)->find();
// if ($is_lj_order) {
// $is_lj_status = false;
// } else {
// $is_lj_status = true;
// }
if ($update['status'] == 3 && isset($merchant['stop']) && $merchant['stop'] > 2) {
# 是否暂停
$num = $order['num'] + 1;
$order_id = $order['order_id'] . '_' . $num;
# 该渠道下单失败,重新下单,并暂停,等待手动启动
# 记录失败的订单信息
$orderAutoService = OrderAutoService::instance();
$estate = $orderAutoService->up($order);
if ($estate) {
$orderAutoService->upChannelMsg($order['order_id'], $update['status'], $update['data'], $order['num']);
# 修改状态
$orderService->upStatus($order['order_id'], -5, '', false, $num);
}
if ($die) {
if (isset($update['yes']) && $update['yes']) {
return $update['yes'];
}
return 'success';
} else {
return true;
}
} elseif ($update['status'] == 3 && isset($merchant['callback_fc']) && $merchant['callback_fc'] > $order['num']) {
$num = $order['num'] + 1;
# 该渠道下单失败,开始复充
# 记录失败的订单信息
$orderAutoService = OrderAutoService::instance();
$estate = $orderAutoService->up($order);
if ($estate) {
$orderAutoService->upChannelMsg($order['order_id'], $update['status'], $update['data'], $order['num']);
# 修改状态
$orderService->upStatus($order['order_id'], -4, '', $merchant['callback_fc_time'], $num);
}
if ($die) {
if (isset($update['yes']) && $update['yes']) {
return $update['yes'];
}
return 'success';
} else {
return true;
}
} elseif ($update['status'] == 3 && $merchant['callback_auto'] == 2 && !$order['apply_refund']) {
# 该渠道下单失败,重新开始找另外一个渠道
$num = $order['num'] + 1;
$new_order_id = $order['order_id'] . '_' . $num;
//
$orderAutoService = OrderAutoService::instance();
$use = $orderAutoService->get($order['order_id']);
$this->use_product[] = $order['pid'];
foreach ($use as $k => $v) {
$this->use_product[] = $v['pid'];
}
$isp = false;
if (isset($order['isp']) && $order['isp'] && $order['isp'] > 0) {
$isp_config = \app\merchant\service\PercentService::instance()->getIsp();
$isp = $isp_config[$order['isp']];
}
$new_product = $this->getProduct($order['mid'], $order['product_key'], $this->use_product, $order['cash'], $isp);
if ($new_product && $order['param']) {
# 记录失败的订单信息
$orderAutoService->up($order);
$orderAutoService->upChannelMsg($order['order_id'], $update['status'], $update['data'], $order['num']);
$channelService->use($order['mid'], $new_product, $order['param'], false, $new_order_id, $this->use_product);
if ($die) {
if (isset($update['yes']) && $update['yes']) {
return $update['yes'];
}
return 'success';
} else {
return true;
}
}
}
if ($update && $up) {
$nup = true;
$orderService->upChannelMsg($order['id'], $update['status'], $update['data']);
}
} elseif ($status) {
$update['status'] = $status;
$update['data'] = $request;
}
if ($update && $order['merchant_callback_error'] != 1) {
//$update['order'] = $order;
$update['project_id'] = false;
if (isset($order['project_id'])) {
$update['project_id'] = $order['project_id'];
}
if (isset($order['card_id'])) {
$update['card_id'] = $order['card_id'];
}
$update['account'] = $order['account'];
$update['cash'] = $order['cash'];
$update['merchant_order_id'] = $order['merchant_order_id'];
$update['order_id'] = $order_id;
$update['notify_num'] = $order['merchant_callback_num'];
if (isset($order['isp']) && $order['isp']) {
$update['isp'] = $order['isp'];
}
if ($order['param'] && isset($order['param']['notify']) && $order['param']['notify']) {
$update['notify'] = $order['param']['notify'];
}
if ($order['mid'] == 33 && $order['cid'] == 10026) {
if (isset($update['s_nubmer'])) {
unset($update['s_nubmer']);
}
if (isset($update['msg'])) {
unset($update['msg']);
}
}
# 商户后续操作
if ($up) {
if (isset($order['error_account_oper']) && $order['error_account_oper'] == 1) {
# 需要进行扣费
MerchantService::instance()->up($order['id'], $order['mid'], $order['pid'], $order['product_key'], $update);
} else {
# 直接发送
MerchantService::instance()->notify($order['id'], $order['mid'], $order['pid'], $order['product_key'], $update);
}
}
}
if ($update) {
if ($up && $nup) {
$orderService->upChannelMsg($order['id'], $update['status'], $update['data']);
}
if ($die) {
if (isset($update['yes']) && $update['yes']) {
return $update['yes'];
}
return 'success';
} else {
return true;
}
}
}
if ($die) {
return 'fail';
} else {
return false;
}
}
private function getProduct($mid, $product, $use_product, $cash, $isp = false)
{
$product_data = MerchantProductService::instance()->getAll($mid, $product);
$where['mid'] = $mid;
$where['pid'] = $use_product[0];
$data1 = MerchantProductService::instance()->db()->where($where)->find();
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 (!$data1) {
$data1 = ['sort' => '10'];
}
if (!in_array($v['pid'], $use_product) && $v['sort'] < $data1['sort']) {
return $v['pid'];
}
}
}
return false;
}
# 通用签名方法,如果有渠道不同的签名方式,需要单独实现
protected function sign($request, $type = 'sha1', $suffix = '')
{
return AuthService::signature($request, $type, $suffix);
}
# 调取服务
protected function channel($merchant, $product, $async = false, $param = false, $order = '')
{
if (!$param) {
$param = $this->input;
}
if ($product == 'cardbuy') {
$async = false;
}
return ChannelService::instance()->use($merchant, $product, $param, $async, $order);
}
/**
* 返回失败的消息
* @param mixed $info
* @param string $data
* @param integer $code
*/
protected function no($code = 0, $info = '', $data = '{-null-}')
{
$msg = $this->code[$code] ?? 'error';
if ($info) {
$msg .= ':' . $info;
}
$data = '{-null-}';
$this->error($msg, $data, $code);
}
/**
* 返回成功的消息
* @param mixed $info
* @param string $data
* @param integer $code
*/
protected function yes($data = '{-null-}', $info = 'ok', $code = 1)
{
if (is_string($data) && $data != 'ok' && $data != 'success') {
if ($data == '订单号重复') {
return $this->no(-102);
}
return $this->no(-100, $data);
}
$this->success($info, $data, $code);
}
# 记录日志
protected function log($data)
{
Log::write('gateway', 'callback', $data);
}
# 队列
protected function queue($key, $value = false)
{
$redis = RedisService::getInstance();
if (!$value) {
return $redis->pop($key);
} else {
return $redis->push($key, $value);
}
}
}