707 lines
20 KiB
PHP
Raw Normal View History

2024-09-29 15:43:18 +08:00
<?php
namespace app\openapi\controller;
use app\channel\service\ChannelService;
use app\core\Service;
use app\gateway\service\AuthService;
use app\gateway\service\RedisService;
use app\merchant\service\MerchantMappingProductService;
2024-09-29 15:43:18 +08:00
use app\merchant\service\MerchantService;
2024-11-02 15:27:08 +08:00
//use app\merchant\service\MerchatMappingProductService;
2024-09-29 15:43:18 +08:00
use app\merchant\service\OrderHistoryService;
use app\merchant\service\OrderLastHistoryService;
use app\merchant\service\OrderLastweekHistoryService;
use app\merchant\service\OrderService;
use app\merchant\service\OrderTwoHistoryService;
use dever\Log;
use Exception;
use think\admin\Controller;
use think\exception\HttpResponseException;
//use think\facade\Http;
/**
* 快手接口核心控制器
* Class Core
* @package app\gateway\service
*/
class Coreks extends Controller
{
# 是否检测数据
protected bool $check = true;
# 商户appid
protected string $appid = '';
# 商户id
protected int $mid = 0;
# 商户信息
protected array $merchant = array();
# token key
protected string $key = '';
# product key
protected string $product = 'query';
# proid
protected $proid = 0;
# mapping proids
protected $mappingid = 0;
# input
protected array $input = array();
# sign_type
protected int $sign_type = 1;
# code码定义
protected array $code = array
(
# 成功
1 => 'ok',
# 快手错误代码
'4013001' => 'appKey参数缺失',
'4013022' => '黑名单',
'4012004' => '查询不到该手机号信息',
'4013017' => '商品售价参数错误',
'4013008' => 'Param参数缺失',
'4013007' => '签名校验失败',
# 小于0为失败
-1 => 'appid为空',
-2 => '产品错误',
-3 => 'appid无效',
-4 => '余额不足或者没有传入价格',
-5 => 'signature不能为空',
-6 => 'nonce不能为空',
-7 => 'time不能为空',
-8 => 'signature已失效',
-9 => 'signature验证失败',
-100 => '请求错误',
-101 => '订单不存在',
-102 => '订单号重复',
-1000 => '系统维护中',
);
public function initialize(): void
{
parent::initialize();
$this->sign_type = sysconf('sign_type');
if ($this->check) {
$this->check();
}
}
# 获取输入的信息
public function input(): void
{
$this->input = input();
Log::write('openapi', 'kuaishou_request', $this->input);#写入到日志里
if (isset($this->input['test'])) {
$this->testtrue = 1;
} else {
$this->testtrue = 2;
}
#
$this->agentId = input('appkey');
if (!$this->agentId) {
$this->noKS(4013001);
}
if (is_string($this->input['param'])) {
$this->input['param'] = json_decode($this->input['param'], true);
2024-09-29 15:43:18 +08:00
}
// var_dump($this->input['param']);die;
$this->input = $inputData = $this->input['param'];
2024-11-02 15:27:08 +08:00
$this->bizType = $inputData['bizType'];
2024-09-29 15:43:18 +08:00
if ($inputData['bizType'] == '10') {
$this->agentId = $this->agentId . '_KC';
2024-09-29 15:43:18 +08:00
}
2024-11-02 15:27:08 +08:00
if (isset($inputData['sellerId']) && $inputData['sellerId']){
$this->agentId = $this->agentId . '_S_'.$inputData['sellerId'];
}
2024-09-29 15:43:18 +08:00
if (!$this->input) {
$this->noKS(4013008);
}
$this->mappingid = $inputData['relItemId'];
// $this->product = 'dhcz';
if ($this->mappingid) {
# 根据产品id 获取信息
$pinfo = MerchantMappingProductService::instance()->getOne($this->mappingid);
2024-11-02 15:27:08 +08:00
// $pinfo = MerchatMappingProductService::instance()->getOne($this->mappingid);
2024-09-29 15:43:18 +08:00
$this->pinfo = $pinfo;
// if($pinfo)
if (!$pinfo) {
$this->product = 'dhcz';
} else {
2024-09-29 15:43:18 +08:00
$this->product = $pinfo['key'];
}
} else {
$this->product = 'dhcz';
}
// $this->product = 'dhcz';
$this->order = $inputData['orderId'];
$this->ksorder = $inputData['ksOrderId'];
$this->salePrice = $inputData['price'];
$this->cash = $inputData['amount'] / 100;
$this->input['cash'] = $this->cash;
$this->input['order'] = $this->order;
$this->encryptAccount = $inputData['encryptAccount'];
$this->input['getMobile_num'] = 0;
unset($this->input['orderId']);
# 从数据库中或者缓存中取出商户的信息,并验证是否有效
$this->getMerchant();
$this->card = $this->getMobile();
$this->input['card'] = $this->card;
$this->input['mobile'] = $this->input['card'];
if ($this->product == 'dhcz') {
2024-09-29 15:43:18 +08:00
$this->getNewProduct();
}
if (isset($this->input['ksOrderId'])) {
$this->input['parent_order_id'] = $this->input['ksOrderId'];
}
}
2024-11-02 15:27:08 +08:00
2024-09-29 15:43:18 +08:00
public function getNewProduct(): void
{
if (is_string($this->merchant['other_param'])) {
$array = json_decode($this->merchant['other_param'], true);
if (is_array($array)) {
if (isset($array['phone_global_sub_product']) && $array['phone_global_sub_product'] == 1) {
$isp = Service::instance()->isp($this->input['mobile']);
if ($isp == 1) {
2024-09-29 15:43:18 +08:00
$this->product = 'ydcz';
} elseif ($isp == 2) {
2024-09-29 15:43:18 +08:00
$this->product = 'ltcz';
} elseif ($isp == 3) {
2024-09-29 15:43:18 +08:00
$this->product = 'dxcz';
}
}
}
}
}
/**
* 检测输入信息是否合法
*/
protected function check()
{
}
# 检测开放或者维护时间
protected function checkOpenTime($opentime): void
{
if ($opentime && strstr($opentime, ':')) {
$opentime = str_replace(':', '', $opentime);
if (str_contains($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->noKS(-1000);
}
} else {
if ($cur >= $value[0] && $cur < $value[1]) {
$this->noKS(-1000);
}
}
}
}
}
/**
* 对输入的信息进行加密
*/
protected function getSignature()
{
$this->input();
$input = $this->input;
if ($this->proid) {
unset($input['cash']);
}
return AuthService::get($input, $this->key, $this->sign_type);
}
public function test1($notify_url, $post_data): mixed
{
// $postdata = http_build_query($post_data);
$options = array(
'http' => array(
'method' => 'POST',
'header' => 'Content-type:application/x-www-form-urlencoded',
'timeout' => 15 * 60 // 超时时间(单位:s
)
);
$context = stream_context_create($options, $post_data);
$result = file_get_contents($notify_url, false, $context);
return $result;
}
public static function get_curl_post($geturl): mixed
{
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => $geturl,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_HTTPHEADER => array(
'User-Agent: Apifox/1.0.0 (https://apifox.com)',
'Accept: */*',
'Host: openapi.kwaixiaodian.com',
'Connection: keep-alive',
'Content-Type: application/x-www-form-urlencoded'
),
));
$response = curl_exec($curl);
curl_close($curl);
return $response;
}
# 获取商户信息
protected function getMobile()
{
// $getUrl = 'https://openapi.kwaixiaodian.com/open/industry/virtual/order/decrypt?';
$param = array();
$param['decryptList'][0] = array(
'encryptedData' => $this->encryptAccount,
'sceneType' => '1'
);
$param['orderId'] = $this->ksorder;
$param = json_encode($param);
$post_data = array(
'appkey' => $this->agentId,
'method' => 'open.industry.virtual.order.decrypt',
'param' => urlencode($param),
'version' => 1,
'signMethod' => 'MD5',
'timestamp' => time()
);
if (isset($this->access_token) && $this->access_token_time > time() && $this->testtrue != 1) {
$post_data['access_token'] = $this->access_token;
} else {
$post_data['access_token'] = $this->getKuaishouToken();
// var_dump($this->input);die;
if ($post_data['access_token'] == 'error') {
return $this->noKS('4012004');
}
}
$post_data['sign'] = $this->sign($post_data, $param);
$getUrl = 'https://open.kwaixiaodian.com/open/industry/virtual/order/decrypt?access_token=' . $post_data['access_token'] . '&method=open.industry.virtual.order.decrypt&param=' . $post_data['param'] . '&sign=' . $post_data['sign'] . '&appkey=' . $post_data['appkey'] . '&version=1&signMethod=MD5&timestamp=' . $post_data['timestamp'];
$result = $this->get_curl_post($getUrl);
$result = json_decode($result, true);
$num = $this->input['getMobile_num'];
$num++;
if ($result['result'] == 1) {
$result = $result['data'][0]['decryptedData'];
} elseif ($num < 3) {
2024-11-02 15:27:08 +08:00
$this->input['getMobile_num'] = $num;
2024-09-29 15:43:18 +08:00
$this->getMobile();
}
return $result;
}
#sing签名
public function sign($post_data, $paramJson): string
{
// $keys = '16fb1715cc284e2653a13f40e2e813f9';
$signData = 'access_token=' . $post_data['access_token'] . '&appkey=' . $post_data['appkey'] . '&method=open.industry.virtual.order.decrypt&param=' . $paramJson . '&signMethod=MD5&timestamp=' . $post_data['timestamp'] . '&version=1&signSecret=' . $this->signkey;
return (md5($signData));
}
//发送回调
public function 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);
}
#测试
/**
* @param $url
* @return bool
*/
public function send_get($url): bool
{
$curl = curl_init(); //初始化
curl_setopt($curl, CURLOPT_URL, $url); //设置抓取的url
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); //设置获取的信息以文件流的形式返回,而不是直接输出。
$output = curl_exec($curl); //执行命令
curl_close($curl); //关闭URL请求
return $output;
}
protected function getMerchant(): void
{
$this->merchant = MerchantService::instance()->get('PT_' . $this->agentId);
2024-11-02 15:27:08 +08:00
if (str_contains($this->agentId, "_S_")) {
$agentId = explode('_S_',$this->agentId);
$this->agentId = $agentId[0];
}
2024-09-29 15:43:18 +08:00
if (str_ends_with($this->agentId, "_KC")) {
$this->agentId = substr($this->agentId, 0, -3);
}
2024-11-02 15:27:08 +08:00
2024-09-29 15:43:18 +08:00
$this->mid = $this->merchant['id'];
// $this->agentId = $this->merchant['agentId'];
$this->agentkey = $this->merchant['agentkey'];
$this->refresh_token = $this->merchant['refresh_token'];
$this->access_token_time = $this->merchant['access_token_time'];
$this->access_token = $this->merchant['access_token'];
$this->callnotify = $this->merchant['notify_url'];
$this->signkey = $this->merchant['other_key'];
}
# 查找订单
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 channel($merchant, $product, $async = false, $param = false, $order = '')
{
if (!$param) {
$param = $this->input;
}
return ChannelService::instance()->use($merchant, $product, $param, $async, $order);
}
2024-09-29 15:43:18 +08:00
/**
* 返回快手下单失败的消息
* @param integer $code
* @param string $ksOrderNo
* @param string $error_msg
* @param string $qudao
2024-09-29 15:43:18 +08:00
*/
protected function noKS($code = 0, $ksOrderNo = '', $error_msg = '', $qudao = '')
{
$msg = $this->code[$code] ?? 'error';
if ($error_msg) {
$error_msg = $msg . ':' . $error_msg;
} elseif ($msg != 'error') {
2024-09-29 15:43:18 +08:00
$error_msg = $msg;
}
$data = array(
'createTime' => date('c'),
'orderNo' => 'E' . $ksOrderNo,
'orederId' => $ksOrderNo,
'status' => 'FAILED'
);
$msg = array(
'result' => $code,
'error_msg' => $error_msg,
'data' => $data
);
throw new HttpResponseException(json($msg));
// $this->error($msg, $data, $code);
}
/**
* 返回成功的消息
* @param string $data
* @param string $qudao
* @param string $OrderNo
* @param mixed $info
2024-09-29 15:43:18 +08:00
* @return mixed
*/
protected function yesks($data = '{-null-}', $qudao = '', $OrderNo = '', $info = false)
{
if (is_string($data) && $data != 'ok') {
if ($data == '订单号重复') {
$data = $this->getOrder('', $OrderNo);
$ksdata = array(
'createTime' => date('c'),
'orderNo' => $OrderNo,
'orederId' => $data['order_id'],
'status' => 'ACCEPTED'
);
$ksmsg = array(
'result' => '1',
'data' => $ksdata
);
throw new HttpResponseException(json($ksmsg));
} elseif (str_contains($data, '已被列入黑名单')) {
$this->blackks($OrderNo);
}
return $this->noKS('JDI_00001', $OrderNo);
}
switch ($qudao) {
case 'submit':
$data = $this->getOrder('', $OrderNo);
$ksdata = array(
'createTime' => date('c'),
'orderNo' => $OrderNo,
'orederId' => $data['order_id'],
'status' => 'ACCEPTED'
);
$ksmsg = array(
'result' => '1',
'data' => $ksdata
);
break;
case '':
break;
default:
}
throw new HttpResponseException(json($ksmsg));
}
/**
* 返回并拉黑的消息
* @param mixed $info
* @param string $data
* @param integer $code
*/
protected function blackks($OrderNo = '')
{
$ksdata = array(
'createTime' => date('c'),
'orderNo' => $OrderNo,
'orederId' => 'E' . $OrderNo,
'status' => 'ACCEPTED'
);
$ksmsg = array(
'result' => '1',
'data' => $ksdata
);
$setData = array(
'mid' => $this->mid,
'orderNo' => $OrderNo,
'agentkey' => $this->agentkey,
'notify_url' => $this->callnotify,
'agentId' => $this->agentId,
'access_token' => $this->access_token,
);
try {
#推送到redis队列
$this->queue('blackcall', $setData);
} catch (Exception $e) {
2024-09-29 15:43:18 +08:00
Log::write('gateway', 'redis_kuaishou_black', $setData);
Log::write('errorTip', 'redis', $e->getMessage());
}
throw new HttpResponseException(json($ksmsg));
//TODO 需要处理redis
}
#获取解密接口
protected function decrypt($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);
}
# 记录日志
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);
}
}
#获取快手token
public function getKuaishouToken()
{
$tokenurl = 'https://openapi.kwaixiaodian.com/oauth2/refresh_token';
$token_data = array(
'grant_type' => 'refresh_token',
'refresh_token' => $this->refresh_token,
'app_id' => $this->agentId,
'app_secret' => $this->agentkey
);
try {
$resulttoken = $this->send_post($tokenurl, $token_data, 'POST');
$tokenresult = json_decode($resulttoken, true);
if ($tokenresult['result'] != 1) {
#判断未获取数据
Log::write('errorTip', 'getKSToken_error', $resulttoken);
return 'error';
}
} catch (Exception $e) {
2024-09-29 15:43:18 +08:00
Log::write('errorTip', 'getKSToken_error', $e->getMessage());
return 'error';
}
// var_dump($resulttoken);die;
#更新refresh_token
$updaterefresh_token = array(
'refresh_token' => $tokenresult['refresh_token'],
'access_token' => $tokenresult['access_token'],
'access_token_time' => time() + $tokenresult['expires_in']
);
2024-11-02 15:27:08 +08:00
// MerchantService::instance()->db()
//// ->where(array('id' => $this->mid))
// ->whereLike('agentId', "%" . $this->agentId . '%')->update($updaterefresh_token);
MerchantService::instance()->db()->where(['id'=>$this->mid])->update($updaterefresh_token);
2024-09-29 15:43:18 +08:00
Log::write('gateway', 'token', $tokenresult);
return $tokenresult['access_token'];
}
}