feat(merchant): 新增用户订单总结查询接口

- 在白名单中添加订单总结接口路径,支持免鉴权访问
- merchant接口新增OrderQuerySummary方法声明
- 删除订单查询接口中调用openai总结的实现,移至单独总结接口
- 定义订单总结请求与响应结构体,支持返回总结结论文本
- 新增OrderQuerySummary控制器方法,整合订单信息及卡密记录生成总结
- 使用openai deepseek模型生成简洁中文订单总结结论
- 调整测试代码使用glog输出OpenAI响应,替换测试示例文本与模型名称
This commit is contained in:
danial
2025-11-28 22:08:31 +08:00
parent 2d317037b0
commit c23e1d7edc
6 changed files with 100 additions and 36 deletions

View File

@@ -24,6 +24,7 @@ type IMerchantV1 interface {
MerchantDeployUpdate(ctx context.Context, req *v1.MerchantDeployUpdateReq) (res *v1.MerchantDeployUpdateRes, err error)
MerchantDeployGetDetail(ctx context.Context, req *v1.MerchantDeployGetDetailReq) (res *v1.MerchantDeployGetDetailRes, err error)
OrderQuery(ctx context.Context, req *v1.OrderQueryReq) (res *v1.OrderQueryRes, err error)
OrderQuerySummary(ctx context.Context, req *v1.OrderQuerySummaryReq) (res *v1.OrderQuerySummaryRes, err error)
StealStatusSet(ctx context.Context, req *v1.StealStatusSetReq) (res *v1.StealStatusSetRes, err error)
StealStatusGet(ctx context.Context, req *v1.StealStatusGetReq) (res *v1.StealStatusGetRes, err error)
StealCreate(ctx context.Context, req *v1.StealCreateReq) (res *v1.StealCreateRes, err error)

View File

@@ -21,12 +21,19 @@ type OrderQueryRecord struct {
}
type OrderQueryRes struct {
g.Meta `mime:"application/json"`
Summary struct {
Msg string `json:"msg"`
} `json:"result"`
g.Meta `mime:"application/json"`
commonApi.CommonPageRes[*OrderQueryRecord]
BankOrderId string `json:"bankOrderId" dc:"平台订单号"`
CreateTime *gtime.Time `json:"createTime" dc:"创建时间"`
Amount float64 `json:"amount" dc:"充值金额"`
}
type OrderQuerySummaryReq struct {
g.Meta `path:"/merchant/order/summary" tags:"商户总结信息" method:"get" summary:"用户查单总结"`
MerchantOrderNo string `json:"merchantOrderNo" description:"商户订单号"`
}
type OrderQuerySummaryRes struct {
g.Meta `mime:"application/json"`
Message string `json:"message" dc:"结论"`
}

View File

@@ -2,10 +2,6 @@ package merchant
import (
"context"
"encoding/json"
"fmt"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
"kami/internal/consts"
"kami/internal/model/entity"
"kami/internal/service"
@@ -60,34 +56,12 @@ func (c *ControllerV1) OrderQuery(ctx context.Context, req *v1.OrderQueryReq) (r
record = append(record, appleRecord...)
redeemRecord := queryRedeemCard(ctx, req.MerchantOrderNo)
record = append(record, redeemRecord...)
msg, err := queryAppleResult(ctx, record)
if err != nil {
msg = "总结失败,请稍候重试"
}
res.Summary.Msg = msg
res.Total = len(record)
res.List = record
return
}
func queryAppleResult(ctx context.Context, record []*v1.OrderQueryRecord) (string, error) {
recordStr, _ := json.Marshal(record)
client := openai.NewClient(
option.WithAPIKey("sk-jYRlGtXAJ3Q82TS_FxWLFX6wn_VubNnyCtfxYZYP32ccqfQaGwQJHMq5I7k"),
option.WithBaseURL("https://hk.uniapi.io/v1"),
)
chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage(fmt.Sprintf("%s\n生成总结用中文回复", string(recordStr))),
},
Model: "qwen3-8b",
})
if err != nil {
return "", err
}
return chatCompletion.Choices[0].Message.Content, nil
}
func queryAppleCard(ctx context.Context, merchantOrderNo string) (record []*v1.OrderQueryRecord) {
record = make([]*v1.OrderQueryRecord, 0)

View File

@@ -0,0 +1,78 @@
package merchant
import (
"context"
"encoding/json"
"fmt"
"github.com/duke-git/lancet/v2/pointer"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
"kami/internal/service"
"kami/utility/utils"
"kami/api/merchant/v1"
)
func (c *ControllerV1) OrderQuerySummary(ctx context.Context, req *v1.OrderQuerySummaryReq) (res *v1.OrderQuerySummaryRes, err error) {
res = &v1.OrderQuerySummaryRes{}
record := make([]*v1.OrderQueryRecord, 0)
orderInfo, err := service.OrderSummary().GetOneById(ctx, req.MerchantOrderNo)
err = utils.HandleNoRowsError(err)
if err != nil || pointer.IsNil(orderInfo) || orderInfo.Id == 0 {
return
}
// 添加订单信息
if orderInfo.PayTime != nil {
record = append(record, &v1.OrderQueryRecord{
CreatedAt: orderInfo.CreateTime,
Operation: "拉取订单",
})
record = append(record, &v1.OrderQueryRecord{
CreatedAt: orderInfo.PayTime,
Operation: "用户提交卡密",
})
} else {
record = append(record, &v1.OrderQueryRecord{
CreatedAt: orderInfo.CreateTime,
Operation: "拉取订单,未上传卡密",
})
}
if orderInfo.IsBlock == 1 {
record = append(record, &v1.OrderQueryRecord{
CreatedAt: orderInfo.UpdateTime,
Operation: "订单被禁用",
})
}
appleRecord := queryAppleCard(ctx, req.MerchantOrderNo)
record = append(record, appleRecord...)
redeemRecord := queryRedeemCard(ctx, req.MerchantOrderNo)
record = append(record, redeemRecord...)
if len(record) > 0 {
msg, err2 := queryAppleResult(ctx, record)
if err2 != nil {
msg = "总结失败,请稍候重试"
}
res.Message = msg
}
return
}
func queryAppleResult(ctx context.Context, record []*v1.OrderQueryRecord) (string, error) {
recordStr, _ := json.Marshal(record)
client := openai.NewClient(
option.WithAPIKey("sk-jYRlGtXAJ3Q82TS_FxWLFX6wn_VubNnyCtfxYZYP32ccqfQaGwQJHMq5I7k"),
option.WithBaseURL("https://hk.uniapi.io/v1"),
)
chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage(fmt.Sprintf("%s\n只生成简洁结论不需要建议使用中文", string(recordStr))),
},
Model: "deepseek-v3.2-exp",
})
if err != nil {
return "", err
}
return chatCompletion.Choices[0].Message.Content, nil
}

View File

@@ -2,7 +2,7 @@ package merchant
import (
"context"
"fmt"
"github.com/gogf/gf/v2/os/glog"
"github.com/openai/openai-go/v3"
"github.com/openai/openai-go/v3/option"
@@ -14,14 +14,17 @@ func Test_queryAppleResult(t *testing.T) {
option.WithAPIKey("sk-jYRlGtXAJ3Q82TS_FxWLFX6wn_VubNnyCtfxYZYP32ccqfQaGwQJHMq5I7k"),
option.WithBaseURL("https://hk.uniapi.io/v1"),
)
msg := "[\n {\n \"orderNo\": \"\",\n \"operation\": \"拉取订单\",\n \"remark\": \"\",\n \"createdAt\": \"2025-11-28 20:39:32\",\n \"accountName\": \"\"\n },\n {\n \"orderNo\": \"\",\n \"operation\": \"用户提交卡密\",\n \"remark\": \"\",\n \"createdAt\": \"2025-11-28 20:39:57\",\n \"accountName\": \"\"\n },\n {\n \"orderNo\": \"019aca7a2f7d73c79f5839417aa63972\",\n \"operation\": \"创建订单\",\n \"remark\": \"\",\n \"createdAt\": \"2025-11-28 20:39:56\",\n \"accountName\": \"\"\n },\n {\n \"orderNo\": \"019aca7a2f7d73c79f5839417aa63972\",\n \"operation\": \"iTunes开始处理\",\n \"remark\": \"分配账户rintoul.pablo19297@funkybusinez.com\",\n \"createdAt\": \"2025-11-28 20:39:56\",\n \"accountName\": \"rintoul.pablo19297@funkybusinez.com\"\n },\n {\n \"orderNo\": \"019aca7a2f7d73c79f5839417aa63972\",\n \"operation\": \"查询账户余额\",\n \"remark\": \"账号【rintoul.pablo19297@funkybusinez.com】充值前余额314.00\",\n \"createdAt\": \"2025-11-28 20:40:01\",\n \"accountName\": \"rintoul.pablo19297@funkybusinez.com\"\n },\n {\n \"orderNo\": \"019aca7a2f7d73c79f5839417aa63972\",\n \"operation\": \"iTunes充值失败\",\n \"remark\": \"卡密不存在使用卡密【XF5P2KPX9YWTY365】为账号【rintoul.pablo19297@funkybusinez.com】充值失败卡密不存在\",\n \"createdAt\": \"2025-11-28 20:40:02\",\n \"accountName\": \"rintoul.pablo19297@funkybusinez.com\"\n },\n {\n \"orderNo\": \"019aca7a2f7d73c79f5839417aa63972\",\n \"operation\": \"查询账户余额\",\n \"remark\": \"账号【rintoul.pablo19297@funkybusinez.com】充值后余额314.00\",\n \"createdAt\": \"2025-11-28 20:40:04\",\n \"accountName\": \"rintoul.pablo19297@funkybusinez.com\"\n }\n ]"
chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{
Messages: []openai.ChatCompletionMessageParamUnion{
openai.UserMessage("用中文回复Say this is a test"),
openai.UserMessage(msg + "\n只生成简洁结论不需要建议使用中文"),
},
Model: "qwen3-8b",
Model: "deepseek-v3.2-exp",
})
if err != nil {
panic(err.Error())
glog.Info(t.Context(), err)
}
fmt.Print(chatCompletion.Choices[0].Message.Content)
glog.Info(t.Context(), chatCompletion.Choices[0].Message.Content)
}

View File

@@ -26,6 +26,7 @@ import (
func whiteListAuth(r *ghttp.Request) gcode.Code {
whiteList := []string{
"/api/merchant/order/query",
"/api/merchant/order/summary",
"/api/restriction/block/order",
"/api/restriction/location/checkIPAllowed",
"/api/cardInfo/appleCard/submit",