Files
jx-callback/business/jxutils/weixinmsg/weixinmsg.go
suyl 4e29eea5ed aa
2021-07-02 13:33:47 +08:00

1153 lines
44 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package weixinmsg
import (
"encoding/json"
"fmt"
"git.rosy.net.cn/baseapi/platformapi/weixinapi"
"math"
"strings"
"time"
beego "github.com/astaxie/beego/server/web"
"git.rosy.net.cn/jx-callback/business/auth2/authprovider/weixin"
"git.rosy.net.cn/jx-callback/business/authz/autils"
"git.rosy.net.cn/jx-callback/business/jxstore/permission"
"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
"git.rosy.net.cn/jx-callback/business/jxutils/netprinter"
"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
"git.rosy.net.cn/jx-callback/business/partner"
"git.rosy.net.cn/baseapi/utils"
"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/business/model/legacymodel"
"git.rosy.net.cn/jx-callback/globals"
"git.rosy.net.cn/jx-callback/globals/api"
"git.rosy.net.cn/jx-callback/globals/api2"
)
const (
WX_TO_ORDER_PAGE_URL = "/#/?jxStoreId="
WX_TO_STORE_SKU_PAGE_URL = "/#/shop?jxStoreId="
WX_TO_SHOW_COMMENTS_DETAIL_URL = "/#/assess-list?jxStoreId=" //展示差评详情的页面
WX_TO_SHOW_MSG = "/#/message-detail?msgID=%d&msgStatusID=%d"
WX_MINI_TO_ORDER_PAGE_URL = "pages/order-manager/main"
WX_MINI_TO_STORE_SKU_PAGE_URL = "pages/goods-manager/main"
WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL = "pages/pagesStore/store-comment/main"
WX_MINI_TO_SHOW_MSG = "pages/pagesStore/msg-page/main?msgID=%d&msgStatusID=%d"
//新订单模板消息文字颜色
WX_NEW_ORDER_TEMPLATE_COLOR = "#173177"
WX_HIGHLEVEL_TEMPLATE_COLOR = "#FF0000" //红色
WX_HIGHLEVEL_TEMPLATE_COLOR2 = "#333333" //黑色
WX_TEMPLATE_VENDERCOLOR_JDDJ = "#47B34F"
WX_TEMPLATE_VENDERCOLOR_MT = "#F4A800"
WX_TEMPLATE_VENDERCOLOR_ELM = "#0191EA" //蓝色
WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS = "#4F4DA0"
WX_NEWORDER_TEMPLATE_ID = "_DtNGwmOeR6TkkTVUblxLIlkV2MAPOX57TkvfdqG6nY" //微信新订单推送
WX_ADJUSTORDER_TEMPLATE_ID = "N5rmV2-PDf3opjkv23IdLc76VnFThr_uOKSh5FzT13M" //微信调整订单推送
WX_MTPS_DELIVERY_GRABDONE_TEMPLATE_ID = "h4dkON6AgnHz1XmaksEUB_8Bcir4V8MSexUhC149pPE" //微信美团配送员接单推送
WX_MTPS_DELIVERY_DONE_TEMPLATE_ID = "YXdCrQAHZlcZX1htYUiarrLmtkmKAjp7rynjwObgODo" //微信美团配送员配送完成推送
WX_MTPS_UNABLE_DELIVER_TEMPLATE_ID = "ZFph5Hp7oLlrzVRXbsKIC_StmaBeB9Dlp4tlHeAmUQ8" //微信美团配送配送能力不足推送
WX_MTPS_DELIVERY_EXCEPTION_TEMPLATE_ID = "RkfOFHgR1N75L4-a6Gv0DljpCsVfOHhLm_vyXh8MR-w" //微信美团配送异常推送
WX_BAD_COMMENT_PUSH_TEMPLATE_ID = "NaMEzjctvVPQ9ishTI1dKpp5QSYV2FWcWftSSjDrpN8" //微信中差评消息推送
WX_DADA_DELIVERY_GRABDONE_TEMPLATE_ID = "h4dkON6AgnHz1XmaksEUB_8Bcir4V8MSexUhC149pPE" //微信达达众包配送员接单推送
WX_DADA_DELIVERY_DONE_TEMPLATE_ID = "YXdCrQAHZlcZX1htYUiarrLmtkmKAjp7rynjwObgODo" //微信达达众包配送员配送完成推送
WX_SALE_BILL_TEMPLATE_ID = "eTUuFZMWH7IsVBfcxNMpmaHYaxRkUaD6zG8wSGJDcic"
WX_NORMAL_STORE_ACT_MSG_TEMPLATE_ID = "eXsfOMvDOKVSht0Q0v4IsDrx3MBlRCVYwYl7Hi2uuuI"
WX_NORMAL_STORE_MSG_TEMPLATE_ID = "EUeIJEz2TLUAn4TU2EffOGYLd3dEaYndD_y6Sw9FcSU"
WX_CHANGE_APPROVED_TEMPLATE_ID = "gIG2olBZtQbjXmp6doNB_dESu60By5xuXYOGxksLv3Y"
WX_CHANGE_REJECTED_TEMPLATE_ID = "OBF4-d5inK95epHcUltpdb1zq9boVp2HESpASVRh1Oo"
WX_ORDER_APPLY_CANCEL_TEMPLATE_ID = "e6urTtcm4PL0rgDMG_1qWNOwrE3Qxqcm_dx0kWWCmEI"
WX_ORDER_ORDER_CANCELED_TEMPLATE_ID = "HXjuSAbIk77Xh18hjgwoxHzbciR9jX3Rn2CpLJz9dZw"
WX_ORDER_CHANGE_INFO_TEMPLATE_ID = "cjmEQFEpvcOuBNqQpTfMU5FeBpGRbQh_gWKz-WPW8Ro"
WX_AFS_ORDER_WAIT4APPROVE_TEMPLATE_ID = "X29udtANvhX6x1Lyh-T40NGNjRXBbUj5oSBTfDhZAqU"
WX_AFS_ORDER_STATUS_CHANGED_TEMPLATE_ID = "99T33rrXX0VboO1hljs4x8dDoLiSj3QX_rOikPHIXkg"
WS_NOTIFY_STORE_STATUS_CHHANGED_TEMPLATE_ID = "Fl0vOnBKTQqRFx3-shGKxdCnxMdQXNeODzgkuwd7oxw"
WX_STORE_ALERT_TEMPLATE_ID = "0AjzVl1wPl6iO4nFOS4IEsJYSzBymlT37DciIvcCOxE"
WX_KNOWLEDGE_BASE_TEMPLATE_ID = "1Fc703r13L3KQ6r_jdql2em_YhQ9CyOXTnqtDx-6Hx8" //知识库模板
)
var (
VendorColors = map[int]string{
model.VendorIDJD: WX_TEMPLATE_VENDERCOLOR_JDDJ,
model.VendorIDMTWM: WX_TEMPLATE_VENDERCOLOR_MT,
model.VendorIDELM: WX_TEMPLATE_VENDERCOLOR_ELM,
model.VendorIDEBAI: WX_TEMPLATE_VENDERCOLOR_ELM,
}
testMiniProgramStoreMap = map[int]int{
101089: 1,
100888: 1,
100204: 1,
100205: 1,
100147: 1,
}
debugOpenIDMap = map[string]int{
"oYN_usk0AeGc_C6VEZfmFQP5VHMQ": 1, // 周小扬
"oYN_ust9hXKEvEv0X6Mq6nlAWs_E": 1, // me
"oYN_usqnpGVQ4xxlao_yybsbYJh4": 1, // 朱丹
}
)
func GetWeixinOpenIDsFromStoreID(storeID int) (retVal []string) {
db := dao.GetDB()
openIDMap := make(map[string]int)
if globals.EnableWXAuth2 {
if userIDList, err2 := api2.RoleMan.GetRoleUserList(autils.NewStoreBossRole(storeID)); err2 == nil {
for _, v := range userIDList {
if authList, err2 := dao.GetUserBindAuthInfo(db, v, model.AuthBindTypeAuth, []string{weixin.AuthTypeMP}, "", "", nil); err2 == nil {
for _, v := range authList {
retVal = append(retVal, v.AuthID)
openIDMap[v.AuthID] = 1
}
}
}
}
}
retVal = jxutils.StringMap2List(openIDMap)
if !globals.ReallyCallPlatformAPI {
// todo调试只发给我
globals.SugarLogger.Debugf("GetWeixinOpenIDsFromStoreID store:%d, openids:%v", storeID, retVal)
if storeID == 100146 {
retVal = []string{"oYN_ust9hXKEvEv0X6Mq6nlAWs_E"}
} else {
retVal = nil
}
}
return retVal
}
func SendMsgToStore(storeID int, templateID, downloadURL, miniPageURL string, data interface{}) (err error) {
globals.SugarLogger.Debugf("SendMsgToStore storeID:%d, templateID:%s, downloadURL:%s, miniPageURL:%s", storeID, templateID, downloadURL, miniPageURL)
if storeID == 0 { // 测试,只发给我
// SmartMessageTemplateSend("oYN_ust9hXKEvEv0X6Mq6nlAWs_E", templateID, downloadURL, miniPageURL, data)
} else {
openIDs := GetWeixinOpenIDsFromStoreID(storeID)
successCount := 0
for _, openID := range openIDs {
realMiniPageURL := miniPageURL
// if testMiniProgramStoreMap[storeID] == 0 && debugOpenIDMap[openID] == 0 {
// realMiniPageURL = ""
// }
globals.SugarLogger.Debugf("SendMsgToStore storeID:%d, openID:%s, templateID:%s, downloadURL:%s, realMiniPageURL:%s", storeID, openID, templateID, downloadURL, realMiniPageURL)
if err2 := SmartMessageTemplateSend(openID, templateID, downloadURL, realMiniPageURL, data); err2 == nil {
successCount++
} else {
err = err2
}
}
if successCount > 0 {
err = nil // 只要成功一个都当成成功
}
if err != nil {
globals.SugarLogger.Debugf("SendMsgToStore all failed storeID:%d, templateID:%s, error:%v", storeID, templateID, err)
}
}
return err
}
func SmartMessageTemplateSend(userOpenID, templateID, downloadURL, miniPageURL string, data interface{}) (err error) {
var miniProgram map[string]interface{}
if miniPageURL != "" {
miniProgram = map[string]interface{}{
"appid": api.WeixinMiniAPI.GetAppID(),
"pagepath": miniPageURL,
}
}
globals.SugarLogger.Debugf("SmartMessageTemplateSend openID:%s, templateID:%s, downloadURL:%s, miniProgram:%s", userOpenID, templateID, downloadURL, utils.Format4Output(miniProgram, true))
if globals.ReallySendWeixinMsg || debugOpenIDMap[userOpenID] == 1 {
if err = api.WeixinAPI.CBMessageTemplateSend(userOpenID, templateID, downloadURL, miniProgram, data); err != nil {
globals.SugarLogger.Debugf("SmartMessageTemplateSend openID:%s, templateID:%s, downloadURL:%s, miniProgram:%s, failed with error:%v", userOpenID, templateID, downloadURL, utils.Format4Output(miniProgram, true), err)
}
}
return err
}
func MediaMessageSendGroup(openIDs []string, mediaID string) (err error) {
return api.WeixinAPI.CBMassSend(openIDs, mediaID)
}
func getOrderDetailBrief(order *model.GoodsOrder) (brief string) {
sb := new(strings.Builder)
sb.WriteString(order.Skus[0].SkuName)
sb.WriteString("等共")
sb.WriteString(utils.Int2Str(order.Skus[0].Count))
sb.WriteString("份(")
sb.WriteString(jxutils.IntPrice2StandardString(order.Skus[0].SalePrice))
sb.WriteString("元/份)等,点击查看详情。")
//,预计收入")
//TODO 2020-07-20 果园和菜市不同
//TODO 2021-06-15 都不显示钱了
//var price int64
//if beego.BConfig.RunMode == "jxgy" {
// price = order.NewEarningPrice
//} else {
// if order.EarningType == model.EarningTypePoints {
// price = order.ActualPayPrice
// } else {
// price = order.EarningPrice
// }
//}
//sb.WriteString(jxutils.IntPrice2StandardString(price))
//sb.WriteString("元")
return sb.String()
}
func NotifyNewOrder(order *model.GoodsOrder) (err error) {
globals.SugarLogger.Debugf("NotifyNewOrder orderID:%s", order.VendorOrderID)
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) {
globals.SugarLogger.Debugf("NotifyWaybillStatus orderID:%s bill:%v", order.VendorOrderID, bill)
if order.VendorID == model.VendorIDELM {
return nil
}
if !model.IsOrderSolid(order) {
globals.SugarLogger.Infof("NotifyWaybillStatus orderID:%s is not solid", order.VendorOrderID)
return nil
}
var title string
suffix := ""
storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "")
if err == nil && storeDetail != nil {
suffix = storeDetail.CityName + "," + storeDetail.Name
}
templateID := ""
remark := ""
titleColor := ""
switch bill.Status {
case model.WaybillStatusAccepted:
if bill.WaybillVendorID == model.VendorIDMTPS {
templateID = WX_MTPS_DELIVERY_GRABDONE_TEMPLATE_ID
} else if bill.WaybillVendorID == model.VendorIDDada {
templateID = WX_DADA_DELIVERY_GRABDONE_TEMPLATE_ID
}
remark = FormatDeliveryTime(order)
if isBillAlreadyCandidate {
titleColor = WX_HIGHLEVEL_TEMPLATE_COLOR
title = fmt.Sprintf("%s 第%d号订单由于之前安排的配送员长时间没有取货我们已重新安排%s配送员%s负责配送。^_^", model.VendorChineseNames[bill.OrderVendorID], order.OrderSeq, model.VendorChineseNames[bill.WaybillVendorID], bill.CourierName)
} else {
titleColor = WX_HIGHLEVEL_TEMPLATE_COLOR2
title = fmt.Sprintf("%s 第%d号订单长时间无人配送我们已安排%s配送员%s负责配送。^_^", model.VendorChineseNames[bill.OrderVendorID], order.OrderSeq, model.VendorChineseNames[bill.WaybillVendorID], bill.CourierName)
}
case model.WaybillStatusDelivered:
if bill.WaybillVendorID == model.VendorIDMTPS {
templateID = WX_MTPS_DELIVERY_DONE_TEMPLATE_ID
} else if bill.WaybillVendorID == model.VendorIDDada {
templateID = WX_DADA_DELIVERY_DONE_TEMPLATE_ID
}
titleColor = VendorColors[bill.OrderVendorID]
title = fmt.Sprintf("%s 第%d号订单的配送完成", model.VendorChineseNames[bill.OrderVendorID], order.OrderSeq)
}
if templateID != "" {
data := map[string]interface{}{
"first": map[string]interface{}{
"value": suffix + title,
"color": titleColor,
},
"keyword1": map[string]interface{}{
"value": bill.VendorOrderID,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword2": map[string]interface{}{
"value": fmt.Sprintf("%s%s", bill.CourierName, model.VendorChineseNames[bill.WaybillVendorID]),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword3": map[string]interface{}{
"value": bill.CourierMobile,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"remark": map[string]interface{}{
"value": remark,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
}
//err = SendMsgToStore(jxutils.GetSaleStoreIDFromOrder(order), templateID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeDetail.ID), WX_MINI_TO_ORDER_PAGE_URL+fmt.Sprintf("?jxStoreId=%v", storeDetail.ID), 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", storeDetail.ID, dataStore)
err = SendMsgToStore(jxutils.GetSaleStoreIDFromOrder(order), templateID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeDetail.ID), WX_MINI_TO_ORDER_PAGE_URL, data)
netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title)
}
return err
}
func NotifyUserApplyCancel(order *model.GoodsOrder, cancelReason string) (err error) {
globals.SugarLogger.Debugf("NotifyUserApplyCancel orderID:%s", order.VendorOrderID)
if order.VendorID == model.VendorIDELM {
return nil
}
if !model.IsOrderSolid(order) {
globals.SugarLogger.Infof("NotifyUserApplyCancel 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
}
title := suffix + "老板,您有订单申请取消!请及时联系客户处理!"
data := map[string]interface{}{
"first": map[string]interface{}{
"value": title,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword1": map[string]interface{}{ // 订单编号
"value": fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, order.VendorOrderID),
"color": VendorColors[order.VendorID],
},
"keyword2": map[string]interface{}{ // 订单日期
"value": utils.Time2Str(order.OrderCreatedAt),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword3": map[string]interface{}{ // 订单内容
"value": cancelReason,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"remark": map[string]interface{}{
"value": order.ConsigneeMobile,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
}
storeID := jxutils.GetSaleStoreIDFromOrder(order)
//err = SendMsgToStore(storeID, WX_ORDER_APPLY_CANCEL_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", storeDetail.ID, dataStore)
err = SendMsgToStore(storeID, WX_ORDER_APPLY_CANCEL_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title)
return err
}
func NotifyOrderChanged(order *model.GoodsOrder) (err error) {
globals.SugarLogger.Debugf("NotifyOrderChanged orderID:%s", order.VendorOrderID)
if order.VendorID == model.VendorIDELM {
return nil
}
suffix := ""
storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "")
if err == nil && storeDetail != nil {
suffix = storeDetail.CityName + "," + storeDetail.Name
}
title := fmt.Sprintf("您有订单的信息已被修改")
data := map[string]interface{}{
"first": map[string]interface{}{
"value": suffix + title,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword1": map[string]interface{}{
"value": order.VendorOrderID,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword2": map[string]interface{}{
"value": "用户修改订单",
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword3": map[string]interface{}{
"value": order.ConsigneeAddress + "" + order.ConsigneeName + "" + order.ConsigneeMobile + "" + order.BuyerComment,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword4": map[string]interface{}{
"value": utils.Time2Str(order.OrderCreatedAt),
"color": VendorColors[order.VendorID],
},
"remark": map[string]interface{}{
"value": "请及时处理",
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
}
storeID := jxutils.GetSaleStoreIDFromOrder(order)
//err = SendMsgToStore(storeID, WX_ORDER_CHANGE_INFO_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", storeDetail.ID, dataStore)
err = SendMsgToStore(storeID, WX_ORDER_CHANGE_INFO_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title)
return err
}
func NotifyOrderCanceled(order *model.GoodsOrder) (err error) {
globals.SugarLogger.Debugf("NotifyOrderCanceled orderID:%s", order.VendorOrderID)
if order.VendorID == model.VendorIDELM {
return nil
}
if !model.IsOrderSolid(order) {
globals.SugarLogger.Infof("NotifyOrderCanceled 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
}
title := fmt.Sprintf(suffix+"老板,您的订单%s第%d号订单, %s被取消了", model.VendorChineseNames[order.VendorID], order.OrderSeq, order.VendorOrderID)
var price int64
if beego.BConfig.RunMode == "jxgy" {
price = order.NewEarningPrice
} else {
if order.EarningType == model.EarningTypePoints {
price = order.ActualPayPrice
} else {
price = order.EarningPrice
}
}
data := map[string]interface{}{
"first": map[string]interface{}{
"value": title,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"orderProductPrice": map[string]interface{}{
"value": jxutils.IntPrice2StandardCurrencyString(price),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"orderProductName": map[string]interface{}{
"value": getOrderDetailBrief(order),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"orderAddress": map[string]interface{}{
"value": order.ConsigneeAddress,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"orderName": map[string]interface{}{
"value": fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[order.VendorID], order.OrderSeq, order.VendorOrderID),
"color": VendorColors[order.VendorID],
},
"remark": map[string]interface{}{
"value": order.ConsigneeMobile,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
}
storeID := jxutils.GetSaleStoreIDFromOrder(order)
//err = SendMsgToStore(storeID, WX_ORDER_ORDER_CANCELED_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", storeDetail.ID, dataStore)
err = SendMsgToStore(storeID, WX_ORDER_ORDER_CANCELED_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromOrder(order), order.VendorOrderID, title)
return err
}
func PushJDBadCommentToWeiXin(comment *legacymodel.JxBadComments, isBadComment bool, order *model.GoodsOrder) (err error) {
globals.SugarLogger.Debugf("PushJDBadCommentToWeiXin orderID:%s", comment.OrderId)
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(fmt.Sprintf(suffix+"你收到了%s客户(", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))]))
sb.WriteString(comment.Userphone)
sb.WriteString(")的一条")
sb.WriteString(utils.Int2Str(comment.Score))
if isBadComment {
sb.WriteString("星差评请商家在1小时内及时联系客户处理!")
} else {
sb.WriteString("星中评如有必要请商家在1小时内及时联系客户处理!")
}
title := sb.String()
var orderInfo string
consigneeName := comment.Userphone
if order != nil {
orderInfo = fmt.Sprintf("%s第%d号订单, %s", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))], order.OrderSeq, comment.OrderId)
consigneeName = order.ConsigneeName
} else {
orderInfo = fmt.Sprintf("%s订单, %s", model.VendorChineseNames[int(utils.Str2Int64WithDefault(comment.OrderFlag, 0))] /*comment.OrderId*/, "")
}
data := map[string]interface{}{
"first": map[string]interface{}{
"value": title,
"color": WX_HIGHLEVEL_TEMPLATE_COLOR,
},
"keyword1": map[string]interface{}{
"value": genJdCommentRemark(comment),
"color": WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS,
},
"keyword2": map[string]interface{}{
"value": comment.Score,
"color": WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS,
},
"keyword3": map[string]interface{}{
"value": orderInfo,
"color": WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS,
},
"keyword4": map[string]interface{}{
"value": consigneeName,
"color": WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS,
},
"keyword5": map[string]interface{}{
"value": comment.Userphone,
"color": WX_TEMPLATE_VENDERCOLOR_BAD_COMMENTS,
},
}
storeID := int(utils.Str2Int64(comment.Jxstoreid))
err = SendMsgToStore(storeID, WX_BAD_COMMENT_PUSH_TEMPLATE_ID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_SHOW_COMMENTS_DETAIL_URL, storeID), WX_MINI_TO_SHOW_COMMENTS_DETAIL_URL, data)
netprinter.NofityOrderMsg(jxcontext.AdminCtx, int(utils.Str2Int64(comment.Jxstoreid)), comment.OrderId, title)
return err
}
func NotifySaleBill(storeID int, title, shopName, fileURL string) (err error) {
globals.SugarLogger.Debugf("NotifySaleBill storeID:%d, fileURL:%s", storeID, fileURL)
if title == "" {
title = "当期账单"
}
if shopName == "" {
shopName = globals.StoreName
}
data := map[string]interface{}{
"first": map[string]interface{}{
"value": "新的账单上传成功!",
"color": "#00008B",
},
"keyword1": map[string]interface{}{
"value": title,
},
"keyword2": map[string]interface{}{
"value": "点击查看详情",
"color": "#00008B",
},
"keyword3": map[string]interface{}{
"value": shopName,
},
"keyword4": map[string]interface{}{
"value": utils.GetCurTimeStr(),
},
"remark": map[string]interface{}{
"value": "手机买菜上京西,极速到家送惊喜",
},
}
return SendMsgToStore(storeID, WX_SALE_BILL_TEMPLATE_ID, fileURL, "", data)
}
func NotifyStoreOpRequestStatus(isAccepted bool, storeID, nameID int, spuName string, originalUnitPrice, unitPrice int, rejectReason string) (err error) {
globals.SugarLogger.Debugf("NotifyStoreOpRequestStatus isAccepted:%t, storeID:%d, nameID:%d, spuName:%s, originalUnitPrice:%d, unitPrice:%d, rejectReason:%s", isAccepted, storeID, nameID, spuName, originalUnitPrice, unitPrice, rejectReason)
templateID := ""
fileURL := globals.WxBackstageHost + fmt.Sprintf("%s%d", WX_TO_STORE_SKU_PAGE_URL, storeID)
data := make(map[string]interface{})
if isAccepted {
templateID = WX_CHANGE_APPROVED_TEMPLATE_ID
data = map[string]interface{}{
"first": map[string]interface{}{
"value": fmt.Sprintf("%s%s元修改为%s元已经通过审核。^_^", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice))),
"color": "#333333",
},
"keyword1": map[string]interface{}{
"value": "审核通过",
"color": "#2E408E",
},
"keyword2": map[string]interface{}{
"value": utils.Time2Str(time.Now()),
"color": "#2E408E",
},
"remark": map[string]interface{}{
"value": "点击查看详情",
},
}
} else {
templateID = WX_CHANGE_REJECTED_TEMPLATE_ID
data = map[string]interface{}{
"first": map[string]interface{}{
"value": fmt.Sprintf("您好!抱歉的通知您。%s%s元修改为%s元未通过审核。原因%s", spuName, jxutils.IntPrice2StandardString(int64(originalUnitPrice)), jxutils.IntPrice2StandardString(int64(unitPrice)), rejectReason),
"color": "#E80000",
},
"keyword1": map[string]interface{}{
"value": "1",
"color": "#2E408E",
},
"keyword2": map[string]interface{}{
"value": "审核不通过",
"color": "#2E408E",
},
"keyword3": map[string]interface{}{
"value": utils.Time2Str(time.Now()),
"color": "#2E408E",
},
"keyword4": map[string]interface{}{
"value": "审核不通过",
"color": "#2E408E",
},
"remark": map[string]interface{}{
"value": "请您及时到商品管理修改价格,修改后请重新提交。",
},
}
}
err = SendMsgToStore(storeID, templateID, fileURL, WX_MINI_TO_STORE_SKU_PAGE_URL, data)
return err
}
func NotifyStoreMessage(storeID, msgID, msgStatusID int, msg *model.Message) (err error) {
globals.SugarLogger.Debugf("NotifyStoreMessage storeID:%d, msgID:%d, title:%s, content:%s", storeID, msgID, msg.Title, msg.Content)
templateID := ""
fileURL := globals.WxBackstageHost + fmt.Sprintf(WX_TO_SHOW_MSG, msgID, msgStatusID)
data := make(map[string]interface{})
switch msg.Type {
case model.MessageTypeStore:
templateID = WX_NORMAL_STORE_MSG_TEMPLATE_ID
data = map[string]interface{}{
"first": map[string]interface{}{
"value": msg.Content,
"color": "#333333",
},
"keyword1": map[string]interface{}{
"value": msg.Title,
"color": "#2E408E",
},
"keyword2": map[string]interface{}{
"value": utils.GetCurTimeStr(),
"color": "#2E408E",
},
"remark": map[string]interface{}{
"value": "",
},
}
case model.MessageTypeStoreAct:
actMap := &model.MessageActInfo{}
err = json.Unmarshal([]byte(msg.ActInfo), &actMap)
templateID = WX_NORMAL_STORE_ACT_MSG_TEMPLATE_ID
data = map[string]interface{}{
"first": map[string]interface{}{
"value": "即将开展[" + msg.Title + "]活动,详情点击",
"color": "#333333",
},
"keyword1": map[string]interface{}{
"value": msg.Title,
"color": "#2E408E",
},
"keyword2": map[string]interface{}{
"value": actMap.BeginAt + "-" + actMap.EndAt,
"color": "#2E408E",
},
"keyword3": map[string]interface{}{
"value": model.VendorNames[int(utils.Interface2Float64WithDefault((actMap.VendorID), 0))],
"color": "#2E408E",
},
"remark": map[string]interface{}{
"value": msg.Content,
},
}
}
return SendMsgToStore(storeID, templateID, fileURL, fmt.Sprintf(WX_MINI_TO_SHOW_MSG, msgID, msgStatusID), data)
}
func NotifyAfsOrderStatus(afsOrder *model.AfsOrder) (err error) {
globals.SugarLogger.Debugf("NotifyAfsOrderStatus orderID:%s", afsOrder.VendorOrderID)
if afsOrder.VendorID == model.VendorIDELM {
return nil
}
suffix := ""
storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromAfsOrder(afsOrder), afsOrder.VendorID, "")
if err == nil && storeDetail != nil {
suffix = storeDetail.CityName + "," + storeDetail.Name
}
var templateID, comment string
if afsOrder.Status == model.AfsOrderStatusWait4Approve {
templateID = WX_AFS_ORDER_WAIT4APPROVE_TEMPLATE_ID
comment = "您有新售后单,请尽快处理"
} else if afsOrder.Status == model.AfsOrderStatusWait4ReceiveGoods {
templateID = WX_AFS_ORDER_STATUS_CHANGED_TEMPLATE_ID
comment = "商家您好!如顾客商品已成功退回,请点击确认收货"
} else {
return err
}
order, err := partner.CurOrderManager.LoadOrder(afsOrder.VendorOrderID, afsOrder.VendorID)
if err != nil {
return err
}
data := map[string]interface{}{
"first": map[string]interface{}{
"value": suffix + fmt.Sprintf("%s 第%d号订单, %s", model.VendorChineseNames[afsOrder.VendorID], order.OrderSeq, afsOrder.VendorOrderID),
"color": WX_HIGHLEVEL_TEMPLATE_COLOR2,
},
"keyword1": map[string]interface{}{
"value": afsOrder.AfsOrderID,
"color": WX_TEMPLATE_VENDERCOLOR_JDDJ,
},
"keyword2": map[string]interface{}{
"value": model.OrderStatusName[afsOrder.Status],
"color": WX_HIGHLEVEL_TEMPLATE_COLOR,
},
"keyword3": map[string]interface{}{
"value": utils.Time2Str(afsOrder.AfsCreatedAt),
"color": VendorColors[order.VendorID],
},
"remark": map[string]interface{}{
"value": comment,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
}
storeID := jxutils.GetSaleStoreIDFromAfsOrder(afsOrder)
//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", storeDetail.ID, dataStore)
err = SendMsgToStore(storeID, templateID, globals.WxBackstageHost+fmt.Sprintf("%s%d", WX_TO_ORDER_PAGE_URL, storeID), WX_MINI_TO_ORDER_PAGE_URL, data)
netprinter.NofityOrderMsg(jxcontext.AdminCtx, jxutils.GetSaleStoreIDFromAfsOrder(afsOrder), afsOrder.VendorOrderID, comment)
return err
}
func FormatDeliveryTime(order *model.GoodsOrder) string {
var tmpTime time.Time
if order.ExpectedDeliveredTime == utils.DefaultTimeValue {
tmpTime = order.OrderCreatedAt.Add(1 * time.Hour)
} else {
tmpTime = order.ExpectedDeliveredTime
}
left := tmpTime.Sub(time.Now()) / time.Minute
leftHours := left / 60
leftMinutes := left % 60
return fmt.Sprintf("请于%s前送达剩余时间%d小时%d分钟", utils.Time2Str(tmpTime), leftHours, leftMinutes)
}
func genJdCommentRemark(comment *legacymodel.JxBadComments) string {
sb := new(strings.Builder)
sb.WriteString("评价标签:")
sb.WriteString(comment.Vendertags)
sb.WriteString(" 评价内容:")
sb.WriteString(comment.Scorecontent)
return sb.String()
}
func NotifyStoreStatusChanged(openUserID, title, content string) (err error) {
SmartMessageTemplateSend(openUserID, WS_NOTIFY_STORE_STATUS_CHHANGED_TEMPLATE_ID, "", "", map[string]interface{}{
"first": map[string]interface{}{
"value": title,
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword1": map[string]interface{}{
"value": "",
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword2": map[string]interface{}{
"value": utils.Time2Str(time.Now()),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword3": map[string]interface{}{
"value": content,
"color": WX_HIGHLEVEL_TEMPLATE_COLOR,
},
"keyword4": map[string]interface{}{
"value": "",
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"remark": map[string]interface{}{
"value": "",
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
})
return err
}
func NotifyStoreAlertMessage(storeID int, storeName, title, content string) (err error) {
globals.SugarLogger.Debugf("NotifyStoreAlertMessage storeID:%d, storeName:%d, title:%s, content:%s", storeID, storeName, title, content)
templateID := WX_STORE_ALERT_TEMPLATE_ID
data := map[string]interface{}{
"first": map[string]interface{}{
"value": "",
"color": "#333333",
},
"keyword1": map[string]interface{}{
"value": storeName,
"color": "#2E408E",
},
"keyword2": map[string]interface{}{
"value": utils.GetCurTimeStr(),
"color": "#2E408E",
},
"keyword3": map[string]interface{}{
"value": content,
"color": "#2E408E",
},
"remark": map[string]interface{}{
"value": "",
},
}
if false {
err = SendMsgToStore(storeID, templateID, "", "", data)
}
return err
}
func SendStoreMessage(ctx *jxcontext.Context, title, content string, storeIDs []int, imgs []string, actInfo string, messageType int, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
//权限
if permission.IsRoled(ctx) {
if storeIDsMap, err := permission.GetUserStoresResultMap(ctx.GetUserID()); err == nil {
var storeIDs2 []int
if len(storeIDs) > 0 {
for _, v := range storeIDs {
if storeIDsMap[v] != 0 {
storeIDs2 = append(storeIDs2, v)
}
}
if len(storeIDs2) == 0 {
storeIDs2 = append(storeIDs2, -1)
}
} else {
for k, _ := range storeIDsMap {
storeIDs2 = append(storeIDs2, k)
}
}
storeIDs = nil
storeIDs = storeIDs2
}
}
txDB, _ := dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db, txDB)
panic(r)
}
}()
msg := &model.Message{
Title: title,
Content: content,
Type: int8(messageType),
ActInfo: actInfo,
Imgs: strings.Join(imgs, ","),
}
dao.WrapAddIDCULDEntity(msg, ctx.GetUserName())
if err = dao.CreateEntity(db, msg); err != nil {
dao.Rollback(db, txDB)
return "", err
}
msgStatusList := make([]*model.MessageStatus, len(storeIDs))
for k, storeID := range storeIDs {
msgStatus := &model.MessageStatus{
MessageID: msg.ID,
StoreID: storeID,
Status: model.MessageStatusNew,
}
dao.WrapAddIDCULDEntity(msgStatus, ctx.GetUserName())
if err = dao.CreateEntity(db, msgStatus); err != nil {
dao.Rollback(db, txDB)
return "", err
}
msgStatusList[k] = msgStatus
}
dao.Commit(db, txDB)
rootTask := tasksch.NewParallelTask("SendStoreMessage", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
db := dao.GetDB()
msgStatus := batchItemList[0].(*model.MessageStatus)
if err = NotifyStoreMessage(msgStatus.StoreID, msgStatus.MessageID, msgStatus.ID, msg); err == nil {
msgStatus.Status = model.MessageStatusSendAllSuccess
} else {
msgStatus.Status = model.MessageStatusSendAllFailed
}
dao.WrapUpdateULEntity(msgStatus, ctx.GetUserName())
// globals.SugarLogger.Debug(utils.Format4Output(msgStatus, false))
_, 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 NotifyAdjustOrder(order *model.GoodsOrder) (err error) {
globals.SugarLogger.Debugf("NotifyAdjustOrder orderID:%s", order.VendorOrderID)
if order.VendorID == model.VendorIDELM {
return nil
}
if len(order.Skus) == 0 {
return
}
suffix := ""
storeDetail, err := dao.GetStoreDetail(dao.GetDB(), jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, "")
if err == nil && storeDetail != nil {
suffix = storeDetail.CityName + "," + storeDetail.Name
}
if !model.IsOrderSolid(order) {
globals.SugarLogger.Infof("NotifyAdjustOrder orderID:%s is not solid", order.VendorOrderID)
return nil
}
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,
},
"keyword1": map[string]interface{}{
"value": math.Round(jxutils.IntPrice2Standard(order.NewEarningPrice)),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword2": map[string]interface{}{
"value": utils.Time2Str(order.CreatedAt),
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
"keyword3": map[string]interface{}{
"value": model.OrderStatusName[order.Status],
"color": WX_NEW_ORDER_TEMPLATE_COLOR,
},
}
storeID := jxutils.GetSaleStoreIDFromOrder(order)
//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", storeDetail.ID, dataStore)
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 SendStoreMessageKnowledge(ctx *jxcontext.Context, title string, knowIDs, storeIDs []int) (hint string, err error) {
var (
db = dao.GetDB()
content string
)
knows, err := dao.GetKnowledgeDepotNoPage(db, knowIDs)
for k, v := range knows {
if k != 0 {
content += weixinapi.SNSCutLine
}
content += v.Content
}
txDB, _ := dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db, txDB)
panic(r)
}
}()
msg := &model.Message{
Title: title,
Content: content,
Type: 4,
}
dao.WrapAddIDCULDEntity(msg, ctx.GetUserName())
if err = dao.CreateEntity(db, msg); err != nil {
dao.Rollback(db, txDB)
return "", err
}
msgStatusList := make([]*model.MessageStatus, len(storeIDs))
for k, storeID := range storeIDs {
msgStatus := &model.MessageStatus{
MessageID: msg.ID,
StoreID: storeID,
Status: model.MessageStatusNew,
}
dao.WrapAddIDCULDEntity(msgStatus, ctx.GetUserName())
if err = dao.CreateEntity(db, msgStatus); err != nil {
dao.Rollback(db, txDB)
return "", err
}
msgStatusList[k] = msgStatus
}
dao.Commit(db, txDB)
rootTask := tasksch.NewParallelTask("SendStoreMessageKnowledge", nil, ctx, func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
db := dao.GetDB()
msgStatus := batchItemList[0].(*model.MessageStatus)
if err = NotifyKnowledge(msgStatus.StoreID, title); err == nil {
msgStatus.Status = model.MessageStatusSendAllSuccess
} else {
msgStatus.Status = model.MessageStatusSendAllFailed
}
dao.WrapUpdateULEntity(msgStatus, ctx.GetUserName())
// globals.SugarLogger.Debug(utils.Format4Output(msgStatus, false))
_, err = dao.UpdateEntity(db, msgStatus)
return nil, err
}, msgStatusList)
tasksch.HandleTask(rootTask, nil, true).Run()
//if !isAsync {
// _, err = rootTask.GetResult(0)
//} else {
hint = rootTask.ID
//}
return "", err
}
func NotifyKnowledge(storeID int, title string) (err error) {
globals.SugarLogger.Debugf("NotifyKnowledge storeID:%d, title:%s", storeID, title)
templateID := WX_KNOWLEDGE_BASE_TEMPLATE_ID
data := map[string]interface{}{
"first": map[string]interface{}{
"value": "今日每日一词已更新!",
"color": "#333333",
},
"keyword1": map[string]interface{}{
"value": time.Now().Format("2006-01-02"),
"color": "#2E408E",
},
"keyword2": map[string]interface{}{
"value": title,
"color": "#2E408E",
},
"remark": map[string]interface{}{
"value": "",
},
}
return SendMsgToStore(storeID, templateID, "", "", data)
}
func SendUserMessage(ctx *jxcontext.Context, title, content string, userIDs []string, isAsync, isContinueWhenError bool) (hint string, err error) {
db := dao.GetDB()
txDB, _ := dao.Begin(db)
defer func() {
if r := recover(); r != nil {
dao.Rollback(db, txDB)
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, txDB)
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, txDB)
return "", err
}
msgStatusList[k] = msgStatus
}
dao.Commit(db, txDB)
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{"weixinsns"}, "", "", []string{"wx2bb99eb5d2c9b82c"})
if err != nil {
return err
}
successCount := 0
if len(authBinds) == 0 {
return fmt.Errorf("此用户未找到微信认证方式userID: %v", userID)
}
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
}