586 lines
26 KiB
PHP
586 lines
26 KiB
PHP
<?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\controller\Controller;
|
||
use app\api\model\partners\Order as OrderModel;
|
||
use app\common\model\Partners as PartnersModel;
|
||
use app\common\crypto\RsaUtil;
|
||
use app\common\service\PartnersBalance;
|
||
use app\common\model\qyt\Enterprise as EnterpriseModel;
|
||
use app\common\service\QytDriver;
|
||
use app\common\service\QytOil;
|
||
use app\common\service\QytRefund;
|
||
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'] ?? '';
|
||
$amount = $data['amount'] ?? '';
|
||
$mobile = $data['mobile'] ?? '';
|
||
$saleOrderNo = $data['saleOrderNo'] ?? '';
|
||
$oilCardType = $data['oilCardType'] ?? '';
|
||
// 企油通:司机姓名(下单平台必传,用于运单油费下发)
|
||
$driverName = trim((string)($data['name'] ?? ''));
|
||
// 企油通:司机身份证号。两个支付通道都要求实名,必传
|
||
$idCard = strtoupper(trim((string)($data['idCard'] ?? '')));
|
||
// 请求参数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', '', '手机号格式不正确');
|
||
}
|
||
if($driverName === ''){
|
||
return $this->oilRenderError('12','0001', '', '缺少必填请求参数 name(司机姓名)');
|
||
}
|
||
// 解析本单使用的企油通企业:合作商绑定的企业 -> 默认企业
|
||
$enterprise = EnterpriseModel::resolve((int)$partners['qyt_enterprise_id']);
|
||
if(!$enterprise){
|
||
$this->saveLog('share 未匹配到可用的企油通企业,partners_id=' . $partners['partners_id']);
|
||
return $this->oilRenderError('99','9999', '', '系统未配置可用企业,请联系平台');
|
||
}
|
||
// 身份证号:两个支付通道都要求实名,必传且必须合法
|
||
if($idCard === ''){
|
||
return $this->oilRenderError('12','0001', '', '缺少必填请求参数 idCard(司机身份证号)');
|
||
}
|
||
if(!preg_match('/^\d{17}[\dX]$/', $idCard)){
|
||
return $this->oilRenderError('12','0013', '', 'idCard 身份证号格式不正确(18位)');
|
||
}
|
||
// 金额:由下单平台直接传入(单位:元,最多两位小数)
|
||
if($amount === '' || !preg_match('/^\d{1,8}(\.\d{1,2})?$/', (string)$amount) || (float)$amount <= 0){
|
||
return $this->oilRenderError('12','0013', '', 'amount 金额格式不正确(单位:元,最多两位小数且大于0)');
|
||
}
|
||
$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'],
|
||
]);
|
||
}
|
||
// 额度管控:先原子扣减合作商余额(余额不足直接拒单,防并发超扣)
|
||
$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();
|
||
try {
|
||
$created = $OrderModel->saveOrder([
|
||
'mobile' => $mobile,
|
||
'driver_name' => $driverName,
|
||
'id_card' => $idCard,
|
||
// 企业与通道随单固化:之后改绑定或切默认企业,在途单仍按下单时的企业发放
|
||
'qyt_enterprise_id' => $enterprise['enterprise_id'],
|
||
'passageway' => $enterprise['passageway'],
|
||
'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);
|
||
// 司机档案(按身份证号归档并标记信息冲突;内部吞异常,不影响建单)
|
||
QytDriver::touch([
|
||
'order_id' => $OrderModel->order_id,
|
||
'id_card' => $idCard,
|
||
'driver_name' => $driverName,
|
||
'mobile' => $mobile,
|
||
'store_id' => $this->storeId,
|
||
]);
|
||
// 存入队列处理
|
||
$queueService = new QueueService();
|
||
$queueService->push('partners_queue', json_encode(['order_id'=>$OrderModel->order_id],320));
|
||
|
||
return $this->oilRenderSuccess([
|
||
'oilCardNo' => $oilCardNo,
|
||
'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'] ?? '');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 订单退款(整单全额)
|
||
* 企油通侧:7.17 查司机支付凭证 -> 7.16 按订单金额调低额度;成功后回补合作商余额,并推送油卡变动通知(optType=refund)
|
||
* @return Json
|
||
*/
|
||
public function refund()
|
||
{
|
||
$headers = Request::header();
|
||
$data = json_decode(Request::instance()->getContent(), true);
|
||
$appKey = $headers['appkey'] ?? '';
|
||
$requestId = $headers['requestid'] ?? '';
|
||
$method = $headers['method'] ?? '';
|
||
if($method != 'syb.oil.oilCard.refund'){
|
||
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') {
|
||
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
|
||
}
|
||
$body = $result['data'];
|
||
if($partners['orgNo'] != ($body['orgNo'] ?? '')){
|
||
return $this->oilRenderError('12','0014');
|
||
}
|
||
$oilCardNo = trim((string)($body['oilCardNo'] ?? ''));
|
||
if($oilCardNo === ''){
|
||
return $this->oilRenderError('12','0001', '', '缺少必填请求参数 oilCardNo');
|
||
}
|
||
$reason = mb_substr(trim((string)($body['reason'] ?? '')), 0, 100);
|
||
|
||
// 只能退自己的订单
|
||
$order = OrderModel::detail(['oilCardNo' => $oilCardNo, 'partners_id' => $partners['partners_id']]);
|
||
if(!$order){
|
||
return $this->oilRenderError('01','2036');
|
||
}
|
||
|
||
$res = QytRefund::apply((int)$order['order_id'], 'api', (string)$appKey, $reason);
|
||
// 已退款(含重复调用的幂等返回)或结果确认中:都按受理成功返回,由 refundStatus 区分
|
||
// 确认中说明 7.16 已发出、上游可能已调额,不能告诉下游「失败」让它重试
|
||
if ($res['ok'] || $res['status'] === QytRefund::CONFIRM) {
|
||
return $this->oilRenderSuccess($res['data'], '00', $res['message']);
|
||
}
|
||
switch ($res['reason']) {
|
||
case QytRefund::REASON_NOT_FOUND:
|
||
return $this->oilRenderError('01', '2036', '', $res['message']);
|
||
case QytRefund::REASON_PROCESSING:
|
||
return $this->oilRenderError('01', '2032', '', $res['message']);
|
||
case QytRefund::REASON_STATE:
|
||
return $this->oilRenderError('01', '2048', '', $res['message']);
|
||
default:
|
||
return $this->oilRenderError('01', '2049', '', $res['message']);
|
||
}
|
||
}
|
||
|
||
public static function createOrderNo(): string
|
||
{
|
||
// 获取当前时间戳到毫秒(13位)
|
||
$time = (int)(microtime(true) * 1000); // 返回形如 1716544103986
|
||
|
||
// 拼接一个 4 位随机数
|
||
$rand = mt_rand(1000, 9999);
|
||
|
||
return (string)($time . $rand); // 拼接成纯数字字符串
|
||
}
|
||
|
||
/**
|
||
* 付款二维码申请
|
||
* @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', '', '未找到对应订单');
|
||
}
|
||
// 企油通:生成司机免登加油 H5 地址(7.15)。出参 qrCode 结构不变,值由二维码链接改为 H5 URL。
|
||
// creditcode 取本单固化的企业,把登录固定到该企业;企业须已通过企油通审核
|
||
$orderEnterprise = EnterpriseModel::detail((int)$order['qyt_enterprise_id']);
|
||
if(!$orderEnterprise){
|
||
return $this->oilRenderError('12','0013', '', '本单绑定的企业不存在,无法生成加油链接');
|
||
}
|
||
$h5Url = QytOil::forEnterprise($orderEnterprise)->h5Url($order['mobile']);
|
||
if(!$h5Url){
|
||
return $this->oilRenderError('12','0013', '', '生成加油链接失败');
|
||
}
|
||
// 插入申请记录(留痕)
|
||
$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'] ?? '');
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 用户分油记录查询
|
||
* @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'],
|
||
'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'], 'partners_id' => $partners['partners_id']]);
|
||
if(!$detail){
|
||
return $this->oilRenderError('01','2036');
|
||
}
|
||
// 组装返回格式
|
||
$result = [
|
||
'mobile' => $detail['mobile'],
|
||
'oilCardNo' => $detail['oilCardNo'],
|
||
'shareNo' => $detail['shareNo'],
|
||
'saleOrderNo' => $detail['partners_order_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'],
|
||
// 一单可多次加油:已加油金额 / 加油次数 / 剩余可加油(即可退)金额
|
||
'used_amount' => number_format((float)$detail['used_amount'], 2, '.', ''),
|
||
'used_num' => (int)$detail['used_num'],
|
||
'remain_amount' => number_format(max(0, (float)$detail['total_price'] - (float)$detail['used_amount']
|
||
- ((int)$detail['refund_status'] === 2 ? (float)$detail['refund_amount'] : 0)), 2, '.', ''),
|
||
// 退款:0未退款 1退款中 2已退款 3退款失败 4退款结果确认中
|
||
'refund_status' => (int)$detail['refund_status'],
|
||
'refund_amount' => number_format((float)$detail['refund_amount'], 2, '.', ''),
|
||
'refund_time' => $detail['refund_time'] ? date('Y-m-d H:i:s', (int)$detail['refund_time']) : '',
|
||
];
|
||
return $this->oilRenderSuccess($result);
|
||
} else {
|
||
// 错误处理
|
||
return $this->oilRenderError($result['code'], $result['errCode'], '', $result['errMessage'] ?? '');
|
||
}
|
||
}
|
||
}
|