第一次更新,完成了初版调整

This commit is contained in:
2026-09-07 22:05:51 +08:00
parent b5a26a8848
commit 4d6a7e7aac
198 changed files with 6142 additions and 3856 deletions
+72 -189
View File
@@ -15,13 +15,9 @@ namespace app\api\controller;
use app\api\controller\Controller;
use app\api\model\partners\Order as OrderModel;
use app\common\model\Partners as PartnersModel;
use app\common\model\PartnersGoods as PartnersGoodsModel;
use app\common\model\Goods as GoodsModel;
use app\api\model\GoodsSku as GoodsSkuModel;
use app\common\crypto\RsaUtil;
use app\common\service\goods\source\Factory as StockFactory;
use app\common\service\IdingjuOil;
use app\store\model\Company as CompanyModel;
use app\common\service\PartnersBalance;
use app\common\service\QytOil;
use app\store\model\order\QrCode as QrCodeModel;
use cores\exception\BaseException;
use think\facade\Request;
@@ -83,10 +79,12 @@ class OilCard extends Controller
// 业务处理
$data = $result['data'];
$orgNo = $data['orgNo'] ?? '';
$goodsNo = $data['goodsNo'] ?? '';
$amount = $data['amount'] ?? '';
$mobile = $data['mobile'] ?? '';
$saleOrderNo = $data['saleOrderNo'] ?? '';
$oilCardType = $data['oilCardType'] ?? '';
// 企油通:司机姓名(下单平台必传,用于运单油费下发)
$driverName = trim((string)($data['name'] ?? ''));
// 请求参数orgNo与请求头appKey不存在对应关系
if($partners['orgNo'] != $orgNo){
return $this->oilRenderError('12','0014');
@@ -94,78 +92,80 @@ class OilCard extends Controller
if(!preg_match('/^1[3-9]\d{9}$/', $mobile)) {
return $this->oilRenderError('12','0013', '', '手机号格式不正确');
}
// 销售平台订单号重复
$order = OrderModel::detail(['partners_id' => $partners['partners_id'], 'partners_order_no' => $saleOrderNo]);
if($order){
return $this->oilRenderError('12','2023');
if($driverName === ''){
return $this->oilRenderError('12','0001', '', '缺少必填请求参数 name(司机姓名)');
}
// 未找到卡券对应的信息
$goods = GoodsModel::detail(['goods_no' => $goodsNo, 'oilCardType' => $oilCardType]);
if(!$goods){
return $this->oilRenderError('12','2047');
// 金额:由下单平台直接传入(单位:元,最多两位小数)
if($amount === '' || !preg_match('/^\d{1,8}(\.\d{1,2})?$/', (string)$amount) || (float)$amount <= 0){
return $this->oilRenderError('12','0013', '', 'amount 金额格式不正确(单位:元,最多两位小数且大于0)');
}
// 判断商品库存
$detail = GoodsSkuModel::detail($goods['goods_id'], '0');
if (1 > $detail['stock_num']) {
return $this->oilRenderError('12','0013', '', "很抱歉,商品 [{$goods['goods_name']}] 平台库存不足");
$amount = round((float)$amount, 2);
// 销售平台订单号幂等:已存在则返回原订单结果(发放失败态除外)
$exist = OrderModel::detail(['partners_id' => $partners['partners_id'], 'partners_order_no' => $saleOrderNo]);
if($exist){
if((int)$exist['oil_status_zsy'] === 3){
return $this->oilRenderError('12','2023','','该销售订单号已提交且发放失败,请使用新订单号');
}
return $this->oilRenderSuccess([
'oilCardNo' => $exist['oilCardNo'],
'amount' => $exist['total_price'],
]);
}
$partnersGoods = PartnersGoodsModel::detail($partners['partners_id'], $goods['goods_id']);
if(!$partnersGoods || $partnersGoods['stock_num'] <= 0){
return $this->oilRenderError('01','2010');
// 额度管控:先原子扣减合作商余额(余额不足直接拒单,防并发超扣)
$balanceLogId = PartnersBalance::deduct((int)$partners['partners_id'], (float)$amount, $saleOrderNo, 0, (int)$this->storeId);
if ($balanceLogId === false) {
return $this->oilRenderError('01','2028', '', '合作商余额不足,请先充值');
}
$OrderModel = new OrderModel();
$oilCardNo = 'OIL' . self::createOrderNo();
if($OrderModel->saveOrder([
'province' => $goods['province'],
'mobile' => $mobile,
'oilCardType' => $oilCardType,
'oilCardNo' => $oilCardNo,
'partners_order_no' => $saleOrderNo,
'partners_id' => $partners['partners_id'],
'goods_id' => $goods['goods_id'],
'goods_name' => $goods['goods_name'],
'goods_no' => $goods['goods_no'],
'goods_price' => $goods['goods_price_min'],
'total_num' => 1,
'total_price' => $goods['goods_price_min'],
'total_pay_price' => $goods['goods_price_min'],
'store_id' => $this->storeId,
])){
// 更新商品库存 (针对下单减库存的商品)
$this->updateGoodsStockNum([
[
'deduct_stock_type' => 10,
'goods_id' => $goods['goods_id'],
'goods_sku_id' => $detail['id'],
'total_num' => 1,
]
try {
$created = $OrderModel->saveOrder([
'mobile' => $mobile,
'driver_name' => $driverName,
'oilCardType' => $oilCardType,
'oilCardNo' => $oilCardNo,
'partners_order_no' => $saleOrderNo,
'partners_id' => $partners['partners_id'],
'goods_price' => $amount,
'total_num' => 1,
'total_price' => $amount,
'total_pay_price' => $amount,
'store_id' => $this->storeId,
]);
} catch (\Throwable $e) {
// 建单失败 -> 回补刚扣减的余额
PartnersBalance::refund((int)$partners['partners_id'], (float)$amount, $saleOrderNo, 0, (int)$this->storeId);
// 并发下 (partners_id, partners_order_no) 唯一键冲突 -> 幂等返回已存在订单
if (strpos($e->getMessage(), 'Duplicate') !== false) {
$again = OrderModel::detail(['partners_id' => $partners['partners_id'], 'partners_order_no' => $saleOrderNo]);
if ($again) {
return $this->oilRenderSuccess(['oilCardNo' => $again['oilCardNo'], 'amount' => $again['total_price']]);
}
}
$this->saveLog('share saveOrder 异常:' . $e->getMessage());
return $this->oilRenderError('99', '9999');
}
if($created){
// 回填流水的订单ID(建单前尚不知 order_id)
PartnersBalance::bindOrder($balanceLogId, (int)$OrderModel->order_id);
// 存入队列处理
$queueService = new QueueService();
$queueService->push('partners_queue', json_encode(['order_id'=>$OrderModel->order_id],320));
return $this->oilRenderSuccess([
'oilCardNo' => $oilCardNo,
'amount' => $goods['goods_price_min'],
'amount' => $amount,
]);
}
// 未建单成功 -> 回补余额
PartnersBalance::refund((int)$partners['partners_id'], (float)$amount, $saleOrderNo, 0, (int)$this->storeId);
return $this->oilRenderError('99', '9999');
} else {
// 错误处理
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
}
}
/**
* 更新商品库存 (针对下单减库存的商品)
* @param $order
* @return void
*/
private function updateGoodsStockNum($goodsList): void
{
StockFactory::getFactory(10)->updateGoodsStock($goodsList);
}
public static function createOrderNo(): string
{
// 获取当前时间戳到毫秒(13位)
@@ -177,36 +177,6 @@ class OilCard extends Controller
return (string)($time . $rand); // 拼接成纯数字字符串
}
/**
* @param $goodsNo
* @return string
*/
public function getCompany($goodsNo): string
{
switch ($goodsNo) {
case 'djgdface100':
case 'djgdface200':
case 'djgdface300':
return 'umQZhIHKofyA';
case 'jmgxyyface100':
case 'jmgxyyface200':
case 'jmgxyyface300':
case 'jmgzface100':
case 'jmgzface200':
case 'jmgzface300':
case 'jmfjface100':
case 'jmfjface200':
case 'jmfjface300':
return 'HpWqXIgYvTBg';
case 'face003':
return 'NKJBgaaRNdiL'; // 测试参数
default:
return '';
}
}
/**
* 付款二维码申请
* @return Json
@@ -266,105 +236,22 @@ class OilCard extends Controller
if(!$order) {
return $this->oilRenderError('12','0013', '', '未找到对应订单');
}
$company = CompanyModel::detail(['orgNo' => $this->getCompany($order['goods_no'])]);
if (!$company) {
return $this->oilRenderError('12','0013', '', '没有可用参数:【' . $order['goods_no'] . '】');
// 企油通:生成司机免登加油 H5 地址(7.15)。出参 qrCode 结构不变,值由二维码链接改为 H5 URL。
$h5Url = (new QytOil())->h5Url($order['mobile']);
if(!$h5Url){
return $this->oilRenderError('12','0013', '', '生成加油链接失败');
}
$IdingjuOil = new IdingjuOil();
// 对接平台接口
$res = $IdingjuOil->payQrCodeRequest(['order_no'=>$oilCardNo], $company);
if(isset($res['code']) && $res['code'] == '1' && isset($res['data']['useQrCodeUrl'])){
// 插入支付码记录
$QrCodeModel = new QrCodeModel();
$QrCodeModel->add([
'oilCardNo'=>$order['oilCardNo'],
'qrCode'=>$res['data']['useQrCodeUrl'],
'amount'=>$order['goods_price'],
'order_id'=>$order['order_id'],
'user_id'=>0,
'store_id'=>$order['store_id'],
]);
return $this->oilRenderSuccess([
'qrCode'=>$res['data']['useQrCodeUrl']
]);
}else{
return $this->oilRenderError('12','0013', '', $res['message'] ?? '');
}
} else {
// 错误处理
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
}
}
/**
* 油券库存查询
* @return Json
* @throws BaseException
* @throws \think\db\exception\DbException
*/
public function stock()
{
// 获取所有 HTTP 请求头
$headers = Request::header();
// 获取 JSON 格式的请求体
$jsonData = Request::instance()->getContent();
$data = json_decode($jsonData, true);
$appKey = $headers['appkey'] ?? '';
$requestId = $headers['requestid'] ?? '';
$method = $headers['method'] ?? '';
// 请求头METHOD参数不正确
if($method != 'syb.oil.oilCard.stockList'){
return $this->oilRenderError('12', '0005');
}
try {
Db::name('request_log')->insert([
'request_id' => $requestId,
'app_key' => $appKey,
'create_time' => time()
]);
} catch (\think\Exception $e) {
// 判断是否唯一索引冲突
if (strpos($e->getMessage(), 'Duplicate entry') !== false) {
return $this->oilRenderError('12', '0012'); // 请求流水号重复
}
// 其他数据库异常
return $this->oilRenderError('99', '9999'); // 未知错误
}
$partners = PartnersModel::detail(['appKey' => $appKey]);
if(!$partners){
return $this->oilRenderError('02','0004');
}
$crypto = new RsaUtil($partners);
$result = $crypto->processResponse(['header'=>$headers,'encryptData'=>$data]);
if ($result['code'] === '00') {
// 业务处理
$data = $result['data'];
$orgNo = $data['orgNo'] ?? '';
$goodsNo = $data['goodsNo'] ?? '';
// 请求参数orgNo与请求头appKey不存在对应关系
if($partners['orgNo'] != $orgNo){
return $this->oilRenderError('12','0014');
}
// 未找到卡券对应的信息
$goods = GoodsModel::detail(['goods_no' => $goodsNo]);
if(!$goods){
return $this->oilRenderError('12','2047');
}
$partnersGoods = PartnersGoodsModel::detail($partners['partners_id'], $goods['goods_id']);
if(!$partnersGoods){
return $this->oilRenderError('01','2010');
}
$orderModel = new OrderModel();
$sucNum = $orderModel->getCount(['partners_id' => $partners['partners_id'], 'goods_id' => $goods['goods_id']], 'all');
$useNum = $orderModel->getCount(['partners_id' => $partners['partners_id'], 'goods_id' => $goods['goods_id']], 'used');
return $this->oilRenderSuccess([
'goodsNo'=>$goods['goods_no'], // 商品编号
'canOrderNum'=>$partnersGoods['stock_num'], // 剩余可下单数量
'unUseNum'=>floatval($sucNum) - floatval($useNum), // 未使用商品数量
'useNum'=>$useNum, // 已使用商品数量
// 插入申请记录(留痕)
$QrCodeModel = new QrCodeModel();
$QrCodeModel->add([
'oilCardNo'=>$order['oilCardNo'],
'qrCode'=>$h5Url,
'amount'=>$order['goods_price'],
'order_id'=>$order['order_id'],
'user_id'=>0,
'store_id'=>$order['store_id'],
]);
return $this->oilRenderSuccess(['qrCode'=>$h5Url]);
} else {
// 错误处理
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
@@ -478,7 +365,6 @@ class OilCard extends Controller
'shareNo' => $item['shareNo'],
'mobile' => $item['mobile'],
'oilCardNo' => $item['oilCardNo'],
'productName' => $item['goods_name'],
'num' => $item['total_num'],
'amount' => $item['total_price'],
'createTime' => $item['create_time'],
@@ -561,13 +447,10 @@ class OilCard extends Controller
$detail = OrderModel::detail(['oilCardNo' => $data['oilCardNo']]);
// 组装返回格式
$result = [
'province' => $detail['province'],
'mobile' => $detail['mobile'],
'oilCardNo' => $detail['oilCardNo'],
'shareNo' => $detail['shareNo'],
'saleOrderNo' => $detail['partners_order_no'],
'goods_name' => $detail['goods_name'],
'goods_no' => $detail['goods_no'],
'total_price' => $detail['total_price'],
'oil_status_zsy' => $detail['oil_status_zsy'],
'oil_status' => $detail['oil_status'],