Merge branch 'develop' into feature/auth

This commit is contained in:
eson 2023-08-10 17:31:03 +08:00
commit 432db5aec5
20 changed files with 276 additions and 233 deletions

View File

@ -52,23 +52,36 @@ func (m *FsResourceModel) RowSelectBuilder(selectData []string) *gorm.DB {
// 事务 // 事务
func (m *FsResourceModel) Trans(ctx context.Context, fn func(ctx context.Context, connGorm *gorm.DB) error) error { func (m *FsResourceModel) Trans(ctx context.Context, fn func(ctx context.Context, connGorm *gorm.DB) error) error {
tx := m.db.Table(m.name).WithContext(ctx).Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
if err := tx.Error; err != nil { return m.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
err := fn(ctx, tx)
return err return err
} })
if err := fn(ctx, tx); err != nil { // tx := m.db.Table(m.name).WithContext(ctx)
tx.Rollback() // defer func() {
return err // if r := recover(); r != nil {
} // tx.Rollback()
// }
// }()
return tx.Commit().Error // if err := tx.Error; err != nil {
// tx.Rollback()
// return err
// }
// if err := fn(ctx, tx); err != nil {
// tx.Rollback()
// return err
// }
// err := tx.Commit().Error
// if err != nil {
// tx.Rollback()
// return err
// }
// return err
} }
func (m *FsResourceModel) TableName() string { func (m *FsResourceModel) TableName() string {

View File

@ -70,3 +70,8 @@ func (m *FsUserMaterialModel) FindLatestOne(ctx context.Context, userId int64, g
err = db.Take(&resp).Error err = db.Take(&resp).Error
return resp, err return resp, err
} }
func (m *FsUserMaterialModel) FindOneById(ctx context.Context, id int64) (resp *FsUserMaterial, err error) {
err = m.db.WithContext(ctx).Model(&FsUserMaterial{}).Where("id = ?", id).Take(&resp).Error
return resp, err
}

View File

@ -76,16 +76,17 @@ func (l *UserOrderCancelLogic) UserOrderCancel(req *types.UserOrderCancelReq, us
var nowTime = time.Now().Unix() var nowTime = time.Now().Unix()
var payList []handlers.PayInfo var payList []handlers.PayInfo
// 事务处理 // 事务处理
err = orderModel.Trans(l.ctx, func(ctx context.Context, connGorm *gorm.DB) (err error) { ctx := l.ctx
err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error {
// 修改订单信息 // 修改订单信息
orderModelTS := gmodel.NewFsOrderModel(connGorm) orderModelTS := gmodel.NewFsOrderModel(tx)
err = orderModelTS.Update(ctx, orderInfo) err = orderModelTS.Update(ctx, orderInfo)
if err != nil { if err != nil {
return err return err
} }
// 新增退款记录 // 新增退款记录
var isRefund int64 = 0 var isRefund int64 = 0
refundReasonModelTS := gmodel.NewFsRefundReasonModel(connGorm) refundReasonModelTS := gmodel.NewFsRefundReasonModel(tx)
refundReasonModelTS.CreateOrUpdate(ctx, &gmodel.FsRefundReason{ refundReasonModelTS.CreateOrUpdate(ctx, &gmodel.FsRefundReason{
IsRefund: &isRefund, IsRefund: &isRefund,
RefundReasonId: &req.RefundReasonId, RefundReasonId: &req.RefundReasonId,
@ -95,7 +96,7 @@ func (l *UserOrderCancelLogic) UserOrderCancel(req *types.UserOrderCancelReq, us
}) })
// 退款申请 // 退款申请
// 退款申请--查询支付信息 // 退款申请--查询支付信息
fsPayModelTS := gmodel.NewFsPayModel(connGorm) fsPayModelTS := gmodel.NewFsPayModel(tx)
rbFsPay := fsPayModelTS.RowSelectBuilder(nil).Where("order_number = ?", orderInfo.Sn).Where("pay_status =?", constants.PAYSTATUS_SUCCESS).Where("is_refund =?", 0) rbFsPay := fsPayModelTS.RowSelectBuilder(nil).Where("order_number = ?", orderInfo.Sn).Where("pay_status =?", constants.PAYSTATUS_SUCCESS).Where("is_refund =?", 0)
payInfoList, err := fsPayModelTS.FindAll(ctx, rbFsPay, nil, "") payInfoList, err := fsPayModelTS.FindAll(ctx, rbFsPay, nil, "")
if err != nil { if err != nil {

View File

@ -107,7 +107,8 @@ func (l *OrderPaymentIntentLogic) OrderPaymentIntent(req *types.OrderPaymentInte
var resData types.OrderPaymentIntentRes var resData types.OrderPaymentIntentRes
// 事务处理 // 事务处理
err = orderModel.Trans(l.ctx, func(ctx context.Context, connGorm *gorm.DB) error { ctx := l.ctx
err = l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
// 支付记录--处理 //支付记录改为一条订单多条,分首款尾款 // 支付记录--处理 //支付记录改为一条订单多条,分首款尾款
var payStatus int64 = 0 var payStatus int64 = 0
var orderSource int64 = 1 var orderSource int64 = 1

View File

@ -153,13 +153,13 @@ func (l *StripeWebhookLogic) HandlePayEventCreate(fsPayEvent *gmodel.FsPayEvent)
func (l *StripeWebhookLogic) HandleChargeRefunded(chargeRefunded *stripe.Charge) (err error) { func (l *StripeWebhookLogic) HandleChargeRefunded(chargeRefunded *stripe.Charge) (err error) {
// 退款成功 // 退款成功
if chargeRefunded.Status == "succeeded" { if chargeRefunded.Status == "succeeded" {
orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn) ctx := l.ctx
err = orderModel.Trans(l.ctx, func(ctx context.Context, connGorm *gorm.DB) (err error) { err = l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
// 查询支付记录 // 查询支付记录
payModelT := gmodel.NewFsPayModel(connGorm) payModelT := gmodel.NewFsPayModel(connGorm)
payModelTRSB := payModelT.RowSelectBuilder(nil) payModelTRSB := payModelT.RowSelectBuilder(nil)
payModelTRSB1 := payModelTRSB.Where("trade_no = ?", chargeRefunded.PaymentIntent.ID).Where("pay_status = ?", constants.PAYSTATUS_SUCCESS).Where("is_refund = ?", 0) payModelTRSB1 := payModelTRSB.Where("trade_no = ?", chargeRefunded.PaymentIntent.ID).Where("pay_status = ?", constants.PAYSTATUS_SUCCESS).Where("is_refund = ?", 0)
payInfo, err := payModelT.FindOneByQuery(l.ctx, payModelTRSB1, nil) payInfo, err := payModelT.FindOneByQuery(ctx, payModelTRSB1, nil)
if err != nil { if err != nil {
return err return err
} }
@ -295,7 +295,8 @@ func (l *StripeWebhookLogic) HandlePaymentIntentSucceeded(paymentIntent *stripe.
} }
} }
err = orderModel.Trans(l.ctx, func(ctx context.Context, connGorm *gorm.DB) (err error) { ctx := l.ctx
err = l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
// 更新支付信息 // 更新支付信息
payModelT := gmodel.NewFsPayModel(connGorm) payModelT := gmodel.NewFsPayModel(connGorm)
*payInfo.PayStatus = 1 *payInfo.PayStatus = 1

View File

@ -101,9 +101,39 @@ func (l *GetPriceByPidLogic) GetPriceByPid(req *types.GetPriceByPidReq, userinfo
// 组装阶梯价格范围 // 组装阶梯价格范围
func (l *GetPriceByPidLogic) dealWithStepRange(stepNumSlice, stepPriceSlice []int, priceInfo gmodel.FsProductPrice) []types.StepRange { func (l *GetPriceByPidLogic) dealWithStepRange(stepNumSlice, stepPriceSlice []int, priceInfo gmodel.FsProductPrice) []types.StepRange {
//要求写死不影响前端展示
return []types.StepRange{
{
Begin: 1000,
End: 2999,
Price: 0.23,
},
{
Begin: 3000,
End: 4999,
Price: 0.2,
},
{
Begin: 5000,
End: -1,
Price: 0.1,
},
}
//下面是正常的
lenStepNum := len(stepNumSlice) lenStepNum := len(stepNumSlice)
lenStepPrice := len(stepPriceSlice) lenStepPrice := len(stepPriceSlice)
stepListRsp := make([]types.StepRange, 0, lenStepNum) stepListRsp := make([]types.StepRange, 0, lenStepNum)
//只有一个阶梯价格
if lenStepPrice == 1 {
stepListRsp = append(stepListRsp, types.StepRange{
Begin: *priceInfo.MinBuyNum * (*priceInfo.EachBoxNum),
End: -1,
Price: float64(stepPriceSlice[0]) / 100,
})
return stepListRsp
}
begin := int64(0)
end := int64(0)
for numKey, stepNum := range stepNumSlice { for numKey, stepNum := range stepNumSlice {
//先取最后一个 //先取最后一个
tmpPrice := float64(stepPriceSlice[lenStepPrice-1]) / 100 tmpPrice := float64(stepPriceSlice[lenStepPrice-1]) / 100
@ -111,23 +141,12 @@ func (l *GetPriceByPidLogic) dealWithStepRange(stepNumSlice, stepPriceSlice []in
if numKey < lenStepPrice { if numKey < lenStepPrice {
tmpPrice = float64(stepPriceSlice[numKey]) / 100 tmpPrice = float64(stepPriceSlice[numKey]) / 100
} }
num := int64(stepNum) * (*priceInfo.EachBoxNum) begin = int64(stepNum) * (*priceInfo.EachBoxNum)
begin := int64(0) //不是最后一个
end := int64(0) if numKey < lenStepNum-1 {
if numKey == 0 { //第一个 nextBegin := int64(stepNumSlice[numKey+1]) * (*priceInfo.EachBoxNum)
begin = *priceInfo.MinBuyNum * (*priceInfo.EachBoxNum) end = nextBegin - 1
//只有一阶价格
if lenStepPrice == 1 {
end = -1
} else { } else {
end = num - 1
}
} else if numKey < lenStepNum-1 { //中间的
nextNum := int64(stepNumSlice[numKey+1]) * (*priceInfo.EachBoxNum)
begin = num
end = nextNum - 1
} else { //最后的
begin = num
end = -1 end = -1
} }
stepListRsp = append(stepListRsp, types.StepRange{ stepListRsp = append(stepListRsp, types.StepRange{

View File

@ -1,12 +1,14 @@
package consumer package consumer
import ( import (
"bytes"
"context" "context"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"fusenapi/constants" "fusenapi/constants"
"fusenapi/initalize" "fusenapi/initalize"
"fusenapi/model/gmodel"
"fusenapi/server/render/internal/svc" "fusenapi/server/render/internal/svc"
"fusenapi/utils/curl" "fusenapi/utils/curl"
"fusenapi/utils/file" "fusenapi/utils/file"
@ -16,7 +18,6 @@ import (
"gorm.io/gorm" "gorm.io/gorm"
"io/ioutil" "io/ioutil"
"strconv" "strconv"
"strings"
) )
// 这里请求的py接口返回数据 // 这里请求的py接口返回数据
@ -47,7 +48,7 @@ func (m *MqConsumerRenderAssemble) Run(ctx context.Context, data []byte) error {
} }
rabbitmq := initalize.RabbitMqHandle{} rabbitmq := initalize.RabbitMqHandle{}
//获取模板产品第一个sku的模板 //获取模板产品第一个sku的模板
templateInfo, err := svcCtx.AllModels.FsProductTemplateV2.FindOneByProductIdTagIdWithSizeTable(ctx, parseInfo.RenderData.ProductId, fmt.Sprintf("%d", parseInfo.RenderData.TemplateTagId)) productTemplate, err := svcCtx.AllModels.FsProductTemplateV2.FindOneByProductIdTagIdWithSizeTable(ctx, parseInfo.RenderData.ProductId, fmt.Sprintf("%d", parseInfo.RenderData.TemplateTagId))
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
logx.Error("template info is not found") logx.Error("template info is not found")
@ -56,6 +57,7 @@ func (m *MqConsumerRenderAssemble) Run(ctx context.Context, data []byte) error {
logx.Error("failed to get template info:", err) logx.Error("failed to get template info:", err)
return err return err
} }
combineImage := "" //刀版图
combineHash := hash.JsonHashKey(parseInfo) //区别于云渲染的taskid,这个用获取刀版图缓存 combineHash := hash.JsonHashKey(parseInfo) //区别于云渲染的taskid,这个用获取刀版图缓存
//获取该hash值下有没有对应的资源 //获取该hash值下有没有对应的资源
resource, err := svcCtx.AllModels.FsResource.FindOneById(ctx, combineHash) resource, err := svcCtx.AllModels.FsResource.FindOneById(ctx, combineHash)
@ -63,10 +65,9 @@ func (m *MqConsumerRenderAssemble) Run(ctx context.Context, data []byte) error {
logx.Error("failed to get resource :", err) logx.Error("failed to get resource :", err)
return err return err
} }
combineImage := "" //刀版图
//如果不存在,则请求生成刀版图 //如果不存在,则请求生成刀版图
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
combineImage, err = getCombineImage(ctx, svcCtx, parseInfo, combineHash) combineImage, err = getCombineImage(ctx, svcCtx, parseInfo, productTemplate, combineHash)
if err != nil { if err != nil {
return err return err
} }
@ -74,10 +75,10 @@ func (m *MqConsumerRenderAssemble) Run(ctx context.Context, data []byte) error {
combineImage = *resource.ResourceUrl combineImage = *resource.ResourceUrl
} }
//获取渲染设置信息 //获取渲染设置信息
element, err := svcCtx.AllModels.FsProductTemplateElement.FindOneByModelId(ctx, *templateInfo.ModelId) element, err := svcCtx.AllModels.FsProductTemplateElement.FindOneByModelId(ctx, *productTemplate.ModelId)
if err != nil { if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) { if errors.Is(err, gorm.ErrRecordNotFound) {
logx.Error("element info is not found,model_id = ?", *templateInfo.ModelId) logx.Error("element info is not found,model_id = ?", *productTemplate.ModelId)
return nil return nil
} }
logx.Error("failed to get element list,", err) logx.Error("failed to get element list,", err)
@ -132,7 +133,7 @@ func (m *MqConsumerRenderAssemble) Run(ctx context.Context, data []byte) error {
"light": *element.Light, "light": *element.Light,
"refletion": refletion, "refletion": refletion,
"scale": *element.Scale, "scale": *element.Scale,
"sku_id": *templateInfo.ProductId, "sku_id": parseInfo.RenderData.ProductId,
"tid": *element.Title, "tid": *element.Title,
"rotation": *element.Rotation, "rotation": *element.Rotation,
"filePath": "", //todo 文件路径,针对千人千面 "filePath": "", //todo 文件路径,针对千人千面
@ -160,14 +161,68 @@ func (m *MqConsumerRenderAssemble) Run(ctx context.Context, data []byte) error {
} }
// 获取刀版图 // 获取刀版图
func getCombineImage(ctx context.Context, svcCtx *svc.ServiceContext, parseInfo websocket_data.AssembleRenderData, combineHash string) (image string, err error) { func getCombineImage(ctx context.Context, svcCtx *svc.ServiceContext, parseInfo websocket_data.AssembleRenderData, productTemplate *gmodel.FsProductTemplateV2, combineHash string) (image string, err error) {
// todo 获取sku对应用来合成刀版图的json数据 if productTemplate.TemplateInfo == nil || *productTemplate.TemplateInfo == "" {
logx.Error("product template info`template_info is empty")
url := "http://192.168.1.7:45678/LogoCombine" return "", errors.New("product template info`template_info is empty")
}
//反序列化替换其中一些参数
var combineInfo map[string]interface{}
if err = json.Unmarshal([]byte(*productTemplate.TemplateInfo), &combineInfo); err != nil {
logx.Error("failed to parse json:template_info:", err)
return "", err
}
//需要替换的参数
replaceData := map[string]interface{}{
"logo_url": parseInfo.RenderData.Logo,
"website": "",
"slogan": "",
"address": "",
"phone": "",
"colors": []string{},
"template_tagid": []string{},
"is_crop": false,
"shape": "",
"ratio": 0,
"line": "",
"other": "",
"other1": "",
}
//获取用户素材信息
if parseInfo.RenderData.UserMaterialId > 0 {
userMaterial, err := svcCtx.AllModels.FsUserMaterial.FindOneById(ctx, parseInfo.RenderData.UserMaterialId)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
logx.Error("user material not exists:", parseInfo.RenderData.UserMaterialId)
return "", errors.New("user material not exists")
}
logx.Error("err failed to get user material info")
}
if userMaterial.Metadata != nil && *userMaterial.Metadata != "" {
//解析元数据
var materialMetaData map[string]interface{}
if err = json.Unmarshal([]byte(*userMaterial.Metadata), &materialMetaData); err != nil {
logx.Error("failed to parse user material`matadata: ", err)
return "", err
}
//赋值
replaceData["colors"] = materialMetaData["colors"]
replaceData["logo_url"] = materialMetaData["logo_url"]
replaceData["shape"] = materialMetaData["shape"]
replaceData["is_crop"] = materialMetaData["is_crop"]
replaceData["ratio"] = materialMetaData["ratio"]
replaceData["line"] = materialMetaData["line"]
replaceData["other"] = materialMetaData["other"]
replaceData["other1"] = materialMetaData["other1"]
}
}
combineInfo["param_data"] = replaceData
postData, _ := json.Marshal(combineInfo)
//请求合成图片
url := svcCtx.Config.PythonApi.CombineImageUrl
header := make(map[string]string) header := make(map[string]string)
header["content-type"] = "application/json" header["content-type"] = "application/json"
postData := "" // todo 请求数据要查出来 httpRsp, err := curl.ApiCall(url, "POST", header, bytes.NewReader(postData), 20)
httpRsp, err := curl.ApiCall(url, "POST", header, strings.NewReader(postData), 20)
if err != nil { if err != nil {
logx.Error("failed to combine logo:", err) logx.Error("failed to combine logo:", err)
return "", err return "", err

View File

@ -14,3 +14,5 @@ AWS:
AccessKeyID: AKIAZB2JKUXDPNRP4YT2 AccessKeyID: AKIAZB2JKUXDPNRP4YT2
Secret: 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 Secret: sjCEv0JxATnPCxno2KNLm0X8oDc7srUR+4vkYhvm
Token: Token:
PythonApi: #python接口
CombineImageUrl: http://192.168.1.7:45678/LogoCombine #合成刀版图接口

View File

@ -21,4 +21,7 @@ type Config struct {
} }
} }
} }
PythonApi struct {
CombineImageUrl string //合图url
}
} }

View File

@ -1,13 +1,9 @@
package handler package handler
import ( import (
"errors"
"net/http" "net/http"
"reflect"
"github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/httpx"
"fusenapi/utils/auth"
"fusenapi/utils/basic" "fusenapi/utils/basic"
"fusenapi/server/upload/internal/logic" "fusenapi/server/upload/internal/logic"
@ -18,72 +14,22 @@ import (
func UploadFileBackendHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { func UploadFileBackendHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
var ( var req types.UploadFileBackendReq
// 定义错误变量 userinfo, err := basic.RequestParse(w, r, svcCtx, &req)
err error
// 定义用户信息变量
userinfo *auth.UserInfo
)
// 解析JWT token,并对空用户进行判断
claims, err := svcCtx.ParseJwtToken(r)
// 如果解析JWT token出错,则返回未授权的JSON响应并记录错误消息
if err != nil { if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401, // 返回401状态码,表示未授权
Message: "unauthorized", // 返回未授权信息
})
logx.Info("unauthorized:", err.Error()) // 记录错误日志
return
}
if claims != nil {
// 从token中获取对应的用户信息
userinfo, err = auth.GetUserInfoFormMapClaims(claims)
// 如果获取用户信息出错,则返回未授权的JSON响应并记录错误消息
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 401,
Message: "unauthorized",
})
logx.Info("unauthorized:", err.Error())
return
}
} else {
// 如果claims为nil,则认为用户身份为白板用户
userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
}
var req types.RequestUploadFileBackend
// 如果端点有请求结构体则使用httpx.Parse方法从HTTP请求体中解析请求数据
if err := httpx.Parse(r, &req); err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 510,
Message: "parameter error",
})
logx.Info(err)
return
}
// 解析upload文件类型
err = basic.RequestFileParse(r, &req)
if err != nil {
httpx.OkJsonCtx(r.Context(), w, &basic.Response{
Code: 510,
Message: err.Error(),
})
return return
} }
// 创建一个业务逻辑层实例 // 创建一个业务逻辑层实例
l := logic.NewUploadFileBackendLogic(r.Context(), svcCtx) l := logic.NewUploadFileBackendLogic(r, svcCtx)
rl := reflect.ValueOf(l)
basic.BeforeLogic(w, r, rl)
resp := l.UploadFileBackend(&req, userinfo) resp := l.UploadFileBackend(&req, userinfo)
// 如果响应不为nil则使用httpx.OkJsonCtx方法返回JSON响应;
if resp != nil { if !basic.AfterLogic(w, r, rl, resp) {
httpx.OkJsonCtx(r.Context(), w, resp) basic.NormalAfterLogic(w, r, resp)
} else {
err := errors.New("server logic is error, resp must not be nil")
httpx.ErrorCtx(r.Context(), w, err)
logx.Error(err)
} }
} }
} }

View File

@ -64,8 +64,8 @@ func (l *UploadCallbackLogic) UploadCallback(req *types.UploadCallbackReq, useri
bucketName = basic.StorageBucketName bucketName = basic.StorageBucketName
} }
resourceModel := gmodel.NewFsResourceModel(l.svcCtx.MysqlConn) ctx := l.ctx
err := resourceModel.Trans(l.ctx, func(ctx context.Context, connGorm *gorm.DB) (err error) { err := l.svcCtx.MysqlConn.Transaction(func(connGorm *gorm.DB) error {
resourceModelTS := gmodel.NewFsResourceModel(l.svcCtx.MysqlConn) resourceModelTS := gmodel.NewFsResourceModel(l.svcCtx.MysqlConn)
resourceInfo, err := resourceModelTS.FindOneById(ctx, req.ResourceId) resourceInfo, err := resourceModelTS.FindOneById(ctx, req.ResourceId)
if err != nil { if err != nil {

View File

@ -3,18 +3,16 @@ package logic
import ( import (
"fusenapi/utils/auth" "fusenapi/utils/auth"
"fusenapi/utils/basic" "fusenapi/utils/basic"
"fusenapi/utils/check" "fusenapi/utils/file"
"fusenapi/utils/format" "fusenapi/utils/hash"
"time" "io"
"net/http"
"context" "context"
"fusenapi/server/upload/internal/svc" "fusenapi/server/upload/internal/svc"
"fusenapi/server/upload/internal/types" "fusenapi/server/upload/internal/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -22,109 +20,91 @@ type UploadFileBackendLogic struct {
logx.Logger logx.Logger
ctx context.Context ctx context.Context
svcCtx *svc.ServiceContext svcCtx *svc.ServiceContext
r *http.Request
} }
func NewUploadFileBackendLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UploadFileBackendLogic { func NewUploadFileBackendLogic(r *http.Request, svcCtx *svc.ServiceContext) *UploadFileBackendLogic {
return &UploadFileBackendLogic{ return &UploadFileBackendLogic{
Logger: logx.WithContext(ctx), Logger: logx.WithContext(r.Context()),
ctx: ctx, ctx: r.Context(),
svcCtx: svcCtx, svcCtx: svcCtx,
r: r,
} }
} }
// UploadFileBackend 这个函数接收一个文件上传请求和用户信息,处理文件上传,并返回响应 // 处理进入前逻辑w,r
func (l *UploadFileBackendLogic) UploadFileBackend(req *types.RequestUploadFileBackend, userinfo *auth.UserInfo) (resp *basic.Response) { // func (l *UploadFileBackendLogic) BeforeLogic(w http.ResponseWriter, r *http.Request) {
// }
// 处理逻辑后 w,r 如:重定向, resp 必须重新处理
// func (l *UploadFileBackendLogic) AfterLogic(w http.ResponseWriter, r *http.Request, resp *basic.Response) {
// // httpx.OkJsonCtx(r.Context(), w, resp)
// }
func (l *UploadFileBackendLogic) UploadFileBackend(req *types.UploadFileBackendReq, userinfo *auth.UserInfo) (resp *basic.Response) {
// 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data)
// userinfo 传入值时, 一定不为null // userinfo 传入值时, 一定不为null
// 检查用户是否是旁观者,旁观者没有文件上传权限
if userinfo.IsOnlooker() { if userinfo.IsOnlooker() {
// 如果是,返回未授权的错误码 // 如果是,返回未授权的错误码
return resp.SetStatus(basic.CodeUnAuth) return resp.SetStatus(basic.CodeUnAuth)
} }
// 定义用户ID和S3键名格式 // 定义用户ID和S3键名格式
var uid int64 var userId int64
var keytype format.TypeFormatS3KeyName var guestId int64
// 检查用户是否是游客 // 检查用户是否是游客
if userinfo.IsGuest() { if userinfo.IsGuest() {
// 如果是使用游客ID和游客键名格式 // 如果是使用游客ID和游客键名格式
uid = userinfo.GuestId guestId = userinfo.GuestId
keytype = format.TypeS3KeyGuest
} else { } else {
// 否则使用用户ID和用户键名格式 // 否则使用用户ID和用户键名格式
uid = userinfo.UserId userId = userinfo.UserId
keytype = format.TypeS3KeyUser
} }
// 设置AWS会话的区域 //设置内存大小
l.svcCtx.AwsSession.Config.Region = aws.String("us-west-1") l.r.ParseMultipartForm(32 << 20)
// 创建新的S3服务实例 fileObject, _, err := l.r.FormFile("file")
svc := s3.New(l.svcCtx.AwsSession)
// 检查类别是否合法
if !check.CheckCategory(req.Category) {
// 如果不合法,返回类别错误的错误码
return resp.SetStatus(basic.CodeS3CategoryErr)
}
// 定义S3请求和当前时间
var s3req *request.Request
now := time.Now()
// 格式化类别
category := format.TypeCategory(req.Category)
// 格式化S3对象键名
ObjectKey := aws.String(format.FormatS3KeyName(
keytype,
uid,
now,
l.svcCtx.Config.Env,
category,
req.File.Filename,
))
// 定义存储桶名称
var bucketName *string
// 根据类别选择存储桶
switch category {
case format.TCategoryRenderMegre:
bucketName = basic.TempfileBucketName
default:
bucketName = basic.StorageBucketName
}
// 创建S3对象存储请求
s3req, _ = svc.PutObjectRequest(
&s3.PutObjectInput{
Bucket: bucketName,
Key: ObjectKey,
},
)
// 设置请求体为文件数据
s3req.SetBufferBody(req.File.Data)
// 发送请求
err := s3req.Send()
// 检查是否有错误
if err != nil { if err != nil {
// 如果有,打印错误并返回错误码
logx.Error(err) logx.Error(err)
return resp.SetStatus(basic.CodeS3PutObjectRequestErr) return resp.SetStatus(basic.CodeFileUploadErr, "file upload err,no files")
} }
// 打印请求URL // 读取数据流
logx.Info(s3req.HTTPRequest.URL.String()) ioData, err := io.ReadAll(fileObject)
if err != nil {
logx.Error(err)
return resp.SetStatus(basic.CodeFileUploadErr, "file upload err,no files")
}
// 上传文件
var upload = file.Upload{
Ctx: l.ctx,
MysqlConn: l.svcCtx.MysqlConn,
AwsSession: l.svcCtx.AwsSession,
}
var resourceId string = hash.JsonHashKey(req.FileKey)
uploadRes, err := upload.UploadFileByByte(&file.UploadBaseReq{
FileHash: resourceId,
FileByte: ioData,
UploadBucket: req.UploadBucket,
ApiType: req.ApiType,
UserId: userId,
GuestId: guestId,
})
if err != nil {
logx.Error(err)
return resp.SetStatus(basic.CodeFileUploadErr, "upload file failed")
}
// 返回成功的响应和上传URL // 返回成功的响应和上传URL
return resp.SetStatus(basic.CodeOK, map[string]interface{}{ return resp.SetStatus(basic.CodeOK, map[string]interface{}{
"upload_url": s3req.HTTPRequest.URL.String(), "upload_data": UploadUrl{
Status: 1,
ResourceId: uploadRes.ResourceId,
ResourceUrl: uploadRes.ResourceUrl,
},
}) })
} }

View File

@ -145,7 +145,7 @@ func (l *UploadFilesBackendLogic) UploadFilesBackend(req *types.UploadFilesReq,
FileHash: resourceId, FileHash: resourceId,
FileByte: uploadDataInfo.FileData, FileByte: uploadDataInfo.FileData,
UploadBucket: 1, UploadBucket: 1,
ApiType: 2, ApiType: req.ApiType,
UserId: userId, UserId: userId,
GuestId: guestId, GuestId: guestId,
}) })

View File

@ -5,8 +5,8 @@ import (
"fusenapi/model/gmodel" "fusenapi/model/gmodel"
"fusenapi/utils/auth" "fusenapi/utils/auth"
"fusenapi/utils/basic" "fusenapi/utils/basic"
"fusenapi/utils/curl"
"io" "io"
"net/http"
"strings" "strings"
"time" "time"
@ -83,11 +83,17 @@ func (l *UploadLogoLogic) UploadLogo(req *types.UploadLogoReq, userinfo *auth.Us
} }
var resultStr string var resultStr string
var err error var err error
var postMap = make(map[string]interface{}, 1) var postMap = make(map[string]interface{}, 1)
postMap["logo_url"] = req.ResourceUrl postMap["logo_url"] = req.ResourceUrl
postMapB, _ := json.Marshal(postMap) postMapB, _ := json.Marshal(postMap)
result, err := http.Post(l.svcCtx.Config.BLMService.ImageProcess.Url, "application/json", strings.NewReader(string(postMapB))) //result, err := http.Post(l.svcCtx.Config.BLMService.ImageProcess.Url, "application/json", strings.NewReader(string(postMapB)))
var headerData = make(map[string]string, 1)
headerData["Content-Type"] = "application/json"
result, err := curl.ApiCall(l.svcCtx.Config.BLMService.ImageProcess.Url, "POST", headerData, strings.NewReader(string(postMapB)), 20)
if err != nil { if err != nil {
logx.Error(err) logx.Error(err)
return resp.SetStatus(basic.CodeFileUploadLogoErr, "service fail") return resp.SetStatus(basic.CodeFileUploadLogoErr, "service fail")

View File

@ -23,9 +23,11 @@ type UploadLogoReq struct {
SkuId int64 `form:"sku_id,default=0"` // 模板ID SkuId int64 `form:"sku_id,default=0"` // 模板ID
} }
type UploadInfo struct { type UploadFileBackendReq struct {
ApiType int64 `form:"api_type,options=[1,2],default=1"` // 调用类型1=对外2=对内
UploadBucket int64 `form:"upload_bucket,options=[1,2],default=1"` // 上传桶名:1=缓存,2=持久
FileKey string `form:"file_key"` // 上传唯一标识信息
FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息 FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息
FileKeys string `form:"file_keys,optional"` // 上传唯一标识信息
Metadata string `form:"meta_data,optional"` // 上传文件额外信息 Metadata string `form:"meta_data,optional"` // 上传文件额外信息
} }

View File

@ -89,14 +89,14 @@ func (l *DataTransferLogic) DataTransfer(svcCtx *svc.ServiceContext, w http.Resp
return return
} }
defer conn.Close() defer conn.Close()
//鉴权不成功10秒后断开 //鉴权不成功后断开
/*var ( /*var (
userInfo *auth.UserInfo userInfo *auth.UserInfo
isAuth bool isAuth bool
) )
isAuth, userInfo = l.checkAuth(svcCtx, r) isAuth, userInfo = l.checkAuth(svcCtx, r)
if !isAuth { if !isAuth {
time.Sleep(time.Second) //兼容下火狐 time.Sleep(time.Second * 4) //兼容下火狐
rsp := websocket_data.DataTransferData{ rsp := websocket_data.DataTransferData{
T: constants.WEBSOCKET_UNAUTH, T: constants.WEBSOCKET_UNAUTH,
D: nil, D: nil,
@ -132,10 +132,12 @@ func (l *DataTransferLogic) DataTransfer(svcCtx *svc.ServiceContext, w http.Resp
//保存连接 //保存连接
mapConnPool.Store(uniqueId, ws) mapConnPool.Store(uniqueId, ws)
defer ws.close() defer ws.close()
go func() {
//把连接成功消息发回去 //把连接成功消息发回去
time.Sleep(time.Second) //兼容下火狐 time.Sleep(time.Second * 4) //兼容下火狐
b := ws.respondDataFormat(constants.WEBSOCKET_CONNECT_SUCCESS, uniqueId) b := ws.respondDataFormat(constants.WEBSOCKET_CONNECT_SUCCESS, uniqueId)
_ = conn.WriteMessage(websocket.TextMessage, b) _ = conn.WriteMessage(websocket.TextMessage, b)
}()
//循环读客户端信息 //循环读客户端信息
go ws.readLoop() go ws.readLoop()
//循环把数据发送给客户端 //循环把数据发送给客户端

View File

@ -60,6 +60,7 @@ func (w *wsConnectItem) renderImage(data []byte) {
renderImageData.RenderData.Logo = "https://s3.us-west-1.amazonaws.com/storage.fusenpack.com/f5ccd11365099fa47a6316b1cd639f6dd6064dcd2d37c8d2fcd0a322160b33cc" renderImageData.RenderData.Logo = "https://s3.us-west-1.amazonaws.com/storage.fusenpack.com/f5ccd11365099fa47a6316b1cd639f6dd6064dcd2d37c8d2fcd0a322160b33cc"
} else { } else {
renderImageData.RenderData.Logo = *userMaterial.ResourceUrl renderImageData.RenderData.Logo = *userMaterial.ResourceUrl
renderImageData.RenderData.UserMaterialId = userMaterial.Id
} }
//用户id赋值 //用户id赋值
renderImageData.RenderData.UserId = w.userId renderImageData.RenderData.UserId = w.userId

View File

@ -17,7 +17,7 @@ service upload {
post /api/upload/upload-file-frontend(RequestUploadFileFrontend) returns (response); post /api/upload/upload-file-frontend(RequestUploadFileFrontend) returns (response);
@handler UploadFileBackendHandler @handler UploadFileBackendHandler
post /api/upload/upload-file-backend(RequestUploadFileBackend) returns (response); post /api/upload/upload-file-backend(UploadFileBackendReq) returns (response);
//生成二维码 //生成二维码
@handler UploadQrcodeHandler @handler UploadQrcodeHandler
post /api/upload/qrcode(UploadQrcodeReq) returns (response); post /api/upload/qrcode(UploadQrcodeReq) returns (response);
@ -67,9 +67,11 @@ type (
) )
type ( type (
UploadInfo { UploadFileBackendReq {
ApiType int64 `form:"api_type,options=[1,2],default=1"` // 调用类型1=对外2=对内
UploadBucket int64 `form:"upload_bucket,options=[1,2],default=1"` // 上传桶名:1=缓存,2=持久
FileKey string `form:"file_key"` // 上传唯一标识信息
FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息 FileSize int64 `form:"file_size,optional"` // 上传唯一标识信息
FileKeys string `form:"file_keys,optional"` // 上传唯一标识信息
Metadata string `form:"meta_data,optional"` // 上传文件额外信息 Metadata string `form:"meta_data,optional"` // 上传文件额外信息
} }

View File

@ -66,10 +66,9 @@ func (upload *Upload) UploadFileByBase64(req *UploadBaseReq) (*UploadBaseRes, er
var resourceId string = req.FileHash var resourceId string = req.FileHash
var uploadBaseRes = UploadBaseRes{} var uploadBaseRes = UploadBaseRes{}
resourceModel := gmodel.NewFsResourceModel(upload.MysqlConn) err := upload.MysqlConn.Transaction(func(tx *gorm.DB) error {
err := resourceModel.Trans(upload.Ctx, func(ctx context.Context, connGorm *gorm.DB) error { var resourceInfo *gmodel.FsResource
resourceModelTS := gmodel.NewFsResourceModel(connGorm) err := tx.Where("resource_id =?", resourceId).Take(&resourceInfo).Error
resourceInfo, err := resourceModelTS.FindOneById(ctx, resourceId)
if err == nil && resourceInfo.ResourceId != "" { if err == nil && resourceInfo.ResourceId != "" {
uploadBaseRes.Status = 1 uploadBaseRes.Status = 1
uploadBaseRes.ResourceId = resourceId uploadBaseRes.ResourceId = resourceId
@ -109,7 +108,7 @@ func (upload *Upload) UploadFileByBase64(req *UploadBaseReq) (*UploadBaseRes, er
uploadBaseRes.ResourceUrl = url uploadBaseRes.ResourceUrl = url
var version string = "0.0.1" var version string = "0.0.1"
var nowTime = time.Now() var nowTime = time.Now()
_, err = resourceModelTS.Create(upload.Ctx, &gmodel.FsResource{ err = tx.Create(&gmodel.FsResource{
ResourceId: resourceId, ResourceId: resourceId,
UserId: &req.UserId, UserId: &req.UserId,
GuestId: &req.GuestId, GuestId: &req.GuestId,
@ -120,15 +119,18 @@ func (upload *Upload) UploadFileByBase64(req *UploadBaseReq) (*UploadBaseRes, er
Metadata: &req.Metadata, Metadata: &req.Metadata,
ApiType: &apiType, ApiType: &apiType,
BucketName: bucketName, BucketName: bucketName,
}) }).Error
if err != nil { if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoAdd.mysql") logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoAdd.mysql")
return err return err
} }
} }
} }
// 返回 nil 提交事务
return nil return nil
}) })
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -161,10 +163,11 @@ func (upload *Upload) UploadFileByByte(req *UploadBaseReq) (*UploadBaseRes, erro
var resourceId string = req.FileHash var resourceId string = req.FileHash
var uploadBaseRes = UploadBaseRes{} var uploadBaseRes = UploadBaseRes{}
resourceModel := gmodel.NewFsResourceModel(upload.MysqlConn)
err := resourceModel.Trans(upload.Ctx, func(ctx context.Context, connGorm *gorm.DB) error { err := upload.MysqlConn.Transaction(func(tx *gorm.DB) error {
resourceModelTS := gmodel.NewFsResourceModel(connGorm) var resourceInfo *gmodel.FsResource
resourceInfo, err := resourceModelTS.FindOneById(ctx, resourceId) err := tx.Where("resource_id =?", resourceId).Take(&resourceInfo).Error
// resourceInfo, err := resourceModelTS.FindOneById(ctx, resourceId)
if err == nil && resourceInfo.ResourceId != "" { if err == nil && resourceInfo.ResourceId != "" {
uploadBaseRes.Status = 1 uploadBaseRes.Status = 1
uploadBaseRes.ResourceId = resourceId uploadBaseRes.ResourceId = resourceId
@ -198,7 +201,7 @@ func (upload *Upload) UploadFileByByte(req *UploadBaseReq) (*UploadBaseRes, erro
uploadBaseRes.ResourceUrl = url uploadBaseRes.ResourceUrl = url
var version string = "0.0.1" var version string = "0.0.1"
var nowTime = time.Now() var nowTime = time.Now()
_, err = resourceModelTS.Create(upload.Ctx, &gmodel.FsResource{ err = tx.Create(&gmodel.FsResource{
ResourceId: resourceId, ResourceId: resourceId,
UserId: &req.UserId, UserId: &req.UserId,
GuestId: &req.GuestId, GuestId: &req.GuestId,
@ -209,7 +212,7 @@ func (upload *Upload) UploadFileByByte(req *UploadBaseReq) (*UploadBaseRes, erro
Metadata: &req.Metadata, Metadata: &req.Metadata,
ApiType: &apiType, ApiType: &apiType,
BucketName: bucketName, BucketName: bucketName,
}) }).Error
if err != nil { if err != nil {
logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoAdd.mysql") logx.Errorf("err:%+vdesc:%+v", err, "fail.upload.resourceInfoAdd.mysql")
return err return err

View File

@ -14,6 +14,7 @@ type RenderImageReqMsg struct {
type RenderData struct { type RenderData struct {
TemplateTagId int64 `json:"template_tag_id"` //模板标签id TemplateTagId int64 `json:"template_tag_id"` //模板标签id
ProductId int64 `json:"product_id"` //产品id ProductId int64 `json:"product_id"` //产品id
UserMaterialId int64 `json:"user_material_id"` //用户素材id
Logo string `json:"logo"` //log资源地址(websocket连接建立再赋值) Logo string `json:"logo"` //log资源地址(websocket连接建立再赋值)
UserId int64 `json:"user_id"` //用户id(websocket连接建立再赋值) UserId int64 `json:"user_id"` //用户id(websocket连接建立再赋值)
GuestId int64 `json:"guest_id"` //游客id(websocket连接建立再赋值) GuestId int64 `json:"guest_id"` //游客id(websocket连接建立再赋值)