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);