diff --git a/business/jxutils/unipush/push.go b/business/jxutils/unipush/push.go index 26dad7ee1..f919d29a0 100644 --- a/business/jxutils/unipush/push.go +++ b/business/jxutils/unipush/push.go @@ -20,7 +20,7 @@ const ( SoundsFileNewOrder = "newOrder.caf" SoundsFileNewAfsOrder = "afsOrder.caf" SoundsFileNewCancelOrder = "cancelOrder.caf" - SoundsFileNewImMsg = "" //TODO 待定 + SoundsFileNewImMsg = "newMsg.caf" ) // NotifyNewOrder 推送新订单 @@ -116,19 +116,11 @@ func NotifyImNewMessage(vendorStoreID string, vendorID int) error { if len(vendorStoreID) == 0 { return nil } - var ( - temp = 0 - msg = MsgContext{} - ) - if vendorID == 10 { //美团 - temp = 1 - } else if vendorID == 11 { //饿了么 - temp = 3 - } + var msg = MsgContext{} - store, err := dao.GetStoreBaseByVendorStoreID(vendorStoreID, temp) + store, err := dao.GetStoreBaseByVendorStoreID(vendorStoreID, vendorID) if err != nil { - return fmt.Errorf("未查到此门店:%s", vendorStoreID) + return fmt.Errorf("未查到此门店/门店未与平台正常绑定:%s", vendorStoreID) } cid, err := GetStoreBoosCID(store.ID) @@ -138,13 +130,12 @@ func NotifyImNewMessage(vendorStoreID string, vendorID int) error { } fmt.Print(cid) msg.MsgType = "newImMsg" - msg.VendorName = model.VendorChineseNames[temp] + msg.VendorName = model.VendorChineseNames[vendorID] msg.StoreTitle = store.Name msg.Context = "老板,你有新的用户消息,请及时查看!" context, _ := json.Marshal(msg) - body := fmt.Sprintf(msg.Context+"(%s)", model.VendorChineseNames[temp]) - pushMsgByUniApp(store.ID, store.Name, cid, string(context), body, SoundsFileNewImMsg) + pushMsgByUniApp(store.ID, store.Name, cid, string(context), "", SoundsFileNewImMsg) return err } diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 507137c3f..a15939678 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -3,10 +3,11 @@ package weixinmsg import ( "encoding/json" "fmt" - "git.rosy.net.cn/baseapi/platformapi/weixinapi" "strings" "time" + "git.rosy.net.cn/baseapi/platformapi/weixinapi" + beego "github.com/astaxie/beego/server/web" "git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin" @@ -48,6 +49,7 @@ const ( WX_TEMPLATE_VENDERCOLOR_ELM = "#0191EA" //蓝色 WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS = "#4F4DA0" + WX_NEWORDER_TEMPLATE_ID2 = "b8-tLyWwAmK-1tEU1eGqp_YAAqQtSzoVDZkHuyUe9lk" //微信新订单推送2 WX_NEWORDER_TEMPLATE_ID = "_DtNGwmOeR6TkkTVUblxLIlkV2MAPOX57TkvfdqG6nY" //微信新订单推送 WX_ADJUSTORDER_TEMPLATE_ID = "N5rmV2-PDf3opjkv23IdLc76VnFThr_uOKSh5FzT13M" //微信调整订单推送 WX_MTPS_DELIVERY_GRABDONE_TEMPLATE_ID = "h4dkON6AgnHz1XmaksEUB_8Bcir4V8MSexUhC149pPE" //微信美团配送员接单推送 @@ -197,6 +199,7 @@ func getOrderDetailBrief(order *model.GoodsOrder) (brief string) { return sb.String() } +//新订单推送模板2 func NotifyNewOrder(order *model.GoodsOrder) (err error) { if order.VendorID == model.VendorIDELM { return nil @@ -210,49 +213,90 @@ func NotifyNewOrder(order *model.GoodsOrder) (err error) { globals.SugarLogger.Infof("NotifyNewOrder orderID:%s is not solid", order.VendorOrderID) return nil } - suffix := "" storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") - if err == nil && storeDetail != nil { - suffix = storeDetail.CityName + "," + storeDetail.Name - } - sb := new(strings.Builder) - sb.WriteString(suffix + "老板,") - sb.WriteString(order.ConsigneeName) - sb.WriteString("购买了商品") - sb.WriteString(getOrderDetailBrief(order)) + data := map[string]interface{}{ - "first": map[string]interface{}{ - "value": sb.String(), - "color": WX_NEW_ORDER_TEMPLATE_COLOR, - }, - "Day": map[string]interface{}{ - "value": FormatDeliveryTime(order), - "color": WX_NEW_ORDER_TEMPLATE_COLOR, - }, - "orderId": map[string]interface{}{ - "value": order.VendorOrderID, - "color": WX_NEW_ORDER_TEMPLATE_COLOR, - }, - "orderType": map[string]interface{}{ - "value": fmt.Sprintf("%s 第%d号订单", model.VendorChineseNames[order.VendorID], order.OrderSeq), + "keyword1": map[string]interface{}{ //订单来源 + "value": fmt.Sprintf("%s #%d", model.VendorChineseNames[order.VendorID], order.OrderSeq), "color": VendorColors[order.VendorID], }, - "customerName": map[string]interface{}{ - "value": order.ConsigneeName, + "keyword2": map[string]interface{}{ //商家信息 + "value": storeDetail.Name, "color": WX_NEW_ORDER_TEMPLATE_COLOR, }, - "customerPhone": map[string]interface{}{ - "value": order.ConsigneeMobile, + "keyword3": map[string]interface{}{ //顾客信息 + "value": order.ConsigneeName + " " + order.ConsigneeMobile, + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword4": map[string]interface{}{ //下单时间及金额 + "value": utils.Time2Str(order.CreatedAt) + "(¥" + utils.Int64ToStr(order.ActualPayPrice) + ")", + "color": WX_NEW_ORDER_TEMPLATE_COLOR, + }, + "keyword5": map[string]interface{}{ //配送时间 + "value": order.ExpectedDeliveredTime, "color": WX_NEW_ORDER_TEMPLATE_COLOR, }, } storeID := jxutils.GetSaleStoreIDFromOrder(order) - //return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL+fmt.Sprintf("?jxStoreId=%v", storeID), data) - //dataStore := fmt.Sprintf(`{"address":"%s","cityName":"%s","id":%d,"name":"%s","payeeName":"%s","status":%d,"tel1":"%s","tel2":"%s"}`, storeDetail.Address, storeDetail.CityName, storeDetail.ID, storeDetail.Name, storeDetail.PayeeName, storeDetail.Status, storeDetail.Tel1, storeDetail.Tel2) - //url := WX_MINI_TO_ORDER_PAGE_URL + fmt.Sprintf("?jxStoreId=%v&data=%v", storeID, dataStore) - return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) + return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID2, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) } +//func NotifyNewOrder(order *model.GoodsOrder) (err error) { +// if order.VendorID == model.VendorIDELM { +// return nil +// } +// +// if len(order.Skus) == 0 { +// return nil +// } +// +// if !model.IsOrderSolid(order) { +// globals.SugarLogger.Infof("NotifyNewOrder orderID:%s is not solid", order.VendorOrderID) +// return nil +// } +// suffix := "" +// storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "") +// if err == nil && storeDetail != nil { +// suffix = storeDetail.CityName + "," + storeDetail.Name +// } +// sb := new(strings.Builder) +// sb.WriteString(suffix + "老板,") +// sb.WriteString(order.ConsigneeName) +// sb.WriteString("购买了商品") +// sb.WriteString(getOrderDetailBrief(order)) +// data := map[string]interface{}{ +// "first": map[string]interface{}{ +// "value": sb.String(), +// "color": WX_NEW_ORDER_TEMPLATE_COLOR, +// }, +// "Day": map[string]interface{}{ +// "value": FormatDeliveryTime(order), +// "color": WX_NEW_ORDER_TEMPLATE_COLOR, +// }, +// "orderId": map[string]interface{}{ +// "value": order.VendorOrderID, +// "color": WX_NEW_ORDER_TEMPLATE_COLOR, +// }, +// "orderType": map[string]interface{}{ +// "value": fmt.Sprintf("%s 第%d号订单", model.VendorChineseNames[order.VendorID], order.OrderSeq), +// "color": VendorColors[order.VendorID], +// }, +// "customerName": map[string]interface{}{ +// "value": order.ConsigneeName, +// "color": WX_NEW_ORDER_TEMPLATE_COLOR, +// }, +// "customerPhone": map[string]interface{}{ +// "value": order.ConsigneeMobile, +// "color": WX_NEW_ORDER_TEMPLATE_COLOR, +// }, +// } +// storeID := jxutils.GetSaleStoreIDFromOrder(order) +// //return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL+fmt.Sprintf("?jxStoreId=%v", storeID), data) +// //dataStore := fmt.Sprintf(`{"address":"%s","cityName":"%s","id":%d,"name":"%s","payeeName":"%s","status":%d,"tel1":"%s","tel2":"%s"}`, storeDetail.Address, storeDetail.CityName, storeDetail.ID, storeDetail.Name, storeDetail.PayeeName, storeDetail.Status, storeDetail.Tel1, storeDetail.Tel2) +// //url := WX_MINI_TO_ORDER_PAGE_URL + fmt.Sprintf("?jxStoreId=%v&data=%v", storeID, dataStore) +// return SendMsgToStore(storeID, WX_NEWORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) +//} + func NotifyWaybillStatus(bill *model.Waybill, order *model.GoodsOrder, isBillAlreadyCandidate bool) (err error) { if order.VendorID == model.VendorIDELM { return nil diff --git a/business/model/api_config.go b/business/model/api_config.go index 0ceb110b2..298283ac0 100644 --- a/business/model/api_config.go +++ b/business/model/api_config.go @@ -2,9 +2,6 @@ package model // VendorIDJD, VendorIDMTWM与VendorIDELM的定义和老系统是兼容的 const ( - IMVendorIDMT = "10" //美团IM - IMVendorIDELM = "11" //饿了么im - VendorTypeUnknown = 0 // 未知 VendorTypePurchase = 1 // 购物平台 VendorTypeDelivery = 2 // 快递平台 diff --git a/business/model/dao/store.go b/business/model/dao/store.go index 35ed12a53..86884ee2d 100644 --- a/business/model/dao/store.go +++ b/business/model/dao/store.go @@ -1653,9 +1653,9 @@ func GetStoreBaseByVendorStoreID(vendorStoreID string, vendorID int) (storeDetai return nil, errors.New("vendorStoreID不能为空") } - DefaultTimeValue := utils.Str2Time("1970-01-01 00:00:00") - sql := `SELECT t.* FROM store t WHERE t.id = (SELECT s.store_id FROM store_map s WHERE s.vendor_store_id= ? AND s.vendor_id= ? AND s.deleted_at= ? )` - if err := GetRow(GetDB(), &storeDetail, sql, []interface{}{vendorStoreID, vendorID, DefaultTimeValue}); err != nil { + //DefaultTimeValue := utils.Str2Time("1970-01-01 00:00:00") + sql := `SELECT t.* FROM store t WHERE t.id = (SELECT s.store_id FROM store_map s WHERE s.vendor_store_id= ? AND s.vendor_id= ? AND s.deleted_at= '1970-01-01 00:00:00' )` + if err := GetRow(GetDB(), &storeDetail, sql, []interface{}{vendorStoreID, vendorID}); err != nil { return nil, err } return storeDetail, err diff --git a/business/partner/printer/trendit/trendit.go b/business/partner/printer/trendit/trendit.go index cf481b47b..07eefb863 100644 --- a/business/partner/printer/trendit/trendit.go +++ b/business/partner/printer/trendit/trendit.go @@ -194,6 +194,7 @@ func (c *PrinterHandler) getOrderContentV2(order *model.GoodsOrder, storeTel str 期望送达: %s 客户姓名: %s 客户电话: %s +店铺名称: %s 订单编号: %s
%s#%d %s @@ -211,6 +212,7 @@ func (c *PrinterHandler) getOrderContentV2(order *model.GoodsOrder, storeTel str utils.Time2Str(expectedDeliveryTime), order.ConsigneeName, order.ConsigneeMobile, + order.StoreName, order.VendorOrderID, jxutils.GetVendorName(order.VendorID), order.OrderSeq, @@ -227,6 +229,7 @@ func (c *PrinterHandler) getOrderContentV2(order *model.GoodsOrder, storeTel str orderParams = append(orderParams, order.SkuCount, order.GoodsCount, order.OrderSeq) return fmt.Sprintf(orderFmt, orderParams...) } + func (c *PrinterHandler) getOrderContentBigV2(order *model.GoodsOrder, storeTel string, storeDetail *dao.StoreDetail) (content string) { expectedDeliveryTime := order.ExpectedDeliveredTime if utils.IsTimeZero(expectedDeliveryTime) { @@ -257,6 +260,7 @@ func (c *PrinterHandler) getOrderContentBigV2(order *model.GoodsOrder, storeTel 期望送达: %s 客户姓名: %s 客户电话: %s +店铺名称: %s 订单编号: %s
%s#%d %s @@ -274,6 +278,7 @@ func (c *PrinterHandler) getOrderContentBigV2(order *model.GoodsOrder, storeTel utils.Time2Str(expectedDeliveryTime), order.ConsigneeName, order.ConsigneeMobile, + order.StoreName, order.VendorOrderID, jxutils.GetVendorName(order.VendorID), order.OrderSeq, diff --git a/business/partner/purchase/ebai/im.go b/business/partner/purchase/ebai/im.go index a1edd851e..d759a8925 100644 --- a/business/partner/purchase/ebai/im.go +++ b/business/partner/purchase/ebai/im.go @@ -9,7 +9,7 @@ import ( ) const ( - IMVendorIDELM = 11 //饿了么 + IMVendorIDELM = 3 //饿了么 ) // OnImMessage 用户/骑手 发送/已读消息 回调 diff --git a/business/partner/purchase/im/im.go b/business/partner/purchase/im/im.go index b7ad0cf4e..b26425a62 100644 --- a/business/partner/purchase/im/im.go +++ b/business/partner/purchase/im/im.go @@ -5,6 +5,10 @@ import ( "errors" "fmt" + "git.rosy.net.cn/jx-callback/business/jxutils" + + "git.rosy.net.cn/baseapi/utils/errlist" + "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/baseapi/platformapi/ebaiapi" @@ -19,7 +23,6 @@ import ( // SendToVendor 向平台发消息 func SendToVendor(msg []byte) { var ( - //w http.ResponseWriter sendData SendData err error elmAppID = api.EbaiAPI.GetSource() @@ -36,7 +39,11 @@ func SendToVendor(msg []byte) { //发送信息 if sendData.VendorID == VendorIDMT { temp, _ := json.Marshal(sendData.Data) - Send(temp) + if sendData.Data.(map[string]interface{})["app_id"] == nil { + globals.SugarLogger.Debug("SendToVendor appId=null") + return + } + Send(temp, sendData.Data.(map[string]interface{})["app_id"]) } if sendData.VendorID == VendorIDELM { param := sendData.Data.(ebaiapi.BusinessSendMsgReq) @@ -46,23 +53,24 @@ func SendToVendor(msg []byte) { } } - if err != nil { - ClientRender(Fail, FailMsg, map[string]string{ - "errMsg": fmt.Sprintf("%v", err), - }) - return - } else { - ClientRender(SuccessCode, SuccessMsg, map[string]interface{}{ - "vendorID": sendData.VendorID, - "msg": "ok", - }) - return - } + //if err != nil { + // ClientRender(Fail, FailMsg, map[string]string{ + // "errMsg": fmt.Sprintf("%v", err), + // }) + // return err + //} else { + // ClientRender(SuccessCode, SuccessMsg, map[string]interface{}{ + // "vendorID": sendData.VendorID, + // "msg": "ok", + // }) + // return nil + //} + return } -func Send(data []byte) { - //生成完整url - fullUrl := GenFullUrl() //clientID暂时不用 +func Send(data []byte, appID interface{}) { + //根据appID生成完整url + fullUrl := GenFullUrl(appID.(float64)) //clientID暂时不用 conn, resp, err := websocket.DefaultDialer.Dial(fullUrl, nil) if err != nil || resp.StatusCode != 101 { @@ -83,11 +91,11 @@ func Send(data []byte) { for { _, msg, err := conn.ReadMessage() + temp := string(msg) if err != nil { break } else { - temp := string(msg) - if temp != HeartCheckSuccess || temp != "成功" { + if temp != HeartSuccessWord { ReadMsgFromVendor(VendorIDMT, "", msg) } } @@ -96,6 +104,83 @@ func Send(data []byte) { return } +// MtInit 发送心跳 +func MtInit() { + data := []byte(HeartCheckMsg) + //生成完整url + url := GenFullUrl2() + //主连接 + jxutils.CallMsgHandlerAsync(func() { + conn, resp, err := websocket.DefaultDialer.Dial(url.UrlMain, nil) + if err != nil || resp.StatusCode != 101 { + fmt.Printf("连接失败:%v http响应不成功", err) + } + //关闭 + defer func(conn *websocket.Conn) { + err := conn.Close() + if err != nil { + return + } + }(conn) + + //client连接事件 + client := NewClient(url.ClientIDMain, conn, ClientTypeMt) + Manager.Connect <- client + + err = conn.WriteMessage(websocket.TextMessage, data) + if err != nil { + fmt.Println(err) + } + + for { + _, msg, err := conn.ReadMessage() + temp := string(msg) + if err != nil || temp != "HB" { + break + } + fmt.Printf("%s receive: %s\n", conn.RemoteAddr(), string(msg)) + } + }, url.ClientIDMain) + + //副连接 + if url.UrlSub != "" { + jxutils.CallMsgHandlerAsync(func() { + connSub, respSub, errSub := websocket.DefaultDialer.Dial(url.UrlSub, nil) + if errSub != nil || respSub.StatusCode != 101 { + fmt.Printf("连接失败:%v http响应不成功", errSub) + } + + //关闭 + defer func(conn *websocket.Conn) { + err := conn.Close() + if err != nil { + return + } + }(connSub) + + //client连接事件 + client := NewClient(url.ClientIDSub, connSub, ClientTypeMt) + Manager.Connect <- client + + errSub = connSub.WriteMessage(websocket.TextMessage, data) + if errSub != nil { + fmt.Println(errSub) + } + + for { + _, msg, err := connSub.ReadMessage() + temp := string(msg) + if err != nil || temp != HeartCheckSuccess { + break + } + fmt.Printf("%s connSub:receive: %s\n", connSub.RemoteAddr(), string(msg)) + } + + }, url.ClientIDSub) + } + +} + // ReadMsgFromClient 存储客户端发送的消息 func ReadMsgFromClient(vendorID int, elmAppID string, msg interface{}) { var ( @@ -221,13 +306,8 @@ func PushMsgByCid(vendorStoreID string, vendorID int) error { func SetMessageDetail(req *JXMsg, vendorID int, elmAppID string) error { //生成京西消息ID detail msgID := GenMsgDetailID(req, vendorID, elmAppID) - err := rdb.Set("test", "可以插入数据sjdfoiqaj", ExpireTimeDay) - if err != nil { - globals.SugarLogger.Debugf("测试插入err:%v", err) - } data, _ := json.Marshal(req) - err = rdb.RPush(msgID, string(data)) - globals.SugarLogger.Debugf("im SetUserList err=%v", err) + err := rdb.RPush(msgID, string(data)) ok, err := rdb.ExpireResult(msgID, ExpireTimeDay) if err != nil || !ok { return err @@ -251,12 +331,6 @@ func SetUserList(jxMsg *JXMsg, userList *UserMessageList, vendorID int, elmAppID //存储当前数据 data, _ := json.Marshal(userList) err = rdb.RPush(msgID, string(data)) - globals.SugarLogger.Debugf("im SetUserList msgID=%s", msgID) - globals.SugarLogger.Debugf("im SetUserList err=%v", err) - //test - str := rdb.Get(msgID) - globals.SugarLogger.Debugf("im SetUserList str=%v", str) - //over ok, err := rdb.ExpireResult(msgID, ExpireTimeDay) if err != nil || !ok { return err @@ -331,6 +405,8 @@ func GetImUserList(req []RelInfo) (map[string][]interface{}, error) { temp := rdb.LRange(j) for _, v := range temp { retVal[j] = append(retVal[j], v) + //暂时写死 + //retVal["userList"] = append(retVal["userList"], v) } } return retVal, nil @@ -351,6 +427,7 @@ func GetImChatDetail(req []UserRelInfo) (map[string][]interface{}, error) { temp := rdb.LRange(j) for _, v := range temp { retVal[j] = append(retVal[j], v) + //retVal["chatDetail"] = append(retVal["chatDetail"], v) } } return retVal, nil @@ -388,3 +465,18 @@ func SetJxMsgRead(appID, vendorStoreID, vendorID, userID string) error { } return nil } + +// DelRedisByKey 清除redis数据 +func DelRedisByKey(keys []string) { + var errList errlist.ErrList + for _, key := range keys { + err := rdb.Del(key) + if err != nil { + errList.AddErr(err) + } + } + if errList.GetErrListAsOne() != nil { + globals.SugarLogger.Debugf("DelRedisByKey err=%v", errList.GetErrListAsOne()) + } + return +} diff --git a/business/partner/purchase/im/im_model.go b/business/partner/purchase/im/im_model.go index a25892efe..3eb6bfa28 100644 --- a/business/partner/purchase/im/im_model.go +++ b/business/partner/purchase/im/im_model.go @@ -12,6 +12,8 @@ import ( "sync" "time" + "git.rosy.net.cn/jx-callback/globals" + "git.rosy.net.cn/baseapi/platformapi/mtwmapi" "git.rosy.net.cn/jx-callback/globals/api" "github.com/gazeboxu/mapstructure" @@ -38,6 +40,7 @@ type ClientManager struct { type Client struct { ClientId string // 标识ID Socket *websocket.Conn // 用户连接 + ClientType string //标识是美团/客户端长链接 ConnectTime uint64 // 首次连接时间 IsDeleted bool // 是否删除或下线 UserId string // 业务端标识用户ID @@ -132,27 +135,45 @@ type UserRelInfo struct { UserID string `json:"userID"` //用户id/groupID } +// UrlInfo 生成美团长链接url信息 +type UrlInfo struct { + UrlMain string `json:"urlMain"` //主连接路由 + ClientIDMain string `json:"ClientIDMain"` //主连接id + UrlSub string `json:"urlSub"` //副连接路由 + ClientIDSub string `json:"ClientIDSub"` //副连接id +} + var ( - cfg *ini.File - rdb = api.Cacher - Manager = NewClientManager() // 管理者 - CommonSetting = &commonConf{} - GlobalSetting = &global{} - ToClientChan chan clientInfo - heartbeatInterval = 60 * time.Second // 心跳间隔 - HeartCheckMsg = "~#HHHBBB#~" //心跳检测消息 - HeartCheckSuccess = "HB" //成功发送返回心跳消息 - VendorIDMT = 10 //im美团 - VendorIDELM = 11 //im饿了么 - SendTypeJx = "jx" //京西客户端发送方标识 - SendTypeMt = "mt" //美团用户发送方标识符 - SendTypeElm = "elm" //饿了么用户发送方标识符 - MTIMPushUrl = "wss://wpush.meituan.com/websocket" //buildPushConnect建立长连接 + cfg *ini.File + rdb = api.Cacher + //客户端相关 + Manager = NewClientManager() // 管理者 + ToClientChan chan clientInfo + ClientTypeJx = "jx" //京西客户端 + ClientTypeMt = "mt" //美团客户端 + //配置文件 + CommonSetting = &commonConf{} + GlobalSetting = &global{} + //心跳相关 + heartbeatInterval = 60 * time.Second // 心跳间隔 + HeartCheckMsg = "~#HHHBBB#~" //心跳检测消息 + HeartCheckSuccess = "HB" //成功发送返回心跳消息 + HeartSuccessWord = "成功" //成功发送返回心跳消息 + //平台标识 + AppID5873 = float64(5873) + AppID589 = "589" + VendorIDMT = 1 //im美团 + VendorIDELM = 3 //im饿了么 + SendTypeJx = "jx" //京西客户端发送方标识 + SendTypeMt = "mt" //美团用户发送方标识符 + SendTypeElm = "elm" //饿了么用户发送方标识符 + MTIMPushUrl = "wss://wpush.meituan.com/websocket" //buildPushConnect建立长连接 + ) const ( - ExpireTimeDay = 24 * time.Hour //redis一天过期时间 - maxMessageSize = 8192 // 最大的消息大小 + ExpireTimeDay = 2 * time.Hour //redis一天过期时间 + maxMessageSize = 8192 // 最大的消息大小 ) type renderData struct { @@ -162,7 +183,7 @@ type renderData struct { const ( SuccessCode = 0 SuccessMsg = "success" - Fail = -1 + FailCode = -1 FailMsg = "fail" SYSTEM_ID_ERROR = -1001 @@ -189,12 +210,13 @@ func Render(conn *websocket.Conn, messageId string, code int, message string, da } } -func ClientRender(code int, msg string, data interface{}) (str string) { +// ClientRender http响应 +func ClientRender(code int, msg string) (str string) { var retData RetData retData.Code = code retData.Msg = msg - retData.Data = data + //retData.Data = data retJson, _ := json.Marshal(retData) str = string(retJson) @@ -272,7 +294,16 @@ func getIntranetIp() string { } // GenFullUrl 组装完整websocket url以及生成clientID -func GenFullUrl() (fullUrl string) { +func GenFullUrl(appID float64) (fullUrl string) { + if appID == AppID5873 { + if resp5873, err := api.Mtwm2API.GetConnectionToken(); err == nil { + r1 := mtwmapi.GetConnTokenResp{} + err = mapstructure.Decode(resp5873, &r1) + fullUrl = MTIMPushUrl + "/" + r1.AppKey + "/" + r1.ConnectionToken + return fullUrl + } + } + //589/4123 resp, err := api.MtwmAPI.GetConnectionToken() if err != nil { return "" @@ -280,13 +311,48 @@ func GenFullUrl() (fullUrl string) { retVal := mtwmapi.GetConnTokenResp{} err = mapstructure.Decode(resp, &retVal) fullUrl = MTIMPushUrl + "/" + retVal.AppKey + "/" + retVal.ConnectionToken - //clientID = api.MtwmAPI.GetAppID() + ":" + retVal.ConnectionToken - //打印输出 - //fmt.Printf("Create websocket connect failCount:%d", retVal.UserCount) + + //todo 测试 + tete := api.MtwmAPI.GetAppID() + globals.SugarLogger.Debugf("GenFullUrl appID=%s", tete) + //todo + + fmt.Printf("GenFullUrl:%s", fullUrl) return fullUrl } -//生成随机字符串 +// GenFullUrl2 组装完整websocket url以及生成clientID +func GenFullUrl2() *UrlInfo { + urlInfo := &UrlInfo{} + //1 589/4123 + resp, err := api.MtwmAPI.GetConnectionToken() + if err != nil { + return nil + } + retVal := mtwmapi.GetConnTokenResp{} + err = mapstructure.Decode(resp, &retVal) + urlInfo.UrlMain = MTIMPushUrl + "/" + retVal.AppKey + "/" + retVal.ConnectionToken + urlInfo.ClientIDMain = retVal.AppKey + ":" + retVal.ConnectionToken + + if api.MtwmAPI.GetAppID() == AppID589 { //目前果园无4123 + if resp5873, err := api.Mtwm2API.GetConnectionToken(); err == nil { + r1 := mtwmapi.GetConnTokenResp{} + err = mapstructure.Decode(resp5873, &r1) + urlInfo.UrlSub = MTIMPushUrl + "/" + r1.AppKey + "/" + r1.ConnectionToken + urlInfo.ClientIDSub = r1.AppKey + ":" + r1.ConnectionToken + } + } + + //todo 测试 + tete := api.MtwmAPI.GetAppID() + globals.SugarLogger.Debugf("GenFullUrl appID=%s", tete) + //todo + + fmt.Printf("GenFullUrl:urlMain=%s, urlSub=%s", urlInfo.UrlMain, urlInfo.UrlSub) + return urlInfo +} + +// RandString 生成随机字符串 func RandString() string { bytes := make([]byte, 16) for i := 0; i < 16; i++ { diff --git a/business/partner/purchase/im/im_server.go b/business/partner/purchase/im/im_server.go index a76db0e23..2c0e1ef11 100644 --- a/business/partner/purchase/im/im_server.go +++ b/business/partner/purchase/im/im_server.go @@ -6,6 +6,8 @@ import ( "net/http" "time" + "git.rosy.net.cn/jx-callback/business/jxutils" + "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" @@ -18,16 +20,21 @@ func Init() { //写入全局变量 Setup() //建立长链接 - go Send([]byte(HeartCheckMsg)) + jxutils.CallMsgHandlerAsync(func() { + MtInit() + }, "MtInit:"+RandString()) //启动定时器 PingTimer() - go WriteMessage() + jxutils.CallMsgHandlerAsync(func() { + WriteMessage() + }, "WriteMessage:"+RandString()) - go Manager.Start() + jxutils.CallMsgHandlerAsync(func() { + Manager.Start() + }, "Manager Start:"+RandString()) - //fmt.Printf("服务器启动成功,端口号:%s\n", CommonSetting.HttpPort) } func Run(w http.ResponseWriter, r *http.Request) { @@ -54,8 +61,8 @@ func Run(w http.ResponseWriter, r *http.Request) { } else { clientID = temp } - globals.SugarLogger.Debugf("Run clientID=%s", clientID) - clientSocket := NewClient(clientID, conn) + + clientSocket := NewClient(clientID, conn, ClientTypeJx) //读取客户端消息 clientSocket.Read() @@ -69,26 +76,6 @@ func Run(w http.ResponseWriter, r *http.Request) { Manager.Connect <- clientSocket } -func StartWebSocket(conn *websocket.Conn, clientID string, err error) { - - //设置读取消息大小上线 - conn.SetReadLimit(maxMessageSize) - - clientSocket := NewClient(clientID, conn) - - //读取客户端消息 - clientSocket.Read() - - if err = ConnRender(conn, renderData{ClientId: clientID}); err != nil { - _ = conn.Close() - return - } - - // 用户连接事件 - Manager.Connect <- clientSocket - -} - // PingTimer 定时器发送心跳 func PingTimer() { go func() { @@ -99,16 +86,20 @@ func PingTimer() { for { i++ <-ticker.C - //对美团发送心跳 - Send([]byte(HeartCheckMsg)) - for clientId, conn := range Manager.AllClient() { - if err := conn.Socket.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second)); err != nil { - Manager.DisConnect <- conn - globals.SugarLogger.Debugf("发送心跳失败: %s 总连接数:%d", clientId, Manager.Count()) - } - if err := ConnRender(conn.Socket, renderData{ClientId: clientId}); err != nil { - return + if conn.ClientType == ClientTypeJx { + if err := conn.Socket.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(time.Second)); err != nil { + Manager.DisConnect <- conn + globals.SugarLogger.Debugf("发送心跳失败: %s 总连接数:%d", clientId, Manager.Count()) + } + if err := ConnRender(conn.Socket, renderData{ClientId: clientId}); err != nil { + return + } + } else { + if err := conn.Socket.WriteMessage(websocket.TextMessage, []byte(HeartCheckMsg)); err != nil { + //对美团重新建立连接 + MtInit() + } } globals.SugarLogger.Debugf("发送心跳 clientId=%s,i=%d", clientId, i) } @@ -121,14 +112,16 @@ func WriteMessage() { i := 0 for { clientInfo := <-ToClientChan - //广播发送通知所有客户端 + //广播发送通知所有京西客户端 i++ fmt.Printf("WriteMessage clientInfo=%s i=%d", utils.Format4Output(clientInfo, false), i) if Manager.AllClient() != nil { for _, conn := range Manager.AllClient() { - globals.SugarLogger.Debugf("WriteMessage conn.ClientId=%s", conn.ClientId) - if err := Render(conn.Socket, clientInfo.MessageId, clientInfo.Code, clientInfo.Msg, clientInfo.Data); err != nil { - Manager.DisConnect <- conn + if conn.ClientType == ClientTypeJx { //只发送给京西 + globals.SugarLogger.Debugf("WriteMessage conn.ClientId=%s", conn.ClientId) + if err := Render(conn.Socket, clientInfo.MessageId, clientInfo.Code, clientInfo.Msg, clientInfo.Data); err != nil { + Manager.DisConnect <- conn + } } } } else { @@ -162,6 +155,8 @@ func (c *Client) Read() { go func() { for { messageType, msg, err := c.Socket.ReadMessage() + //temp := string(msg) + //fmt.Print(temp) if err != nil { if messageType == -1 && websocket.IsCloseError(err, websocket.CloseGoingAway, websocket.CloseNormalClosure, websocket.CloseNoStatusReceived) { Manager.DisConnect <- c @@ -169,10 +164,8 @@ func (c *Client) Read() { } else if messageType != websocket.PingMessage { return } - } else { - SendToVendor(msg) - return } + SendToVendor(msg) } }() } @@ -197,10 +190,11 @@ func (manager *ClientManager) EventDisconnect(client *Client) { //以下为客户端Client操作******************************************* // NewClient 初始化Client -func NewClient(clientId string, socket *websocket.Conn) *Client { +func NewClient(clientId string, socket *websocket.Conn, clientType string) *Client { return &Client{ ClientId: clientId, Socket: socket, + ClientType: clientType, ConnectTime: uint64(time.Now().Unix()), IsDeleted: false, } diff --git a/controllers/im.go b/controllers/im.go index 862003efd..7f691df49 100644 --- a/controllers/im.go +++ b/controllers/im.go @@ -11,46 +11,13 @@ type IMController struct { web.Controller } -var maxMessageSize = int64(8192) // 最大的消息大小 - // @Title IM初始化长链接 // @Description IM初始化长链接 // @Success 200 {object} controllers.CallResult // @Failure 200 {object} controllers.CallResult // @router /StartWebSocket [get] func (c *IMController) StartWebSocket() { - im.Run(c.Ctx.ResponseWriter, c.Ctx.Request) - // - //upgrader.CheckOrigin = func(r *http.Request) bool { - // return true - //} - //conn, err := upgrader.Upgrade(c.Ctx.ResponseWriter, c.Ctx.Request, nil) - //if err != nil { - // globals.SugarLogger.Errorf("upgrade error: %v", err) - // return - //} - //defer conn.Close() - // - //clientID := c.GetString("clientID") - //globals.SugarLogger.Debugf("clientID=%s", clientID) - // - ////设置读取消息大小上线 - //conn.SetReadLimit(maxMessageSize) - // - //clientSocket := im.NewClient(clientID, conn) - // - ////读取客户端消息 - //clientSocket.Read() - // - //if err = im.ConnRender(conn, im.RetData{Data: clientID}); err != nil { - // _ = conn.Close() - // return - //} - // - //// 用户连接事件 - //im.Manager.Connect <- clientSocket - } // @Title IM获取门店用户聊天列表 diff --git a/main.go b/main.go index 7e233a897..48d01c5c7 100644 --- a/main.go +++ b/main.go @@ -97,11 +97,10 @@ func Init() { auto_delivery.Init() // 初始化骑手列表 im.Init() //初始化ws连接 - //http.HandleFunc("/ws", im.Run) //test //mux := http.NewServeMux() - //mux.HandleFunc("/v2/im/Run", im.Run) + //mux.HandleFunc("/v2/im/SendToVendor", im.Run) //go http.ListenAndServe(":8082", mux) }