// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\controller; use app\api\model\Goods as GoodsModel; use app\api\model\Order as OrderModel; use app\api\model\OrderGoods as OrderGoodsModel; use app\api\model\Code as CodeModel; use app\api\model\Merchant as MerchantModel; use app\api\model\Setting as SettingModel; use app\common\service\SybOil; use app\common\service\IdingjuOil; use app\store\model\Company as CompanyModel; use app\store\model\Express as ExpressModel; use app\common\enum\order\PayType as OrderPayTypeEnum; use app\store\model\order\QrCode as QrCodeModel; use app\common\model\qyt\Enterprise as EnterpriseModel; use app\common\service\QytOil; use app\api\service\User as UserService; use think\facade\Db; use cores\exception\BaseException; use think\facade\Request; use think\response\Json; use think\cache\driver\Redis; use GatewayWorker\Lib\Gateway; /** * 我的订单控制器 * Class Order * @package app\api\controller */ class Order extends Controller { private $redis = null; /** * 获取当前用户待处理的订单数量 * @return Json * @throws BaseException */ public function todoCounts(): Json { $model = new OrderModel; $counts = $model->getTodoCounts(); return $this->renderSuccess(compact('counts')); } /** * 我的订单列表 * @param string $dataType 订单类型 (all全部 payment待付款 received待发货 deliver待收货 comment待评价) * @return Json * @throws \think\db\exception\DbException * @throws BaseException */ public function list(string $dataType): Json { $model = new OrderModel; $list = $model->getList($dataType); return $this->renderSuccess(compact('list')); } /** * 订单详情信息 * @param int $orderId 订单ID * @return Json * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @throws BaseException */ public function detail(int $orderId): Json { // 订单详情 $model = OrderModel::getUserOrderDetail($orderId); return $this->renderSuccess([ 'order' => $model, // 订单详情 'setting' => [ // 积分名称 'points_name' => SettingModel::getPointsName(), ], ]); } /** * 获取物流信息 * @param int $orderId 订单ID * @return Json * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @throws BaseException */ public function express(int $orderId): Json { // 订单信息 $order = OrderModel::getDetail($orderId); if (!$order['express_no']) { return $this->renderError('没有物流信息'); } // 获取物流信息 $model = ExpressModel::detail($order['express_id']); $express = $model->dynamic($model['express_name'], $model['kuaidi100_code'], $order['express_no']); if ($express === false) { return $this->renderError($model->getError()); } return $this->renderSuccess(compact('express')); } /** * 取消订单 * @param int $orderId * @return Json * @throws BaseException */ public function cancel(int $orderId): Json { $model = OrderModel::getDetail($orderId); if ($model->cancel()) { return $this->renderSuccess('订单取消成功'); } return $this->renderError($model->getError() ?: '订单取消失败'); } /** * 确认收货 * @param int $orderId * @return Json * @throws BaseException */ public function receipt(int $orderId): Json { $model = OrderModel::getDetail($orderId); if ($model->receipt()) { return $this->renderSuccess('确认收货成功'); } return $this->renderError($model->getError()); } /** * 立即支付 * @param int $orderId 订单ID * @param int $payType 支付方式 * @return Json * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @throws BaseException */ public function pay(int $orderId, int $payType = OrderPayTypeEnum::WECHAT): Json { // 获取订单详情 $model = OrderModel::getUserOrderDetail($orderId); // 订单支付事件 if (!$model->onPay($payType)) { return $this->renderError($model->getError() ?: '订单支付失败'); } // 构建微信支付请求 $payment = $model->onOrderPayment($model, $payType); // 支付状态提醒 return $this->renderSuccess([ 'order_id' => $model['order_id'], // 订单id 'pay_type' => $payType, // 支付方式 'payment' => $payment // 微信支付参数 ]); } /** * 提交订单 * @return Json * @throws \think\db\exception\DbException * @throws BaseException */ public function submitOrder(): Json { $data = $this->postData(); $verify = $this->verifySign($data); if($verify['code'] > 0){ return $this->renderError($verify['msg']); }else { $data['merchant_id'] = $verify['merchant_id']; $data['callback'] = $verify['callback']; $model = new OrderModel; $data['order_no'] = $this->insertNo($data['order_no']); $data['ip'] = Request::instance()->ip(); if(!$bool = $model->putInto($data)) { $this->saveLog("提交订单,订单:" . $data['order_no'] . ",数据:".json_encode($data,320).",结果:" . $bool); return $this->renderError('插入订单失败'); } $domain = Request::instance()->domain(); $qrcode = $domain.'/pay?passageway='.$data['passageway'].'&orderId='.$model->order_id; $res = [ 'qrcode'=>$qrcode, ]; return $this->renderSuccess($res, '提交成功'); } } public function generateRandomString($length = 10, $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ') { $charactersLength = strlen($characters); $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, $charactersLength - 1)]; } return $randomString; } /** * 查询订单 * @return Json * @throws \think\db\exception\DbException * @throws BaseException */ public function searchOrder(): Json { $data = $this->postData(); $verify = $this->verifySign($data); if($verify['code'] > 0){ return $this->renderError($verify['msg']); }else { $order = OrderModel::detail(['order_no'=>$data['order_no']]); if(empty($order['order_id'])){ return $this->renderError('订单错误'); } $res = [ 'order_no'=>$order['order_no'], 'pay_status'=>$order['pay_status'], 'pay_time'=>$order['pay_time'] ]; return $this->renderSuccess($res, '提交成功'); } } /** * 提交订单 * @return * @throws \app\common\exception\BaseException * @throws \think\exception\DbException * @throws \Exception */ public function testOrder() { $data = $this->request->get(); $money = isset($data['money'])?$data['money']:299; $passageway = isset($data['passageway'])?$data['passageway']:'WX'; $shop_id = isset($data['shop_id'])?$data['shop_id']:''; $merchant = MerchantModel::detail($shop_id); if(empty($merchant['merchant_id'])){ return $this->renderError('商户不存在'); } $domain = Request::instance()->domain(); $ip = Request::instance()->ip(); $data = [ 'appid'=>$merchant['appId'], 'name'=>'系统订单', 'money'=>$money, 'order_no'=> 'XT'.$this->generateRandomString(10), 'timestamp'=>time(), 'passageway'=>$passageway, 'notifyUrl'=>$domain.'/index.php?s=/api/notify/received', 'ip'=>$ip, ]; $data['merchant_id'] = $merchant['merchant_id']; $data['shop_id'] = 10033; $model = new OrderModel; $data['order_no'] = $this->insertNo($data['order_no']); if(!$bool = $model->putInto($data)) { $this->saveLog("提交订单,订单:" . $data['order_no'] . ",数据:".json_encode($data,320).",结果:" . $bool); return $this->renderError('插入系统订单失败'); } $domain = Request::instance()->domain(); $qrcode = $domain.'/pay?passageway='.$data['passageway'].'&orderId='.$model->order_id; /*$qrcode = $domain.'/index.php?s=/store/passport/detail&orderId='.$model->order_id; return $qrcode;*/ header('location: '.$qrcode.''); exit(); } /** 测试发送数据 */ public function send() { //Gateway::sendToClient("7f00000107d00000001b", json_encode(['type' => 'test_send'])); var_export(Gateway::getAllUidList()); //Gateway::sendToClient('c0a8008a07d000000002',json_encode(['type' => 'test_send'])); if(Gateway::isUidOnline(10001)) { // 在线就转发消息给对应的uid Gateway::sendToUid(10001, json_encode(['type' => 'test_send'])); } var_export(Gateway::isUidOnline(10001)); //Gateway::sendToUid('10001', json_encode(['type' => 'test_send'])); //return $this->renderSuccess([], '提交成功'); } /** * 获取支付二维码 * @return Json * @throws \think\db\exception\DbException */ public function qrCode(): Json { $orderGoodsId = (int)$this->request->param('orderGoodsId'); [$order, $error] = $this->findOilOrder($orderGoodsId); if ($error !== '') { return $this->renderError($error); } // 免登链接要带本单企业的 creditcode(营业执照号),把登录固定到该企业 $enterprise = EnterpriseModel::detail((int)$order['qyt_enterprise_id']); if (!$enterprise) { return $this->renderError('本单绑定的企油通企业不存在,无法获取加油地址'); } if ($enterprise['status'] !== 'approved') { return $this->renderError('企业尚未通过企油通审核,暂时无法加油'); } $h5Url = QytOil::forEnterprise($enterprise)->h5Url((string)$order['mobile']); if (!$h5Url) { return $this->renderError('获取加油地址失败,请稍后重试'); } // 留痕 (new QrCodeModel())->add([ 'oilCardNo' => $order['oilCardNo'], 'qrCode' => $h5Url, 'amount' => $order['goods_price'], 'order_id' => (int)$order['mall_order_id'], 'user_id' => (int)$order['user_id'], 'store_id' => (int)$order['store_id'], ]); return $this->renderSuccess(['qrCode' => $h5Url], '提交成功'); } /** * 按订单商品行找到对应的企油通发放单,并校验是否还能加油 * * 小程序单在支付成功后由 MallOil::create 建了一条 yoshop_partners_order * (source='mall',mall_order_goods_id 指回这里的订单商品行)。 * * @param int $orderGoodsId * @return array [发放单, 错误信息] * @throws BaseException */ private function findOilOrder(int $orderGoodsId): array { if ($orderGoodsId <= 0) { return [null, '缺少参数 orderGoodsId']; } $userId = (int)UserService::getCurrentLoginUserId(); $orderGoods = Db::name('order_goods')->where('order_goods_id', '=', $orderGoodsId)->find(); if (!$orderGoods) { return [null, '未找到订单商品']; } // 越权校验:只能取自己订单的加油地址 if ((int)$orderGoods['user_id'] !== $userId) { return [null, '未找到订单商品']; } $order = Db::name('partners_order') ->where('source', '=', 'mall') ->where('mall_order_goods_id', '=', $orderGoodsId) ->find(); if (!$order) { return [null, '该订单还没有发放记录']; } if ((int)$order['oil_status'] !== 1) { return [null, '油费还在发放中,请稍后再试']; } if ((int)$order['refund_status'] === 2) { return [null, '该订单已退款,不能再加油']; } // 一单可以分多次加油:没加完的单继续给加油地址 if ((float)$order['used_amount'] + 0.005 >= (float)$order['total_price']) { return [null, '该订单金额已全部加油']; } return [$order, '']; } /** * 获取支付二维码图片 * @return Json * @throws \think\db\exception\DbException */ public function qrCodeImg(): Json { // 企油通给的是 H5 免登链接,没有二维码图片接口。 // 本商城跑在 H5(微信内置浏览器)下,走的是 qrCode + webview; // 本方法只在微信小程序环境下被调用,暂不支持。 return $this->renderError('请在微信或浏览器中打开加油链接'); } public function getBase64($url){ $publicPath = app()->getRootPath() . 'public/'; $escaped_url = escapeshellarg($url); $command = "node {$publicPath}myscript.js {$escaped_url} 2>&1"; $content = shell_exec($command); return (string)$content; } }