Explorar el Código

Merge branch 'dev2.8.5' of http://192.168.3.207:10080/qmx/jy into dev2.8.5

wangkaiyue hace 5 años
padre
commit
84e73c9969

+ 58 - 0
src/jfw/modules/subscribepay/README.md

@@ -0,0 +1,58 @@
+/**************************微信模板消息**************************/
+模版ID
+owspgSN6Tn3z0Olx4odQTLqg9JfiMi30SlZBPDrxlOc
+开发者调用模版消息接口时需提供模版ID
+标题
+续费提醒
+行业
+IT科技 - 互联网|电子商务
+详细内容
+{{first.DATA}}
+账号名:{{keyword1.DATA}}
+用户ID:{{keyword2.DATA}}
+服务项目:{{keyword3.DATA}}
+过期时间:{{keyword4.DATA}}
+{{remark.DATA}}
+
+模版ID
+tI13Li1FN0K6YY3fSn527-HcYIKfgrQ-k0qYxsESM3k
+开发者调用模版消息接口时需提供模版ID
+标题
+订单未支付提醒
+行业
+IT科技 - 互联网|电子商务
+详细内容
+{{first.DATA}}
+下单时间:{{keyword1.DATA}}
+订单号:{{keyword2.DATA}}
+待付金额:{{keyword3.DATA}}
+订单信息:{{keyword4.DATA}}
+{{remark.DATA}}
+
+模版ID
+xDdO4kzp5_zv-QXqr4L38RWjzp1RJLzJCTxwmutXqQA
+开发者调用模版消息接口时需提供模版ID
+标题
+购买成功通知
+行业
+IT科技 - 互联网|电子商务
+详细内容
+{{first.DATA}}
+商品名称:{{keyword1.DATA}}
+订单编号:{{keyword2.DATA}}
+购买时间:{{keyword3.DATA}}
+到期时间:{{keyword4.DATA}}
+{{remark.DATA}}
+
+模版ID
+6SMSSwz5c26YjMac71CD4PbDA_GB-MTtRxmC7BdeWRk
+开发者调用模版消息接口时需提供模版ID
+标题
+试用版到期提醒
+行业
+IT科技 - 互联网|电子商务
+详细内容
+{{first.DATA}}
+账号:{{keyword1.DATA}}
+到期时间:{{keyword2.DATA}}
+{{remark.DATA}}

+ 27 - 14
src/jfw/modules/subscribepay/src/config/config.go

@@ -35,25 +35,38 @@ type config struct {
 		Pwd  string
 		User string
 	}
-	ExpireRemind []int
-	WxTplExpire  string
 }
-type timetaskConfig struct {
-	ExpireRemind   string
-	SyncVipUpgrade string
-	CheckIsExpire  string
+type timeTaskConfig struct {
+	ExpireRemind   string   //到期提醒
+	SyncVipUpgrade string   //同步未及时生效的数据
+	CheckIsExpire  string   //定时更新用户vip状态
+	UnpaidRemind   struct { //未支付订单提醒
+		AfterOrder   int64 //下单后n小时提醒
+		BeforeExpire int64 //n小时自动关闭提醒
+		Duration     int   //定时任务时间间隔
+	}
 }
 type messageConfig struct {
-	WxTplExpire struct {
-		Id       string
-		First    *qrpc.TmplItem
-		Keyword2 *qrpc.TmplItem
-		Keyword3 *qrpc.TmplItem
-	}
+	WxTpl_OnTrial_SoonExpire *WxTplMsg //试用即将到期
+	WxTpl_OnTrial_Expired    *WxTplMsg //试用已到期
+	WxTpl_SoonExpire         *WxTplMsg //即将到期
+	WxTpl_Expired            *WxTplMsg //已到期
+	WxTpl_Unpaid             *WxTplMsg //未支付订单
+	WxTpl_PaySuccess         *WxTplMsg //支付成功
+}
+
+type WxTplMsg struct {
+	Id       string
+	First    *qrpc.TmplItem
+	Keyword1 *qrpc.TmplItem
+	Keyword2 *qrpc.TmplItem
+	Keyword3 *qrpc.TmplItem
+	Keyword4 *qrpc.TmplItem
+	Remark   *qrpc.TmplItem
 }
 
 var Config *config
-var TimetaskConfig *timetaskConfig
+var TimeTaskConfig *timeTaskConfig
 var MessageConfig *messageConfig
 
 //发送邮件邮箱
@@ -69,7 +82,7 @@ var Wxoauth, Wxoauthinfo string
 func init() {
 	//程序配置文件
 	qutil.ReadConfig(&Config)
-	qutil.ReadConfig("./timetask.json", &TimetaskConfig)
+	qutil.ReadConfig("./timetask.json", &TimeTaskConfig)
 	qutil.ReadConfig("./message.json", &MessageConfig)
 	for _, v := range Config.Mail {
 		mail := &mail.GmailAuth{

+ 62 - 3
src/jfw/modules/subscribepay/src/message.json

@@ -1,15 +1,74 @@
 {
-	"wxTplExpire": {
+	"WxTpl_OnTrial_SoonExpire": {
+		"id": "_2qGuk_KkOQtiO8oV_7ZOCWfjX2FQjs6pUDYBHkpygI",
+		"first":{
+			"value":"您试用的VIP订阅服务即将到期,如需获取更多精准招标信息,请及时购买。"
+		},
+		"remark": {
+			"value":"感谢您的试用,如已购买,请忽略此信息。"
+		}
+	},
+	"WxTpl_OnTrial_Expired": {
+		"id": "_2qGuk_KkOQtiO8oV_7ZOCWfjX2FQjs6pUDYBHkpygI",
+		"first":{
+			"value":"您试用的VIP订阅服务已到期,如需获取更多精准招标信息,请及时购买。"
+		},
+		"remark": {
+			"value":"感谢您的试用,如已购买,请忽略此信息。"
+		}
+	},
+	"WxTpl_SoonExpire": {
+		"id": "3_VPNbD7fmfd8BsdjLW-a7FOP4wIhEGV7Jx-11-9c7g",
+		"first":{
+			"value":"您的VIP订阅服务即将到期,为了不影响您所获取更全面的招标信息,请您及时续费。"
+		},
+		"keyword2": {
+			"value":"-"
+		},
+		"keyword3": {
+			"value":"VIP订阅"
+		},
+		"remark": {
+			"value":"如已续费,请忽略此信息。"
+		}
+	},
+	"WxTpl_Expired": {
 		"id": "3_VPNbD7fmfd8BsdjLW-a7FOP4wIhEGV7Jx-11-9c7g",
 		"first":{
-			"value":"您的VIP订阅服务%s到期,为不影响您的使用。请立即续费",
-			"color":"#FF0000"
+			"value":"您的VIP订阅服务已到期,如需获取更多精准招标信息,请再次购买。"
 		},
 		"keyword2": {
 			"value":"-"
 		},
 		"keyword3": {
 			"value":"VIP订阅"
+		},
+		"remark": {
+			"value":"如已续费,请忽略此信息。"
+		}
+	},
+	"WxTpl_Unpaid": {
+		"id": "9oRmG95lUQZMH-ZVTryoKpAuZTDQWVEsJBhZmJp_41c",
+		"first":{
+			"value":"您的订单 %s 处于未支付状态,为了使您获取更多招标信息,请您及时付款。"
+		},
+		"keyword3": {
+			"value":"%s元"
+		},
+		"keyword4": {
+			"value":"VIP订阅%s"
+		},
+		"remark": {
+			"value":"订单将在%.0f小时后自动关闭,请及时支付。"
+		}
+	},
+	"WxTpl_PaySuccess": {
+		"id": "Pr6QjYUit1Tc7GMHhziU5pnfYAiKsa11l2NMGdHO-NU",
+		"first":{
+			"value":"您的订单 %s 已支付成功,剑鱼标讯将为您提供更多精准招标信息,感谢您的购买!"
+		},
+		"keyword1": {
+			"value":"VIP订阅%s"
 		}
 	}
 }

+ 6 - 1
src/jfw/modules/subscribepay/src/timetask.json

@@ -1,5 +1,10 @@
 {
 	"expireRemind": "10:00",
 	"syncVipUpgrade": "00:00",
-	"checkIsExpire": "00:00"
+	"checkIsExpire": "00:00",
+	"unpaidRemind": {
+		"afterOrder": 7200,
+		"beforeExpire": 7200,
+		"duration": 10
+	}
 }

+ 56 - 27
src/jfw/modules/subscribepay/src/timetask/timetask.go

@@ -16,8 +16,6 @@ const (
 	threeday = 259200
 )
 
-var Se = qutil.SimpleEncrypt{Key: "topnet"}
-
 func Run() {
 	go syncVipUpgrade()
 	go checkIsExpire()
@@ -26,7 +24,7 @@ func Run() {
 
 //vip升级 下个月生效 同步
 func syncVipUpgrade() {
-	crontab(true, TimetaskConfig.SyncVipUpgrade, func() {
+	crontab(true, TimeTaskConfig.SyncVipUpgrade, func() {
 		log.Println("定时任务,开始同步vip升级数据")
 		sess := util.MQFW.GetMgoConn()
 		defer util.MQFW.DestoryMongoConn(sess)
@@ -73,7 +71,7 @@ func syncVipUpgrade() {
 
 //每天0点 检查试用、vip服务是否到期
 func checkIsExpire() {
-	crontab(true, TimetaskConfig.CheckIsExpire, func() {
+	crontab(true, TimeTaskConfig.CheckIsExpire, func() {
 		log.Println("定时任务,开始更新vip状态")
 		now_unix := time.Now().Unix()
 		sess := util.MQFW.GetMgoConn()
@@ -103,16 +101,15 @@ func checkIsExpire() {
 				delSess := util.MQFW.GetMgoConn()
 				defer util.MQFW.DestoryMongoConn(delSess)
 				for _, pushColl := range []string{"pushspace", "pushspace_temp", "pushspace_vip", "pushspace_fail", "pushspace_project"} {
-					log.Println("用户", _id, "已到期开始删除", pushColl, "表数据。。。")
 					_, err := delSess.DB("qfw").C(pushColl).RemoveAll(map[string]interface{}{"userid": _id})
 					if err != nil {
 						log.Println("用户", _id, "已到期删除", pushColl, "表数据出错", err)
 					} else {
-						log.Println("用户", _id, "已到期删除", pushColl, "表数据结束。。。")
+						log.Println("用户", _id, "已到期删除", pushColl, "表数据")
 					}
 				}
 				log.Println("用户", _id, i_vip_status, l_vip_endtime, "修改已到期状态")
-			} else if l_vip_endtime-now_unix <= threeday && i_vip_expire_tip != 1 && i_vip_expire_tip != -1 {
+			} else if l_vip_endtime-now_unix <= threeday && i_vip_expire_tip != 1 {
 				updateOk := util.MQFW.UpdateById("user", _id, map[string]interface{}{
 					"$set": map[string]interface{}{
 						"i_vip_expire_tip": 1,
@@ -128,8 +125,8 @@ func checkIsExpire() {
 
 //即将到期或者已到期发推送消息
 func expireRemind() {
-	crontab(false, TimetaskConfig.ExpireRemind, func() {
-		log.Println("定时任务,开始推送消息")
+	crontab(true, TimeTaskConfig.ExpireRemind, func() {
+		log.Println("定时任务,到期提醒,开始推送消息")
 		sess := util.MQFW.GetMgoConn()
 		defer util.MQFW.DestoryMongoConn(sess)
 		it := sess.DB("qfw").C("user").Find(map[string]interface{}{
@@ -142,7 +139,6 @@ func expireRemind() {
 			"s_jpushid":        1,
 			"s_opushid":        1,
 			"s_appponetype":    1,
-			"i_applystatus":    1,
 			"s_nickname":       1,
 			"i_ispush":         1,
 			"i_vip_status":     1,
@@ -152,19 +148,17 @@ func expireRemind() {
 		}).Iter()
 		for m := make(map[string]interface{}); it.Next(&m); {
 			_id := qutil.BsonIdToSId(m["_id"])
-			i_vip_expire_tip := qutil.Int64All(m["i_vip_expire_tip"])
+			i_vip_status := qutil.IntAll(m["i_vip_status"])
+			i_vip_expire_tip := qutil.IntAll(m["i_vip_expire_tip"])
 			wxPushOk, appPushOk := false, false
 			if i_vip_expire_tip == 1 || i_vip_expire_tip == 2 {
 				tp := "will"
-				tpMsg := "即将"
 				if i_vip_expire_tip == 2 {
 					tp = "exprie"
-					tpMsg = "已"
 				}
 				l_vip_starttime := qutil.Int64All(m["l_vip_starttime"])
 				l_vip_endtime := qutil.Int64All(m["l_vip_endtime"])
 				s_m_openid := qutil.ObjToString(m["s_m_openid"])
-				i_applystatus := qutil.IntAll(m["i_applystatus"])
 				isPushWx := qutil.IntAllDef(m["i_ispush"], 1)
 				s_jpushid := qutil.ObjToString(m["s_jpushid"])
 				s_opushid := qutil.ObjToString(m["s_opushid"])
@@ -178,45 +172,80 @@ func expireRemind() {
 				if order != nil && len(*order) > 0 {
 					orderId = fmt.Sprint((*order)["id"])
 				}
-				log.Println("推送消息", _id, "i_vip_status", m["i_vip_status"], "orderId", orderId, "l_vip_starttime", l_vip_starttime, "l_vip_endtime", l_vip_endtime, "i_vip_expire_tip", i_vip_expire_tip, "s_m_openid", s_m_openid, "isPushWx", isPushWx, "i_applystatus", i_applystatus, "s_appponetype", s_appponetype, "s_jpushid", s_jpushid, "s_opushid", s_opushid)
-				if isPushWx == 1 && i_applystatus == 1 && s_m_openid != "" {
+				log.Println("到期提醒,推送消息", _id, "i_vip_status", i_vip_status, "orderId", orderId, "l_vip_starttime", l_vip_starttime, "l_vip_endtime", l_vip_endtime, "i_vip_expire_tip", i_vip_expire_tip, "s_m_openid", s_m_openid, "isPushWx", isPushWx, "s_appponetype", s_appponetype, "s_jpushid", s_jpushid, "s_opushid", s_opushid)
+				if isPushWx == 1 && s_m_openid != "" {
+					tplId, first_value, keyword1_value, keyword2_value, keyword3_value, keyword4_value, remark := "", "", "", "", "", "", ""
+					switch i_vip_status {
+					case 1, -1:
+						if i_vip_expire_tip == 1 {
+							tplId = MessageConfig.WxTpl_OnTrial_SoonExpire.Id
+							first_value = MessageConfig.WxTpl_OnTrial_SoonExpire.First.Value
+							remark = MessageConfig.WxTpl_OnTrial_SoonExpire.Remark.Value
+						} else if i_vip_expire_tip == 2 {
+							tplId = MessageConfig.WxTpl_OnTrial_Expired.Id
+							first_value = MessageConfig.WxTpl_OnTrial_Expired.First.Value
+							remark = MessageConfig.WxTpl_OnTrial_Expired.Remark.Value
+						}
+						keyword1_value = qutil.ObjToString(m["s_nickname"])
+						keyword2_value = qutil.FormatDateByInt64(&l_vip_endtime, qutil.Date_Short_Layout)
+						break
+					case 2, -2:
+						if i_vip_expire_tip == 1 {
+							tplId = MessageConfig.WxTpl_SoonExpire.Id
+							first_value = MessageConfig.WxTpl_SoonExpire.First.Value
+							keyword2_value = MessageConfig.WxTpl_SoonExpire.Keyword2.Value
+							keyword3_value = MessageConfig.WxTpl_SoonExpire.Keyword3.Value
+							remark = MessageConfig.WxTpl_SoonExpire.Remark.Value
+						} else if i_vip_expire_tip == 2 {
+							tplId = MessageConfig.WxTpl_Expired.Id
+							first_value = MessageConfig.WxTpl_Expired.First.Value
+							keyword2_value = MessageConfig.WxTpl_Expired.Keyword2.Value
+							keyword3_value = MessageConfig.WxTpl_Expired.Keyword3.Value
+							remark = MessageConfig.WxTpl_Expired.Remark.Value
+						}
+						keyword1_value = qutil.ObjToString(m["s_nickname"])
+						keyword4_value = qutil.FormatDateByInt64(&l_vip_endtime, qutil.Date_Short_Layout)
+						break
+					}
 					tmplData := map[string]*qrpc.TmplItem{
 						"first": &qrpc.TmplItem{
-							Value: fmt.Sprintf(MessageConfig.WxTplExpire.First.Value, tpMsg),
-							Color: MessageConfig.WxTplExpire.First.Color,
+							Value: first_value,
 						},
 						"keyword1": &qrpc.TmplItem{
-							Value: qutil.ObjToString(m["s_nickname"]),
+							Value: keyword1_value,
 						},
 						"keyword2": &qrpc.TmplItem{
-							Value: MessageConfig.WxTplExpire.Keyword2.Value,
+							Value: keyword2_value,
 						},
 						"keyword3": &qrpc.TmplItem{
-							Value: MessageConfig.WxTplExpire.Keyword3.Value,
+							Value: keyword3_value,
 						},
 						"keyword4": &qrpc.TmplItem{
-							Value: qutil.FormatDateByInt64(&l_vip_endtime, qutil.Date_Short_Layout),
+							Value: keyword4_value,
+						},
+						"remark": &qrpc.TmplItem{
+							Value: remark,
 						},
 					}
 					wxPushOk, _ = qrpc.WxSendTmplMsg(Config.Weixinrpc, &qrpc.WxTmplMsg{
 						OpenId:   s_m_openid,
-						TplId:    MessageConfig.WxTplExpire.Id,
+						TplId:    tplId,
 						TmplData: tmplData,
-						Url:      Config.WebDomain + "/front/sess/" + Se.EncodeString(s_m_openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",expireTip") + "__" + tp + "__" + fmt.Sprint(orderId) + "__" + fmt.Sprint(l_vip_starttime) + "__" + fmt.Sprint(l_vip_endtime),
+						Url:      Config.WebDomain + "/front/sess/" + util.Se_Topnet.EncodeString(s_m_openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",msgremind") + "__" + fmt.Sprint("type=%s&orderid=%d", tp, orderId),
 					})
-					log.Println("微信推送", _id, wxPushOk)
+					log.Println("到期提醒,微信推送", _id, wxPushOk)
 				}
 			}
 			if wxPushOk || appPushOk {
 				util.MQFW.UpdateById("user", _id, map[string]interface{}{
 					"$set": map[string]interface{}{
-						"i_vip_expire_tip": -i_vip_expire_tip,
+						"i_vip_expire_tip": 0,
 					},
 				})
 			}
 			m = make(map[string]interface{})
 		}
-		log.Println("定时任务,推送消息结束")
+		log.Println("定时任务,到期提醒,推送消息结束")
 	})
 }
 

+ 228 - 0
src/jfw/modules/subscribepay/src/util/msgremind.go

@@ -0,0 +1,228 @@
+//未支付订单提醒
+package util
+
+import (
+	. "config"
+	"fmt"
+	"log"
+	"math"
+	"qfw/util"
+	qrpc "qfw/util/rpc"
+	"strconv"
+	"strings"
+	"sync"
+	"time"
+)
+
+var MsgRemind = &msgRemind{
+	unpaidOrders: &sync.Map{},
+}
+
+type msgRemind struct {
+	unpaidOrders *sync.Map
+}
+
+type unpaidOrder struct {
+	orderId      int    //订单id
+	orderCode    string //订单编号
+	userId       string //用户id
+	createTime   int64  //下单时间
+	remindStatus int    //1-下单时间2小时提醒 2-剩余2小时自动关闭时再次提醒
+	vipType      int    //-1:直接购买 0:试用 1:续费 2:升级
+	orderMoney   int    //订单金额
+}
+
+/*新的订单存库以后,再存入内存中
+ *@param orderId 订单id
+ *@param orderMoney 订单金额
+ *@param vipType -1:直接购买 0:试用 1:续费 2:升级
+ *@param remindStatus 1-下单时间2小时提醒 2-剩余2小时自动关闭时再次提醒
+ *@param orderCode 订单编号
+ *@param userId 用户id
+ *@param createTime 购买时间
+ */
+func (m *msgRemind) Add(orderId, orderMoney, vipType, remindStatus int, orderCode, userId string, createTime int64) {
+	log.Println("未支付待提醒订单加入", orderId, orderCode, userId, createTime)
+	m.unpaidOrders.Store(orderId, &unpaidOrder{
+		orderCode:    orderCode,
+		userId:       userId,
+		createTime:   createTime,
+		orderId:      orderId,
+		orderMoney:   orderMoney,
+		vipType:      vipType,
+		remindStatus: remindStatus,
+	})
+}
+
+/*
+ *订单支付成功以后,消息通知处理
+ *@param orderId 订单id
+ *@param orderCode 订单编号
+ *@param userId 用户id
+ *@param createTime 购买时间
+ *@param vipType -1:直接购买 0:试用 1:续费 2:升级
+ */
+func (m *msgRemind) PaySuccess(orderId int, orderCode, userId, createTime string, vipType int) {
+	go func() {
+		defer util.Catch()
+		log.Println("支付成功以后,消息提醒处理", orderId, orderCode, userId, createTime)
+		m.unpaidOrders.Delete(orderId)
+		user, ok := MQFW.FindById("user", userId, `{"s_m_openid":1,"s_jpushid":1,"s_opushid":1,"s_appponetype":1,"i_ispush":1,"l_vip_endtime":1}`)
+		if !ok || user == nil || len(*user) == 0 {
+			return
+		}
+		isPushWx := util.IntAllDef((*user)["i_ispush"], 1)
+		s_m_openid, _ := (*user)["s_m_openid"].(string)
+		s_jpushid, _ := (*user)["s_jpushid"].(string)
+		s_opushid, _ := (*user)["s_opushid"].(string)
+		s_appponetype, _ := (*user)["s_appponetype"].(string)
+		log.Println("支付成功,推送消息", userId, "s_m_openid", s_m_openid, "s_jpushid", s_jpushid, "s_opushid", s_opushid, "s_appponetype", s_appponetype)
+		if isPushWx == 1 {
+			l_vip_endtime := (*user)["l_vip_endtime"]
+			expireTime := util.FormatDateWithObj(&l_vip_endtime, util.Date_Short_Layout)
+			wxPushOk, _ := qrpc.WxSendTmplMsg(Config.Weixinrpc, &qrpc.WxTmplMsg{
+				OpenId: s_m_openid,
+				TplId:  MessageConfig.WxTpl_PaySuccess.Id,
+				TmplData: map[string]*qrpc.TmplItem{
+					"first": &qrpc.TmplItem{
+						Value: fmt.Sprintf(MessageConfig.WxTpl_PaySuccess.First.Value, orderCode),
+					},
+					"keyword1": &qrpc.TmplItem{
+						Value: fmt.Sprintf(MessageConfig.WxTpl_PaySuccess.Keyword1.Value, m.getVipType(vipType)),
+					},
+					"keyword2": &qrpc.TmplItem{
+						Value: orderCode,
+					},
+					"keyword3": &qrpc.TmplItem{
+						Value: strings.Split(createTime, " ")[0],
+					},
+					"keyword4": &qrpc.TmplItem{
+						Value: expireTime,
+					},
+				},
+				Url: Config.WebDomain + "/front/sess/" + Se_Topnet.EncodeString(s_m_openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",msgremind") + "__" + fmt.Sprintf("type=paid&orderid=%d", orderId),
+			})
+			log.Println("支付成功,微信推送", userId, wxPushOk)
+		}
+	}()
+}
+
+func (m *msgRemind) getVipType(vipType int) string {
+	switch vipType {
+	case 0:
+		return "(试用)"
+	case 1:
+		return "(续费)"
+	case 2:
+		return "(升级)"
+	}
+	return ""
+}
+
+func (m *msgRemind) run() {
+	duration := time.Duration(TimeTaskConfig.UnpaidRemind.Duration) * time.Minute
+	log.Println("未支付订单定时任务run after", duration)
+	time.AfterFunc(duration, func() {
+		defer util.Catch()
+		m.unpaidOrders.Range(func(k interface{}, v interface{}) bool {
+			orderId, _ := k.(int)
+			unpaidOrder, _ := v.(*unpaidOrder)
+			now_unix := time.Now().Unix()
+			remind_status := 0
+			//剩余2小时
+			if unpaidOrder.remindStatus != 2 && now_unix >= unpaidOrder.createTime+259200-TimeTaskConfig.UnpaidRemind.BeforeExpire {
+				remind_status = 2
+			} else if unpaidOrder.remindStatus == 0 && now_unix > unpaidOrder.createTime+TimeTaskConfig.UnpaidRemind.AfterOrder { //下单时间后2小时未支付
+				remind_status = 1
+			}
+			if remind_status == 0 {
+				return true
+			}
+			user, ok := MQFW.FindById("user", unpaidOrder.userId, `{"s_m_openid":1,"s_jpushid":1,"s_opushid":1,"s_appponetype":1,"i_ispush":1}`)
+			if !ok || user == nil || len(*user) == 0 {
+				return true
+			}
+			isPushWx := util.IntAllDef((*user)["i_ispush"], 1)
+			s_m_openid, _ := (*user)["s_m_openid"].(string)
+			s_jpushid, _ := (*user)["s_jpushid"].(string)
+			s_opushid, _ := (*user)["s_opushid"].(string)
+			s_appponetype, _ := (*user)["s_appponetype"].(string)
+			log.Println("未支付订单,推送消息", unpaidOrder.userId, "remind_status", remind_status, "i_ispush", isPushWx, "s_m_openid", s_m_openid, "s_jpushid", s_jpushid, "s_opushid", s_opushid, "s_appponetype", s_appponetype)
+			wxPushOk, appPushOk := false, false
+			if isPushWx == 1 {
+				tmplData := map[string]*qrpc.TmplItem{
+					"first": &qrpc.TmplItem{
+						Value: fmt.Sprintf(MessageConfig.WxTpl_Unpaid.First.Value, unpaidOrder.orderCode),
+					},
+					"keyword1": &qrpc.TmplItem{
+						Value: util.FormatDateByInt64(&unpaidOrder.createTime, util.Date_Short_Layout),
+					},
+					"keyword2": &qrpc.TmplItem{
+						Value: unpaidOrder.orderCode,
+					},
+					"keyword3": &qrpc.TmplItem{
+						Value: fmt.Sprintf(MessageConfig.WxTpl_Unpaid.Keyword3.Value, fmt.Sprintf("%.2f", float64(unpaidOrder.orderMoney)/100)),
+					},
+					"keyword4": &qrpc.TmplItem{
+						Value: fmt.Sprintf(MessageConfig.WxTpl_Unpaid.Keyword4.Value, m.getVipType(unpaidOrder.vipType)),
+					},
+				}
+				if remind_status == 2 {
+					tmplData["remark"] = &qrpc.TmplItem{
+						Value: fmt.Sprintf(MessageConfig.WxTpl_Unpaid.Remark.Value, math.Ceil(float64(TimeTaskConfig.UnpaidRemind.BeforeExpire)/3600)),
+					}
+				}
+				wxPushOk, _ = qrpc.WxSendTmplMsg(Config.Weixinrpc, &qrpc.WxTmplMsg{
+					OpenId:   s_m_openid,
+					TplId:    MessageConfig.WxTpl_Unpaid.Id,
+					TmplData: tmplData,
+					Url:      Config.WebDomain + "/front/sess/" + Se_Topnet.EncodeString(s_m_openid+",uid,"+strconv.Itoa(int(time.Now().Unix()))+",msgremind") + "__" + fmt.Sprintf("type=unpaid&orderid=%d", orderId),
+				})
+				log.Println("未支付订单,微信推送", unpaidOrder.userId, wxPushOk)
+			}
+			if wxPushOk || appPushOk {
+				if remind_status == 2 {
+					m.unpaidOrders.Delete(orderId)
+				} else {
+					unpaidOrder.remindStatus = 1
+					m.unpaidOrders.Store(orderId, unpaidOrder)
+				}
+				Mysql.Update("dataexport_order", map[string]interface{}{
+					"id": orderId,
+				}, map[string]interface{}{
+					"remind_status": remind_status,
+				})
+			}
+			return true
+		})
+		m.run()
+	})
+}
+
+func init() {
+	go func() {
+		log.Println("开始加载72小时内的订单到内存中。。。")
+		startTime := time.Now().Local().AddDate(0, 0, -3).Format(util.Date_Full_Layout)
+		list := Mysql.SelectBySql("select id,order_code,order_money,user_id,create_time,remind_status,vip_type from dataexport_order where create_time>=? and product_type='VIP订阅' and order_status=0 and (remind_status<>2 or remind_status is null)", startTime)
+		if list == nil {
+			log.Println("加载72小时内的订单到内存中失败")
+			return
+		}
+		for _, v := range *list {
+			order_code, _ := v["order_code"].(string)
+			user_id, _ := v["user_id"].(string)
+			create_time, _ := v["create_time"].(string)
+			if order_code == "" || user_id == "" || create_time == "" {
+				continue
+			}
+			createTime, err := time.ParseInLocation(util.Date_Full_Layout, create_time, time.Local)
+			if err != nil {
+				continue
+			}
+			orderId := util.IntAll(v["id"])
+			MsgRemind.Add(orderId, util.IntAll(v["order_money"]), util.IntAllDef(v["vip_type"], -1), util.IntAll(v["remind_status"]), order_code, user_id, createTime.Unix())
+		}
+		log.Println("加载72小时内的订单到内存中结束。。。", len(*list))
+	}()
+	MsgRemind.run()
+}

+ 3 - 1
src/jfw/modules/subscribepay/src/util/public.go

@@ -1,10 +1,13 @@
 package util
 
 import (
+	qutil "qfw/util"
 	"qfw/util/sms"
 	"strings"
 )
 
+var Se_Topnet = qutil.SimpleEncrypt{Key: "topnet"}
+
 //根据模板发送短信,模板是运营商设定的。
 //第三个参数是可变参数,可以传入多个,但要和模板相匹配
 func SendSMS(tplcode /*模板代码*/, mobile /*手机号码*/ string, param map[string]string) {
@@ -15,4 +18,3 @@ func SendSMS(tplcode /*模板代码*/, mobile /*手机号码*/ string, param map
 	text := strings.Join(tmp, "&")
 	sms.SendSms(mobile, tplcode, text)
 }
-

+ 2 - 2
src/jfw/modules/weixin/src/jrpc/jrpc.go

@@ -40,7 +40,7 @@ func (w *WeiXinRpc) SubscribePush(param *qrpc.NotifyMsg, ret *qrpc.RpcResult) er
 			"first":    weixin.TmplItem{param.Title, util.If(param.Color != "", param.Color, "#0987FF").(string)},
 			"keyword1": weixin.TmplItem{param.Detail, ""},
 			"keyword2": weixin.TmplItem{param.Service, ""},
-			"remark":   weixin.TmplItem{param.Remark, util.If(param.Color != "", param.DetailColor, "#0987FF").(string)},
+			"remark":   weixin.TmplItem{param.Remark, util.If(param.DetailColor != "", param.DetailColor, "#0987FF").(string)},
 		})
 	if err != nil {
 		*ret = qrpc.RpcResult(err.Error())
@@ -58,7 +58,7 @@ func (w *WeiXinRpc) SendPushMsg(param *qrpc.NotifyMsg, ret *qrpc.RpcResult) erro
 			"first":    weixin.TmplItem{param.Title, util.If(param.Color != "", param.Color, "#0987FF").(string)},
 			"keyword1": weixin.TmplItem{param.Detail, ""},
 			"keyword2": weixin.TmplItem{param.Service, ""},
-			"remark":   weixin.TmplItem{param.Remark, util.If(param.Color != "", param.DetailColor, "#0987FF").(string)},
+			"remark":   weixin.TmplItem{param.Remark, util.If(param.DetailColor != "", param.DetailColor, "#0987FF").(string)},
 		})
 	if err != nil {
 		*ret = qrpc.RpcResult(err.Error())