410 lines
14 KiB
PHP
410 lines
14 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\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;
|
||
}
|
||
}
|