From a30ba2bf1bb518d61b47f71be3fbe7e4af75a50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E5=B0=B9=E5=B2=9A?= <770236076@qq.com> Date: Sat, 26 Sep 2020 10:30:28 +0800 Subject: [PATCH] =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=8F=91=E9=80=81=E6=B6=88?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- business/jxutils/weixinmsg/weixinmsg.go | 101 ++++++++++++++++++++++++ business/model/message.go | 10 ++- controllers/cms_msg.go | 22 ++++++ routers/commentsRouter_controllers.go | 9 +++ 4 files changed, 138 insertions(+), 4 deletions(-) diff --git a/business/jxutils/weixinmsg/weixinmsg.go b/business/jxutils/weixinmsg/weixinmsg.go index 16f5ba45f..54d60e0da 100644 --- a/business/jxutils/weixinmsg/weixinmsg.go +++ b/business/jxutils/weixinmsg/weixinmsg.go @@ -816,3 +816,104 @@ func NotifyAdjustOrder(order *model.GoodsOrder) (err error) { storeID := jxutils.GetSaleStoreIDFromOrder(order) return SendMsgToStore(storeID, WX_ADJUSTORDER_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data) } + +func SendUserMessage(ctx *jxcontext.Context, title, content string, userIDs []string, isAsync, isContinueWhenError bool) (hint string, err error) { + db := dao.GetDB() + dao.Begin(db) + defer func() { + if r := recover(); r != nil { + dao.Rollback(db) + panic(r) + } + }() + msg := &model.Message{ + Title: title, + Content: content, + Type: model.MessageTypeUser, + } + dao.WrapAddIDCULDEntity(msg, ctx.GetUserName()) + if err = dao.CreateEntity(db, msg); err != nil { + dao.Rollback(db) + return "", err + } + msgStatusList := make([]*model.MessageStatus, len(userIDs)) + for k, userID := range userIDs { + msgStatus := &model.MessageStatus{ + MessageID: msg.ID, + UserID: userID, + Status: model.MessageStatusNew, + } + dao.WrapAddIDCULDEntity(msgStatus, ctx.GetUserName()) + if err = dao.CreateEntity(db, msgStatus); err != nil { + dao.Rollback(db) + return "", err + } + msgStatusList[k] = msgStatus + } + dao.Commit(db) + + rootTask := tasksch.NewParallelTask("SendUserMessage", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) { + db := dao.GetDB() + msgStatus := batchItemList[0].(*model.MessageStatus) + if err = NotifyUserMessage(msgStatus.UserID, msg.Title, msg.Content); err == nil { + msgStatus.Status = model.MessageStatusSendAllSuccess + } else { + msgStatus.Status = model.MessageStatusSendAllFailed + } + dao.WrapUpdateULEntity(msgStatus, ctx.GetUserName()) + _, err = dao.UpdateEntity(db, msgStatus) + return nil, err + }, msgStatusList) + tasksch.HandleTask(rootTask, nil, len(msgStatusList) > 5).Run() + if !isAsync { + _, err = rootTask.GetResult(0) + } else { + hint = rootTask.ID + } + return "", err +} + +func NotifyUserMessage(userID string, title, content string) (err error) { + globals.SugarLogger.Debugf("NotifyUserMessage userID:%d, title:%s, content:%s", userID, title, content) + templateID := WX_NORMAL_STORE_MSG_TEMPLATE_ID + data := map[string]interface{}{ + "first": map[string]interface{}{ + "value": content, + "color": "#333333", + }, + "keyword1": map[string]interface{}{ + "value": title, + "color": "#2E408E", + }, + "keyword2": map[string]interface{}{ + "value": utils.GetCurTimeStr(), + "color": "#2E408E", + }, + "remark": map[string]interface{}{ + "value": "", + }, + } + return SendMsgToUser(userID, templateID, data) +} + +func SendMsgToUser(userID string, templateID string, data interface{}) (err error) { + globals.SugarLogger.Debugf("SendMsgToUser userID:%d, templateID:%s", userID, templateID) + authBinds, err := dao.GetUserBindAuthInfo(dao.GetDB(), userID, model.AuthBindTypeAuth, []string{"weixinmini"}, "", "", "wx4b5930c13f8b1170") + if err != nil { + return err + } + successCount := 0 + globals.SugarLogger.Debugf("SendMsgToUser userID:%d, openID:%s, templateID:%s", userID, authBinds[0].AuthID, templateID) + if err2 := SmartMessageTemplateSend(authBinds[0].AuthID, templateID, "", "", data); err2 == nil { + successCount++ + } else { + err = err2 + } + if successCount > 0 { + err = nil // 只要成功一个都当成成功 + } + if err != nil { + globals.SugarLogger.Debugf("SendMsgToUser all failed userID:%d, templateID:%s, error:%v", userID, templateID, err) + } + return err +} diff --git a/business/model/message.go b/business/model/message.go index a389d2bb0..8065fea01 100644 --- a/business/model/message.go +++ b/business/model/message.go @@ -2,6 +2,7 @@ package model const ( MessageTypeStore = 1 + MessageTypeUser = 2 ) const ( @@ -36,10 +37,11 @@ func (*Message) TableIndex() [][]string { type MessageStatus struct { ModelIDCULD - MessageID int `orm:"column(message_id)" json:"messageID"` - StoreID int `orm:"column(store_id)" json:"storeID"` - Status int8 `json:"status"` - ReadCount int `json:"readCount"` + MessageID int `orm:"column(message_id)" json:"messageID"` + StoreID int `orm:"column(store_id)" json:"storeID"` + Status int8 `json:"status"` + ReadCount int `json:"readCount"` + UserID string `orm:"column(user_id)" json:"userID"` } func (*MessageStatus) TableIndex() [][]string { diff --git a/controllers/cms_msg.go b/controllers/cms_msg.go index 994581de6..b408c8876 100644 --- a/controllers/cms_msg.go +++ b/controllers/cms_msg.go @@ -37,6 +37,28 @@ func (c *MsgController) SendStoreMessage() { }) } +// @Title 发送用户微信消息 +// @Description 发送用户微信消息 +// @Param token header string true "认证token" +// @Param userIDs formData string true "用户 ID列表" +// @Param title formData string true "消息标题" +// @Param content formData string true "消息内容" +// @Param isAsync formData bool false "是否异步操作,缺省否" +// @Param isContinueWhenError formData bool false "单个失败是否继续,缺省false" +// @Success 200 {object} controllers.CallResult +// @Failure 200 {object} controllers.CallResult +// @router /SendUserMessage [post] +func (c *MsgController) SendUserMessage() { + c.callSendUserMessage(func(params *tMsgSendUserMessageParams) (retVal interface{}, errCode string, err error) { + var userIDs []string + if err = jxutils.Strings2Objs(params.UserIDs, &userIDs); err != nil { + return retVal, "", err + } + retVal, err = weixinmsg.SendUserMessage(params.Ctx, params.Title, params.Content, userIDs, params.IsAsync, params.IsContinueWhenError) + return retVal, "", err + }) +} + // @Title 门店读微信消息 // @Description 门店读微信消息(此API是自动调用的) // @Param token header string true "认证token" diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index ef9ee799b..d5415b350 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -864,6 +864,15 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:MsgController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:MsgController"], + beego.ControllerComments{ + Method: "SendUserMessage", + Router: `/SendUserMessage`, + AllowHTTPMethods: []string{"post"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:NetSpiderController"] = append(beego.GlobalControllerRouter["git.rosy.net.cn/jx-callback/controllers:NetSpiderController"], beego.ControllerComments{ Method: "GetAndStoreCitiesShops",