From 69ad23a7dd3f7986e571bb48aeb3c8f31537ebc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=82=B9=E5=AE=97=E6=A5=A0?= Date: Fri, 5 Jan 2024 16:19:35 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- business/model/print_open.go | 96 ++++++++ controllers/api_controller.go | 452 ++++++++++++++++++++++++++++++++++ routers/router.go | 7 + 3 files changed, 555 insertions(+) create mode 100644 business/model/print_open.go create mode 100644 controllers/api_controller.go diff --git a/business/model/print_open.go b/business/model/print_open.go new file mode 100644 index 000000000..40a7acd17 --- /dev/null +++ b/business/model/print_open.go @@ -0,0 +1,96 @@ +package model + +const ( + PrinterStatusOnlineWithoutPaper = 2 //在线缺纸 + PrinterStatusOnline = 1 //在线正常 + PrinterStatusOffline = -1 //离线 + PrinterStatusNoFlow = -2 //当月流量超30m了 + + PrintMsgAlreadySend = 2 //已经发出打印消息 + PrintMsgSuccess = 1 //打印成功 + PrintMsgWait = 0 //待打印 + PrintMsgFail = -1 //打印失败(打印机报出) + PrintMsgErr = -2 //京西报出 + PrintMsgAll = -9 +) + +type AddPrinterParam struct { + PrintNo string `json:"print_no"` //打印机编号 + Name string `json:"name"` //打印机备注名 + SIM string `json:"sim"` //sim卡号-电话号码,接受验证的电话 + StoreId int64 `json:"store_id"` // 门店id +} + +//type Printer struct { +// ModelIDCULD +// +// AppID int `orm:"column(app_id)" json:"app_id" db:"app_id"` //应用编号 +// PrintNo string `json:"print_no" db:"print_no"` //打印机编号 +// PrintKey string `json:"print_key" db:"print_key"` //打印机识别码 +// Name string `json:"name" db:"name"` //打印机备注名 +// Status int `json:"status" db:"status"` //打印机状态 +// IsOnline int `json:"is_online" db:"is_online"` //1在线,0离线 +// IccID string `orm:"column(icc_id)" json:"IccID" db:"icc_id"` //sim卡号 +// Sound string `json:"sound" db:"sound"` //声音类型 sounda ,b,c,d,e,f,g +// Volume int `json:"volume" db:"volume"` //音量,1-5 ,对应打印机2-10 +// FlowFlag int `json:"flowFlag" db:"flow_flag"` //是否超流量了,1表示超了 +// OfflineCount int `json:"offlineCount" db:"offline_count"` //掉线次数 +// UserId string `orm:"column(user_id)" json:"user_id" db:"user_id"` //用户id +//} + +func (v *Printer) TableIndex() [][]string { + return [][]string{ + []string{"PrintNo"}, + } +} + +// +//type PrintMsg struct { +// ModelIDCULD +// +// MsgID string `orm:"column(msg_id)" json:"msg_id" db:"msg_id"` //消息ID +// PrintNo string `json:"print_no" db:"print_no"` //打印机编号 +// OrderNo string `json:"order_no" db:"order_no"` //订单序号 +// Content string `orm:"type(text)" json:"content" db:"content"` //订单内容 +// Status int `json:"status" db:"status"` //打印状态 +// Comment string `json:"comment" db:"comment"` //失败原因 +// ContentEncryption string `orm:"type(text)" json:"content_encryption" db:"content_encryption"` //订单类容进制文件 +//} + +func (v *PrintMsg) TableIndex() [][]string { + return [][]string{ + []string{"PrintNo"}, + } +} + +//流量支出 +//type SimFlowExpend struct { +// ModelIDCUL +// +// IccID string `orm:"column(icc_id)" json:"iccID" db:"icc_id"` //sim卡iccid +// Flow float64 `json:"flow" db:"flow"` //流量数 +// FlowUnit string `json:"flowUnit" db:"flow_unit"` //流量单位 +//} + +func (v *SimFlowExpend) TableIndex() [][]string { + return [][]string{ + []string{"IccID"}, + } +} + +//流量划入 +//type SimFlowIncome struct { +// ModelIDCUL +// +// IccID string `orm:"column(icc_id)" json:"iccID" db:"icc_id"` //sim卡iccid +// Flow float64 `json:"flow" db:"flow"` //流量数 +// FlowUnit string `json:"flowUnit" db:"flow_unit"` //流量单位 +// IncomeType int `json:"incomeType" db:"income_type"` //1 表示系统每月自动划转,2 表示商户自己冲的 +// OrderID string `orm:"column(order_id)" json:"order_id" db:"order_id"` //订单号 +//} + +func (v *SimFlowIncome) TableIndex() [][]string { + return [][]string{ + []string{"IccID"}, + } +} diff --git a/controllers/api_controller.go b/controllers/api_controller.go new file mode 100644 index 000000000..fb51f7e82 --- /dev/null +++ b/controllers/api_controller.go @@ -0,0 +1,452 @@ +package controllers + +import ( + "bytes" + "crypto/md5" + "encoding/json" + "errors" + "fmt" + "git.rosy.net.cn/baseapi/utils" + "git.rosy.net.cn/jx-callback/business/jxstore/cms" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/jx-callback/business/model" + "git.rosy.net.cn/jx-callback/business/model/dao" + "git.rosy.net.cn/jx-callback/globals" + "github.com/astaxie/beego/client/orm" + "github.com/astaxie/beego/server/web" + "net/http" + "net/url" + "reflect" + "strconv" + "strings" + "time" +) + +type ApiController struct { + web.Controller +} + +const ( + keyAppID = "app_id" + keyTimestamp = "timestamp" + keyMethod = "method" + keySign = "sign" +) + +const ( + keyPrintNo = "print_no" + keyPrintKey = "print_key" + keyName = "name" + keyStatus = "status" + keyOrderNo = "order_no" + keyContent = "content" + keyMsgID = "msg_id" + keySound = "sound" + keyVolume = "volume" + keySim = "sim" +) + +var ( + routerMap map[string]reflect.Value +) + +func Init() { + routerMap = make(map[string]reflect.Value) + var ruTest ApiController + vf := reflect.ValueOf(&ruTest) + vft := vf.Type() + //读取方法数量 + mNum := vf.NumMethod() + fmt.Println("mNum", mNum) + //遍历路由器的方法,并将其存入控制器映射变量中 + for i := 0; i < mNum; i++ { + mName := vft.Method(i).Name + routerMap[mName] = vf.Method(i) + } +} + +// @Title api调用入口 +// @Description api调用入口 +// @Param app_id formData string false "应用ID" +// @Param timestamp formData int64 false "unix时间戳" +// @Param sign formData string false "签名" +// @Param method formData string false "接口名" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /CallOpenAPI [post] +func (c *ApiController) CallOpenAPI() { + var ( + err error + errCode = model.ErrCodeGeneralFailed + callResult = &CallResult{} + accessID = utils.GetUUID() + requireParams []string + dataMap = make(map[string]interface{}) + now = time.Now().Unix() + parms, result []reflect.Value + urls = url.Values{} + app = &model.Apps{} + db = dao.GetDB() + ) + var ( + appID int + sign, method string + timestamp int64 + ) + //判断必传参数是否传入begin + if appID, err = c.GetInt(keyAppID); err != nil { + requireParams = append(requireParams, keyAppID) + } + if method = c.GetString(keyMethod); method == "" { + requireParams = append(requireParams, keyMethod) + } + if sign = c.GetString(keySign); sign == "" { + requireParams = append(requireParams, keySign) + } + if timestamp, err = c.GetInt64(keyTimestamp); err != nil { + requireParams = append(requireParams, keyTimestamp) + } + if len(requireParams) > 0 { + err = buildParamRequiredErr(requireParams) + } + //判断必传参数是否传入end + if err != nil { + goto end + } + //判断timestamp传入是否正确begin + if len(utils.Int64ToStr(timestamp)) != len(utils.Int64ToStr(now)) { + err = buildTimestampParamErr() + errCode = model.ErrCodeOpenAPIParamErrTimeStamp + } + //判断timestamp传入是否正确end + if err != nil { + goto end + } + //判断app_id和sign匹配begin ,sign = app_id + app_key + timestamp的MD5加密 + app.ID = appID + if err = dao.GetEntity(db, app); err != nil { + if err == orm.ErrNoRows { + err = fmt.Errorf("未查询到该应用!app_id: %v", appID) + } + goto end + } else { + if app.Status != model.UserStatusNormal || app.DeletedAt != utils.DefaultTimeValue { + errCode = model.ErrCodeGeneralFailed + err = fmt.Errorf("很抱歉您的应用已失效!") + goto end + } + appKey := app.AppKey + signOrigin := fmt.Sprintf("%x", md5.Sum([]byte(utils.Int2Str(appID)+appKey+utils.Int64ToStr(timestamp)))) + if strings.Compare(sign, signOrigin) != 0 { + errCode = model.ErrCodeOpenAPIParamErrSign + err = buildMethodParamSign() + goto end + } + } + //判断app_id和sign匹配end + //call + urls, _ = c.Input() + dataMap = utils.URLValues2Map(urls) + delete(dataMap, keyMethod) + delete(dataMap, keyTimestamp) + delete(dataMap, keySign) + parms = []reflect.Value{reflect.ValueOf(dataMap)} + if routerMap[method] == reflect.ValueOf(nil) { + errCode = model.ErrCodeOpenAPIParamErrMethod + err = buildMethodParamErr() + goto end + } + globals.SugarLogger.Debugf("Begin API CallOpenAPI Method: %s, accessUUID:%s, sign:%s, ip:%s\n", method, accessID, sign, getRealRemoteIP(c.Ctx.Request)) + if err == nil { + result = routerMap[method].Call(parms) + if result[2].Interface() != nil { + err = result[2].Interface().(error) + errCode = result[1].String() + goto end + } + goto success + } else { + callResult.Code = errCode + callResult.Desc = err.Error() + goto end + } +success: + { + c.Ctx.ResponseWriter.Header().Set("Content-Type", "application/json; charset=utf-8") + callResult.Code = model.ErrCodeSuccess + if len(result) > 0 { + callResult.Data = result[0].Interface() + } + c.Data["json"] = callResult + c.ServeJSON() + } +end: + { + callResult.Code = errCode + if err != nil { + callResult.Desc = err.Error() + } + c.Data["json"] = callResult + c.ServeJSON() + } +} + +//添加打印机,一次最多50条 +func (c *ApiController) AddPrinter(dataMap map[string]interface{}) (data, errCode string, err error) { + var ( + printers []*model.AddPrinterParam + appID int + ) + globals.SugarLogger.Debugf("Begin API AddPrinter data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap["prints"].(string); !ok { + return buildParamErrCodeAndErr("prints_str_nil") + } + + if err = utils.UnmarshalUseNumber([]byte(dataMap["prints"].(string)), &printers); err != nil { + return buildParamErrCodeAndErr("prints_bind_fail") + } + + for _, v := range printers { + if v.PrintNo == "" { + return buildParamErrCodeAndErr("prints_no_nil") + } + } + + appID = utils.Str2Int(dataMap[keyAppID].(string)) + if err = cms.AddPrinter(appID, printers); err != nil { + return "", model.ErrCodeGeneralFailed, err + } + return "", errCode, err +} + +//删除打印机绑定 +func (c *ApiController) DelPrinter(dataMap map[string]interface{}) (data, errCode string, err error) { + var ( + printNos []string + printNosStr string + appID int + storeId string + ) + globals.SugarLogger.Debugf("Begin API DelPrinter data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap["print_nos"].(string); !ok { + return buildParamErrCodeAndErr("print_nos") + } else { + if printNosStr = dataMap["print_nos"].(string); printNosStr == "" { + return buildParamErrCodeAndErr("print_nos") + } + } + if _, ok := dataMap["storeId"].(string); !ok { + return buildParamErrCodeAndErr("storeId") + } + if err = utils.UnmarshalUseNumber([]byte(printNosStr), &printNos); err != nil { + return buildParamErrCodeAndErr("print_nos") + } + for _, v := range printNos { + if v == "" { + return buildParamErrCodeAndErr("print_nos") + } + } + appID = utils.Str2Int(dataMap[keyAppID].(string)) + if err = cms.DelPrinter(appID, printNos, storeId); err != nil { + return "", model.ErrCodeGeneralFailed, err + } + return "", errCode, err +} + +//修改打印机信息 +func (c *ApiController) UpdatePrinter(dataMap map[string]interface{}) (data, errCode string, err error) { + var ( + printNo string + name, sim, sound *string + volume *int + appID int + ) + globals.SugarLogger.Debugf("Begin API UpdatePrinter data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap[keyPrintNo].(string); !ok { + return buildParamErrCodeAndErr(keyPrintNo) + } else { + if printNo = dataMap[keyPrintNo].(string); printNo == "" { + return buildParamErrCodeAndErr(keyPrintNo) + } + } + if nameStr, ok := dataMap[keyName].(string); !ok { + name = nil + } else { + name = &nameStr + } + if simStr, ok := dataMap[keySim].(string); !ok { + sim = nil + } else { + sim = &simStr + } + if soundStr, ok := dataMap[keySound].(string); !ok { + sound = nil + } else { + sound = &soundStr + } + if volumeStr, ok := dataMap[keyVolume].(string); !ok { + volume = nil + } else { + if volumeInt64, err2 := strconv.ParseInt(volumeStr, 10, 64); err2 == nil { + volumeInt := int(volumeInt64) + volume = &volumeInt + } else { + return buildParamErrCodeAndErr(keyVolume) + } + } + appID = utils.Str2Int(dataMap[keyAppID].(string)) + if err = cms.UpdatePrinter(appID, printNo, name, sim, sound, volume); err != nil { + globals.SugarLogger.Debugf("End API UpdatePrinter err: %v", err) + return "", model.ErrCodeGeneralFailed, err + } + return "", errCode, err +} + +//清空打印机队列 +func (c *ApiController) DelPrinterSeq(dataMap map[string]interface{}) (data, errCode string, err error) { + var ( + printNo string + appID int + ) + globals.SugarLogger.Debugf("Begin API DelPrinterSeq data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap[keyPrintNo].(string); !ok { + return buildParamErrCodeAndErr(keyPrintNo) + } else { + if printNo = dataMap[keyPrintNo].(string); printNo == "" { + return buildParamErrCodeAndErr(keyPrintNo) + } + } + appID = utils.Str2Int(dataMap[keyAppID].(string)) + if err = cms.DelPrinterSeq(appID, printNo); err != nil { + return "", model.ErrCodeGeneralFailed, err + } + return "", errCode, err +} + +//发送打印消息 +func (c *ApiController) DoPrint(dataMap map[string]interface{}) (data, errCode string, err error) { + var ( + printNo, content string + appID int + orderNo string + ) + globals.SugarLogger.Debugf("Begin API DoPrint data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap[keyPrintNo].(string); !ok { + return buildParamErrCodeAndErr(keyPrintNo) + } + + if _, ok := dataMap[keyContent].(string); !ok { + return buildParamErrCodeAndErr(keyContent) + } + + if _, ok := dataMap[keyOrderNo].(string); !ok { + return buildParamErrCodeAndErr(keyOrderNo) + } + + appID = utils.Str2Int(dataMap[keyAppID].(string)) + msgID := time.Now().Format("20060102150405") + "_" + jxutils.RandStringBytes(8) + printNo = dataMap[keyPrintNo].(string) + orderNo = dataMap[keyOrderNo].(string) + content = dataMap[keyContent].(string) + // 打印文件转结构体 + contentMap := make(map[string]string) + if err := json.Unmarshal([]byte(content), &contentMap); err != nil { + globals.SugarLogger.Debugf("json.Unmarshal 1 err := %v", err) + return "", model.ErrCodeGeneralFailed, err + } + // 查询打印机设置 + printSetting, err := dao.GetPrintSetting(printNo) + if err != nil { + globals.SugarLogger.Debugf("GetPrintSetting 2 err := %v", err) + return "", model.ErrCodeGeneralFailed, err + } + printObj, err := dao.QueryUserPrinter("", printNo) + if err != nil { + globals.SugarLogger.Debugf("QueryUserPrinter 3 err := %v", err) + return "", model.ErrCodeGeneralFailed, err + } + + // 查询用户模板 + printMsg, err := dao.MakePrintMsgOnTempVoice(contentMap, printSetting, printObj.UserId) + if err != nil { + globals.SugarLogger.Debugf("MakePrintMsgOnTempVoice 4 err := %v", err) + return "", model.ErrCodeGeneralFailed, err + } + if printMsg == "" { + return "", model.ErrCodeGeneralFailed, errors.New("无打印数据") + } + content = printMsg + + if err = cms.DoPrintMsg(appID, msgID, printNo, content, orderNo); err != nil { + globals.SugarLogger.Debugf("DoPrint 5 err := %v", err) + return "", model.ErrCodeGeneralFailed, err + } + return msgID, errCode, err +} + +//获取某打印消息 +func (c *ApiController) GetPrintMsg(dataMap map[string]interface{}) (data map[string]interface{}, errCode string, err error) { + var ( + msgID string + appID int + ) + globals.SugarLogger.Debugf("Begin API GetPrintMsg data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap[keyMsgID].(string); !ok { + return data, model.ErrCodeOpenAPIParamErrNormal, fmt.Errorf("参数[%s]错误,请传入正确的值!", keyMsgID) + } else { + if msgID = dataMap[keyMsgID].(string); msgID == "" { + return data, model.ErrCodeOpenAPIParamErrNormal, fmt.Errorf("参数[%s]错误,请传入正确的值!", keyMsgID) + } + } + appID = utils.Str2Int(dataMap[keyAppID].(string)) + if printMsg, err := cms.GetPrintMsg(appID, msgID); err != nil { + return data, model.ErrCodeGeneralFailed, err + } else if printMsg == nil { + return data, model.ErrCodeGeneralFailed, fmt.Errorf("未查询到该消息! msg_id: %v", msgID) + } else { + bf := bytes.NewBuffer([]byte{}) + jsonEncoder := json.NewEncoder(bf) + jsonEncoder.SetEscapeHTML(false) + jsonEncoder.Encode(printMsg) + json.Unmarshal([]byte(bf.String()), &data) + return data, model.ErrCodeGeneralFailed, err + } + return data, errCode, err +} + +//查询打印机状态 +func (c *ApiController) GetPrinterStatus(dataMap map[string]interface{}) (data, errCode string, err error) { + var ( + printNo string + //appID int + ) + globals.SugarLogger.Debugf("Begin API GetPrinterStatus data: [%v]", utils.Format4Output(dataMap, false)) + if _, ok := dataMap[keyPrintNo].(string); !ok { + return buildParamErrCodeAndErr(keyPrintNo) + } else { + if printNo = dataMap[keyPrintNo].(string); printNo == "" { + return buildParamErrCodeAndErr(keyPrintNo) + } + } + appID := utils.Str2Int(dataMap[keyAppID].(string)) + if status, err := cms.GetPrinterStatus(appID, printNo); err != nil { + return "", model.ErrCodeGeneralFailed, err + } else { + return utils.Int2Str(status), errCode, err + } +} + +func getRealRemoteIP(r *http.Request) (ip string) { + if r != nil { + ip = r.Header.Get("X-Forwarded-For") + if ip == "" { + ip = r.Header.Get("X-real-ip") + } + if ip == "" { + ip = strings.Split(r.RemoteAddr, ":")[0] + } else { + ip = strings.Split(ip, ",")[0] + } + } + return ip +} diff --git a/routers/router.go b/routers/router.go index 9f010da29..4fc2bda32 100644 --- a/routers/router.go +++ b/routers/router.go @@ -85,6 +85,13 @@ func init() { &controllers.RechargeManagerController{}, ), ), + + /*****************打印机openAPI**********************/ + web.NSNamespace("/openapi", + web.NSInclude( + &controllers.ApiController{}, + ), + ), ) web.AddNamespace(ns)