Commit c32b7c05 by zhangjie

1.增加留言相关功能

parent 53919eb0
package api_we_card_operate
import (
"dc_golang_server_1/api"
"dc_golang_server_1/data_db_cache/cache"
"dc_golang_server_1/logger"
"dc_golang_server_1/util"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net/http"
)
type qr2StudentsRes struct {
AreaID uint32 `json:"areaID"` // 区域ID 用作创建学生
AreaName string `json:"areaName"` // 区域名字 用作创建学生
CardNum string `json:"cardNum"` // 卡号 等会调绑卡接口来用
CardType uint8 `json:"cardType"` // 卡类型:1电话卡 等会调绑卡接口来用
Students []struct {
Expiry string `json:"expiry"` // 缴费的到期时间,年月日(日期当天则仍在有效期内),展示给用户看,如果过了,就要先缴费才能绑卡,如果是"0001-01-01",则表示从来未缴过费
Name string `json:"name"` // 学生昵称,另外去把头像也拉下来展示出来
Sex uint8 `json:"sex"` // 性别 0,无信息,1女,2男
CID uint32 `json:"cid"` // 学生ID 等会调绑卡接口来用
Master bool `json:"master"` // 是否为主家长,页面上展示出来
} `json:"students"` // 学生列表
}
// Qr2Students 根据二维码,返回用户状态信息及卡号
// @Tags 家长微信-卡操作
// @Summary 根据二维码,返回用户状态信息及卡号
// @Description 根据二维码,返回用户状态信息及卡号
// @Produce json
// @Param qrcode path string true "QR内容"
// @Success 0 {object} qr2StudentsRes "result"
// @Router /we/qr2students/{qrcode} [GET]
// @Security ApiKeyAuth
func Qr2Students(c *gin.Context) {
qrCode := c.Param("qrcode")
if len(qrCode) != 36 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara] + " 二维码长度错误",
})
return
}
cardID, err := util.DecryptBase64URLToBytes(qrCode, "keyQR123@dcrym01")
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara] + " 无效二维码",
})
return
}
for i := 0; i < 26; i++ {
cardID[i] -= uint8(i)%3 + 0x18
}
cardID[11], cardID[25], cardID[20], cardID[22], cardID[9], cardID[24], cardID[21], cardID[12], cardID[0] = cardID[0], cardID[9], cardID[11], cardID[12], cardID[20], cardID[21], cardID[22], cardID[24], cardID[25]
if cardID[20] != 0x16 || cardID[21] != 0x11 || cardID[22] != 0x03 || !util.CheckCRC(cardID) {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara] + " 无效二维码",
})
return
}
res := qr2StudentsRes{
CardNum: string(cardID[:20]),
CardType: 1,
}
// 获取sim卡信息
simInfo := cache.GetSimInfo(res.CardNum) // 根据请求的卡号,获取系统中卡的信息
if simInfo == nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": "卡号错误:系统找不到该卡号",
})
return
}
if simInfo.CardUserID != 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": "该卡已被绑定",
})
return
}
if simInfo.Status == 0 || simInfo.AreaServiceID == 0 { // 没绑校区的卡视为未出库的卡
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": "无效卡",
})
return
}
areaServiceInfo := cache.GetAreaServiceInfo(simInfo.AreaServiceID)
if areaServiceInfo == nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr] + " 查询不到区域服务信息",
})
return
}
// 取微信用户
v, ok := c.Get("userID")
weUserID := v.(uint32)
if ok != true || weUserID == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("Qr2Students",
zap.Reflect("c.Get(\"userID\")", v))
return
}
weUserInfo := cache.GetWeUserInfoFromMapAndDB(weUserID)
if weUserInfo == nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("Qr2Students weUserInfo == nil",
zap.Uint32("weUserID", weUserID))
return
}
res.AreaID = areaServiceInfo.AreaID
res.AreaName = cache.GetAreaMapName(areaServiceInfo.AreaID, weUserInfo.TestRole)
if len(res.AreaName) == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": "对不起,您不具备测试区域权限,请联系管理员",
})
return
}
for _, cardUserID := range weUserInfo.MasterCardUserID {
cardUserInfo := cache.GetCardUserInfo(cardUserID)
if cardUserInfo != nil && cardUserInfo.AreaID == res.AreaID && len(cardUserInfo.SimCardID) == 0 { // 在卡这个校区的,且没绑卡的
res.Students = append(res.Students, struct {
Expiry string `json:"expiry"` // 缴费的到期时间,年月日(日期当天则仍在有效期内),展示给用户看,如果过了,就要先缴费才能绑卡
Name string `json:"name"` // 学生昵称,另外去把头像也拉下来展示出来
Sex uint8 `json:"sex"` // 性别 0,无信息,1女,2男
CID uint32 `json:"cid"` // 学生ID 等会调绑卡接口来用
Master bool `json:"master"` // 是否为主家长,页面上展示出来
}{
Expiry: cardUserInfo.PhoneExpiry.Format("2006-01-02"),
Name: cardUserInfo.Name,
Sex: cardUserInfo.Sex,
CID: cardUserID,
Master: true,
})
}
}
for _, cardUserID := range weUserInfo.SlaveCardUserID {
cardUserInfo := cache.GetCardUserInfo(cardUserID)
if cardUserInfo != nil && cardUserInfo.AreaID == res.AreaID && len(cardUserInfo.SimCardID) == 0 { // 在卡这个校区的,且没绑卡的
res.Students = append(res.Students, struct {
Expiry string `json:"expiry"` // 缴费的到期时间,年月日(日期当天则仍在有效期内),展示给用户看,如果过了,就要先缴费才能绑卡
Name string `json:"name"` // 学生昵称,另外去把头像也拉下来展示出来
Sex uint8 `json:"sex"` // 性别 0,无信息,1女,2男
CID uint32 `json:"cid"` // 学生ID 等会调绑卡接口来用
Master bool `json:"master"` // 是否为主家长,页面上展示出来
}{
Expiry: cardUserInfo.PhoneExpiry.Format("2006-01-02"),
Name: cardUserInfo.Name,
Sex: cardUserInfo.Sex,
CID: cardUserID,
Master: false,
})
}
}
c.JSON(http.StatusOK, gin.H{
"code": api.Success,
"data": res,
})
}
package api_we_msg
import (
"dc_golang_server_1/api"
"dc_golang_server_1/data_db_cache/cache"
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/logger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net/http"
"strconv"
)
//type reqDeleteMsg struct {
// CardUserID uint32 `json:"cardUserID"` // 学生ID
// MsgID []uint32 `json:"msgID"` // 留言ID
//}
// DeleteMsg 家长删除未读留言,主家长可删所有留言,附家长只能删自己发起的
// @Tags 家长微信-留言
// @Summary 家长删除未读留言
// @Description 家长删除未读留言
// @Produce json
// @Param cid path integer true "学生ID"
// @Param mid path integer true "留言ID"
// @Success 0
// @Router /we/msg/{cid}/{mid} [DELETE]
// @Security ApiKeyAuth
func DeleteMsg(c *gin.Context) {
cardUserIDInt64, _ := strconv.ParseInt(c.Param("cid"), 10, 32)
msgIDInt64, _ := strconv.ParseInt(c.Param("mid"), 10, 32)
if cardUserIDInt64 == 0 || msgIDInt64 == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara],
})
return
}
cardUserID := uint32(cardUserIDInt64)
msgID := uint32(msgIDInt64)
// 取微信用户
v, ok := c.Get("userID")
weUserID := v.(uint32)
if ok != true || weUserID == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("DeleteMsg",
zap.Reflect("c.Get(\"userID\")", v))
return
}
// 校验weUserID是否有cardUserID权限
if cache.CheckCardUserMaserAndSlaveWeID(cardUserID, weUserID) < 2 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorUserRole,
"message": api.CodeMsg[api.ErrorUserRole],
})
return
}
if dbcurd.DeleteUMsgNRead(cardUserID, msgID) {
cache.DeleteOneNReadMsg(cardUserID, msgID)
c.JSON(http.StatusOK, gin.H{
"code": api.Success,
})
} else {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemBusy,
"message": api.CodeMsg[api.ErrorSystemBusy],
})
}
}
package api_we_msg
import (
"dc_golang_server_1/api"
"dc_golang_server_1/data_db_cache/cache"
"dc_golang_server_1/logger"
"dc_golang_server_1/util"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net/http"
"strconv"
"time"
)
type resNReadMsg struct {
ID uint32 `json:"id"`
Msg string `json:"msg"`
Nickname string `json:"nickname"` // 微信昵称
AvatarURL string `json:"avatarURL"` // 头像URL
Phone string `json:"phone"` // 手机号
CreateAt string `json:"createAt"` // 创建时间
DelEnable bool `json:"delEnable"` // 是否可删除
}
type msgPayStruct struct {
Status uint8 `json:"status"` // 0 留言服务已到期 1 未开通留言服务
Amount int32 `json:"amount"` // 金额
Expiry string `json:"expiry"` // 缴费后有效期
}
// GetMsgNRead 家长获取未读留言列表,主家长删所有留言,附家长只能删自己发起的
// @Tags 家长微信-留言
// @Summary 家长获取未读留言列表,注意,这个接口有可能返回 []resNReadMsg ,也有可能返回 msgPayStruct
// @Description 家长获取未读留言列表
// @Produce json
// @Param cid path integer true "学生ID"
// @Success 0 {object} []resNReadMsg "留言列表"
// @Failure 1 {object} msgPayStruct “支付信息”
// @Router /we/msgnread/{aid}/{cid} [GET]
// @Security ApiKeyAuth
func GetMsgNRead(c *gin.Context) {
cardUserIDInt64, _ := strconv.ParseInt(c.Param("cid"), 10, 32)
areaServiceIDInt64, _ := strconv.ParseInt(c.Param("aid"), 10, 32)
if cardUserIDInt64 == 0 || areaServiceIDInt64 == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara],
})
return
}
cardUserID := uint32(cardUserIDInt64)
cardUserInfo := cache.GetCardUserInfo(cardUserID)
if cardUserInfo == nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("GetMsgNRead cardUserInfo == nil",
zap.Uint32("cardUserID", cardUserID))
return
}
if time.Now().After(cardUserInfo.PhoneExpiry.Add(23 * time.Hour)) { // 话费服务都到期了
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": "对不起,您的公话服务已到期",
})
return
}
if time.Now().Before(cardUserInfo.MsgExpiry.Add(23 * time.Hour)) { // 留言服务费未到期
// 取微信用户
v, ok := c.Get("userID")
weUserID := v.(uint32)
if ok != true || weUserID == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("GetMsgNRead",
zap.Reflect("c.Get(\"userID\")", v))
return
}
// 校验weUserID是否有cardUserID权限
if cache.CheckCardUserMaserAndSlaveWeID(cardUserID, weUserID) < 2 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorUserRole,
"message": api.CodeMsg[api.ErrorUserRole],
})
return
}
cacheRes := cache.GetNReadMsgMap(cardUserID)
res := make([]resNReadMsg, len(cacheRes))
for i, v1 := range cacheRes {
weInfo := cache.GetWeUserInfoFromMapAndDB(v1.WeUserID)
if weInfo != nil {
res[i].Nickname = weInfo.Nickname
res[i].Phone = weInfo.WePhone
res[i].AvatarURL = weInfo.AvatarURL
}
res[i].Msg = v1.Msg
res[i].DelEnable = true
res[i].ID = v1.ID
res[i].CreateAt = v1.CreateAt.Format("2006-01-02 15:04:05")
}
c.JSON(http.StatusOK, gin.H{
"code": api.Success,
"data": res,
})
} else {
msgFee := cache.GetPhoneMsgFeeMap(uint32(areaServiceIDInt64))
if msgFee == nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorServiceStop,
"message": api.CodeMsg[api.ErrorServiceStop],
})
return
}
var res msgPayStruct
if cardUserInfo.MsgExpiry == *new(time.Time) { // 未开通留言服务
res.Status = 1
}
res.Expiry = cardUserInfo.PhoneExpiry.Format("2006-01-02")
res.Amount = msgFee.Amount * util.SubMonth(cardUserInfo.PhoneExpiry, time.Now())
if res.Amount <= 0 {
res.Amount = 1 // 先收1分钱,后面来处理 todo
if msgFee.Amount == 0 {
logger.Log.Error("费率为0居然没开留言服务 GetMsgNRead", zap.Int64("areaServiceIDInt64", areaServiceIDInt64), zap.Uint32("cardUserID", cardUserID))
}
}
c.JSON(http.StatusOK, gin.H{
"code": api.Success,
"data": res,
})
}
}
package api_we_msg
import (
"dc_golang_server_1/api"
"dc_golang_server_1/data_db_cache/cache"
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/logger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net/http"
"strconv"
)
// GetMsgRead 家长获取已读留言列表
// @Tags 家长微信-留言
// @Summary 家长获取已读留言列表
// @Description 家长获取已读留言列表
// @Produce json
// @Param cid path integer true "学生ID"
// @Success 0 {object} []dbcurd.SelectUMsgReadRecordRes "留言列表"
// @Router /we/msgread/{aid}/{cid} [GET]
// @Security ApiKeyAuth
func GetMsgRead(c *gin.Context) {
cardUserIDInt64, _ := strconv.ParseInt(c.Param("cid"), 10, 32)
areaServiceIDInt64, _ := strconv.ParseInt(c.Param("aid"), 10, 32)
if cardUserIDInt64 == 0 || areaServiceIDInt64 == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara],
})
return
}
cardUserID := uint32(cardUserIDInt64)
// 取微信用户
v, ok := c.Get("userID")
weUserID := v.(uint32)
if ok != true || weUserID == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("GetMsgRead",
zap.Reflect("c.Get(\"userID\")", v))
return
}
// 校验weUserID是否有cardUserID权限
if cache.CheckCardUserMaserAndSlaveWeID(cardUserID, weUserID) < 2 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorUserRole,
"message": api.CodeMsg[api.ErrorUserRole],
})
return
}
res := dbcurd.SelectUMsgReadRecord(cardUserID, uint32(areaServiceIDInt64))
for i, d := range res {
weUserInfo := cache.GetWeUserInfoFromMapAndDB(d.WeUserID)
if weUserInfo != nil {
res[i].Nickname = weUserInfo.Nickname
res[i].AvatarURL = weUserInfo.AvatarURL
res[i].Phone = weUserInfo.WePhone
}
}
c.JSON(http.StatusOK, gin.H{
"code": api.Success,
"data": res,
})
}
package api_we_msg
import (
"dc_golang_server_1/api"
"dc_golang_server_1/data_db_cache/cache"
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/data_db_cache/model"
"dc_golang_server_1/logger"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
"net/http"
"time"
)
// PostMsg 家长向学生发起留言
// @Tags 家长微信-留言
// @Summary 家长向学生发起留言
// @Description 家长向学生发起留言,注意,超过10条将删除前面的留言
// @Accept json
// @Produce json
// @Param data body dbcurd.InsertTableUMsgNReadStruct true "留言信息"
// @Success 0
// @Router /we/msg [POST]
// @Security ApiKeyAuth
func PostMsg(c *gin.Context) {
var reqData dbcurd.InsertTableUMsgNReadStruct
err := c.ShouldBindJSON(&reqData)
if err != nil || reqData.CardUserID == 0 || reqData.AreaServiceID == 0 || len(reqData.Msg) == 0 || len(reqData.Msg) > 300 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqParaFormat,
"message": api.CodeMsg[api.ErrorReqParaFormat],
})
return
}
// 取微信用户
v, ok := c.Get("userID")
reqData.WeUserID = v.(uint32)
if ok != true || reqData.WeUserID == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemErr,
"message": api.CodeMsg[api.ErrorSystemErr],
})
logger.Log.Error("GetCallRecord",
zap.Reflect("c.Get(\"userID\")", v))
return
}
// 校验weUserID是否有cardUserID权限
if cache.CheckCardUserMaserAndSlaveWeID(reqData.CardUserID, reqData.WeUserID) < 2 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorUserRole,
"message": api.CodeMsg[api.ErrorUserRole],
})
return
}
//cardUserInfo := cache.GetCardUserInfo(reqData.CardUserID)
//if cardUserInfo == nil {
// c.JSON(http.StatusOK, gin.H{
// "code": api.ErrorSystemErr,
// "message": api.CodeMsg[api.ErrorSystemErr],
// })
// logger.Log.Error("PostMsg cardUserInfo == nil",
// zap.Reflect("reqData", reqData))
// return
//}
//CardUserID uint32 `json:"cardUserID"` // 学生ID
//AreaServiceID uint32 `json:"-"`
//WeUserID uint32 `json:"-"`
//Msg string `json:"msg"` // 留言内容
reqData.CreateAt = time.Now()
msgID := dbcurd.InsertUMsgNRead(&reqData)
if msgID == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorSystemBusy,
"message": api.CodeMsg[api.ErrorSystemBusy],
})
return
}
cache.InsertNReadMsgMap(reqData.CardUserID, &model.CacheCardUserNReadMsgStruct{
ID: msgID,
CreateAt: reqData.CreateAt,
WeUserID: reqData.WeUserID,
Msg: reqData.Msg,
})
c.JSON(http.StatusOK, gin.H{
"code": api.Success,
})
}
......@@ -17,6 +17,7 @@ type getPhoneCardStatusRes struct {
model.CacheSimInfoStruct
ExpiryAtString string `json:"expiryAt"` // 给前端返回年月日
MaxFamily uint8 `json:"maxFamily"` // 最多可以添加几个亲情号
MsgEnable bool `json:"msgEnable"` // 是否显示留言按钮(本区域服务是否开通留言服务)
}
// GetPhoneCardStatus 获取学生公话卡状态
......@@ -146,6 +147,7 @@ func GetPhoneCardStatus(c *gin.Context) { // 以后要改成根据区域服务
CacheSimInfoStruct: *res,
ExpiryAtString: res.ExpiryAt.Format("2006-01-02"),
MaxFamily: 2,
MsgEnable: cache.GetPhoneMsgFeeMap(res.AreaServiceID) != nil, // 如果留言服务费缓存有该区域服务ID,则说明该区域服务开通了留言功能
},
})
}
......
......@@ -20,6 +20,7 @@ import (
type wePostPayReq struct {
CID uint32 `json:"cid"` // 学生id
LID uint32 `json:"lid"` // 选填,话费支付列表id,若不传则不充话费,只是开卡或补卡(实际应用中,补卡就不传这个)
Msg bool `json:"msg"` // 选填,补开通留言服务或充话费时才有效,且即便是充话费的时候都可以不填,不填就默认不开通留言服务,若只填了CID和Msg则为补开通留言服务
CardFeeType uint8 `json:"cardFeeType"` // 选填 1开卡/2补卡
}
......@@ -46,7 +47,7 @@ func PostPay(c *gin.Context) {
}
aidInt64, _ := strconv.ParseInt(c.Param("aid"), 10, 32)
if aidInt64 == 0 || reqData.CID == 0 || (reqData.LID == 0 && reqData.CardFeeType == 0) { // 既不缴卡费又不充话
if aidInt64 == 0 || reqData.CID == 0 || (reqData.LID == 0 && reqData.CardFeeType == 0 && reqData.Msg == false) { // 既不缴卡费又不充话费还不是补交留言
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara],
......@@ -159,6 +160,7 @@ func PostPay(c *gin.Context) {
//orderNum := strconv.FormatUint(uint64(reqData.CID), 10) + "_" + //strconv.FormatInt(lidInt64, 10) + "_" +
// strconv.FormatUint(uint64(payInfo.Amount), 10) + "_" + productTime.Format("060102150405.000000000") + "_" + payInfo.Expiry
var expiry uint8
if reqData.LID > 0 { // 要缴话费
payType |= 0x10
var payInfo model.CacheAreaServicePhonePayListStruct
......@@ -172,6 +174,7 @@ func PostPay(c *gin.Context) {
newExpiry = util.RenewExpiry(cardUserInfo.PhoneExpiry, payInfo.Expiry) // 续费
}
expiry = payInfo.Expiry
applyPayPara.Amount += payInfo.Amount
applyPayPara.SplitAmount = payInfo.SplitAmount
break
......@@ -187,6 +190,42 @@ func PostPay(c *gin.Context) {
}
}
if reqData.Msg { // 要缴留言服务费
msgFee := cache.GetPhoneMsgFeeMap(aid)
if msgFee == nil {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara] + "该区域未开通留言服务",
})
return
}
payType |= 0x20 // 要开通留言服务
if msgFee.Amount > 0 {
if expiry > 0 {
applyPayPara.Amount += msgFee.Amount * int32(expiry)
} else { // todo 处理下留言续费逻辑
applyPayPara.Amount += msgFee.Amount * util.SubMonth(cardUserInfo.PhoneExpiry, time.Now())
}
for v1i, v1 := range applyPayPara.SplitAmount {
for v2i, v2 := range msgFee.SplitAmount {
if v1.AdminID == v2.AdminID {
applyPayPara.SplitAmount[v1i].Amount += v2.Amount * int32(expiry)
applyPayPara.SplitAmount[v1i].Remark += "(" + strconv.FormatUint(uint64(v1.Amount), 10) + "分)+留言服务费:" + v2.Remark + "(" + strconv.FormatUint(uint64(v2.Amount), 10) + "分)"
msgFee.SplitAmount = append(msgFee.SplitAmount[:v2i], msgFee.SplitAmount[v2i+1:]...)
break
}
}
}
for _, v1 := range msgFee.SplitAmount {
applyPayPara.SplitAmount = append(applyPayPara.SplitAmount, model.PaySplitMoneyStruct{
AdminID: v1.AdminID,
Amount: v1.Amount,
Remark: "留言服务费:" + v1.Remark,
})
}
}
}
if payType == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
......@@ -195,7 +234,15 @@ func PostPay(c *gin.Context) {
return
}
// 订单号生成规则:4B cardUserID,4B到期时间,4B 金额amount,8B 时间纳秒
if applyPayPara.Amount == 0 {
c.JSON(http.StatusOK, gin.H{
"code": api.ErrorReqPara,
"message": api.CodeMsg[api.ErrorReqPara] + " 对应充值项已失效",
})
return
}
// 订单号生成规则:4B cardUserID,4B到期时间,4B 金额amount,,1B payType,8B 时间纳秒
productTime := time.Now()
unixNano := productTime.UnixNano()
ex := uint32(newExpiry.Unix())
......@@ -212,6 +259,7 @@ func PostPay(c *gin.Context) {
byte(applyPayPara.Amount >> 16),
byte(applyPayPara.Amount >> 8),
byte(applyPayPara.Amount),
payType,
byte(unixNano >> 56),
byte(unixNano >> 48),
byte(unixNano >> 40),
......@@ -220,7 +268,6 @@ func PostPay(c *gin.Context) {
byte(unixNano >> 16),
byte(unixNano >> 8),
byte(unixNano),
byte(0x55),
})
dbInsertData := dbcurd.InsertTableUPhonePayRecordAndSplit{
......@@ -236,8 +283,8 @@ func PostPay(c *gin.Context) {
ProductAt: productTime,
PayAdminID: areaServiceInfo.PayAdminID, // 通联支付取消微信MchID增加收款主体的adminID
// Describe: "",
ExpiryAt: newExpiry,
Type: payType, // // 缴费类型:1仅开卡 2仅补卡 16续费 17开卡+充值 18补卡+续费
ExpiryAt: newExpiry,
Type: payType, // // 缴费类型:1仅开卡 2仅补卡 16续费 17开卡+充值 18补卡+续费
SplitAmount: applyPayPara.SplitAmount,
}
switch payType {
......@@ -251,6 +298,15 @@ func PostPay(c *gin.Context) {
dbInsertData.Describe = "充值(含开卡)"
case 0x12:
dbInsertData.Describe = "充值(含补卡)"
case 0x20: // 仅补缴留言服务
// todo zjzjzj 判断是否已经有家长缴费了,如果有了不允许再补交
dbInsertData.Describe = "留言服务费"
case 0x20 + 0x10:
dbInsertData.Describe = "话费充值(含留言服务)"
case 0x20 + 0x11:
dbInsertData.Describe = "充值(含开卡、留言服务)"
case 0x20 + 0x12:
dbInsertData.Describe = "充值(含补卡、留言服务)"
}
//if dbcurd.InsertUPhonePayRecord(&dbInsertData) != dbcurd.InsertOK {
......@@ -282,8 +338,6 @@ func PostPay(c *gin.Context) {
"code": api.Success,
"data": res,
})
return
}
//type wechatPostPayTest struct {
......
......@@ -15,6 +15,7 @@ type getPreviewCardUserStruct struct {
Name string `json:"name"` // 学生名字,脱敏显示
Area string `json:"area" example:"温江实验中学"` // 区域名字
ID uint32 `json:"id"` // 学生ID
Sex uint8 `json:"sex"` //0,无信息,1女,2男
}
// GetPreviewCardUser 通过邀请码获取学生预览信息
......@@ -147,6 +148,7 @@ func GetPreviewCardUser(c *gin.Context) {
cardUserInfo.Name,
cache.GetAreaMapName(cardUserInfo.AreaID, true),
cardUserID, //api_we_student.GetCardUserDownSmallAvatarQiNiuURL(cardUserID),
cardUserInfo.Sex,
},
})
}
......@@ -11,7 +11,7 @@ import (
)
type slaveWeUserRes struct {
WeUserID uint32 `json:"weUserID"` // 微信UnionID
WeUserID uint32 `json:"weUserID"` // 微信用户ID
Nickname string `json:"nickname"` // 微信昵称
AvatarURL string `json:"avatarURL"` // 头像URL
Phone string `json:"phone"` // 手机号
......
......@@ -6,6 +6,7 @@ import (
"dc_golang_server_1/api/api_server_ops"
"dc_golang_server_1/api/api_we/api_we_card_operate"
"dc_golang_server_1/api/api_we/api_we_login_we_info"
"dc_golang_server_1/api/api_we/api_we_msg"
"dc_golang_server_1/api/api_we/api_we_phone_card"
"dc_golang_server_1/api/api_we/api_we_phone_pay"
"dc_golang_server_1/api/api_we/api_we_slave"
......@@ -135,10 +136,11 @@ func InitRouter() { //*gin.Engine{
//wechat.PUT("cardusershareoff/:id", api_we.PutCardUserShareOff) //关闭邀请码开关(仅主家长有权限)
wechat.DELETE("slaveweuser/:id", api_we_slave.DeleteSlaveWeUser) //删除副家长(仅主家长有权限)
wechat.GET("qr2cardid/:qrcode", api_we_card_operate.Qr2CardID) // Qr2CardID 根据二维码,返回卡号信息
wechat.PUT("cardloss/:id", api_we_card_operate.CardLoss) //卡挂失/解挂
wechat.PUT("cardbind/:id", api_we_card_operate.CardBind) //绑定卡
wechat.DELETE("cardbind/:id", api_we_card_operate.DeleteCardBind) //解绑卡
wechat.GET("qr2cardid/:qrcode", api_we_card_operate.Qr2CardID) // Qr2CardID 根据二维码,返回卡号信息
wechat.GET("qr2students/:qrcode", api_we_card_operate.Qr2Students) // Qr2CardID 根据二维码,返回用户状态信息及卡号
wechat.PUT("cardloss/:id", api_we_card_operate.CardLoss) //卡挂失/解挂
wechat.PUT("cardbind/:id", api_we_card_operate.CardBind) //绑定卡
wechat.DELETE("cardbind/:id", api_we_card_operate.DeleteCardBind) //解绑卡
wechat.GET("phonecardstatus/:id", api_we_phone_card.GetPhoneCardStatus) //获取学生公话卡状态
wechat.POST("familynum/:id", api_we_phone_card.AddFamilyNum) //添加亲情号
......@@ -157,8 +159,10 @@ func InitRouter() { //*gin.Engine{
// wechat.GET("replacecardfee/phone/:aid", api_we_phone_pay.GetReplaceCardFeePhone) //查询补卡费(目前仅公话卡)
// wechat.POST("payreplacecard/phone/:aid/:cid", api_we_phone_pay.PostPayReplaceCard) //补卡缴费(目前仅公话卡)
//获取学生定位卡状态
//查询通行记录
wechat.GET("msgnread/:aid/:cid", api_we_msg.GetMsgNRead) // 家长获取未读留言列表
wechat.GET("msgread/:aid/:cid", api_we_msg.GetMsgRead) // 家长获取已读留言列表
wechat.POST("msg", api_we_msg.PostMsg) // 家长向学生发起留言
wechat.DELETE("msg/:cid/:mid", api_we_msg.DeleteMsg) // 家长删除未读留言,主家长删所有留言,附家长只能删自己发起的
}
//// r.POST("ad/login", api_we.AdminLogin)
......@@ -184,7 +188,7 @@ func InitRouter() { //*gin.Engine{
phone := r.Group("phone20/")
// phone.Use(adminCors(),api.JeffWTPublic())
dcphone20.TCP.NewDCPhone20API(phone)
dcphone20.TCP.NewDCPhone20API(phone) // todo 改到admin去
fmt.Println("根路径: " + setting.HttpServerMainHost + setting.HttpServerPort)
......
[token]
KEY = `jeffWT@666%b;'~+`
KEY = `dcrymk12testabcd`
[grpc_server]
Grpc2AdminListenPort = :7010
Grpc2TcpConnListenPort = :7011
[grpc_client]
GrpcFromDeviceConnServerIpPort = 127.0.0.1:7020
#GrpcFromDeviceConnServerIpPort = 127.0.0.1:7020
#GrpcFromDeviceConnServerIpPort = 192.168.1.43:7020
GrpcFromDeviceConnServerIpPort = k12t.shero.plus:7020
[allin_pay]
#测试 K12B 正式 K12B-
......@@ -57,11 +59,13 @@ AppSecret = 8e007ad30204af2a64af27ecc88b54e7
[sms_captcha]
#短信验证码服务器请求地址
#url = http://127.0.0.1:6051
url = http://192.168.1.43:6051
url = http://k12t.shero.plus:6051
#url = http://192.168.1.43:6051
[firmware_server]
#固件服务器地址
baseUrl = http://192.168.1.41:6031
#baseUrl = http://192.168.1.41:6031
baseUrl = http://k12t.shero.plus:6031
deviceUrl = http://k12t.shero.plus:6031
[log]
......
......@@ -14,8 +14,11 @@ func Init() {
initWechatAndCardUserRelationToWechatCustomerMapAndCardUserMap()
initSimInfoMap()
initAreaServiceMap()
initPhoneMsgFeeMap()
initPhone20DeviceMap()
initCardUserTrendMap()
initNReadMsgMap()
initAreaServicePhonePayListMap()
areaServicePhonePayListMapAddSplit() // 区域服务收款项列表添加分账列表
// initWechatMchInfoMap()
......@@ -36,6 +39,9 @@ var areaMap sync.Map // 有列表,全局锁增删改 仅GRPC
// status不为0的所有区域服务 map[uint32_areaServiceID]model.CacheAreaServiceStruct -----OK
var areaServiceMap sync.Map // 无列表,直接增删改 仅GRPC
// 话机留言服务费缓存,若没有对应的区域服务ID,则该区域服务未开通留言功能 map[uint32_areaServiceID]model.CachePhoneMsgFeeStruct
var phoneMsgFeeMap sync.Map
// 校区服务支付信息 map[uint32_areaServiceID][]model.CacheAreaServicePhonePayListStruct 仅缓存库里面status==true的项 -----OK
var areaServicePhonePayListMap sync.Map // 列表,全局锁增删改 仅GRPC
......@@ -66,5 +72,8 @@ var cardUserMap sync.Map //有列表,大并发量,channel增删改
// 学生最新动态 map[uint32_cardUserID][]model.CacheCardUserTrendStruct -----OK
var cardUserTrendMap sync.Map //有列表,全局锁增删改
// 学生未读留言缓存,每个学生最多10条未读留言 map[uint32_cardUserID][]model.CacheCardUserNReadMsgStruct
var nReadMsgMap sync.Map //
// 固件升级缓存 存设备号和期望的固件版本,如果设备已经是期望版本,则删除
var deviceUpdateFirmwareMapPhone20 sync.Map // map[deviceID uint32]firmwareName string
......@@ -17,7 +17,7 @@ func initAreaServicePhonePayListMap() { // 存入status为true且verify_result=1
fmt.Println(time.Now(), "cache: initAreaServicePhonePayListMap begin")
// rows, err := dbcurd.PgDb.Query("SELECT id,area_service_id,expiry,amount,month_min,describe FROM b_phone_pay_list WHERE status=true and verify_result=1 ORDER BY create_at") // 暂时不管审核的事情
rows, err := dbcurd.PgDb.Query("SELECT id,area_service_id,expiry,amount,month_min,describe,status FROM b_phone_pay_list ORDER BY create_at") // 暂时不管审核的事情
rows, err := dbcurd.PgDb.Query("SELECT id,area_service_id,expiry,amount,month_min,describe,status,msg_enable FROM b_phone_pay_list ORDER BY create_at") // 暂时不管审核的事情
if err != nil {
log.Panicln("initAreaServicePhonePayListMap rows", err)
}
......@@ -28,20 +28,20 @@ func initAreaServicePhonePayListMap() { // 存入status为true且verify_result=1
var temp model.CacheAreaServicePhonePayListStruct
for rows.Next() {
var list []model.CacheAreaServicePhonePayListStruct
err = rows.Scan(&temp.ID, &areaServiceID, &temp.Expiry, &temp.Amount, &temp.MonthMin, &temp.Describe, &temp.Status)
err = rows.Scan(&temp.ID, &areaServiceID, &temp.Expiry, &temp.Amount, &temp.MonthMin, &temp.Describe, &temp.Status, &temp.MsgEnable)
if err != nil {
log.Panicln("initAreaServicePhonePayListMap rows.Scan", err)
}
//if t.After(time.Now()) {
if areaServiceID > 0 {
if v, ok := areaServicePhonePayListMap.Load(areaServiceID); ok {
list, _ = v.([]model.CacheAreaServicePhonePayListStruct)
}
list = append(list, temp)
areaServicePhonePayListMap.Store(areaServiceID, list)
// fmt.Println(areaServiceID,list)
if areaServiceID > 0 {
if v, ok := areaServicePhonePayListMap.Load(areaServiceID); ok {
list, _ = v.([]model.CacheAreaServicePhonePayListStruct)
}
list = append(list, temp)
areaServicePhonePayListMap.Store(areaServiceID, list)
// fmt.Println(areaServiceID,list)
}
//} else {
// logger.Log.Error("充值项已到期",
// zap.String("Src", "initAreaServicePhonePayListMap"),
......@@ -89,20 +89,20 @@ func GetAreaServicePhonePayListMap(areaServiceID uint32) []model.CacheAreaServic
var areaServicePhonePayListMapUpdateLock sync.Mutex // 直接全局锁
// AddPhonePayListMap 仅GRPC调用,给校区服务添加一项支付项
func AddPhonePayListMap(areaServiceID uint32,newData *model.CacheAreaServicePhonePayListStruct) error {
func AddPhonePayListMap(areaServiceID uint32, newData *model.CacheAreaServicePhonePayListStruct) error {
areaServicePhonePayListMapUpdateLock.Lock()
defer areaServicePhonePayListMapUpdateLock.Unlock()
if v, ok := areaServicePhonePayListMap.Load(areaServiceID); ok {
if list, ok := v.([]model.CacheAreaServicePhonePayListStruct); ok {
for i,oldData := range list {
if oldData.ID == newData.ID{ // 如果已经有这个ID的了,先删除
for i, oldData := range list {
if oldData.ID == newData.ID { // 如果已经有这个ID的了,先删除
list = append(list[:i], list[i+1:]...)
// break 等它遍历完
}
}
list = append(list,*newData)
areaServicePhonePayListMap.Store(areaServiceID,list)
list = append(list, *newData)
areaServicePhonePayListMap.Store(areaServiceID, list)
return nil
} else {
areaServicePhonePayListMap.Delete(areaServiceID)
......@@ -112,24 +112,24 @@ func AddPhonePayListMap(areaServiceID uint32,newData *model.CacheAreaServicePhon
}
}
areaServicePhonePayListMap.Store(areaServiceID,[]model.CacheAreaServicePhonePayListStruct{*newData})
areaServicePhonePayListMap.Store(areaServiceID, []model.CacheAreaServicePhonePayListStruct{*newData})
return nil
}
// DelPhonePayListMap 仅GRPC调用,校区服务删除一项支付项
func DelPhonePayListMap(areaServiceID , payListID uint32) {
func DelPhonePayListMap(areaServiceID, payListID uint32) {
areaServicePhonePayListMapUpdateLock.Lock()
defer areaServicePhonePayListMapUpdateLock.Unlock()
if v, ok := areaServicePhonePayListMap.Load(areaServiceID); ok {
if list, ok := v.([]model.CacheAreaServicePhonePayListStruct); ok {
for i,oldData := range list {
if oldData.ID == payListID{
for i, oldData := range list {
if oldData.ID == payListID {
list = append(list[:i], list[i+1:]...)
if len(list) == 0 {
areaServicePhonePayListMap.Delete(areaServiceID)
} else {
areaServicePhonePayListMap.Store(areaServiceID,list)
areaServicePhonePayListMap.Store(areaServiceID, list)
}
return
}
......@@ -144,16 +144,16 @@ func DelPhonePayListMap(areaServiceID , payListID uint32) {
}
// UpdatePhonePayListMap 仅GRPC调用,修改校区服务支付项
func UpdatePhonePayListMap(areaServiceID uint32,newData *model.CacheAreaServicePhonePayListStruct) error {
func UpdatePhonePayListMap(areaServiceID uint32, newData *model.CacheAreaServicePhonePayListStruct) error {
areaServicePhonePayListMapUpdateLock.Lock()
defer areaServicePhonePayListMapUpdateLock.Unlock()
if v, ok := areaServicePhonePayListMap.Load(areaServiceID); ok {
if list, ok := v.([]model.CacheAreaServicePhonePayListStruct); ok {
for i,oldData := range list {
if oldData.ID == newData.ID{
for i, oldData := range list {
if oldData.ID == newData.ID {
list[i] = *newData
areaServicePhonePayListMap.Store(areaServiceID,list)
areaServicePhonePayListMap.Store(areaServiceID, list)
return nil
}
}
......@@ -165,5 +165,5 @@ func UpdatePhonePayListMap(areaServiceID uint32,newData *model.CacheAreaServiceP
}
}
return errors.New("未找到ID为:"+ strconv.FormatUint(uint64(newData.ID),10) +"的支付项")
}
\ No newline at end of file
return errors.New("未找到ID为:" + strconv.FormatUint(uint64(newData.ID), 10) + "的支付项")
}
......@@ -26,17 +26,17 @@ func areaServicePhonePayListMapAddSplit() { // 区域服务收款项列表添加
return true
})
fmt.Println(time.Now(), "init areaServicePhonePayListMap SplitAmount end")
fmt.Println(time.Now(), "cache: init areaServicePhonePayListMap SplitAmount end")
}
func areaServicePhonePayListMapAddSplitByPayListID(payListID uint32) (res []model.PhonePaySplitMoneyStruct) {
func areaServicePhonePayListMapAddSplitByPayListID(payListID uint32) (res []model.PaySplitMoneyStruct) {
rows, err := dbcurd.PgDb.Query("SELECT admin_id,amount FROM b_pay_split_money WHERE pay_list_id=$1", payListID) //
if err != nil {
log.Panicln("areaServicePhonePayListMapAddSplit rows", err)
}
defer rows.Close()
var temp model.PhonePaySplitMoneyStruct
var temp model.PaySplitMoneyStruct
for rows.Next() {
err = rows.Scan(&temp.AdminID, &temp.Amount)
if err != nil {
......
......@@ -20,15 +20,16 @@ func initCardUserMapNoSimID() {
var cardUserID uint32
var temp model.CacheCardUserStruct
// rows, err := dbcurd.PgDb.Query("SELECT id,name,sex,area_id,grade,class,student_num,phone_expiry FROM u_card_user WHERE delete_at is null")
rows, err := dbcurd.PgDb.Query("SELECT id,name,sex,area_id,phone_expiry,birthday FROM u_card_user WHERE delete_at is null")
rows, err := dbcurd.PgDb.Query("SELECT id,name,sex,area_id,phone_expiry,birthday,msg_expiry FROM u_card_user WHERE delete_at is null")
if err != nil {
log.Panicln("Select u_card_user To Map rows", err)
}
defer rows.Close()
// var simInfo model.CacheSimInfoStruct
var expiry string
var msgExpiry string
for rows.Next() {
err = rows.Scan(&cardUserID, &temp.Name, &temp.Sex, &temp.AreaID, &expiry, &temp.Birthday)
err = rows.Scan(&cardUserID, &temp.Name, &temp.Sex, &temp.AreaID, &expiry, &temp.Birthday, &msgExpiry)
if err != nil {
log.Panicln("initCardUserMapAndSimInfoMapNoFamilyNum rows.Scan", err)
}
......@@ -54,7 +55,9 @@ func initCardUserMapNoSimID() {
temp.Birthday = temp.Birthday[:7]
}
temp.PhoneExpiry, _ = time.Parse("2006-01-02T00:00:00Z", expiry)
//fmt.Println("temp.PhoneExpiry",temp.PhoneExpiry,expiry)
temp.MsgExpiry, _ = time.Parse("2006-01-02T00:00:00Z", msgExpiry)
// fmt.Println("temp.PhoneExpiry",temp.PhoneExpiry,expiry)
// fmt.Println("temp.MsgExpiry",temp.MsgExpiry,msgExpiry)
cardUserMap.Store(cardUserID, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
......@@ -178,6 +181,9 @@ func UpdateCardUserMap(cardUserID uint32, newData *model.CacheUpdateCardUserStru
if newData.PhoneExpiry != nil {
data.PhoneExpiry = *newData.PhoneExpiry
}
if newData.MsgExpiry != nil {
data.MsgExpiry = *newData.MsgExpiry
}
if newData.SimCardID != nil {
data.SimCardID = *newData.SimCardID
}
......@@ -219,6 +225,32 @@ func GetCardUserMapPhoneExpiry(cardUserID uint32) *time.Time {
return nil
}
// GetCardUserMapPhoneExpiryAndMsgExpiry 查询学生电话卡和留言服务到期时间
func GetCardUserMapPhoneExpiryAndMsgExpiry(cardUserID uint32) (*time.Time, *time.Time) {
if s, ok := cardUserMap.Load(cardUserID); ok { // map有
if v, ok := s.(model.CacheCardUserStruct); ok { //类型断言正确
return &v.PhoneExpiry, &v.MsgExpiry
} else { //类型断言失败
cardUserMap.Delete(cardUserID)
logger.Log.Error("cardUserMap 类型断言错误",
zap.Uint32("cardUserID", cardUserID),
zap.String("src", "GetCardUserMapMsgExpiry"))
}
} else {
logger.Log.Error("cardUserMap 有问题,没数据",
zap.Uint32("cardUserID", cardUserID),
zap.String("src", "GetCardUserMapMsgExpiry"))
}
//if cardUserID == 0 {
// fmt.Println("GetCardUserInfo 居然传入了0")
// return nil
//}
// var temp model.CacheCardUserStruct
// todo1 再去查一盘库
return nil, nil
}
// AddOrDelSlaveWeUserIDInCardUserMap 给学生缓存增加或删除附家长
func AddOrDelSlaveWeUserIDInCardUserMap(weUserID, cardUserID uint32, del bool) {
cardUserMapUpdateLock.Lock()
......
......@@ -3,29 +3,70 @@ package cache
import (
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/data_db_cache/model"
"dc_golang_server_1/logger"
"fmt"
"log"
"go.uber.org/zap"
"sync"
"time"
)
// initCardUserTrendMap 获取学生近20条动态,现在只有通话记录
// initCardUserTrendMap 获取学生近20条动态 // ,现在只有通话记录
//func initCardUserTrendMap() {
// fmt.Println(time.Now(), "cache: initCardUserTrendMap begin")
// var cardUserID uint32
// var ok bool
// cardUserMap.Range(func(k, _ interface{}) bool {
// cardUserID, ok = k.(uint32)
// if ok != true {
// log.Panicln(time.Now(), "initCardUserTrendMap k.(uint32) error", k)
// }
// trends := dbcurd.SelectCardUserTrendsLimit20FromUCallRecordByCardUserID(cardUserID)
// if trends != nil {
// cardUserTrendMap.Store(cardUserID, trends)
// }
// return true
// })
// fmt.Println(time.Now(), "cache: initCardUserTrendMap OK")
//}
func initCardUserTrendMap() {
fmt.Println(time.Now(), "cache: initCardUserTrendMap begin")
rows, err := dbcurd.PgDb.Query("SELECT card_user_id,service_type,title,content,ctime FROM nlog_user_trend ORDER BY ID")
if err != nil {
fmt.Println("initCardUserTrendMap rows", err)
}
defer rows.Close()
var cardUserID uint32
var ok bool
cardUserMap.Range(func(k, _ interface{}) bool {
cardUserID, ok = k.(uint32)
if ok != true {
log.Panicln(time.Now(), "initCardUserTrendMap k.(uint32) error", k)
var temp model.CacheCardUserTrendStruct
for rows.Next() {
err = rows.Scan(&cardUserID, &temp.ServiceType, &temp.Title, &temp.Content, &temp.Time)
if err != nil {
fmt.Println("initCardUserTrendMap rows.Scan", err)
}
trends := dbcurd.SelectCardUserTrendsLimit20FromUCallRecordByCardUserID(cardUserID)
if trends != nil {
cardUserTrendMap.Store(cardUserID, trends)
}
return true
})
fmt.Println(time.Now(), "cache: initCardUserTrendMap OK")
if info, ok := cardUserTrendMap.Load(cardUserID); ok { //map有
if v, ok := info.([]model.CacheCardUserTrendStruct); ok { //类型断言正确
v = append(v, temp)
cardUserTrendMap.Store(cardUserID, v)
continue
} else { //类型断言失败
fmt.Println("cardUserTrendMap 类型断言失败")
//cardUserTrendMap.Store(cardUserID, append([]model.CacheCardUserTrendStruct{}, temp))
}
} //else {
cardUserTrendMap.Store(cardUserID, append([]model.CacheCardUserTrendStruct{}, temp))
//}
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
logger.Log.Error("rows.Err()",
zap.Error(err),
zap.String("src", "initCardUserTrendMap"))
fmt.Println(time.Now(), "initCardUserTrendMap rows.Err()", err)
} else {
fmt.Println(time.Now(), "cache: initCardUserTrendMap end")
}
}
var cardUserTrendMapUpdateLock sync.Mutex // 直接全局锁
......@@ -36,8 +77,7 @@ func InsertCardUserTrendMap(cardUserID uint32, temp *model.CacheCardUserTrendStr
if v, ok := cardUserTrendMap.Load(cardUserID); ok {
if trends, ok := v.([]model.CacheCardUserTrendStruct); ok {
trends = append([]model.CacheCardUserTrendStruct{*temp}, trends...)
length := len(trends)
if length > 20 {
if len(trends) > 20 {
trends = trends[:20]
}
cardUserTrendMap.Store(cardUserID, trends)
......@@ -56,10 +96,10 @@ func InsertCardUserTrendMap(cardUserID uint32, temp *model.CacheCardUserTrendStr
func GetCardUserTrendMapByCardUserID(cardUserID uint32) (trends []model.CacheCardUserTrendStruct) {
if v, ok := cardUserTrendMap.Load(cardUserID); ok {
if trends, ok = v.([]model.CacheCardUserTrendStruct); ok {
return trends
return
} else { // 类型断言错误
cardUserTrendMap.Delete(cardUserID)
fmt.Println("InsertCardUserTrendMap cardUserTrendMap 类型断言错误")
fmt.Println("GetCardUserTrendMapByCardUserID cardUserTrendMap 类型断言错误")
}
} /*else {
logger.Log.Error("cardUserTrendMap 有问题,没数据",
......@@ -72,9 +112,13 @@ func GetCardUserTrendMapByCardUserID(cardUserID uint32) (trends []model.CacheCar
// cardUserTrendMap.Store(cardUserID,trends)
//}
return nil
return
}
func DeleteCardUserTrendMap(cardUserID uint32) {
cardUserTrendMap.Delete(cardUserID)
}
func SystemExitToSaveTrend() {
dbcurd.InsertNLogUserTrend(&cardUserTrendMap)
}
package cache
import (
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/data_db_cache/model"
"fmt"
"log"
"sync"
"time"
)
// initNReadMsgMap 获取学生留言
func initNReadMsgMap() {
fmt.Println(time.Now(), "cache: initNReadMsgMap begin")
var cardUserID uint32
var ok bool
cardUserMap.Range(func(k, _ interface{}) bool {
cardUserID, ok = k.(uint32)
if ok != true {
log.Panicln(time.Now(), "initNReadMsgMap k.(uint32) error", k)
}
msg := dbcurd.SelectUMsgNReadByCardUserID(cardUserID)
if msg != nil {
nReadMsgMap.Store(cardUserID, msg)
}
return true
})
fmt.Println(time.Now(), "cache: initNReadMsgMap OK")
}
var nReadMsgMapUpdateLock sync.Mutex // 直接全局锁
func InsertNReadMsgMap(cardUserID uint32, temp *model.CacheCardUserNReadMsgStruct) {
nReadMsgMapUpdateLock.Lock()
defer nReadMsgMapUpdateLock.Unlock()
if v, ok := nReadMsgMap.Load(cardUserID); ok {
if msg, ok := v.([]model.CacheCardUserNReadMsgStruct); ok {
msg = append([]model.CacheCardUserNReadMsgStruct{*temp}, msg...)
if len(msg) > 10 {
msg = msg[:10]
}
nReadMsgMap.Store(cardUserID, msg)
return
} else { // 类型断言错误
nReadMsgMap.Delete(cardUserID)
fmt.Println("InsertNReadMsgMap nReadMsgMap 类型断言错误")
}
}
msg := make([]model.CacheCardUserNReadMsgStruct, 1)
msg[0] = *temp
nReadMsgMap.Store(cardUserID, msg)
}
func GetNReadMsgMap(cardUserID uint32) []model.CacheCardUserNReadMsgStruct {
if v, ok := nReadMsgMap.Load(cardUserID); ok {
if temp, ok := v.([]model.CacheCardUserNReadMsgStruct); ok {
if len(temp) > 10 {
temp = temp[:10]
nReadMsgMap.Store(cardUserID, temp)
}
return temp
} else { // 类型断言错误
nReadMsgMap.Delete(cardUserID)
fmt.Println("GetNReadMsgMapByCardUserID nReadMsgMap 类型断言错误")
}
} /*else {
logger.Log.Error("cardUserTrendMap 有问题,没数据",
zap.Uint32("cardUserID", cardUserID),
zap.String("src", "GetCardUserTrendMapByCardUserID"))
}*/
//trends = dbcurd.SelectCardUserTrendsLimit20FromUCallRecordByCardUserID(cardUserID)
//if trends != nil {
// cardUserTrendMap.Store(cardUserID,trends)
//}
return []model.CacheCardUserNReadMsgStruct{}
}
func GetOneNReadMsgAndLenByCardUserID(cardUserID uint32) (*model.CacheCardUserNReadMsgStruct, uint8) {
if v, ok := nReadMsgMap.Load(cardUserID); ok {
if temp, ok := v.([]model.CacheCardUserNReadMsgStruct); ok {
totalLen := uint8(len(temp))
if totalLen > 0 {
return &temp[0], totalLen
}
} else { // 类型断言错误
nReadMsgMap.Delete(cardUserID)
fmt.Println("GetNReadMsgMapByCardUserID nReadMsgMap 类型断言错误")
}
} /*else {
logger.Log.Error("cardUserTrendMap 有问题,没数据",
zap.Uint32("cardUserID", cardUserID),
zap.String("src", "GetCardUserTrendMapByCardUserID"))
}*/
//trends = dbcurd.SelectCardUserTrendsLimit20FromUCallRecordByCardUserID(cardUserID)
//if trends != nil {
// cardUserTrendMap.Store(cardUserID,trends)
//}
return nil, 0
}
func DeleteOneNReadMsg(cardUserID, msgID uint32) { // 用于删除一条留言缓存,家长主动删除或学生查看后硬件上报删除
if v, ok := nReadMsgMap.Load(cardUserID); ok {
if temp, ok := v.([]model.CacheCardUserNReadMsgStruct); ok {
for i, msg := range temp {
if msg.ID == msgID {
temp = append(temp[:i], temp[i+1:]...)
nReadMsgMap.Store(cardUserID, temp)
return
}
}
} else { // 类型断言错误
nReadMsgMap.Delete(cardUserID)
fmt.Println("GetNReadMsgMapByCardUserID nReadMsgMap 类型断言错误")
}
}
}
func DeleteNReadMsgMap(cardUserID uint32) {
nReadMsgMap.Delete(cardUserID)
}
package cache
import (
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/data_db_cache/model"
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"strconv"
"time"
)
// initPhoneMsgFeeMap 缓存 b_phone_msg_fee 全表 并缓存 b_msg_split_money 的分账信息
func initPhoneMsgFeeMap() {
fmt.Println(time.Now(), "cache: initPhoneMsgFeeMap begin")
rows, err := dbcurd.PgDb.Query("SELECT area_service_id,amount FROM b_phone_msg_fee")
if err != nil {
panic("initPhoneMsgFeeMap SELECT b_phone_msg_fee rows" + err.Error())
}
defer rows.Close()
var areaServiceID uint32
var temp model.CachePhoneMsgFeeStruct
for rows.Next() {
err = rows.Scan(&areaServiceID, &temp.Amount)
if err != nil {
panic("initPhoneMsgFeeMap SELECT b_phone_msg_fee rows.Scan" + err.Error())
}
temp.SplitAmount = getMsgSplitMoney(areaServiceID)
phoneMsgFeeMap.Store(areaServiceID, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
logger.Log.Error("rows.Err()",
zap.Error(err),
zap.String("src", "getMsgSplitMoney"))
fmt.Println(time.Now(), "initPhoneMsgFeeMap rows.Err()", err)
} else {
fmt.Println(time.Now(), "cache: initPhoneMsgFeeMap end")
}
}
func getMsgSplitMoney(areaServiceID uint32) (d []model.PaySplitMoneyStruct) {
rows, err := dbcurd.PgDb.Query("SELECT admin_id,amount,remark FROM b_msg_split_money WHERE area_service_id=$1", areaServiceID)
if err != nil {
panic("getMsgSplitMoney rows" + err.Error() + strconv.FormatUint(uint64(areaServiceID), 10))
}
defer rows.Close()
var temp model.PaySplitMoneyStruct
for rows.Next() {
err = rows.Scan(&temp.AdminID, &temp.Amount, &temp.Remark)
if err != nil {
panic("getMsgSplitMoney rows.Scan" + err.Error() + strconv.FormatUint(uint64(areaServiceID), 10))
}
d = append(d, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
logger.Log.Error("rows.Err()",
zap.Error(err),
zap.String("src", "getMsgSplitMoney"))
fmt.Println(time.Now(), "getMsgSplitMoney rows.Err()", err, strconv.FormatUint(uint64(areaServiceID), 10))
}
return
}
// GetPhoneMsgFeeMap 根据区域服务ID获取缓存
func GetPhoneMsgFeeMap(areaServiceID uint32) *model.CachePhoneMsgFeeStruct {
if fee, ok := phoneMsgFeeMap.Load(areaServiceID); ok { //map有
if msgFee, ok := fee.(model.CachePhoneMsgFeeStruct); ok { //类型断言正确
return &msgFee
} else { //类型断言失败
phoneMsgFeeMap.Delete(areaServiceID)
logger.Log.Error("GetPhoneMsgFeeMap 类型断言错误",
zap.Uint32("areaServiceID", areaServiceID),
zap.String("src", "GetPhoneMsgFeeMap"))
}
}
return nil
}
package dbcurd
import (
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
//CREATE TABLE IF NOT EXISTS public.d_hex_command_err
//(
//device_id bigint NOT NULL,
......@@ -21,17 +14,17 @@ import (
// createAt timestamp.Timestamp
//}
func InsertDevCommandErr(devId uint32, ciphertext string, errMsg string) {
fmt.Println("InsertDevCommandErr", errMsg, devId, ciphertext)
var err error
for i := 0; i < 10; i++ {
_, err = PgDb.Exec("INSERT INTO d_command_err(device_id, ciphertext, err)VALUES($1,$2,$3)", devId, ciphertext, errMsg)
if err == nil {
return
}
fmt.Println("硬件问题 InsertDevCommandErr:", i, err)
time.Sleep(3 * time.Second)
}
logger.Log.Error("InsertDevCommandErr Err",
zap.Error(err))
}
//func InsertDevCommandErr(devId uint32, ciphertext string, errMsg string) {
// fmt.Println("InsertDevCommandErr", errMsg, devId, ciphertext)
// var err error
// for i := 0; i < 10; i++ {
// _, err = PgDb.Exec("INSERT INTO d_command_err(device_id, ciphertext, err)VALUES($1,$2,$3)", devId, ciphertext, errMsg)
// if err == nil {
// return
// }
// fmt.Println("硬件问题 InsertDevCommandErr:", i, err)
// time.Sleep(3 * time.Second)
// }
// logger.Log.Error("InsertDevCommandErr Err",
// zap.Error(err))
//}
package dbcurd
import (
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
//CREATE TABLE IF NOT EXISTS public.d_hex_connect_record
//(
//dev_id bigint NOT NULL,
......@@ -14,17 +7,17 @@ import (
//create_at timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
//)
// DevConnectRecord state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
func DevConnectRecord(devId uint32, state uint8) {
var err error
for i := 0; i < 100; i++ {
_, err = stmtInsertDevConnectRecord.Exec(devId, state)
if err == nil {
return
}
fmt.Println("DevConnectRecord:", i, err)
time.Sleep(20 * time.Millisecond)
}
logger.Log.Error("DevConnectRecord Err",
zap.Error(err))
}
//// DevConnectRecord state 0:新连接来了 1:设备正常离线 2:正常离线 3:新连接挤掉就连接 4:未知异常(连接池类型断言失败)
//func DevConnectRecord(devId uint32, state uint8) {
// var err error
// for i := 0; i < 100; i++ {
// _, err = stmtInsertDevConnectRecord.Exec(devId, state)
// if err == nil {
// return
// }
// fmt.Println("DevConnectRecord:", i, err)
// time.Sleep(20 * time.Millisecond)
// }
// logger.Log.Error("DevConnectRecord Err",
// zap.Error(err))
//}
......@@ -17,7 +17,7 @@ const ( //0 成功 1 唯一约束重复 9 系统繁忙
var PgDb *sql.DB
var stmtInsertDevConnectRecord *sql.Stmt // 硬件联网流水
// var stmtInsertDevConnectRecord *sql.Stmt // 硬件联网流水
var stmtInsertDevCommandRecord *sql.Stmt // 硬件通讯流水
var stmtInsertDevCommandRecordRW *sql.Stmt // 硬件通讯流水,一收一发的情况同时记录
var stmtInsertDevResetRecord *sql.Stmt // 硬件复位流水
......@@ -49,11 +49,11 @@ func InitDb() {
panic("stmtInsertDevCommandRecord:" + err.Error())
}
// 硬件联网流水
stmtInsertDevConnectRecord, err = PgDb.Prepare("INSERT INTO d_connect_record VALUES($1,$2)")
if err != nil {
panic("stmtInsertDevConnectRecord:" + err.Error())
}
//// 硬件联网流水
//stmtInsertDevConnectRecord, err = PgDb.Prepare("INSERT INTO d_connect_record VALUES($1,$2)")
//if err != nil {
// panic("stmtInsertDevConnectRecord:" + err.Error())
//}
// 硬件复位流水
stmtInsertDevResetRecord, err = PgDb.Prepare("INSERT INTO d_reset_record VALUES($1,$2,$3,$4,$5,$6,$7,$8)")
if err != nil {
......@@ -76,9 +76,9 @@ func CloseDb() {
_ = stmtInsertDevCommandRecordRW.Close()
}
if stmtInsertDevConnectRecord != nil { // 硬件联网流水
_ = stmtInsertDevConnectRecord.Close()
}
//if stmtInsertDevConnectRecord != nil { // 硬件联网流水
// _ = stmtInsertDevConnectRecord.Close()
//}
if stmtInsertDevResetRecord != nil { // 硬件复位流水
_ = stmtInsertDevResetRecord.Close()
......
package dbcurd
import (
"dc_golang_server_1/data_db_cache/model"
"fmt"
"strconv"
"sync"
"time"
)
func SelectNLogUserTrend(data *sync.Map) {
fmt.Println(time.Now(), "cache: SelectNLogUserTrend")
i := 0
var err error
for {
_, err = PgDb.Exec("TRUNCATE TABLE nlog_user_trend")
if err == nil {
break
}
i++
if i == 5 {
fmt.Println(time.Now(), "缓存的用户最新动态持久化 InsertNLogUserTrend 清表失败", i, err)
return
} else {
fmt.Println(err)
time.Sleep(100 * time.Millisecond)
}
}
i = 0
sql := "INSERT INTO nlog_user_trend VALUES"
data.Range(func(k, v interface{}) bool {
if values, ok := v.([]model.CacheCardUserTrendStruct); ok {
if len(values) > 20 {
values = values[:20]
}
for _, t := range values {
sql += "(" + strconv.FormatUint(uint64(k.(uint32)), 10) + "," + strconv.FormatUint(uint64(t.ServiceType), 10) + ",'" + t.Title + "','" + t.Content + "','" + t.Time.Format("2006-01-02 15:04:05") + "'),"
}
i++
if i >= 3000 {
sql = sql[:len(sql)-1]
insertNLogUserTrendOneSQL(&sql)
i = 0
sql = "INSERT INTO nlog_user_trend VALUES"
}
}
return true
})
if i > 0 {
sql = sql[:len(sql)-1]
insertNLogUserTrendOneSQL(&sql)
}
fmt.Println(time.Now(), "缓存的用户最新动态持久化 InsertNLogUserTrend 成功")
}
func InsertNLogUserTrend(data *sync.Map) {
fmt.Println(time.Now(), "缓存的用户最新动态持久化 InsertNLogUserTrend")
i := 0
var err error
for {
_, err = PgDb.Exec("TRUNCATE TABLE nlog_user_trend")
if err == nil {
break
}
i++
if i == 5 {
fmt.Println(time.Now(), "缓存的用户最新动态持久化 InsertNLogUserTrend 清表失败", i, err)
return
} else {
fmt.Println(err)
time.Sleep(100 * time.Millisecond)
}
}
i = 0
sql := "INSERT INTO nlog_user_trend VALUES"
data.Range(func(k, v interface{}) bool {
if values, ok := v.([]model.CacheCardUserTrendStruct); ok {
if len(values) > 20 {
values = values[:20]
}
for _, t := range values {
sql += "(" + strconv.FormatUint(uint64(k.(uint32)), 10) + "," + strconv.FormatUint(uint64(t.ServiceType), 10) + ",'" + t.Title + "','" + t.Content + "','" + t.Time.Format("2006-01-02 15:04:05") + "'),"
}
i++
if i >= 3000 {
sql = sql[:len(sql)-1]
insertNLogUserTrendOneSQL(&sql)
i = 0
sql = "INSERT INTO nlog_user_trend VALUES"
}
}
return true
})
if i > 0 {
sql = sql[:len(sql)-1]
insertNLogUserTrendOneSQL(&sql)
}
fmt.Println(time.Now(), "缓存的用户最新动态持久化 InsertNLogUserTrend 成功")
}
func insertNLogUserTrendOneSQL(sql *string) {
var err error
for i := 0; i < 5; i++ {
_, err = PgDb.Exec(*sql)
if err == nil {
return
}
fmt.Println(err)
time.Sleep(10 * time.Millisecond)
}
fmt.Println(err, *sql)
}
......@@ -13,7 +13,7 @@ import (
type InsertTableUCallRecordStruct struct {
CardUserId uint32
DeviceId uint32
CallStartAt string
CallStartAt time.Time //string
CardUserName string
SimID string
CalledNumber string
......@@ -65,12 +65,13 @@ func InsertUCallRecordAndUpdateUSimInfo(insertData *InsertTableUCallRecordStruct
// panic("反正是测试,先退出2")
//}
//fmt.Println(rowAffected)
_, err = tx.Exec("UPDATE u_sim_info SET total_talk_minutes=total_talk_minutes+$1,month_talk_minutes=month_talk_minutes+$1 WHERE sim_id=$2", (insertData.TalkTime+59)/60, insertData.SimID)
if err != nil {
logger.Log.Error("InsertUCallRecordAndUpdateUSimInfo UPDATE u_sim_info:",
zap.Error(err))
return InsertSysErr
if insertData.TalkTime > 0 {
_, err = tx.Exec("UPDATE u_sim_info SET total_talk_minutes=total_talk_minutes+$1,month_talk_minutes=month_talk_minutes+$1 WHERE sim_id=$2", (insertData.TalkTime+59)/60, insertData.SimID)
if err != nil {
logger.Log.Error("InsertUCallRecordAndUpdateUSimInfo UPDATE u_sim_info:",
zap.Error(err))
return InsertSysErr
}
}
//rowAffected, err = rs.RowsAffected()
//if err != nil {
......@@ -89,9 +90,9 @@ func InsertUCallRecordAndUpdateUSimInfo(insertData *InsertTableUCallRecordStruct
}
func SelectCardUserTrendsLimit20FromUCallRecordByCardUserID(cardUserID uint32) (trends []model.CacheCardUserTrendStruct) {
rows, err := PgDb.Query("SELECT call_start_at, called_nickname, talk_time, place_user FROM u_call_record WHERE card_user_id=$1 ORDER BY create_at DESC LIMIT 20", cardUserID)
rows, err := PgDb.Query("SELECT call_start_at,called_nickname,talk_time,place_user FROM u_call_record WHERE card_user_id=$1 ORDER BY create_at DESC LIMIT 20", cardUserID)
if err != nil {
fmt.Println("SELECT call_start_at, called_nickname, talk_time, place_user FROM u_call_record WHERE card_user_id=$1 ORDER BY create_at DESC LIMIT 20", err)
fmt.Println("SELECT call_start_at, called_nickname, talk_time, place_user FROM u_call_record WHERE card_user_id=$1 ORDER BY create_at DESC LIMIT 20", cardUserID, err)
return
}
defer rows.Close()
......@@ -103,19 +104,19 @@ func SelectCardUserTrendsLimit20FromUCallRecordByCardUserID(cardUserID uint32) (
for rows.Next() {
err = rows.Scan(&startAt, &nickname, &talkTime, &place)
if err != nil {
fmt.Println("selectCardUserTrendsLimit20FromUCallRecordByCardUserID rows", err)
fmt.Println("selectCardUserTrendsLimit20FromUCallRecordByCardUserID rows", cardUserID, err)
return
}
trends = append(trends, model.CacheCardUserTrendStruct{
ServiceType: 1,
Title: "公话机-" + place,
Content: "被叫:" + nickname + " 时长:" + strconv.Itoa((talkTime+59)/60) + "分",
Time: startAt.Format("2006-01-02 15:04:05"),
Time: startAt, //.Format("2006-01-02 15:04:05"),
})
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
fmt.Println(time.Now(), "selectCardUserTrendsLimit20FromUCallRecordByCardUserID rows.Err()", err)
fmt.Println(time.Now(), "selectCardUserTrendsLimit20FromUCallRecordByCardUserID rows.Err()", cardUserID, err)
}
return
}
......
package dbcurd
import (
"dc_golang_server_1/data_db_cache/model"
"dc_golang_server_1/logger"
"fmt"
"go.uber.org/zap"
"time"
)
type InsertTableUMsgNReadStruct struct {
CardUserID uint32 `json:"cardUserID"` // 学生ID
AreaServiceID uint32 `json:"aid"` // 区域服务ID
WeUserID uint32 `json:"-"`
Msg string `json:"msg"` // 留言内容
CreateAt time.Time `json:"-"`
}
func InsertUMsgNRead(insertData *InsertTableUMsgNReadStruct) (msgID uint32) {
tx, err := PgDb.Begin()
if err != nil {
logger.Log.Error("InsertUMsgNRead PgDb.Begin():",
zap.Error(err))
return
}
defer clearTransaction(tx)
_, err = tx.Exec("DELETE FROM u_msg_nread WHERE id IN(SELECT id FROM u_msg_nread WHERE card_user_id=$1 ORDER BY id DESC OFFSET 9)", insertData.CardUserID)
if err != nil {
logger.Log.Error("InsertUMsgNRead DELETE",
zap.Reflect("insertData", insertData),
zap.Error(err))
return 0
}
err = tx.QueryRow("INSERT INTO u_msg_nread(card_user_id,area_service_id,we_user_id,create_at,msg)VALUES($1,$2,$3,$4,$5)RETURNING id",
insertData.CardUserID,
insertData.AreaServiceID,
insertData.WeUserID,
insertData.CreateAt,
insertData.Msg,
).Scan(&msgID)
if err != nil {
logger.Log.Error("InsertUMsgNRead INSERT",
zap.Reflect("insertData", insertData),
zap.Error(err))
return
}
if err = tx.Commit(); err != nil {
logger.Log.Error("InsertUCardUserAndUserWeCardUser Commit",
zap.Reflect("insertData", insertData),
zap.Error(err))
return 0
}
return
}
func SelectUMsgNReadByCardUserID(cardUserID uint32) (msg []model.CacheCardUserNReadMsgStruct) {
rows, err := PgDb.Query("SELECT id,we_user_id,create_at,msg FROM u_msg_nread WHERE card_user_id=$1 ORDER BY create_at DESC LIMIT 10", cardUserID)
if err != nil {
fmt.Println("SELECT id,we_user_id,create_at FROM u_msg_nread WHERE card_user_id=$1 ORDER BY create_at DESC LIMIT 10", cardUserID, err)
return
}
defer rows.Close()
var temp model.CacheCardUserNReadMsgStruct
for rows.Next() {
err = rows.Scan(&temp.ID, &temp.WeUserID, &temp.CreateAt, &temp.Msg)
if err != nil {
fmt.Println("selectCardUserTrendsLimit20FromUCallRecordByCardUserID rows", cardUserID, err)
return
}
msg = append(msg, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
fmt.Println(time.Now(), "selectCardUserTrendsLimit20FromUCallRecordByCardUserID rows.Err()", err)
}
return
}
func DeleteUMsgNReadAndInsertReadRecord(msgID, deviceID uint32, place string) uint32 {
tx, err := PgDb.Begin()
if err != nil {
logger.Log.Error("DeleteUMsgNReadAndInsertReadRecord PgDb.Begin():",
zap.Error(err))
return 0
}
defer clearTransaction(tx)
var cardUserID, areaServiceID, weUserID uint32
var createAt, msg string
err = tx.QueryRow("DELETE FROM u_msg_nread WHERE id=$1 RETURNING card_user_id,area_service_id,we_user_id,create_at,msg",
msgID,
).Scan(&cardUserID, &areaServiceID, &weUserID, &createAt, &msg)
if err != nil {
logger.Log.Error("DeleteUMsgNReadAndInsertReadRecord DELETE:",
zap.Error(err))
return 0
}
_, err = tx.Exec("INSERT INTO u_msg_read_record(id,card_user_id,area_service_id,we_user_id,create_at,msg,device_id,device_place)VALUES($1,$2,$3,$4,$5,$6,$7,$8)",
msgID, cardUserID, areaServiceID, weUserID, createAt, msg, deviceID, place)
if err != nil {
logger.Log.Error("DeleteUMsgNReadAndInsertReadRecord INSERT:",
zap.Error(err))
return 0
}
if err = tx.Commit(); err != nil {
logger.Log.Error("DeleteUMsgNReadAndInsertReadRecord Commit:",
zap.Error(err))
return 0
}
return cardUserID
}
func DeleteUMsgNRead(cardUserID, msgID uint32) bool {
_, err := PgDb.Exec("DELETE FROM u_msg_nread WHERE id=$1 AND card_user_id=$2", msgID, cardUserID)
if err == nil {
return true
}
return false
}
// u_msg_read_record
type SelectUMsgReadRecordRes struct {
WeUserID uint32 `json:"-"`
CreateAt string `json:"createAt"` // 创建时间
Msg string `json:"msg"`
ReadAt string `json:"readAt"` // 学生读取时间
Place string `json:"place"` // 读取的设备位置
Nickname string `json:"nickname"` // 微信昵称
AvatarURL string `json:"avatarURL"` // 头像URL
Phone string `json:"phone"` // 手机号
}
func SelectUMsgReadRecord(cardUserID, areaServiceID uint32) (d []SelectUMsgReadRecordRes) {
rows, err := PgDb.Query("SELECT we_user_id,create_at,msg,read_at,device_place FROM u_msg_read_record WHERE card_user_id=$1 AND area_service_id=$2 ORDER BY read_at DESC LIMIT 100", cardUserID, areaServiceID)
if err != nil {
logger.Log.Error("SelectUMsgReadRecord SELECT", zap.Error(err), zap.Uint32("cardUserID", cardUserID), zap.Uint32("areaServiceID", areaServiceID))
return
}
defer rows.Close()
var temp SelectUMsgReadRecordRes
for rows.Next() {
err = rows.Scan(&temp.WeUserID, &temp.CreateAt, &temp.Msg, &temp.ReadAt, &temp.Place)
if err != nil {
logger.Log.Error("SelectUMsgReadRecord rows", zap.Error(err), zap.Uint32("cardUserID", cardUserID), zap.Uint32("areaServiceID", areaServiceID))
return
}
d = append(d, temp)
}
// 处理完毕后,需要判断一次遍历过程中是否有错误产生
if err = rows.Err(); err != nil {
logger.Log.Error("SelectUMsgReadRecord rows.Err()", zap.Error(err), zap.Uint32("cardUserID", cardUserID), zap.Uint32("areaServiceID", areaServiceID))
}
return
}
......@@ -71,7 +71,7 @@ type InsertTableUPhonePayRecordAndSplit struct {
Describe string // 描述
ExpiryAt time.Time // 本次缴费后,话费有效期
Type uint8 // 缴费类型:1开卡+充值 2续费 3补卡 4补卡+续费
SplitAmount []model.PhonePaySplitMoneyStruct
SplitAmount []model.PaySplitMoneyStruct
}
// InsertUPhonePayRecordAndSplit 通过事务插入缴费记录和分账记录表
......@@ -79,7 +79,7 @@ func InsertUPhonePayRecordAndSplit(values *InsertTableUPhonePayRecordAndSplit) b
splitSql := "INSERT INTO u_trade_split_record(trade_num,admin_id,amount,remark)VALUES"
header := "('" + values.TradeNum + "',"
for _, v := range values.SplitAmount {
splitSql += header + strconv.FormatUint(uint64(v.AdminID), 10) + "," + strconv.FormatUint(uint64(v.Amount), 10) +",'"+v.Remark +"'),"
splitSql += header + strconv.FormatUint(uint64(v.AdminID), 10) + "," + strconv.FormatUint(uint64(v.Amount), 10) + ",'" + v.Remark + "'),"
}
splitSql = splitSql[:len(splitSql)-1]
......@@ -135,17 +135,17 @@ func InsertUPhonePayRecordAndSplit(values *InsertTableUPhonePayRecordAndSplit) b
}
type UpdateUPhonePayRecordStruct struct {
CardUserID uint32
Expiry *time.Time
PayAt *time.Time
NotifyAt time.Time
TradeNum string
ThirdNum string
CardUserID uint32
Expiry *time.Time
PayAt *time.Time
NotifyAt time.Time
TradeNum string
ThirdNum string
TencentTradeNum string
Fee uint32
Fee uint32
}
func UpdateUPhonePayRecordPayAtAndUCardUserPhoneExpiryTransaction(upData *UpdateUPhonePayRecordStruct) bool {
func UpdateUPhonePayRecordPayAtAndUCardUserPhoneExpiryTransaction(upData *UpdateUPhonePayRecordStruct, msg bool) bool {
tx, err := PgDb.Begin()
if err != nil {
logger.Log.Error("UpdateUCardUserPhoneExpiryAndUPhonePayRecordPayAtTransaction PgDb.Begin():",
......@@ -157,7 +157,7 @@ func UpdateUPhonePayRecordPayAtAndUCardUserPhoneExpiryTransaction(upData *Update
// 先更新充值订单
res, err := tx.Exec("UPDATE u_phone_pay_record SET pay_at=$1,result=1,notify_at=$2,third_num=$3,tencent_trade_num=$4,fee=$5 WHERE trade_num=$6",
upData.PayAt,upData.NotifyAt,upData.ThirdNum,upData.TencentTradeNum,upData.Fee,upData.TradeNum)
upData.PayAt, upData.NotifyAt, upData.ThirdNum, upData.TencentTradeNum, upData.Fee, upData.TradeNum)
if err != nil {
logger.Log.Error("UpdateUCardUserPhoneExpiryAndUPhonePayRecordPayAtTransaction UPDATE u_phone_pay_record",
zap.Reflect("upData", upData),
......@@ -178,7 +178,11 @@ func UpdateUPhonePayRecordPayAtAndUCardUserPhoneExpiryTransaction(upData *Update
}
// 更新UCardUserPhone
res, err = tx.Exec("UPDATE u_card_user SET phone_expiry=$1 WHERE id=$2 AND(phone_expiry<=$1 OR phone_expiry is null)AND delete_at is null", upData.Expiry, upData.CardUserID)
if msg {
res, err = tx.Exec("UPDATE u_card_user SET phone_expiry=$1,msg_expiry=$1 WHERE id=$2 AND(phone_expiry<=$1 OR phone_expiry is null)AND delete_at is null", upData.Expiry, upData.CardUserID)
} else {
res, err = tx.Exec("UPDATE u_card_user SET phone_expiry=$1 WHERE id=$2 AND(phone_expiry<=$1 OR phone_expiry is null)AND delete_at is null", upData.Expiry, upData.CardUserID)
}
if err != nil {
logger.Log.Error("UpdateUCardUserPhoneExpiryAndUPhonePayRecordPayAtTransaction UPDATE u_card_user res.RowsAffected()",
zap.Reflect("upData", upData),
......
......@@ -9,7 +9,7 @@ import (
"time"
)
func UpdateUWeCustomerLoginTime(weUserID uint32) { //todoN 以后添加微信登录流水表 也可以先存缓存,半夜来插入
func UpdateUWeCustomerLoginTime(weUserID uint32) { //todo 考虑开个协程单独慢慢记
var err error
for i := 0; i < 10; i++ {
_, err = stmtUpdateWechatUserLogin.Exec(time.Now().Format("2006-01-02 15:04:05.000"), weUserID) //这里格式化可加可不加
......@@ -18,7 +18,7 @@ func UpdateUWeCustomerLoginTime(weUserID uint32) { //todoN 以后添加微信登
return
}
fmt.Println("UpdateUWeCustomerLoginTime:", i, err)
time.Sleep(3 * time.Second)
time.Sleep(30 * time.Millisecond)
}
logger.Log.Error("UpdateUWeCustomerLoginTime Err",
zap.Error(err))
......
......@@ -30,6 +30,11 @@ type CacheAreaServiceStruct struct {
ReplacementCardFee int32 // 补卡费
}
type CachePhoneMsgFeeStruct struct {
Amount int32 // 留言月服务费,单位分
SplitAmount []PaySplitMoneyStruct // 分账信息
}
type CacheWeCustomerStruct struct {
// TokenCreatTime int64
OpenID string // 微信OpenID
......@@ -53,6 +58,7 @@ type CacheUpdateCardUserStruct struct {
// Class *int8
// StuNum *string
PhoneExpiry *time.Time //电话机判断有效期按这个来,电话卡充没充值按这个来
MsgExpiry *time.Time // 留言服务到期时间
SimCardID *string
// LocationCardID uint32
// IcCardID uint32
......@@ -68,17 +74,25 @@ type CacheCardUserStruct struct {
// Grade int8
// Class int8
// StuNum string
PhoneExpiry time.Time //电话机判断有效期按这个来,电话卡充没充值按这个来
PhoneExpiry time.Time // 电话机判断有效期按这个来,电话卡充没充值按这个来
MsgExpiry time.Time // 留言服务到期时间
SimCardID string
// LocationCardID uint32
// IcCardID uint32
}
type CacheCardUserTrendStruct struct {
ServiceType uint8 `json:"service" example:"1"` // 服务项目 1公话2定位3饮水4卡消费5洗浴6洗衣机 决定UI图标及颜色等
Title string `json:"title" example:"公话机-教1楼3层"` // 显示在第一行 公话机-PlaceUser
Content string `json:"content" example:"被叫:爸爸 时长:2分"` // 显示在第二行 nickname+talkTime
Time string `json:"time" example:"2021-10-23 17:00:00"` // 显示在第三行,呼叫起始时间
ServiceType uint8 `json:"service" example:"1"` // 服务项目 1公话2定位3饮水4卡消费5洗浴6洗衣机 决定UI图标及颜色等
Title string `json:"title" example:"公话机-教1楼3层"` // 显示在第一行 公话机-PlaceUser
Content string `json:"content" example:"被叫:爸爸 时长:2分"` // 显示在第二行 nickname+talkTime
Time time.Time `json:"time" example:"2021-10-23 17:00:00"` // 显示在第三行,呼叫起始时间
}
type CacheCardUserNReadMsgStruct struct {
ID uint32 // 留言ID
CreateAt time.Time // 留言时间
WeUserID uint32 // 留言人的微信ID
Msg string // 留言内容
}
type CacheUpdateSimInfoStruct struct {
......@@ -124,7 +138,7 @@ type CachePhone20DeviceStruct struct { // 绑定了校区的才存
//
//}
type PhonePaySplitMoneyStruct struct {
type PaySplitMoneyStruct struct {
AdminID uint32 //`json:"adminID"` //
Amount int32 //`json:"amount"` // 金额分
Remark string
......@@ -135,14 +149,15 @@ type CacheAreaServicePhonePayBase struct {
Amount int32 `json:"amount" example:"6000"` // 金额(单位分)
MonthMin uint16 `json:"monthMin"` // 月套餐通话分钟数
// ExpiryAt string `json:"expiry" example:"2021-12-31 23:59:59"` // 有效期至:2021-12-31 23:59:59 // 数据库无此字段,现算出来的
Expiry uint8 `json:"-"` // 有效期月数,前端计算到期时间,显示有效期
Describe string `json:"describe" example:"完成充值后生活老师会将电话卡配发给学生"` // 描述
Expiry uint8 `json:"-"` // 有效期月数,前端计算到期时间,显示有效期
Describe string `json:"describe" example:"完成充值后生活老师会将电话卡配发给学生"` // 描述
MsgEnable uint8 `json:"msgEnable"` // 是否展示 0 不展示 1 必选项 2 可选项默认不勾选 3 可选项默认勾选
}
type CacheAreaServicePhonePayListStruct struct {
CacheAreaServicePhonePayBase
SplitAmount []PhonePaySplitMoneyStruct `json:"-"` // 分账信息 不生成json,即不用传给小程序
Status bool `json:"-"` // 是否有效,不传给小程序
SplitAmount []PaySplitMoneyStruct `json:"-"` // 分账信息 不生成json,即不用传给小程序
Status bool `json:"-"` // 是否有效,不传给小程序
}
//type CacheWechatMchInfoStruct struct { // MchID string // 商户ID
......
......@@ -3,23 +3,26 @@ package dcphone20
import (
"dc_golang_server_1/grpc_client/GrpcFromDeviceConn"
"dc_golang_server_1/grpc_server/Grpc2Phone20TcpConn"
myGRPC "dc_golang_server_1/my_grpc/grpc_k122Server"
"dc_golang_server_1/my_grpc/grpc_k122Server"
"dc_golang_server_1/util/setting"
"google.golang.org/grpc"
"net"
)
var TCP DCPhone20 // http接口改到admin,这个变量放到函数里面去
func NewDCPhone20() {
go func() { // todo 加下 recover
GrpcFromDeviceConn.Init()
var tcp DCPhone20
tcp.NewDCPhone20("DCRYM-2018-pswd.", "I can't tell YOU", 0x5B) // setting
l, err := net.Listen("tcp", ":7011")
TCP.NewDCPhone20("DCRYM-2018-pswd.", "I can't tell YOU", 0x5B) // setting
l, err := net.Listen("tcp", setting.Grpc2TcpConnListenPort)
if err != nil {
panic(err)
}
s := grpc.NewServer()
myGRPC.RegisterGrpc2TcpConnServer(s, &Grpc2Phone20TcpConn.ToTcpConnServer{
ReceiveResponse: tcp.ReceiveResponse,
k122Server.RegisterGrpc2TcpConnServer(s, &Grpc2Phone20TcpConn.ToTcpConnServer{
ReceiveResponse: TCP.ReceiveResponse,
})
err = s.Serve(l)
if err != nil {
......
......@@ -66,6 +66,42 @@ definitions:
example: 1
type: integer
type: object
api_we_card_operate.qr2StudentsRes:
properties:
areaID:
description: 区域ID 用作创建学生
type: integer
areaName:
description: 区域名字 用作创建学生
type: string
cardNum:
description: 卡号 等会调绑卡接口来用
type: string
cardType:
description: 卡类型:1电话卡 等会调绑卡接口来用
type: integer
students:
description: 学生列表
items:
properties:
cid:
description: 学生ID 等会调绑卡接口来用
type: integer
expiry:
description: 缴费的到期时间,年月日(日期当天则仍在有效期内),展示给用户看,如果过了,就要先缴费才能绑卡,如果是"0001-01-01",则表示从来未缴过费
type: string
master:
description: 是否为主家长,页面上展示出来
type: boolean
name:
description: 学生昵称,另外去把头像也拉下来展示出来
type: string
sex:
description: 性别 0,无信息,1女,2男
type: integer
type: object
type: array
type: object
api_we_login_we_info.weLoginReq:
properties:
code:
......@@ -113,6 +149,40 @@ definitions:
iv:
type: string
type: object
api_we_msg.msgPayStruct:
properties:
amount:
description: 金额
type: integer
expiry:
description: 缴费后有效期
type: string
status:
description: 0 留言服务已到期 1 未开通留言服务
type: integer
type: object
api_we_msg.resNReadMsg:
properties:
avatarURL:
description: 头像URL
type: string
createAt:
description: 创建时间
type: string
delEnable:
description: 是否可删除
type: boolean
id:
type: integer
msg:
type: string
nickname:
description: 微信昵称
type: string
phone:
description: 手机号
type: string
type: object
api_we_phone_card.apiDeleteFamilyNumStruct:
properties:
phone:
......@@ -141,6 +211,9 @@ definitions:
monthPack:
description: 月套餐分钟数
type: integer
msgEnable:
description: 是否显示留言按钮(本区域服务是否开通留言服务)
type: boolean
simID:
description: 卡号
type: string
......@@ -200,6 +273,12 @@ definitions:
monthMin:
description: 月套餐通话分钟数
type: integer
msgAmount:
description: 留言服务费
type: integer
msgEnable:
description: 是否展示 0 不展示 1 必选项 2 可选项默认不勾选 3 可选项默认勾选
type: integer
type: object
type: array
type: object
......@@ -214,6 +293,9 @@ definitions:
lid:
description: 选填,话费支付列表id,若不传则不充话费,只是开卡或补卡(实际应用中,补卡就不传这个)
type: integer
msg:
description: 选填,补开通留言服务或充话费时才有效,且即便是充话费的时候都可以不填,不填就默认不开通留言服务,若只填了CID和Msg则为补开通留言服务
type: boolean
type: object
api_we_slave.apiDeleteSlaveWeUserStruct:
properties:
......@@ -233,6 +315,9 @@ definitions:
name:
description: 学生名字,脱敏显示
type: string
sex:
description: 0,无信息,1女,2男
type: integer
type: object
api_we_slave.slaveWeUserRes:
properties:
......@@ -246,7 +331,7 @@ definitions:
description: 手机号
type: string
weUserID:
description: 微信UnionID
description: 微信用户ID
type: integer
type: object
api_we_student.GetCardUserAndTrendRes:
......@@ -349,6 +434,41 @@ definitions:
description: Grade int8 `json:"grade"` // 必填,"1~9对应一年级~九年级,10~12对应高一~高三"
type: integer
type: object
dbcurd.InsertTableUMsgNReadStruct:
properties:
aid:
description: 区域服务ID
type: integer
cardUserID:
description: 学生ID
type: integer
msg:
description: 留言内容
type: string
type: object
dbcurd.SelectUMsgReadRecordRes:
properties:
avatarURL:
description: 头像URL
type: string
createAt:
description: 创建时间
type: string
msg:
type: string
nickname:
description: 微信昵称
type: string
phone:
description: 手机号
type: string
place:
description: 读取的设备位置
type: string
readAt:
description: 学生读取时间
type: string
type: object
dbcurd.SelectUPhonePayRecordStruct:
properties:
amount:
......@@ -528,7 +648,14 @@ info:
/we/pay 接口调整
/we/payrecord 接口调整
/we/payrecord/{aid} [GET] 接口增加字段
2022-02-26 /serverops/sysstate [GET] 取消PhoneTcpSocketNo字段,在adminServer去增加,因为连接硬件的服务从本服务剥离出去了
2022-02-26 /serverops/sysstate [GET] 取消PhoneTcpSocketNo字段,在adminServer增加了本字段,因为连接硬件的服务从本服务剥离出去了
2022-02-26 /we/qr2students/{qrcode} [GET] 增加这个接口,请仔细阅读下方接口说明
2022-03-03 /we/phonecardstatus/{id} [GET] 这个接口返回的status=1时,显示留言按钮
家长点击自己的微信头像,重新问用户要昵称和头像授权并上传更新
/we/phonecardstatus/{id} [GET] 接口增加 msgEnable字段,用于表示该区域有没有留言服务
/we/paylist/{aid}/{id} [GET] 接口增加留言服务费及是否可选项字段
/we/pay/{aid} [POST] 支付接口增加msg字段,补交留言服务费也用这个接口
title: 多彩中小学一卡通系统
version: V0.0.9
paths:
......@@ -1197,6 +1324,102 @@ paths:
summary: 登录(测试的假code) [complete]
tags:
- 家长微信-登录及微信信息上传
/we/msg:
post:
consumes:
- application/json
description: 家长向学生发起留言,注意,超过10条将删除前面的留言
parameters:
- description: 留言信息
in: body
name: data
required: true
schema:
$ref: '#/definitions/dbcurd.InsertTableUMsgNReadStruct'
produces:
- application/json
responses:
"0":
description: ""
security:
- ApiKeyAuth: []
summary: 家长向学生发起留言
tags:
- 家长微信-留言
/we/msg/{cid}/{mid}:
delete:
description: 家长删除未读留言
parameters:
- description: 学生ID
in: path
name: cid
required: true
type: integer
- description: 留言ID
in: path
name: mid
required: true
type: integer
produces:
- application/json
responses:
"0":
description: ""
security:
- ApiKeyAuth: []
summary: 家长删除未读留言
tags:
- 家长微信-留言
/we/msgnread/{aid}/{cid}:
get:
description: 家长获取未读留言列表
parameters:
- description: 学生ID
in: path
name: cid
required: true
type: integer
produces:
- application/json
responses:
"0":
description: 留言列表
schema:
items:
$ref: '#/definitions/api_we_msg.resNReadMsg'
type: array
"1":
description: ""
schema:
$ref: '#/definitions/api_we_msg.msgPayStruct'
security:
- ApiKeyAuth: []
summary: 家长获取未读留言列表,注意,这个接口有可能返回 []resNReadMsg ,也有可能返回 msgPayStruct
tags:
- 家长微信-留言
/we/msgread/{aid}/{cid}:
get:
description: 家长获取已读留言列表
parameters:
- description: 学生ID
in: path
name: cid
required: true
type: integer
produces:
- application/json
responses:
"0":
description: 留言列表
schema:
items:
$ref: '#/definitions/dbcurd.SelectUMsgReadRecordRes'
type: array
security:
- ApiKeyAuth: []
summary: 家长获取已读留言列表
tags:
- 家长微信-留言
/we/pay/{aid}:
post:
consumes:
......@@ -1347,6 +1570,27 @@ paths:
summary: 根据二维码,返回卡号信息[complete]
tags:
- 家长微信-卡操作
/we/qr2students/{qrcode}:
get:
description: 根据二维码,返回用户状态信息及卡号
parameters:
- description: QR内容
in: path
name: qrcode
required: true
type: string
produces:
- application/json
responses:
"0":
description: result
schema:
$ref: '#/definitions/api_we_card_operate.qr2StudentsRes'
security:
- ApiKeyAuth: []
summary: 根据二维码,返回用户状态信息及卡号
tags:
- 家长微信-卡操作
/we/replacecardfee/phone/{aid}:
get:
description: 查询补卡费(目前仅公话卡)
......
......@@ -16,9 +16,9 @@ func (s *ToAdminServer) CacheAddPhonePayList(ctx context.Context, req *myGRPC.Ca
return new(myGRPC.Empty), errors.New("AreaServiceID err")
}
splitAmount := make([]model.PhonePaySplitMoneyStruct, len(req.SplitAmount))
splitAmount := make([]model.PaySplitMoneyStruct, len(req.SplitAmount))
for i, v := range req.SplitAmount {
splitAmount[i] = model.PhonePaySplitMoneyStruct{
splitAmount[i] = model.PaySplitMoneyStruct{
AdminID: v.AdminID,
Amount: v.Amount,
Remark: v.Remark,
......@@ -46,9 +46,9 @@ func (s *ToAdminServer) CacheUpdatePhonePayList(ctx context.Context, req *myGRPC
return new(myGRPC.Empty), errors.New("AreaServiceID err")
}
splitAmount := make([]model.PhonePaySplitMoneyStruct, len(req.SplitAmount))
splitAmount := make([]model.PaySplitMoneyStruct, len(req.SplitAmount))
for i, v := range req.SplitAmount {
splitAmount[i] = model.PhonePaySplitMoneyStruct{
splitAmount[i] = model.PaySplitMoneyStruct{
AdminID: v.AdminID,
Amount: v.Amount,
Remark: v.Remark,
......
......@@ -5,6 +5,7 @@ import (
"dc_golang_server_1/data_db_cache/cache"
"dc_golang_server_1/data_db_cache/dbcurd"
"dc_golang_server_1/dev_product/dcphone20"
"dc_golang_server_1/grpc_client/GrpcFromDeviceConn"
"dc_golang_server_1/grpc_server/Grpc2Admin"
"dc_golang_server_1/logger"
myGRPC "dc_golang_server_1/my_grpc/grpc_k122Server"
......@@ -32,7 +33,14 @@ import (
// @Description /we/pay 接口调整
// @Description /we/payrecord 接口调整
// @Description /we/payrecord/{aid} [GET] 接口增加字段
// @Description 2022-02-26 /serverops/sysstate [GET] 取消PhoneTcpSocketNo字段,在adminServer去增加,因为连接硬件的服务从本服务剥离出去了
// @Description 2022-02-26 /serverops/sysstate [GET] 取消PhoneTcpSocketNo字段,在adminServer增加了本字段,因为连接硬件的服务从本服务剥离出去了
// @Description 2022-02-26 /we/qr2students/{qrcode} [GET] 增加这个接口,请仔细阅读下方接口说明
// @Description 2022-03-03 /we/phonecardstatus/{id} [GET] 这个接口返回的status=1时,显示留言按钮
// @Description
// @Description 家长点击自己的微信头像,重新问用户要昵称和头像授权并上传更新
// @Description /we/phonecardstatus/{id} [GET] 接口增加 msgEnable字段,用于表示该区域有没有留言服务
// @Description /we/paylist/{aid}/{id} [GET] 接口增加留言服务费及是否可选项字段
// @Description /we/pay/{aid} [POST] 支付接口增加msg字段,补交留言服务费也用这个接口
// @securityDefinitions.apikey ApiKeyAuth
// @in header
// @name token
......@@ -44,25 +52,27 @@ func main() { //
setting.Init()
logger.Init()
dbcurd.InitDb()
cache.Init()
go func() {
osc := make(chan os.Signal, 1)
signal.Notify(osc, syscall.SIGTERM, syscall.SIGINT, syscall.SIGKILL)
s := <-osc
cache.SystemExitToSaveTrend()
dbcurd.CloseDb()
GrpcFromDeviceConn.CloseGrpc()
fmt.Println(time.Now(), "程序退出:", s)
os.Exit(1)
}()
cache.Init()
//tencent.InitWechatPay()
dcphone20.NewDCPhone20()
GrpcFromDeviceConn.Init()
//dcdrinking60.NewDCDrinking60()
go func() {
l, err := net.Listen("tcp", ":7010")
l, err := net.Listen("tcp", setting.Grpc2AdminListenPort)
if err != nil {
panic(err)
}
......@@ -82,6 +92,10 @@ func main() { //
router.InitRouter()
}
// 1. 新增区域服务若选择公话,则新增开启留言服务的可选项,若选择开启留言服务,则应输入留言月服务费,若留言月服务费>0,则可添加分账项
// 2. b_phone_pay_list, 增加 msg_enable 字段
// 定时任务:
// 1. 每月最后一天晚上11点半开始,统一从移动系统删除亲情号,然后更新亲情号可修改次数,然后更新套餐分钟数。
// 2. 每晚校验缓存,同时更新用户登录次数和时间
......@@ -2,7 +2,7 @@ syntax = "proto3";
option go_package = "./k122Server";
package my_grpc;
package k122Server;
message CacheAreaReq {
uint32 AreaID = 1;
......
......@@ -92,7 +92,7 @@ type ConsumeApplyStruct struct {
AreaServiceAllinPayID uint32 //收款主体的adminID
OrderNum string // 订单号
Amount int32
SplitAmount []model.PhonePaySplitMoneyStruct
SplitAmount []model.PaySplitMoneyStruct
}
type WxMiniRequestPayment struct {
......@@ -205,7 +205,7 @@ func Pay(req *ConsumeApplyStruct) *WxMiniRequestPayment { //
//}
//if len(req.SplitAmount) == 0 { // 如果没有传入分账信息,则全部收入收款主体
// req.SplitAmount = append(req.SplitAmount,model.PhonePaySplitMoneyStruct{
// req.SplitAmount = append(req.SplitAmount,model.PaySplitMoneyStruct{
// AdminID: req.AreaServiceAllinPayID,
// Amount: req.Amount,
// })
......@@ -386,7 +386,7 @@ func PayCallback(c *gin.Context) {
c.Status(404)
return // 订单号都不对,看看要不要回复它,免得它一直发
}
//订单号生成规则:4B cardUserID,4B到期时间,4B 金额amount,8B 时间纳秒
//订单号生成规则:4B cardUserID,4B到期时间,4B 金额amount,1B payType,8B 时间纳秒
cardUserID := uint32(orderBytes[0])<<24 + uint32(orderBytes[1])<<16 + uint32(orderBytes[2])<<8 + uint32(orderBytes[3])
expiryUnix := int64(orderBytes[4])<<24 + int64(orderBytes[5])<<16 + int64(orderBytes[6])<<8 + int64(orderBytes[7])
// amount := uint32(orderBytes[8])<<24 + uint32(orderBytes[9])<<16 +uint32(orderBytes[10])<<8 + uint32(orderBytes[11])
......@@ -410,6 +410,24 @@ func PayCallback(c *gin.Context) {
}
expiry := time.Unix(expiryUnix, 0)
//switch orderBytes[12] { // payType
//case 0x01: // "开卡费"
//case 0x02: // "补卡费"
//case 0x10: // "话费充值"
//case 0x11: // "充值(含开卡)"
//case 0x12: // "充值(含补卡)"
//case 0x20+0x10: // "话费充值(含留言服务)"
//case 0x20+0x11: // "充值(含开卡、留言服务)"
//case 0x20+0x12: // "充值(含补卡、留言服务)"
//case 0x20: // 仅补缴留言服务
//}
//if orderBytes[12] == 0x20 {
// // todo zjzjzj 判断是否已经有家长缴费了,如果有了则这一单缴费缴重复了应该退款
//}
msgNew := orderBytes[12]&0x20 == 0x20
// 1. 更新库 用事务处理
if dbcurd.UpdateUPhonePayRecordPayAtAndUCardUserPhoneExpiryTransaction(&dbcurd.UpdateUPhonePayRecordStruct{
CardUserID: cardUserID,
......@@ -420,11 +438,16 @@ func PayCallback(c *gin.Context) {
ThirdNum: orderData.OrderNo,
TencentTradeNum: orderData.PayInterfaceOutTradeNo,
Fee: uint32(fee),
}) {
}, msgNew) {
// 更新两个库都成功,那就写缓存回成功 2. 修改缓存的到期时间
if cache.UpdateCardUserMap(cardUserID, &model.CacheUpdateCardUserStruct{
temp := model.CacheUpdateCardUserStruct{
PhoneExpiry: &expiry,
}) == false {
}
if msgNew {
temp.MsgExpiry = &expiry
}
if cache.UpdateCardUserMap(cardUserID, &temp) == false {
fmt.Println("WechatPay 写缓存失败", cardUserID)
}
c.Status(200)
......
......@@ -8,14 +8,14 @@ import (
// NewCardAddExpiry 计算新开卡充值后话费有效期
// 计算逻辑:本月免费,下月开始计费
func NewCardAddExpiry(month uint8) time.Time{
return dateAddExpiryMonth(time.Now(),month)
func NewCardAddExpiry(month uint8) time.Time {
return dateAddExpiryMonth(time.Now(), month)
}
// RenewExpiry 续费时计算新的有效期
// 计算逻辑:原有效期基础上加有效期月份,例如原有效期为2022-03-31 23:59:59 续费12个月 则为2023-03-31 23:59:59
func RenewExpiry(t time.Time,month uint8) time.Time{
return dateAddExpiryMonth(t,month)
func RenewExpiry(t time.Time, month uint8) time.Time {
return dateAddExpiryMonth(t, month)
}
// JudgeCardCancel 判断学生话费状态 返回 0 有效期内 3 服务已到期 4 未充值(即从未充过值) 5 已销号,请补卡
......@@ -25,11 +25,11 @@ func JudgeCardCancel(t time.Time) uint8 {
return 4
}
if time.Now().Before(t) {
if time.Now().Before(t.Add(23 * time.Hour)) {
return 0
}
if time.Now().Before(dateAddExpiryMonth(t,1)) {
if time.Now().Before(dateAddExpiryMonth(t, 1)) {
return 3
}
......@@ -37,17 +37,41 @@ func JudgeCardCancel(t time.Time) uint8 {
}
// 加有效期月份,返回某年某月的最后一天的23:59:59,为0则为当月底,例如:3月10号加1个月有效期,即到4-30 23:59:59
func dateAddExpiryMonth(t time.Time,months uint8) time.Time {
func dateAddExpiryMonth(t time.Time, months uint8) time.Time {
year, month, day := t.Date()
// firstDayOfMonthAfterAddDate: years 年,months 月后的 那个月份的1号
firstDayOfMonthAfterAddDate := time.Date(year, month+time.Month(months), 1,
0, 0, 0, 0,time.Now().Location())
0, 0, 0, 0, time.Now().Location())
// firstDayOfMonthAfterAddDate 月份的最后一天
day = firstDayOfMonthAfterAddDate.AddDate(0,1,-1).Day()
day = firstDayOfMonthAfterAddDate.AddDate(0, 1, -1).Day()
return time.Date(year, month+time.Month(months), day,
23, 59, 59, 0, time.Now().Location())
23, 00, 00, 0, time.Now().Location())
}
// SubMonth 计算日期相差多少月,当月就是0个月
func SubMonth(t1, t2 time.Time) (month int32) {
y1 := int32(t1.Year())
y2 := int32(t2.Year())
m1 := int32(t1.Month())
m2 := int32(t2.Month())
d1 := t1.Day()
d2 := t2.Day()
yearInterval := y1 - y2
// 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
if m1 < m2 || m1 == m2 && d1 < d2 {
yearInterval--
}
// 获取月数差值
monthInterval := (m1 + 12) - m2
if d1 < d2 {
monthInterval--
}
monthInterval %= 12
month = yearInterval*12 + monthInterval
return
}
//// NowDateAddMonth 加月份,返回年月日
......@@ -69,4 +93,4 @@ func dateAddExpiryMonth(t time.Time,months uint8) time.Time {
//
// return time.Date(year, month+time.Month(months), day,
// 0, 0, 0, 0, time.Now().Location())
//}
\ No newline at end of file
//}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment