diff --git a/Server/application/ai/controller/DouBaoAI.php b/Server/application/ai/controller/DouBaoAI.php index e7a50646..5cb71a3b 100644 --- a/Server/application/ai/controller/DouBaoAI.php +++ b/Server/application/ai/controller/DouBaoAI.php @@ -4,15 +4,18 @@ namespace app\ai\controller; use app\common\util\JwtUtil; use think\facade\Env; +use think\Controller; -class DouBaoAI +class DouBaoAI extends Controller { protected $apiUrl; protected $apiKey; protected $headers; - public function __init() + public function __construct() { + parent::__construct(); + $this->apiUrl = Env::get('doubaoAi.api_url'); $this->apiKey = Env::get('doubaoAi.api_key'); @@ -31,7 +34,7 @@ class DouBaoAI public function text($params = []) { - $this->__init(); + if (empty($params)){ return json_encode(['code' => 500, 'msg' => '提示词缺失']); } diff --git a/Server/application/common/controller/Attachment.php b/Server/application/common/controller/Attachment.php index 68659283..7a2973bf 100644 --- a/Server/application/common/controller/Attachment.php +++ b/Server/application/common/controller/Attachment.php @@ -28,7 +28,7 @@ class Attachment extends Controller $validate = \think\facade\Validate::rule([ 'file' => [ 'fileSize' => 10485760, // 10MB - 'fileExt' => 'jpg,jpeg,png,gif,doc,docx,pdf,zip,rar,mp4,mp3,csv,xlsx,xls,ppt,pptx', + 'fileExt' => 'jpg,jpeg,png,gif,doc,docx,pdf,zip,rar,mp4,mp3,csv,xlsx,xls,ppt,pptx,txt', ] ]); diff --git a/Server/application/common/controller/GetOpenid.php b/Server/application/common/controller/GetOpenid.php new file mode 100644 index 00000000..b33c81de --- /dev/null +++ b/Server/application/common/controller/GetOpenid.php @@ -0,0 +1,52 @@ + Env::get('weChat.appid'), + 'secret' => Env::get('weChat.secret'), + 'response_type' => 'array' + ]; + $this->app = Factory::officialAccount($config); + } + + + + public function index() + { + $app = $this->app; + $oauth = $app->oauth; + + // 未登录 + if (empty($_SESSION['wechat_user'])) { + + $_SESSION['target_url'] = 'user/profile'; + + $redirectUrl = $oauth->redirect(); + + exit_data($redirectUrl); + header("Location: {$redirectUrl}"); + exit; + } + + // 已经登录过 + $user = $_SESSION['wechat_user']; + + exit_data($user); + + return 'Hello, World!'; + } + +} \ No newline at end of file diff --git a/Server/application/common/controller/PaymentService.php b/Server/application/common/controller/PaymentService.php index 3d4f31eb..60e5385b 100644 --- a/Server/application/common/controller/PaymentService.php +++ b/Server/application/common/controller/PaymentService.php @@ -16,38 +16,74 @@ use app\common\model\Order; class PaymentService { /** - * 下单 + * 统一支付下单接口 + * 支持扫码付款、微信支付、支付宝支付 * * @param array $order - * - out_trade_no: string 商户订单号(必填) - * - total_fee: int 金额(分,必填) - * - body: string 商品描述(必填) - * - notify_url: string 异步通知地址(可覆盖配置) - * - attach: string 附加数据(可选) - * - time_expire: string 订单失效时间(可选) - * - client_ip: string 终端IP(可选) - * - sign_type: string MD5/RSA_1_256/RSA_1_1(可选,默认MD5) - * - pay_type: string 支付场景,如 JSAPI/APP/H5(可选) - * @return array - * @throws \Exception + * - orderNo: string 商户订单号(必填) + * - money: int 金额(分,必填) + * - goodsName: string 商品描述(必填) + * - service: string 支付服务类型(可选) + * - 'wechat' 或 'pay.weixin.jspay': 微信JSAPI支付 + * - 'alipay' 或 'pay.alipay.jspay': 支付宝JSAPI支付 + * - 不传或空: 默认扫码付款 + * - openid: string 微信用户openid(微信JSAPI支付必填) + * - buyer_id: string 支付宝用户ID(支付宝JSAPI支付可选) + * - notify_url: string 异步通知地址(可选) + * @return string JSON格式响应 */ public function createOrder(array $order) { + // 确定service类型:支持简写形式 wechat/alipay,或完整的 service 值 + $serviceType = $order['service'] ?? ''; + + // 映射简写形式到完整的 service 值 + if ($serviceType === 'wechat' || $serviceType === 'pay.weixin.jspay') { + $service = 'pay.weixin.jspay'; + } elseif ($serviceType === 'alipay' || $serviceType === 'pay.alipay.jspay') { + $service = 'pay.alipay.jspay'; + } elseif ($serviceType === 'qrCode' || $serviceType === 'unified.trade.native') { + $service = 'unified.trade.native'; + } else { + // 默认扫码支付 + $service = 'unified.trade.native'; + } + + // 构建基础参数 $params = [ - 'service' => 'unified.trade.native', + 'service' => $service, 'sign_type' => PaymentUtil::SIGN_TYPE_MD5, 'mch_id' => Env::get('payment.mchId'), 'out_trade_no' => $order['orderNo'], 'body' => $order['goodsName'] ?? '', 'total_fee' => $order['money'] ?? 0, 'mch_create_ip' => Request::ip(), - 'notify_url' => Env::get('payment.notify_url', '127.0.0.1'), + 'notify_url' => $order['notify_url'] ?? Env::get('payment.notify_url', '127.0.0.1'), 'nonce_str' => PaymentUtil::generateNonceStr(), ]; + $ddd = new GetOpenid(); + $ddd->index(); + exit_data(1111); + + // 微信JSAPI支付需要openid + if ($service == 'pay.weixin.jspay') { + // $params['sub_openid'] = 'oB44Yw1T6bfVAZwjj729P-6CUSPE'; + $params['is_raw'] = 0; + $params['mch_app_name'] = '存客宝'; + $params['mch_app_id'] = 'https://kr-op.quwanzhi.com'; + } + + // 支付宝JSAPI支付需要buyer_id(可选) + if ($service == 'pay.alipay.jspay') { + $params['is_raw'] = 0; + $params['quit_url'] = $params['notify_url']; + $params['buyer_id'] = ''; + } + Db::startTrans(); try { - // 过滤空值签名 + // 签名 $secret = Env::get('payment.key'); $params['sign_type'] = 'MD5'; $params['sign'] = PaymentUtil::generateSign($params, $secret, 'MD5'); @@ -57,7 +93,7 @@ class PaymentService throw new \Exception('支付网关地址未配置'); } - //创建订单 + // 创建订单 Order::create([ 'mchId' => $params['mch_id'], 'companyId' => isset($order['companyId']) ? $order['companyId'] : 0, @@ -73,17 +109,43 @@ class PaymentService 'nonceStr' => isset($order['nonceStr']) ? $order['nonceStr'] : '', 'createTime' => time(), ]); + // XML POST 请求 $xmlBody = $this->arrayToXml($params); $response = $this->postXml($url, $xmlBody); $parsed = $this->parseXmlOrRaw($response); + + exit_data($parsed); + if ($parsed['status'] == 0 && $parsed['result_code'] == 0) { Db::commit(); - return json_encode(['code' => 200, 'msg' => '订单创建成功', 'data' => $parsed['code_img_url']]); + + // 根据service类型返回不同的数据格式(仅返回接口文档中的字段) + $responseData = null; + if ($service == 'unified.trade.native') { + // 扫码支付返回二维码URL + $responseData = $parsed['code_img_url'] ?? ''; + } elseif ($service == 'pay.weixin.jspay') { + // 微信JSAPI支付返回支付参数(仅返回接口文档中存在的字段) + $responseData = []; + if (isset($parsed['appid'])) $responseData['appid'] = $parsed['appid']; + if (isset($parsed['time_stamp'])) $responseData['time_stamp'] = $parsed['time_stamp']; + if (isset($parsed['nonce_str'])) $responseData['nonce_str'] = $parsed['nonce_str']; + if (isset($parsed['package'])) $responseData['package'] = $parsed['package']; + if (isset($parsed['sign_type'])) $responseData['sign_type'] = $parsed['sign_type']; + if (isset($parsed['pay_sign'])) $responseData['pay_sign'] = $parsed['pay_sign']; + } elseif ($service == 'pay.alipay.jspay') { + // 支付宝JSAPI支付返回订单信息(仅返回接口文档中存在的字段) + $responseData = []; + if (isset($parsed['order_info'])) $responseData['order_info'] = $parsed['order_info']; + if (isset($parsed['order_string'])) $responseData['order_string'] = $parsed['order_string']; + } + + return json_encode(['code' => 200, 'msg' => '订单创建成功', 'data' => $responseData]); } else { Db::rollback(); - return json_encode(['code' => 500, 'msg' => '订单创建失败:' . $parsed['err_msg']]); + return json_encode(['code' => 500, 'msg' => '订单创建失败:' . ($parsed['err_msg'] ?? '未知错误')]); } } catch (\Exception $e) { @@ -194,54 +256,104 @@ class PaymentService /** * 支付结果异步通知 * - 威富通回调为 XML;需校验签名与业务字段并更新订单 - * - 回应:成功回"success",失败回"fail" - * @return void + * - 支持扫码付款、微信支付、支付宝支付的通知 + * - 回应:成功返回XML格式SUCCESS,失败返回XML格式FAIL + * @return string XML响应 */ public function notify() { $rawBody = file_get_contents('php://input'); $payload = $this->parseXmlOrRaw($rawBody); if (!is_array($payload) || empty($payload)) { - return json_encode(['code' => 500, 'msg' => 'XML解析错误']); + \think\facade\Log::error('支付通知:XML解析错误', ['rawBody' => $rawBody]); + return ''; } + // 验证签名 + $secret = Env::get('payment.key'); + if (!empty($secret) && isset($payload['sign'])) { + $signType = $payload['sign_type'] ?? 'MD5'; + if (!PaymentUtil::verifySign($payload, $secret, $signType)) { + \think\facade\Log::error('支付通知:签名验证失败', ['payload' => $payload]); + return ''; + } + } - if ($payload['status'] != 0 || $payload['result_code'] != 0) { - $errMsg = (isset($payload['err_msg']) ? $payload['err_msg'] : isset($payload['err_msg'])) ? $payload['err_msg'] : '未知错误'; - return json_encode(['code' => 500, 'msg' => $errMsg]); + // 检查通信状态 + if (isset($payload['status']) && $payload['status'] != 0) { + $errMsg = $payload['err_msg'] ?? '通信失败'; + \think\facade\Log::error('支付通知:通信失败', ['payload' => $payload]); + return ''; + } + + // 检查业务结果 + if (isset($payload['result_code']) && $payload['result_code'] != 0) { + $errMsg = $payload['err_msg'] ?? '业务处理失败'; + \think\facade\Log::error('支付通知:业务处理失败', ['payload' => $payload]); + return ''; } // 业务处理:更新订单 Db::startTrans(); try { - $outTradeNo = $payload['out_trade_no']; - $pay_result = $payload['pay_result']; - $time_end = $payload['time_end']; + $outTradeNo = $payload['out_trade_no'] ?? ''; + $pay_result = $payload['pay_result'] ?? 0; + $time_end = $payload['time_end'] ?? ''; + + if (empty($outTradeNo)) { + Db::rollback(); + \think\facade\Log::error('支付通知:订单号为空', ['payload' => $payload]); + return ''; + } + $order = Order::where('orderNo', $outTradeNo)->find(); if (!$order) { Db::rollback(); - return json_encode(['code' => 500, 'msg' => '该订单不存在']); + \think\facade\Log::error('支付通知:订单不存在', ['out_trade_no' => $outTradeNo]); + return ''; + } + + // 如果订单已支付,直接返回成功(防止重复处理) + if ($order->status == 1) { + Db::rollback(); + return ''; } if ($pay_result != 0) { - $order->payInfo = $payload['pay_info']; + $order->payInfo = $payload['pay_info'] ?? '支付失败'; $order->status = 3; $order->save(); Db::commit(); - return json_encode(['code' => 500, 'msg' => $payload['pay_info']]); + \think\facade\Log::error('支付通知:支付失败', ['orderNo' => $outTradeNo, 'pay_info' => $payload['pay_info'] ?? '']); + return ''; } - $order->payType = $payload['trade_type'] == 'pay.wechat.jspay' ? 1 : 2; + + // 根据trade_type判断支付方式 + $tradeType = $payload['trade_type'] ?? ''; + if (strpos($tradeType, 'wechat') !== false || strpos($tradeType, 'weixin') !== false) { + $order->payType = 1; // 微信支付 + } elseif (strpos($tradeType, 'alipay') !== false) { + $order->payType = 2; // 支付宝支付 + } else { + // 默认根据原有逻辑判断 + $order->payType = $tradeType == 'pay.wechat.jspay' ? 1 : 2; + } + $order->status = 1; $order->payTime = $this->parsePayTime($time_end); + $order->transactionId = $payload['transaction_id'] ?? ''; $order->save(); //订单处理 $this->processOrder($order); Db::commit(); - return json_encode(['code' => 200, 'msg' => '付款成功']); + + // 返回成功响应(XML格式) + return ''; } catch (\Exception $e) { Db::rollback(); - return json_encode(['code' => 500, 'msg' => '付款失败' . $e->getMessage()]); + \think\facade\Log::error('支付通知:处理异常', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]); + return ''; } } @@ -359,12 +471,12 @@ class PaymentService //订单处理 $this->processOrder($order); Db::commit(); - return json_encode(['code' => 200, 'msg' => '支付成功'] ); + return json_encode(['code' => 200, 'msg' => '支付成功']); } catch (\Exception $e) { Db::rollback(); return json_encode(['code' => 500, 'msg' => '付款失败' . $e->getMessage()]); } - }else{ + } else { $order = Order::where('orderNo', $resp['out_trade_no'])->lock(true)->find(); if ($order) { $order->status = 3; @@ -373,8 +485,8 @@ class PaymentService } return json_encode(['code' => 500, 'msg' => '支付失败', 'data' => $resp]); } - - }else{ + + } else { return json_encode(['code' => 500, 'msg' => '通信失败']); } } @@ -413,7 +525,7 @@ class PaymentService $record->form = 5; $record->wechatAccountId = 0; $record->friendIdOrGroupId = 0; - $record->remarks = '购买算力【'.$goodsSpecs['name'].'】'; + $record->remarks = '购买算力【' . $goodsSpecs['name'] . '】'; $record->tokens = $goodsSpecs['tokens']; $record->balanceTokens = $newTokens; $record->createTime = time(); @@ -423,4 +535,5 @@ class PaymentService return true; } + } \ No newline at end of file diff --git a/Server/application/cunkebao/config/route.php b/Server/application/cunkebao/config/route.php index 2b9d9665..cf64cef7 100644 --- a/Server/application/cunkebao/config/route.php +++ b/Server/application/cunkebao/config/route.php @@ -154,9 +154,10 @@ Route::group('v1/', function () { // 算力相关 Route::group('tokens', function () { Route::get('list', 'app\cunkebao\controller\TokensController@getList'); - Route::post('pay', 'app\cunkebao\controller\TokensController@pay'); - Route::get('queryOrder', 'app\cunkebao\controller\TokensController@queryOrder'); + Route::post('pay', 'app\cunkebao\controller\TokensController@pay'); // 扫码付款 + Route::get('queryOrder', 'app\cunkebao\controller\TokensController@queryOrder'); // 查询订单(扫码付款) Route::get('orderList', 'app\cunkebao\controller\TokensController@getOrderList'); // 获取订单列表 + Route::get('statistics', 'app\cunkebao\controller\TokensController@getTokensStatistics'); // 获取算力统计 }); @@ -165,6 +166,7 @@ Route::group('v1/', function () { Route::group('knowledge', function () { Route::get('init', 'app\cunkebao\controller\AiSettingsController@init'); Route::get('release', 'app\cunkebao\controller\AiSettingsController@release'); + Route::post('savePrompt', 'app\cunkebao\controller\AiSettingsController@savePrompt'); // 保存统一提示词 Route::get('typeList', 'app\cunkebao\controller\AiKnowledgeBaseController@typeList'); Route::get('getList', 'app\cunkebao\controller\AiKnowledgeBaseController@getList'); Route::post('add', 'app\cunkebao\controller\AiKnowledgeBaseController@add'); diff --git a/Server/application/cunkebao/controller/AiKnowledgeBaseController.php b/Server/application/cunkebao/controller/AiKnowledgeBaseController.php index 8ba90722..06a95c88 100644 --- a/Server/application/cunkebao/controller/AiKnowledgeBaseController.php +++ b/Server/application/cunkebao/controller/AiKnowledgeBaseController.php @@ -46,13 +46,35 @@ class AiKnowledgeBaseController extends BaseController $where[] = ['type', '=', AiKnowledgeBaseType::TYPE_USER]; } + // 统计开启的类型总数 + $enabledCountWhere = $where; + $enabledCountWhere[] = ['status', '=', 1]; + $enabledCount = AiKnowledgeBaseType::where($enabledCountWhere)->count(); + // 查询数据 $list = AiKnowledgeBaseType::where($where) ->order('type', 'asc') // 系统类型排在前面 ->order('createTime', 'desc') ->paginate($pageSize, false, ['page' => $page]); - return ResponseHelper::success($list, '获取成功'); + // 为每个类型添加素材数量统计 + $listData = $list->toArray(); + foreach ($listData['data'] as &$item) { + // 统计该类型下的知识库数量(素材数量) + $item['materialCount'] = AiKnowledgeBase::where([ + ['typeId', '=', $item['id']], + ['isDel', '=', 0] + ])->count(); + } + + // 重新构造返回数据 + $result = [ + 'total' => $listData['total'], + 'data' => $listData['data'], + 'enabledCount' => $enabledCount, // 开启的类型总数 + ]; + + return ResponseHelper::success($result, '获取成功'); } catch (\Exception $e) { return ResponseHelper::error('系统异常:' . $e->getMessage()); @@ -419,6 +441,11 @@ class AiKnowledgeBaseController extends BaseController ->order('createTime', 'desc') ->paginate($pageSize, false, ['page' => $page]); + foreach ($list as &$v){ + $v['size'] = 0; + } + unset($v); + return ResponseHelper::success($list, '获取成功'); } catch (\Exception $e) { diff --git a/Server/application/cunkebao/controller/AiSettingsController.php b/Server/application/cunkebao/controller/AiSettingsController.php index 8eb41423..429410be 100644 --- a/Server/application/cunkebao/controller/AiSettingsController.php +++ b/Server/application/cunkebao/controller/AiSettingsController.php @@ -40,6 +40,7 @@ class AiSettingsController extends BaseController // 确保智能体已创建 if (empty($settings->botId)) { + $settings->releaseTime = 0; $botCreated = $this->createBot($settings); if (!$botCreated) { return ResponseHelper::error('智能体创建失败'); @@ -48,12 +49,13 @@ class AiSettingsController extends BaseController // 确保知识库已创建 if (empty($settings->datasetId)) { + $settings->releaseTime = 0; $knowledgeCreated = $this->createKnowledge($settings); if (!$knowledgeCreated) { return ResponseHelper::error('知识库创建失败'); } } - if (!empty($settings->botId) && !empty($settings->datasetId)) { + if (!empty($settings->botId) && !empty($settings->datasetId) && $settings->releaseTime <= 0) { $cozeAI = new CozeAI(); $config = json_decode($settings->config,true); $config['bot_id'] = $settings->botId; @@ -133,7 +135,8 @@ class AiSettingsController extends BaseController ## 限制 - 仅依据知识库内容回答问题,对于知识库中没有的信息,如实告知用户无法回答。 - 回答必须严格遵循中国法律法规,不得出现任何违法违规内容。 -- 回答需简洁明了,避免冗长复杂的表述。'; +- 回答需简洁明了,避免冗长复杂的表述(尽量在100字内)。 +- 适当加些表情点缀。'; } /** @@ -341,4 +344,90 @@ class AiSettingsController extends BaseController $settings->save(); return ResponseHelper::success('', '发布成功'); } + + /** + * 保存统一提示词 + * 先更新数据库,再调用CozeAI接口更新智能体 + * + * @return \think\response\Json + */ + public function savePrompt() + { + try { + $companyId = $this->getUserInfo('companyId'); + if (empty($companyId)) { + return ResponseHelper::error('公司信息获取失败'); + } + + // 获取提示词参数 + $promptInfo = $this->request->param('promptInfo', ''); + if (empty($promptInfo)) { + return ResponseHelper::error('提示词内容不能为空'); + } + + // 查找AI设置 + $settings = AiSettingsModel::where(['companyId' => $companyId])->find(); + if (empty($settings)) { + return ResponseHelper::error('AI设置不存在,请先初始化'); + } + + // 检查智能体是否已创建 + if (empty($settings->botId)) { + return ResponseHelper::error('智能体未创建,请先初始化AI设置'); + } + + // 解析现有配置 + $config = json_decode($settings->config, true); + if (!is_array($config)) { + $config = []; + } + + // 更新提示词 + $config['prompt_info'] = $promptInfo; + + // 第一步:更新数据库 + $settings->config = json_encode($config, JSON_UNESCAPED_UNICODE); + $settings->isRelease = 0; // 标记为未发布状态 + $settings->updateTime = time(); + + if (!$settings->save()) { + return ResponseHelper::error('数据库更新失败'); + } + + // 第二步:调用CozeAI接口更新智能体 + try { + $cozeAI = new CozeAI(); + + // 参考 init 方法的参数格式,传递完整的 config + $updateData = $config; + $updateData['bot_id'] = $settings->botId; + + // 如果有知识库,也一并传入 + if (!empty($settings->datasetId)) { + $updateData['dataset_ids'] = [$settings->datasetId]; + } + + $result = $cozeAI->updateBot($updateData); + $result = json_decode($result, true); + + if ($result['code'] != 200) { + \think\facade\Log::error('更新智能体提示词失败:' . json_encode($result)); + return ResponseHelper::error('更新智能体失败:' . ($result['msg'] ?? '未知错误')); + } + + return ResponseHelper::success([ + 'prompt_info' => $promptInfo, + 'isRelease' => 0 + ], '提示词保存成功,请重新发布智能体'); + + } catch (\Exception $e) { + \think\facade\Log::error('调用CozeAI更新接口异常:' . $e->getMessage()); + return ResponseHelper::error('更新智能体接口调用失败:' . $e->getMessage()); + } + + } catch (\Exception $e) { + \think\facade\Log::error('保存提示词异常:' . $e->getMessage()); + return ResponseHelper::error('系统异常:' . $e->getMessage()); + } + } } \ No newline at end of file diff --git a/Server/application/cunkebao/controller/TokensController.php b/Server/application/cunkebao/controller/TokensController.php index b6ec7728..e59fab74 100644 --- a/Server/application/cunkebao/controller/TokensController.php +++ b/Server/application/cunkebao/controller/TokensController.php @@ -5,6 +5,8 @@ namespace app\cunkebao\controller; use app\common\controller\PaymentService; use app\common\model\Order; use app\cunkebao\model\TokensPackage; +use app\chukebao\model\TokensCompany; +use app\chukebao\model\TokensRecord; use library\ResponseHelper; use think\facade\Env; @@ -23,9 +25,9 @@ class TokensController extends BaseController $list = $query->where($where)->page($page, $limit)->order('sort ASC,id desc')->select(); foreach ($list as &$item) { $item['description'] = json_decode($item['description'], true); - $item['discount'] = round(((($item['originalPrice'] - $item['price']) / $item['originalPrice']) * 100),2); - $item['price'] = round( $item['price'], 2); - $item['unitPrice'] = round( $item['price'] / $item['tokens'],6); + $item['discount'] = round(((($item['originalPrice'] - $item['price']) / $item['originalPrice']) * 100), 2); + $item['price'] = round($item['price'], 2); + $item['unitPrice'] = round($item['price'] / $item['tokens'], 6); $item['originalPrice'] = round($item['originalPrice'] / 100, 2); $item['tokens'] = number_format($item['tokens']); } @@ -40,6 +42,12 @@ class TokensController extends BaseController $price = $this->request->param('price', ''); $userId = $this->getUserInfo('id'); $companyId = $this->getUserInfo('companyId'); + $payType = $this->request->param('payType', ''); + + if (!in_array($payType, ['wechat', 'alipay', 'qrCode'])) { + return ResponseHelper::error('付款类型不正确'); + } + if (empty($id) && empty($price)) { return ResponseHelper::error('套餐和自定义购买金额必须选一个'); @@ -73,6 +81,7 @@ class TokensController extends BaseController ]; } + $orderNo = date('YmdHis') . rand(100000, 999999); $order = [ 'companyId' => $companyId, @@ -82,7 +91,8 @@ class TokensController extends BaseController 'goodsName' => $specs['name'], 'goodsSpecs' => $specs, 'orderType' => 1, - 'money' => $specs['price'] + 'money' => $specs['price'], + 'service' => $payType ]; $paymentService = new PaymentService(); $res = $paymentService->createOrder($order); @@ -106,16 +116,18 @@ class TokensController extends BaseController $res = $paymentService->queryOrder($orderNo); $res = json_decode($res, true); if ($res['code'] == 200) { - return ResponseHelper::success('','订单已支付'); + return ResponseHelper::success('', '订单已支付'); } else { $errorMsg = !empty($order['payInfo']) ? $order['payInfo'] : '订单未支付'; return ResponseHelper::error($errorMsg); } } else { - return ResponseHelper::success('','订单已支付'); + return ResponseHelper::success('', '订单已支付'); } } + + /** * 获取订单列表 * @return \think\response\Json @@ -164,7 +176,7 @@ class TokensController extends BaseController // 分页查询 $query = Order::where($where) - ->where(function($query) { + ->where(function ($query) { $query->whereNull('deleteTime')->whereOr('deleteTime', 0); }); $total = $query->count(); @@ -178,12 +190,12 @@ class TokensController extends BaseController foreach ($list as &$item) { // 金额转换(分转元) $item['money'] = round($item['money'] / 100, 2); - + // 解析商品规格 if (!empty($item['goodsSpecs'])) { $specs = is_string($item['goodsSpecs']) ? json_decode($item['goodsSpecs'], true) : $item['goodsSpecs']; $item['goodsSpecs'] = $specs; - + // 添加算力数量 if (isset($specs['tokens'])) { $item['tokens'] = number_format($specs['tokens']); @@ -229,4 +241,75 @@ class TokensController extends BaseController return ResponseHelper::error('获取订单列表失败:' . $e->getMessage()); } } + + /** + * 获取公司算力统计信息 + * 包括:总算力、今日使用、本月使用、剩余算力 + * + * @return \think\response\Json + */ + public function getTokensStatistics() + { + try { + $companyId = $this->getUserInfo('companyId'); + if (empty($companyId)) { + return ResponseHelper::error('公司信息获取失败'); + } + + // 获取公司算力余额 + $tokensCompany = TokensCompany::where('companyId', $companyId)->find(); + $remainingTokens = $tokensCompany ? intval($tokensCompany->tokens) : 0; + + // 获取今日开始和结束时间戳 + $todayStart = strtotime(date('Y-m-d 00:00:00')); + $todayEnd = strtotime(date('Y-m-d 23:59:59')); + + // 获取本月开始和结束时间戳 + $monthStart = strtotime(date('Y-m-01 00:00:00')); + $monthEnd = strtotime(date('Y-m-t 23:59:59')); + + // 统计今日消费(type=0表示消费) + $todayUsed = TokensRecord::where([ + ['companyId', '=', $companyId], + ['type', '=', 0], // 0为减少(消费) + ['createTime', '>=', $todayStart], + ['createTime', '<=', $todayEnd] + ])->sum('tokens'); + $todayUsed = intval($todayUsed); + + // 统计本月消费 + $monthUsed = TokensRecord::where([ + ['companyId', '=', $companyId], + ['type', '=', 0], // 0为减少(消费) + ['createTime', '>=', $monthStart], + ['createTime', '<=', $monthEnd] + ])->sum('tokens'); + $monthUsed = intval($monthUsed); + + // 计算总算力(当前剩余 + 历史总消费) + $totalConsumed = TokensRecord::where([ + ['companyId', '=', $companyId], + ['type', '=', 0] + ])->sum('tokens'); + $totalConsumed = intval($totalConsumed); + + // 总充值算力 + $totalRecharged = TokensRecord::where([ + ['companyId', '=', $companyId], + ['type', '=', 1] // 1为增加(充值) + ])->sum('tokens'); + $totalRecharged = intval($totalRecharged); + + return ResponseHelper::success([ + 'totalTokens' => $totalRecharged, // 总算力(累计充值) + 'todayUsed' => $todayUsed, // 今日使用 + 'monthUsed' => $monthUsed, // 本月使用 + 'remainingTokens' => $remainingTokens, // 剩余算力 + 'totalConsumed' => $totalConsumed, // 累计消费 + ], '获取成功'); + + } catch (\Exception $e) { + return ResponseHelper::error('获取算力统计失败:' . $e->getMessage()); + } + } } \ No newline at end of file diff --git a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php index f51e5d76..aae46d9c 100644 --- a/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php +++ b/Server/application/cunkebao/controller/plan/PosterWeChatMiniProgram.php @@ -12,17 +12,28 @@ use think\Db; class PosterWeChatMiniProgram extends Controller { + + protected $config; + + + public function __construct() + { + parent::__construct(); + + // 从环境变量获取配置 + $this->config = [ + 'app_id' => Env::get('weChat.appidMiniApp','wx789850448e26c91d'), + 'secret' => Env::get('weChat.secretMiniApp','d18f75b3a3623cb40da05648b08365a1'), + 'response_type' => 'array' + ]; + } + + public function index() { return 'Hello, World!'; } - const MINI_PROGRAM_CONFIG = [ - 'app_id' => 'wx789850448e26c91d', - 'secret' => 'd18f75b3a3623cb40da05648b08365a1', - 'response_type' => 'array' - ]; - // 生成小程序码,存客宝-操盘手调用 public function generateMiniProgramCodeWithScene($taskId = '') @@ -34,7 +45,7 @@ class PosterWeChatMiniProgram extends Controller try { - $app = Factory::miniProgram(self::MINI_PROGRAM_CONFIG); + $app = Factory::miniProgram($this->config); // scene参数长度限制为32位 //$scene = 'taskId=' . $taskId; $scene = sprintf("%s", $taskId); @@ -83,7 +94,7 @@ class PosterWeChatMiniProgram extends Controller ]); } - $app = Factory::miniProgram(self::MINI_PROGRAM_CONFIG); + $app = Factory::miniProgram($this->config); $result = $app->phone_number->getUserPhoneNumber($code);