// +---------------------------------------------------------------------- declare (strict_types=1); 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\store\model\order\QrCode as QrCodeModel; use cores\exception\BaseException; use think\facade\Request; use think\response\Json; use think\facade\Db; use think\db\exception\PDOException; use app\common\service\QueueService; use think\facade\Validate; /** * 用户分油 * Class OilCard * @package app\api\controller\v1_0_0\oil */ class OilCard extends Controller { /** * 用户分油 * @return Json * @throws BaseException * @throws \think\db\exception\DbException */ public function share() { // 获取所有 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.share'){ 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'] ?? ''; $mobile = $data['mobile'] ?? ''; $saleOrderNo = $data['saleOrderNo'] ?? ''; $oilCardType = $data['oilCardType'] ?? ''; // 请求参数orgNo与请求头appKey不存在对应关系 if($partners['orgNo'] != $orgNo){ return $this->oilRenderError('12','0014'); } 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'); } // 未找到卡券对应的信息 $goods = GoodsModel::detail(['goods_no' => $goodsNo, 'oilCardType' => $oilCardType]); if(!$goods){ return $this->oilRenderError('12','2047'); } // 判断商品库存 $detail = GoodsSkuModel::detail($goods['goods_id'], '0'); if (1 > $detail['stock_num']) { return $this->oilRenderError('12','0013', '', "很抱歉,商品 [{$goods['goods_name']}] 平台库存不足"); } $partnersGoods = PartnersGoodsModel::detail($partners['partners_id'], $goods['goods_id']); if(!$partnersGoods || $partnersGoods['stock_num'] <= 0){ return $this->oilRenderError('01','2010'); } $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, ] ]); // 存入队列处理 $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'], ]); } } 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位) $time = (int)(microtime(true) * 1000); // 返回形如 1716544103986 // 拼接一个 4 位随机数 $rand = mt_rand(1000, 9999); 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 * @throws BaseException * @throws \think\db\exception\DbException */ public function getPayQrCode() { // 获取所有 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.pay.qrCode.request'){ 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'] ?? ''; $oilCardNo = $data['oilCardNo'] ?? ''; $oilCardType = $data['oilCardType'] ?? ''; $mobile = $data['mobile'] ?? ''; // 请求参数orgNo与请求头appKey不存在对应关系 if($partners['orgNo'] != $orgNo){ return $this->oilRenderError('12','0014'); } if(!preg_match('/^1[3-9]\d{9}$/', $mobile)) { return $this->oilRenderError('12','0013', '', '手机号格式不正确'); } $order = OrderModel::detail(['oilCardNo' => $oilCardNo]); 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'] . '】'); } $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, // 已使用商品数量 ]); } else { // 错误处理 return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? ''); } } /** * 用户分油记录查询 * @return Json * @throws BaseException * @throws \think\db\exception\DbException */ public function shareList() { // 获取所有 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.shareList'){ 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']; $data['orgNo'] = $data['orgNo'] ?? ''; $data['mobile'] = $data['mobile'] ?? ''; $data['shareNo'] = $data['shareNo'] ?? ''; $data['saleOrderNo'] = $data['saleOrderNo'] ?? ''; $data['beginDate'] = $data['beginDate'] ?? ''; $data['endDate'] = $data['endDate'] ?? ''; $data['pageLimit'] = $data['pageLimit'] ?? 10; $data['pageNum'] = $data['pageNum'] ?? 1; $data['partners_id'] = $partners['partners_id']; // 请求参数orgNo与请求头appKey不存在对应关系 if($partners['orgNo'] != $data['orgNo']){ return $this->oilRenderError('12','0014'); } if(!preg_match('/^1[3-9]\d{9}$/', $data['mobile'])) { return $this->oilRenderError('12','0013', '', '手机号格式不正确'); } $rule = [ 'beginDate' => 'require|dateFormat:Ymd', 'endDate' => 'require|dateFormat:Ymd', 'pageLimit' => 'number|between:1,30', 'pageNum' => 'number|min:1' ]; $message = [ 'beginDate.require' => 'beginDate 不能为空', 'beginDate.dateFormat' => 'beginDate 格式错误,正确格式为 yyyyMMdd', 'endDate.require' => 'endDate 不能为空', 'endDate.dateFormat' => 'endDate 格式错误,正确格式为 yyyyMMdd', 'pageLimit.number' => 'pageLimit 必须是数字', 'pageLimit.between' => 'pageLimit 必须在 1-30 之间', 'pageNum.number' => 'pageNum 必须是数字', 'pageNum.min' => 'pageNum 必须大于等于 1', ]; $validate = Validate::rule($rule)->message($message); if (!$validate->check($data)) { return $this->oilRenderError('12','0013', '', $validate->getError()); } // 检查日期间隔 $begin = date_create_from_format('Ymd', $data['beginDate']); $end = date_create_from_format('Ymd', $data['endDate']); if ($begin > $end) { return $this->oilRenderError('12','0013', '', 'endDate 必须大于或等于 beginDate'); } if ($begin->diff($end)->days > 365) { return $this->oilRenderError('12','0013', '', '日期间隔不能超过 365 天'); } $model = new OrderModel; $list = $model->getList($data); // 组装返回格式 $result = [ 'totalNum' => $list->total(), 'totalPage' => $list->lastPage(), 'pageNum' => $list->currentPage(), 'pageLimit' => $list->listRows(), 'orderList' => array_map(function ($item) { return [ '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'], ]; }, $list->items()) ]; return $this->oilRenderSuccess($result); } else { // 错误处理 return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? ''); } } /** * 订单状态查询 * @return Json * @throws BaseException * @throws \think\db\exception\DbException */ public function orderStatus() { // 获取所有 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.orderStatus'){ 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']; $data['orgNo'] = $data['orgNo'] ?? ''; $data['oilCardNo'] = $data['oilCardNo'] ?? ''; // $data['saleOrderNo'] = $data['saleOrderNo'] ?? ''; // 请求参数orgNo与请求头appKey不存在对应关系 if($partners['orgNo'] != $data['orgNo']){ return $this->oilRenderError('12','0014'); } $rule = [ 'oilCardNo' => 'require', ]; $message = [ 'oilCardNo.require' => 'oilCardNo 不能为空', ]; $validate = Validate::rule($rule)->message($message); if (!$validate->check($data)) { return $this->oilRenderError('12','0013', '', $validate->getError()); } $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'], 'oil_time' => $detail['oil_time'], 'use_status' => $detail['use_status'], 'use_time' => $detail['use_time'], ]; return $this->oilRenderSuccess($result); } else { // 错误处理 return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? ''); } } }