初始化项目
This commit is contained in:
@@ -0,0 +1,396 @@
|
||||
<?php
|
||||
// +----------------------------------------------------------------------
|
||||
// | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
|
||||
// +----------------------------------------------------------------------
|
||||
// | Copyright (c) 2017~2023 https://www.yiovo.com All rights reserved.
|
||||
// +----------------------------------------------------------------------
|
||||
// | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
|
||||
// +----------------------------------------------------------------------
|
||||
// | Author: 萤火科技 <admin@yiovo.com>
|
||||
// +----------------------------------------------------------------------
|
||||
declare (strict_types=1);
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\api\model\Code as CodeModel;
|
||||
use app\api\model\Notify as NotifyModel;
|
||||
use app\api\model\Shop as ShopModel;
|
||||
use app\api\model\Order as OrderModel;
|
||||
use think\cache\driver\Redis;
|
||||
use cores\exception\BaseException;
|
||||
use think\facade\Cache;
|
||||
use think\response\Json;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Psr7\Request;
|
||||
use GuzzleHttp\Cookie\CookieJar;
|
||||
|
||||
/**
|
||||
* 产码控制器
|
||||
* Class Code
|
||||
* @package app\api\controller
|
||||
*/
|
||||
class Code extends Controller
|
||||
{
|
||||
/**
|
||||
* 查询支付状态
|
||||
* @throws \app\common\exception\BaseException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function payStatus()
|
||||
{
|
||||
$data = $this->request->get();
|
||||
$zone = isset($data['zone'])?$data['zone']:1; //订单分区
|
||||
$this->saveLog("进入支付查询");
|
||||
//开始
|
||||
$model = new CodeModel();
|
||||
$orderModel = new OrderModel();
|
||||
$NotifyModel = new NotifyModel();
|
||||
|
||||
$array = $model->getList($zone);
|
||||
|
||||
$this->saveLog("进入支付查询,分区:".$zone.",订单数量:".count($array));
|
||||
//获取IP组
|
||||
$iPGroup = $this->getIPGroup();
|
||||
foreach ($array as $k=>$val) {
|
||||
$payTotal = $orderModel->getZoneOrderTotal([['code_id', '=', $val['code_id']],['order_status', '=', 20]]);
|
||||
$waitPayTotal = $orderModel->getZoneOrderTotal([['code_id', '=', $val['code_id']],['order_status', '=', 10]]);
|
||||
$modelOr = OrderModel::detail([['code_id', '=', $val['code_id']],['order_status', '=', 10]]);
|
||||
$text = $val['passageway'] == 'ZFBH5'?'订单已支付':'该订单已完成支付';
|
||||
if (isset($modelOr['order_id']) && !empty($modelOr['order_id']) && $payTotal <= 0 && $waitPayTotal == 1) {
|
||||
if(isset($iPGroup[0]['ip'])) {
|
||||
$res = $this->checkStatusProxy(htmlspecialchars_decode($val['search_url']), $val['passageway'], $iPGroup[0]['ip'], $iPGroup[0]['port'], $text);
|
||||
}else {
|
||||
$res = $this->checkStatus(htmlspecialchars_decode($val['search_url']), $val['passageway'], $text);
|
||||
}
|
||||
if ($res !== false) { //支付成功
|
||||
$pass = $modelOr['callback'] == 1 ? $NotifyModel->add($modelOr) : true;
|
||||
if ($pass) {
|
||||
$model->update([
|
||||
'order_id' => $modelOr['order_id'],
|
||||
'pay_status' => 1,
|
||||
],['code_id'=>$val['code_id']]);
|
||||
$modelOr->save([
|
||||
'pay_status' => 20,
|
||||
'pay_time' => time(),
|
||||
'order_status' => 20,
|
||||
]);
|
||||
return $this->renderSuccess('操作成功');
|
||||
} else {
|
||||
return $this->renderError($NotifyModel->getError() ?: '操作失败');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->saveLog("支付查询结束,分区:".$zone.",订单数量:".count($array));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询失效状态
|
||||
* @throws \app\common\exception\BaseException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function lapseStatus()
|
||||
{
|
||||
//连接本地的 Redis 服务
|
||||
// 获取分布式锁
|
||||
$lock_key = 'lapseStatus_lock';
|
||||
$max_wait_time = 10; // 最大等待时间(秒)
|
||||
$retry_interval = 100; // 重试间隔时间(毫秒)
|
||||
$lock_ttl = 600; // 锁定时间(秒)
|
||||
$lock_count = 0; // 锁的重试次数
|
||||
// 获取分布式锁
|
||||
$redis = Cache::store('redis');
|
||||
$lock = false;
|
||||
$wait_time = 0;
|
||||
$lock_value = '';
|
||||
while ($wait_time <= $max_wait_time) {
|
||||
$lock_value = uniqid(); // 生成唯一的锁值
|
||||
if ($redis->set($lock_key, $lock_value, 'EX', $lock_ttl, 'NX')) {
|
||||
$lock = true;
|
||||
break;
|
||||
} else {
|
||||
// 获取锁失败,等待一段时间后重试
|
||||
$lock_count++;
|
||||
usleep($retry_interval * 1000);
|
||||
$wait_time += ($retry_interval / 1000);
|
||||
if ($lock_count > 40) {
|
||||
// 重试次数超过限制,抛出异常
|
||||
$this->saveLog("失效查询重试次数超过限制");
|
||||
}
|
||||
}
|
||||
}
|
||||
if($lock) {
|
||||
try {
|
||||
// TODO: 需要加锁的业务逻辑
|
||||
// 字符串操作
|
||||
$conn = new \think\cache\driver\Redis(config('cache.stores.redis'));
|
||||
$codesIp = $conn->get('codesIp');
|
||||
$codesPort = $conn->get('codesPort');
|
||||
$codeNum = $conn->get('codeNum');
|
||||
if (empty($codesIp) || empty($codeNum) || $codeNum <= 0) {
|
||||
//获取IP组
|
||||
$iPGroup = $this->getIPGroup();
|
||||
$codesIp = isset($iPGroup[0]['ip']) ? $iPGroup[0]['ip'] : '';
|
||||
$codesPort = isset($iPGroup[0]['port']) ? $iPGroup[0]['port'] : '';
|
||||
$codeNum = 20;
|
||||
$conn->set('codesIp', $codesIp);
|
||||
$conn->set('codesPort', $codesPort);
|
||||
}
|
||||
$modelOr = new OrderModel();
|
||||
$model = new CodeModel();
|
||||
$this->saveLog("失效查询开始");
|
||||
//非失效码的状态更新
|
||||
$nonFailure = $model->getNonFailure();
|
||||
foreach ($nonFailure as $val) {
|
||||
$codeM = CodeModel::detail($val['code_id']);
|
||||
$create_time = is_numeric($val['create_time']) ? $val['create_time'] : strtotime($val['create_time']);
|
||||
//支付码失效
|
||||
if ($create_time + $val['expiration_time'] < time()) {
|
||||
$codeM->save([
|
||||
'status' => 3,
|
||||
]);
|
||||
//分配时间过长未支付,订单超时,支付码释放
|
||||
} elseif ($val['allot_time'] + 300 < time()) {
|
||||
$text = $val['passageway'] == 'ZFBH5' ? '订单已支付' : '该订单已完成支付';
|
||||
if (!empty($codesIp)) {
|
||||
$conn->set('codeNum', $codeNum - 1);
|
||||
$res = $this->checkStatusProxy(htmlspecialchars_decode($val['search_url']), $val['passageway'], $codesIp, $codesPort, $text);
|
||||
} else {
|
||||
$res = $this->checkStatus(htmlspecialchars_decode($val['search_url']), $val['passageway'], $text);
|
||||
}
|
||||
$status = 1;
|
||||
$pay_status = 0;
|
||||
if ($res !== false) { //已支付 更改状态
|
||||
$status = 3;
|
||||
$pay_status = 1;
|
||||
} else {
|
||||
//重新写入队列左边(为的是后进先出,失败的一般代表比较前面的码,所以放在左边)
|
||||
$code_queue = ['code_id' => (int)$val['code_id'], 'expire_time' => $create_time + (float)$val['expiration_time']]; // 过期时间
|
||||
//先清楚队列再加入,避免重复
|
||||
Cache::store('redis')->lRem($val['passageway'] . '_' . ($val['money'] * 1), json_encode($code_queue, 320), 1);
|
||||
Cache::store('redis')->lPush($val['passageway'] . '_' . ($val['money'] * 1), json_encode($code_queue, 320));
|
||||
$this->saveLog("回码:".json_encode($code_queue, 320));
|
||||
}
|
||||
|
||||
$codeM->save([
|
||||
'allot_time' => 0,
|
||||
'back_time' => time(),
|
||||
'status' => $status,
|
||||
'pay_status' => $pay_status,
|
||||
]);
|
||||
}
|
||||
if ($val['code_id']) {
|
||||
$modelOr->update([
|
||||
'code_id' => 0,
|
||||
'order_status' => 30,
|
||||
'old_code_id' => $val['code_id']
|
||||
], ['code_id' => $val['code_id'],
|
||||
'order_status' => 10]);
|
||||
}
|
||||
}
|
||||
//处理未匹配上码的订单为超时
|
||||
$modelOr->update([
|
||||
'order_status' => 30,
|
||||
], [['code_id', '=', 0],
|
||||
['order_status', '=', 10], ['create_time', '<', time() - 120]]);
|
||||
$this->saveLog("失效查询结束");
|
||||
} finally {
|
||||
// 释放锁
|
||||
$lock_value_in_redis = $redis->get($lock_key);
|
||||
if ($lock_value_in_redis === $lock_value) { // 如果当前锁的值和刚才设置的值相等,则说明当前线程持有该锁,可以进行释放
|
||||
$redis->del($lock_key); // 删除锁
|
||||
}
|
||||
}
|
||||
}
|
||||
//未使用超过调起次数的支付码
|
||||
/*$modelNew = new CodeModel();
|
||||
$modelNew->setStatusLose([],['status' => array('=', 1),
|
||||
'num' => array('>=', 100)]);*/
|
||||
}
|
||||
|
||||
public function getIPGroup(): array
|
||||
{
|
||||
$html = @file_get_contents("http://http.tiqu.letecs.com/getip3?num=1&type=2&pro=&city=0&yys=0&port=1&time=1&ts=0&ys=0&cs=0&lb=1&sb=0&pb=4&mr=1®ions=");
|
||||
$result = json_decode($html,true);
|
||||
$ips = is_array($result['data'])?$result['data']:[];
|
||||
return $ips;
|
||||
}
|
||||
|
||||
public function test(){
|
||||
$data = $this->request->get();
|
||||
$queue_name = $data['passageway'].'_'.$data['money'];
|
||||
$queue_length = Cache::store('redis')->lLen($queue_name);
|
||||
var_dump($queue_length);
|
||||
// 获取队列中的所有值
|
||||
$queue_values = Cache::store('redis')->lRange($queue_name, 0, $queue_length - 1);
|
||||
var_dump($queue_values);
|
||||
die();
|
||||
/*return $this->renderSuccess([], '提交成功');
|
||||
$html = @file_get_contents("http://http.tiqu.letecs.com/getip3?num=1&type=2&pro=&city=0&yys=0&port=1&pack=301270&ts=0&ys=0&cs=0&lb=1&sb=0&pb=4&mr=1®ions=");
|
||||
$result = json_decode($html,true);
|
||||
$ips = $result['data'];
|
||||
var_dump(date("Y-m-d H:i:s"));*/
|
||||
$data = $this->request->get();
|
||||
$order_id = $data['order_id'];
|
||||
var_dump($this->checkQueue($order_id));die();
|
||||
$val = OrderModel::detail($order_id);
|
||||
$codesIp = '';
|
||||
$codesPort = '';
|
||||
//获取IP组
|
||||
$iPGroup = $this->getIPGroup();
|
||||
var_dump($iPGroup);
|
||||
$codesIp = isset($iPGroup[0]['ip'])?$iPGroup[0]['ip']:'';
|
||||
$codesPort = isset($iPGroup[0]['port'])?$iPGroup[0]['port']:'';
|
||||
/*$aa = str_replace("&", "%26", $val['search_url']);
|
||||
$bb = str_replace("amp;", "", $aa);
|
||||
$stream_opts = [
|
||||
"ssl" => [
|
||||
"verify_peer" => false,
|
||||
"verify_peer_name" => false,
|
||||
]
|
||||
];
|
||||
$html = @file_get_contents(urldecode($bb), false, stream_context_create($stream_opts));
|
||||
$res = strpos($html, '该订单已完成支付');*/
|
||||
$text = $val['passageway'] == 'ZFBH5'?'订单已支付':'该订单已完成支付';
|
||||
/*if(!empty($codesIp)) {
|
||||
$res = $this->checkStatusProxy(htmlspecialchars_decode($val['search_url']), $val['passageway'], $codesIp, $codesPort, $text);
|
||||
}else {
|
||||
$res = $this->checkStatus(htmlspecialchars_decode($val['search_url']), $val['passageway'], $text);
|
||||
}*/
|
||||
$res = $this->checkStatusProxy(htmlspecialchars_decode($val['search_url']), $val['passageway'], $codesIp, $codesPort, $text);
|
||||
//$res = $this->checkStatus(htmlspecialchars_decode($val['search_url']));
|
||||
var_dump($res);
|
||||
var_dump(date("Y-m-d H:i:s"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 插入队列判断当前是否可执行
|
||||
* @param $code_id
|
||||
* @return
|
||||
*/
|
||||
public function checkQueue($code_id)
|
||||
{
|
||||
$message = Cache::store('redis')->lPop("queue:$code_id");
|
||||
// 如果队列为空,则写入队列
|
||||
if ($message === null || $message === false) {
|
||||
// 消息内容
|
||||
$message = 1;
|
||||
// 监控客户的消息 Hash
|
||||
Cache::store('redis')->watch("code:$code_id");
|
||||
// 开始事务
|
||||
Cache::store('redis')->multi();
|
||||
// 将消息添加到队列末尾
|
||||
Cache::store('redis')->rPush("queue:$code_id", $message);
|
||||
// 提交事务
|
||||
$result = Cache::store('redis')->exec();
|
||||
if ($result !== null && $result !== false) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkStatus($url,$passageway,$text='该订单已完成支付'){
|
||||
if(in_array($passageway,['WX','SNZFBH5'])){
|
||||
$ch = curl_init();
|
||||
curl_setopt ($ch, CURLOPT_URL, $url);
|
||||
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,10);
|
||||
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt ($ch, CURLOPT_MAXREDIRS, 3);
|
||||
$content = curl_exec($ch);
|
||||
}else {
|
||||
$publicPath = app()->getRootPath() . 'public/';
|
||||
$escaped_url = escapeshellarg($url);
|
||||
$command = "node {$publicPath}myscript.js {$escaped_url} 2>&1";
|
||||
$content = shell_exec($command);
|
||||
}
|
||||
//$res = strpos((string)$content,$text);
|
||||
return (string)$content;
|
||||
}
|
||||
|
||||
public function checkStatusProxy($targetUrl,$passageway,$ip,$port,$text='该订单已完成支付'){
|
||||
if(in_array($passageway,['WX','SNZFBH5'])){
|
||||
// 代理服务器
|
||||
$proxyServer = "http://" . $ip . ":" . $port;
|
||||
// 隧道身份信息
|
||||
$ch = curl_init();
|
||||
|
||||
curl_setopt($ch, CURLOPT_URL, $targetUrl);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false);
|
||||
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
// 设置代理服务器
|
||||
//curl_setopt($ch, CURLOPT_PROXYTYPE, 0); //http
|
||||
|
||||
curl_setopt($ch, CURLOPT_PROXYTYPE, 5); //sock5
|
||||
|
||||
curl_setopt($ch, CURLOPT_PROXY, $proxyServer);
|
||||
|
||||
// 设置隧道验证信息
|
||||
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
|
||||
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727;)");
|
||||
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
|
||||
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
|
||||
|
||||
curl_setopt($ch, CURLOPT_HEADER, true);
|
||||
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
|
||||
$result = curl_exec($ch);
|
||||
|
||||
curl_close($ch);
|
||||
}else{
|
||||
$publicPath = app()->getRootPath() . 'public/';
|
||||
$escaped_url = escapeshellarg($targetUrl);
|
||||
//$command = "node {$publicPath}myscript_proxy.js {$escaped_url} {$ip} {$port} 2>&1";
|
||||
$command = "node {$publicPath}myscript.js {$escaped_url} 2>&1";
|
||||
$result = shell_exec($command);
|
||||
}
|
||||
$res = strpos((string)$result,$text);
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function jysx(){
|
||||
$res = $this->checkStatus('https://t-h5.einrkv.com/qAvYzu2Uraqq/ak7X8TC8Vq6TCkRvtlHzJZE2%252FeIBI0HjIVvQc0IIwXhcng%252FC2I3D0bicsYRpOpUqmtASUp6v7MiNCtPpPPV%2BKgeNvxF%2BQ%252FEXaPT886oB785uqOkFAlj6KDk8hEzwLQ4pjMuZ1xnPeU5fljvX84bwZPx9J%2Bb7nMmsvF2yTahh6FU%3D', 'zfb');
|
||||
var_dump($res);
|
||||
return;
|
||||
$this->saveLog("码校验查询开始");
|
||||
//开始
|
||||
$model = new CodeModel();
|
||||
//连接本地的 Redis 服务
|
||||
$conn = new \Redis(); // 实例化
|
||||
$conn->connect('127.0.0.1','6379');
|
||||
$codepage = $conn->get('codepagejy');
|
||||
$codepage = empty($codepage)?1:$codepage;
|
||||
$array = $model->getSx($codepage);
|
||||
|
||||
$this->saveLog("进入码校验查询,页码:".$codepage.",码数:".count($array));
|
||||
//获取IP组
|
||||
$iPGroup = $this->getIPGroup();
|
||||
foreach ($array as $k=>$val) {
|
||||
$text = $val['passageway'] == 'ZFBH5'?'订单已支付':'该订单已完成支付';
|
||||
if(isset($iPGroup[0]['ip'])) {
|
||||
$res = $this->checkStatusProxy(htmlspecialchars_decode($val['search_url']), $iPGroup[0]['ip'], $iPGroup[0]['port'], $text);
|
||||
}else {
|
||||
$res = $this->checkStatus(htmlspecialchars_decode($val['search_url']), $text);
|
||||
}
|
||||
if ($res !== false) { //支付成功
|
||||
$model->update([
|
||||
'status' => 3,
|
||||
],['code_id'=>$val['code_id']]);
|
||||
}
|
||||
}
|
||||
if(count($array) < 20){
|
||||
$conn->set('codepagejy',1);
|
||||
}else{
|
||||
$conn->set('codepagejy',$codepage+1);
|
||||
}
|
||||
$this->saveLog("码校验查询结束");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user