|
@@ -0,0 +1,961 @@
|
|
|
+package shanghu
|
|
|
+
|
|
|
+import (
|
|
|
+ "duoduo/apis/common"
|
|
|
+ "duoduo/apis/pdd"
|
|
|
+ "duoduo/apis/shanghu/models"
|
|
|
+ "duoduo/models/shanghu"
|
|
|
+ "duoduo/tools"
|
|
|
+ "duoduo/tools/app"
|
|
|
+ "encoding/base64"
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "github.com/gin-gonic/gin"
|
|
|
+ "github.com/go-pay/gopay"
|
|
|
+ "github.com/go-pay/gopay/wechat"
|
|
|
+ "github.com/shopspring/decimal"
|
|
|
+ "math/rand"
|
|
|
+ "net/http"
|
|
|
+ "strconv"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func ActiveConfigCreate(c *gin.Context) {
|
|
|
+ var inData models.CreateActiveConfigRequest
|
|
|
+ var sqlData shanghu.MerchantActiveConfig
|
|
|
+ var drawProduct shanghu.MerchantActiveDrawProduct
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if inData.DrawMode != 0 {
|
|
|
+ if len(inData.DrawId) <= 0 {
|
|
|
+ app.Error(c, 500, errors.New("奖品未配置"), "奖品未配置")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ drawList, _, err := drawProduct.GetDrawProductListById(inData.DrawId)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ sumOdds := 0
|
|
|
+
|
|
|
+ for _, v := range drawList {
|
|
|
+ sumOdds = sumOdds + v.DrawOdds
|
|
|
+ }
|
|
|
+ if sumOdds != 100 {
|
|
|
+ app.Error(c, 500, errors.New("配置的总中奖率不满100%"), "配置的总中奖率不满100%")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if inData.GroupBuyMode == 0 && inData.DrawMode == 0 {
|
|
|
+ app.Error(c, 500, errors.New("请选择抽奖与开团"), "请选择抽奖与开团")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlData.ActivityEndTime, err = tools.TimeToInt64(inData.ActivityEndTime, "2006-01-02")
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlData.ActivityStartTime, err = tools.TimeToInt64(inData.ActivityStartTime, "2006-01-02")
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ sqlData.ActiveName = inData.ActiveName
|
|
|
+ sqlData.MerchantOpenID = inData.MerchantOpenID
|
|
|
+ sqlData.CreatedAt = time.Now()
|
|
|
+ sqlData.UpdatedAt = time.Now()
|
|
|
+ sqlData.ConfigMode = 1
|
|
|
+ sqlData.DrawOneBiZhong = inData.DrawOneBiZhong
|
|
|
+ sqlData.DrawMode = inData.DrawMode
|
|
|
+ sqlData.GroupBuyMode = inData.GroupBuyMode
|
|
|
+ sqlData.GroupBuyUrl = inData.GroupBuyUrl
|
|
|
+ sqlData.GroupBuy = `{}`
|
|
|
+ sqlData.DrawProduct = `{}`
|
|
|
+ sqlData.BackgroundImage = inData.BackgroundImage
|
|
|
+
|
|
|
+ configData, err := sqlData.Create()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range inData.DrawId {
|
|
|
+ var drawData shanghu.MerchantActiveDrawProduct
|
|
|
+ drawData.ActiveConfigID = configData.ID
|
|
|
+ err = drawData.UpdateConfigId(v)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for _, v := range inData.GroupBuyId {
|
|
|
+ var groupBuy shanghu.MerchantActiveGroupBuy
|
|
|
+ groupBuy.ActiveConfigID = configData.ID
|
|
|
+ err = groupBuy.UpdateConfigId(v)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ app.OK(c, nil, app.Success)
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func ActiveConfigInfo(c *gin.Context) {
|
|
|
+ var inData models.ActiveConfigRequest
|
|
|
+ var sqlData shanghu.MerchantActiveConfig
|
|
|
+ var outData models.ActiveConfigReply
|
|
|
+ var drawInfoSql shanghu.MerchantActiveDrawProduct
|
|
|
+ var groupBuy shanghu.MerchantActiveGroupBuy
|
|
|
+ var drawNumSql shanghu.ClientActiveDrawNum
|
|
|
+ var draw shanghu.ClientActiveDrawLog
|
|
|
+
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ sqlData.ID = inData.ActiveConfigId
|
|
|
+
|
|
|
+ configInfo, err := sqlData.GetConfigInfoById()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ outData.GroupBuyMode = configInfo.GroupBuyMode
|
|
|
+ outData.DrawMode = configInfo.DrawMode
|
|
|
+ outData.GroupBuyUrl = configInfo.GroupBuyUrl
|
|
|
+ outData.DrawOneBiZhong = configInfo.DrawOneBiZhong
|
|
|
+ outData.ActivityEndTime = tools.TimeToStr(configInfo.ActivityEndTime)
|
|
|
+ outData.ActivityStartTime = tools.TimeToStr(configInfo.ActivityStartTime)
|
|
|
+ outData.ActiveName = configInfo.ActiveName
|
|
|
+ outData.BackgroundImage = configInfo.BackgroundImage
|
|
|
+
|
|
|
+
|
|
|
+ drawInfoSql.ActiveConfigID = configInfo.ID
|
|
|
+
|
|
|
+ drawInfo, _, err := drawInfoSql.GetDrawProductList()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range drawInfo {
|
|
|
+ var drawProduct models.DrawProduct
|
|
|
+ drawProduct.DrawProductName = v.DrawProductName
|
|
|
+ drawProduct.DrawUrl = v.DrawUrl
|
|
|
+ drawProduct.DrawOdds = v.DrawOdds
|
|
|
+ drawProduct.IsPrize = v.IsPrize
|
|
|
+ drawProduct.TotalStock = v.TotalStock
|
|
|
+ drawProduct.Stock = v.Stock
|
|
|
+ outData.DrawProduct = append(outData.DrawProduct, drawProduct)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ groupBuy.ActiveConfigID = configInfo.ID
|
|
|
+
|
|
|
+ groupBuyInfoList, _, err := groupBuy.GetGroupBuyList()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range groupBuyInfoList {
|
|
|
+ var groupBuyInfo models.DrawGroupBuyInfo
|
|
|
+ var groupBuyProject shanghu.MerchantActiveGroupByProject
|
|
|
+ groupBuyInfo.GroupBuyName = v.GroupBuyName
|
|
|
+ groupBuyInfo.GroupBuyMode = v.GroupBuyMode
|
|
|
+ groupBuyInfo.GroupBuyUrl = v.GroupBuyUrl
|
|
|
+ groupBuyInfo.GroupBuyThreeNum = v.GroupBuyThreeNum
|
|
|
+ groupBuyInfo.GroupBuyThreePrice = v.GroupBuyThreePrice
|
|
|
+ groupBuyInfo.GroupBuyFourNum = v.GroupBuyFourNum
|
|
|
+ groupBuyInfo.GroupBuyFourPrice = v.GroupBuyFourPrice
|
|
|
+ groupBuyInfo.GroupBuyTwoNum = v.GroupBuyTwoNum
|
|
|
+ groupBuyInfo.GroupBuyTwoPrice = v.GroupBuyTwoPrice
|
|
|
+ groupBuyInfo.GroupBuyOneNum = v.GroupBuyOneNum
|
|
|
+ groupBuyInfo.GroupBuyOnePrice = v.GroupBuyOnePrice
|
|
|
+ groupBuyInfo.MerchantOpenID = v.MerchantOpenID
|
|
|
+ groupBuyInfo.OriginalPrice = v.OriginalPrice
|
|
|
+ groupBuyInfo.RebateRate = v.RebateRate
|
|
|
+ groupBuyInfo.GroupBuyId = v.ID
|
|
|
+
|
|
|
+ groupBuyInfo.MaxRebatePrice = v.GroupBuyOnePrice.Mul(decimal.NewFromInt32(int32(v.RebateRate)).Div(decimal.NewFromInt32(100)))
|
|
|
+
|
|
|
+ groupBuyProject.GroupBuyID = v.ID
|
|
|
+
|
|
|
+ projectList, _, err := groupBuyProject.GetGroupBuyProjectList()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range projectList {
|
|
|
+ var groupBuyProjectInfo models.GroupBuyProject
|
|
|
+ groupBuyProjectInfo.ProjectName = v.ProjectName
|
|
|
+ groupBuyProjectInfo.CancelNum = v.CancelNum
|
|
|
+ groupBuyInfo.GroupBuyProject = append(groupBuyInfo.GroupBuyProject, groupBuyProjectInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+ outData.DrawGroupBuy = append(outData.DrawGroupBuy, groupBuyInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if inData.ClientOpenID != "" {
|
|
|
+
|
|
|
+
|
|
|
+ drawNumSql.ActiveConfigID = inData.ActiveConfigId
|
|
|
+ drawNumSql.ClientOpenID = inData.ClientOpenID
|
|
|
+ drawNum, err := drawNumSql.GetDrawNum()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ draw.ActiveConfigID = inData.ActiveConfigId
|
|
|
+ draw.ClientOpenID = inData.ClientOpenID
|
|
|
+ clientDrawNum, err := draw.GetClientActiveDrawLogNum()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ outData.DrawNum = drawNum + 1 - clientDrawNum
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ app.OK(c, outData, app.Success)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func UpdateActiveConfigWHXY(c *gin.Context) {
|
|
|
+ var inData models.ActiveConfigWHXYRequest
|
|
|
+ var sqlData shanghu.MerchantActiveConfig
|
|
|
+ var whxy []models.WHXYStr
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ err = json.Unmarshal([]byte(inData.WHXY), &whxy)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ for i := 0; i < len(whxy); i++ {
|
|
|
+ if !whxy[i].Y.IsZero() {
|
|
|
+ sqlData.W = whxy[i].W.String()
|
|
|
+ sqlData.X = whxy[i].X.String()
|
|
|
+ sqlData.Y = whxy[i].Y.String()
|
|
|
+ sqlData.H = whxy[i].H.String()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ sqlData.ID = inData.ActiveConfigId
|
|
|
+
|
|
|
+ err = sqlData.UpdateMerchantWHXY()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ app.OK(c, nil, app.Success)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func ActiveConfigList(c *gin.Context) {
|
|
|
+ var inData models.ActiveConfigListRequest
|
|
|
+ var sqlData shanghu.MerchantActiveConfig
|
|
|
+ var outData []models.ActiveConfigListReply
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sqlData.MerchantOpenID = inData.OpenId
|
|
|
+ var pageSize = 10
|
|
|
+ var pageIndex = 1
|
|
|
+
|
|
|
+ if inData.PageSize != 0 {
|
|
|
+ pageSize = inData.PageSize
|
|
|
+ }
|
|
|
+ if inData.PageIndex != 0 {
|
|
|
+ pageIndex = inData.PageIndex
|
|
|
+ }
|
|
|
+
|
|
|
+ activeConfigList, count, err := sqlData.GetActiveConfigList(pageSize, pageIndex)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range activeConfigList {
|
|
|
+ var activeConfig models.ActiveConfigListReply
|
|
|
+ activeConfig.ID = v.ID
|
|
|
+ activeConfig.ActivityStart = tools.TimeToStr(v.ActivityStartTime)
|
|
|
+ activeConfig.ActivityEnd = tools.TimeToStr(v.ActivityEndTime)
|
|
|
+ activeConfig.ActiveName = v.ActiveName
|
|
|
+ activeConfig.CreatedAt = v.CreatedAt.Format(time.DateTime)
|
|
|
+
|
|
|
+ outData = append(outData, activeConfig)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ app.PageOK(c, outData, count, pageIndex, pageSize, app.Success)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func Draw(c *gin.Context) {
|
|
|
+ var inData models.DrawRequest
|
|
|
+ var sqlData shanghu.MerchantActiveConfig
|
|
|
+ var drawNumSql shanghu.ClientActiveDrawNum
|
|
|
+ var draw shanghu.ClientActiveDrawLog
|
|
|
+ var outData models.DrawReply
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ drawNumSql.ActiveConfigID = inData.ActiveConfigID
|
|
|
+ drawNumSql.ClientOpenID = inData.ClientOpenID
|
|
|
+ drawNum, err := drawNumSql.GetDrawNum()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ draw.ActiveConfigID = inData.ActiveConfigID
|
|
|
+ draw.ClientOpenID = inData.ClientOpenID
|
|
|
+ clientDrawNum, err := draw.GetClientActiveDrawLogNum()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if drawNum < clientDrawNum {
|
|
|
+ app.Error(c, 500, errors.New("抽奖次数用完"), "抽奖次数用完")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ sqlData.ID = inData.ActiveConfigID
|
|
|
+ config, err := sqlData.GetConfigInfoById()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if config.DrawOneBiZhong > 0 {
|
|
|
+
|
|
|
+ var drawConfig shanghu.ClientActiveDrawLog
|
|
|
+ drawConfig.ActiveConfigID = inData.ActiveConfigID
|
|
|
+ drawConfig.ClientOpenID = inData.ClientOpenID
|
|
|
+ drawConfig.DrawProductID = config.DrawOneBiZhong
|
|
|
+
|
|
|
+ count, err := drawConfig.GetClientActiveDrawLogByBiZHong()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if count == 0 {
|
|
|
+
|
|
|
+ var drawProduct shanghu.MerchantActiveDrawProduct
|
|
|
+
|
|
|
+ drawProduct.ID = config.DrawOneBiZhong
|
|
|
+ drawProductInfo, err := drawProduct.GetDrawProductById()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if drawProductInfo.ActiveConfigID != inData.ActiveConfigID {
|
|
|
+ app.Error(c, 500, errors.New("必中配置活动不一致"), "必中配置活动不一致")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if drawProductInfo.Stock <= 0 {
|
|
|
+ app.Error(c, 500, errors.New("库存不足"), "库存不足")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Println(drawProductInfo)
|
|
|
+
|
|
|
+
|
|
|
+ err = subStockAddLog(drawProductInfo, inData.ClientOpenID)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ outData.DrawProductName = drawProductInfo.DrawProductName
|
|
|
+ outData.DrawUrl = drawProductInfo.DrawUrl
|
|
|
+ outData.ID = config.DrawOneBiZhong
|
|
|
+
|
|
|
+ app.OK(c, outData, app.Success)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var drawProductList shanghu.MerchantActiveDrawProduct
|
|
|
+ var prizeList []Prize
|
|
|
+ drawProductList.ActiveConfigID = inData.ActiveConfigID
|
|
|
+ drawProductInfo, _, err := drawProductList.GetDrawProductListByActiveId()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ for _, v := range drawProductInfo {
|
|
|
+ var prize Prize
|
|
|
+ if v.Stock <= 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ prize.Name = v.DrawProductName
|
|
|
+ prize.ID = v.ID
|
|
|
+ prize.Weight = v.DrawOdds
|
|
|
+ prize.InitStock = v.TotalStock
|
|
|
+ prize.Stock = v.Stock
|
|
|
+ prizeList = append(prizeList, prize)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ lottery := NewLottery(prizeList)
|
|
|
+
|
|
|
+
|
|
|
+ results, err := lottery.Draw(1)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ fmt.Println(results)
|
|
|
+ var drawProduct shanghu.MerchantActiveDrawProduct
|
|
|
+ for _, v := range drawProductInfo {
|
|
|
+ if results[0].ID == v.ID {
|
|
|
+ outData.ID = v.ID
|
|
|
+ outData.DrawUrl = v.DrawUrl
|
|
|
+ outData.DrawProductName = v.DrawProductName
|
|
|
+ drawProduct = v
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ err = subStockAddLog(drawProduct, inData.ClientOpenID)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ app.OK(c, outData, app.Success)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+type Prize struct {
|
|
|
+ ID int64
|
|
|
+ Name string
|
|
|
+ Weight int
|
|
|
+ Stock int
|
|
|
+ InitStock int
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+type Lottery struct {
|
|
|
+ Prizes []Prize
|
|
|
+ TotalWeight int
|
|
|
+}
|
|
|
+
|
|
|
+func NewLottery(prizes []Prize) *Lottery {
|
|
|
+ totalWeight := 0
|
|
|
+ for _, prize := range prizes {
|
|
|
+ totalWeight += prize.Weight
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ prizeCopy := make([]Prize, len(prizes))
|
|
|
+ for i, p := range prizes {
|
|
|
+ prizeCopy[i] = p
|
|
|
+ prizeCopy[i].InitStock = p.Stock
|
|
|
+ }
|
|
|
+
|
|
|
+ return &Lottery{
|
|
|
+ Prizes: prizeCopy,
|
|
|
+ TotalWeight: totalWeight,
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+func (l *Lottery) Draw(times int) ([]Prize, error) {
|
|
|
+
|
|
|
+ totalStock := 0
|
|
|
+ for _, prize := range l.Prizes {
|
|
|
+ totalStock += prize.Stock
|
|
|
+ }
|
|
|
+ if totalStock < times {
|
|
|
+ return nil, fmt.Errorf("剩余总库存(%d)不足以支持%d次抽奖", totalStock, times)
|
|
|
+ }
|
|
|
+
|
|
|
+ rand.Seed(time.Now().UnixNano())
|
|
|
+ results := make([]Prize, 0, times)
|
|
|
+
|
|
|
+ for i := 0; i < times; i++ {
|
|
|
+
|
|
|
+ if l.TotalWeight <= 0 {
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ randNum := rand.Intn(l.TotalWeight)
|
|
|
+ currentWeight := 0
|
|
|
+
|
|
|
+ for j := range l.Prizes {
|
|
|
+ if l.Prizes[j].Stock <= 0 {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+
|
|
|
+ currentWeight += l.Prizes[j].Weight
|
|
|
+ if randNum < currentWeight {
|
|
|
+
|
|
|
+ results = append(results, l.Prizes[j])
|
|
|
+
|
|
|
+ l.Prizes[j].Stock--
|
|
|
+
|
|
|
+ if l.Prizes[j].Stock == 0 {
|
|
|
+ l.TotalWeight -= l.Prizes[j].Weight
|
|
|
+ }
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return results, nil
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+func subStockAddLog(drawProductInfo shanghu.MerchantActiveDrawProduct, clientOpenId string) error {
|
|
|
+ var draw shanghu.ClientActiveDrawLog
|
|
|
+
|
|
|
+
|
|
|
+ if drawProductInfo.Stock <= 0 {
|
|
|
+
|
|
|
+ return errors.New("库存不足")
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ err := drawProductInfo.SubStock()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ draw.DrawProductID = drawProductInfo.ID
|
|
|
+ draw.ActiveConfigID = drawProductInfo.ActiveConfigID
|
|
|
+ draw.ClientOpenID = clientOpenId
|
|
|
+
|
|
|
+ if drawProductInfo.IsPrize {
|
|
|
+ draw.IsPrize = models.NotClaimed
|
|
|
+ } else {
|
|
|
+ draw.IsPrize = models.NotWon
|
|
|
+ }
|
|
|
+
|
|
|
+ draw.CreatedAt = time.Now()
|
|
|
+ draw.UpdatedAt = time.Now()
|
|
|
+ _, err = draw.Create()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func GetClientActiveQR(c *gin.Context) {
|
|
|
+ var inData models.ClientActiveQRRequest
|
|
|
+ var sqlData shanghu.ActiveUser
|
|
|
+ var outData models.ClientCardQRReply
|
|
|
+ var qr models.QRRequest
|
|
|
+ var getQR models.GetQRRequest
|
|
|
+ var activeSql shanghu.MerchantActiveConfig
|
|
|
+ var out models.ClientActiveQRReply
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ val, err := pdd.DuoDuoGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx43e320d3ffaa4d7b&secret=97d811cde197515ed03b7c7a6e24d4e8")
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ err = tools.JsonUnmarshal(val, &outData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if outData.AccessToken == "" {
|
|
|
+ app.Error(c, 500, err, "token error")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ code := ""
|
|
|
+ if inData.Code == "yuanshima" {
|
|
|
+ code = "yuanshima"
|
|
|
+ } else {
|
|
|
+ sqlData.OpenID = inData.OpenId
|
|
|
+ userInfo, err := sqlData.GetUserInfo()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ code = userInfo.Code
|
|
|
+ }
|
|
|
+
|
|
|
+ url := "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + outData.AccessToken
|
|
|
+
|
|
|
+ qr.CheckPath = false
|
|
|
+ qr.Page = "pages/home/home"
|
|
|
+ qr.EnvVersion = "develop"
|
|
|
+ qr.Scene = "id-" + strconv.FormatInt(inData.ActiveConfigId, 10) + "-c-" + code
|
|
|
+
|
|
|
+ data, err := json.Marshal(&qr)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ reply, err := common.Post(data, url)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if getQR.Errcode != 0 {
|
|
|
+ app.Error(c, 500, err, getQR.Errmsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ activeSql.ID = inData.ActiveConfigId
|
|
|
+ activeInfo, err := activeSql.GetConfigInfoById()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 500, err, getQR.Errmsg)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ encoded := base64.StdEncoding.EncodeToString(reply)
|
|
|
+ out.H = activeInfo.H
|
|
|
+ out.W = activeInfo.W
|
|
|
+ out.X = activeInfo.X
|
|
|
+ out.Y = activeInfo.Y
|
|
|
+ out.Encoded = encoded
|
|
|
+
|
|
|
+ app.OK(c, out, app.Success)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func GroupByUnifiedOrder(c *gin.Context) {
|
|
|
+ var inData models.GroupBuyUnifiedOrderRequest
|
|
|
+ var sqlData shanghu.ClientActivePayTrans
|
|
|
+ var activeConfig shanghu.MerchantActiveConfig
|
|
|
+ var outData models.GroupBuyUnifiedOrderReply
|
|
|
+ var groupBuySql shanghu.MerchantActiveGroupBuy
|
|
|
+
|
|
|
+ err := c.ShouldBindJSON(&inData)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ activeConfig.ID = inData.ActiveConfigId
|
|
|
+
|
|
|
+ activeConfigInfo, err := activeConfig.GetConfigInfoById()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if activeConfigInfo.GroupBuyMode != 1 {
|
|
|
+ app.Error(c, 500, errors.New("非虚拟开团,不允许下单"), "非虚拟开团,不允许下单.")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if inData.ClientOpenId == "" {
|
|
|
+ app.OK(c, nil, app.Success)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ sqlData.RequestID = inData.RequestId
|
|
|
+ if sqlData.GetRequestNum() > 0 {
|
|
|
+ app.Error(c, 400, errors.New("交易已存在"), "交易已存在")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ if !inData.Amount.GreaterThan(decimal.NewFromInt(0)) {
|
|
|
+ app.Error(c, 400, errors.New("amount:金额必须大于0"), "amount:金额必须大于0")
|
|
|
+ return
|
|
|
+
|
|
|
+ }
|
|
|
+ if inData.Amount.Round(2).String() != inData.Amount.String() {
|
|
|
+ app.Error(c, 400, errors.New("total_fee:金额最多只能保留两位小数"), "total_fee:金额最多只能保留两位小数")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ if inData.InvitationCode == "yuanshima" {
|
|
|
+ sqlData.MerchantAmount = inData.Amount
|
|
|
+ sqlData.ClientAmount = decimal.NewFromInt32(0)
|
|
|
+ } else {
|
|
|
+ groupBuySql.ID = inData.GroupBuyId
|
|
|
+ groupBuyInfo, err := groupBuySql.GetMerchantActiveGroupBuyById()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, err.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ sqlData.ClientAmount = inData.Amount.Mul(decimal.NewFromInt32(int32(groupBuyInfo.RebateRate))).Div(decimal.NewFromInt32(100))
|
|
|
+ sqlData.MerchantAmount = inData.Amount.Sub(sqlData.ClientAmount)
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ sqlData.ClientOpenID = inData.ClientOpenId
|
|
|
+ sqlData.RequestID = inData.RequestId
|
|
|
+ sqlData.CreatedAt = time.Now()
|
|
|
+ sqlData.UpdatedAt = time.Now()
|
|
|
+ sqlData.Amount = inData.Amount
|
|
|
+ sqlData.OutTradeNo = strconv.FormatInt(inData.ActiveConfigId, 10) + strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
|
+ sqlData.Status = 1
|
|
|
+ sqlData.ActiveConfigID = inData.ActiveConfigId
|
|
|
+ sqlData.InvitationCode = inData.InvitationCode
|
|
|
+ sqlData.GroupBuyID = inData.GroupBuyId
|
|
|
+ sqlData.MerchantOpenID = activeConfigInfo.MerchantOpenID
|
|
|
+ _, err = sqlData.Create()
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, "创建支付失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ fmt.Println(sqlData.OutTradeNo)
|
|
|
+ bm := make(gopay.BodyMap)
|
|
|
+ bm.Set("nonce_str", common.GetRandomString(32))
|
|
|
+ bm.Set("body", "商户卡")
|
|
|
+ bm.Set("out_trade_no", sqlData.OutTradeNo)
|
|
|
+ bm.Set("total_fee", inData.Amount.Mul(decimal.NewFromInt(100)).IntPart())
|
|
|
+ bm.Set("spbill_create_ip", "127.0.0.1")
|
|
|
+ bm.Set("notify_url", "https://tao1024.com/v1/active/pay/callback")
|
|
|
+ bm.Set("device_info", "WEB")
|
|
|
+ bm.Set("trade_type", "JSAPI")
|
|
|
+ bm.Set("sign_type", wechat.SignType_MD5)
|
|
|
+ bm.Set("openid", inData.ClientOpenId)
|
|
|
+
|
|
|
+ appid := "wx43e320d3ffaa4d7b"
|
|
|
+ mchId := "1670841410"
|
|
|
+ apiKey := "33c424fAa69942086f82A003e283E9C8"
|
|
|
+
|
|
|
+ client := NewWechatServiceTwo(appid, mchId, apiKey)
|
|
|
+
|
|
|
+
|
|
|
+ wxResp, err := client.UnifiedOrder(c, bm)
|
|
|
+ if err != nil {
|
|
|
+ app.Error(c, 400, err, "下单失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if wxResp.ReturnCode != "SUCCESS" {
|
|
|
+ app.Error(c, 400, errors.New(wxResp.ReturnMsg), "下单失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if wxResp.ResultCode != "SUCCESS" {
|
|
|
+ app.Error(c, 400, errors.New(wxResp.ErrCode+"--"+wxResp.ErrCodeDes), "下单失败")
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ timestamp := strconv.FormatInt(time.Now().Unix(), 10)
|
|
|
+ pac := "prepay_id=" + wxResp.PrepayId
|
|
|
+ paySign := wechat.GetMiniPaySign("wx8595c589dd736486", wxResp.NonceStr, pac, wechat.SignType_MD5, timestamp, "33c424fAa69942086f82A003e283E9C8")
|
|
|
+
|
|
|
+ outData.Timestamp = timestamp
|
|
|
+ outData.NonceStr = wxResp.NonceStr
|
|
|
+ outData.Package = pac
|
|
|
+ outData.PaySign = paySign
|
|
|
+ outData.SignType = wechat.SignType_MD5
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ app.OK(c, outData, app.Success)
|
|
|
+}
|
|
|
+
|
|
|
+func Pay(c *gin.Context) {
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+func ActivePayCallBack(c *gin.Context) {
|
|
|
+ var payLog shanghu.ActivePayCallbackLog
|
|
|
+ var payTrans shanghu.ClientActivePayTrans
|
|
|
+ wxNotify, err := wechat.ParseNotifyToBodyMap(c.Request)
|
|
|
+ if err != nil {
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ payLog.CallBackLog = wxNotify.JsonBody()
|
|
|
+ payLog.ThirdTradeNo = wxNotify.Get("transaction_id")
|
|
|
+ payLog.OutTradeNo = wxNotify.Get("out_trade_no")
|
|
|
+ payLog.CreatedAt = time.Now()
|
|
|
+ payLog.UpdatedAt = time.Now()
|
|
|
+
|
|
|
+ _, err = payLog.Create()
|
|
|
+ if err != nil {
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if wxNotify.Get("return_code") != "SUCCESS" || wxNotify.Get("result_code") != "SUCCESS" {
|
|
|
+ payLog.ErrLog = "微信返回错误:" + wxNotify.Get("return_code") + "--" + wxNotify.Get("result_code")
|
|
|
+ payLog.UpdateMerchant()
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ payTrans.OutTradeNo = wxNotify.Get("out_trade_no")
|
|
|
+ payTransInfo, err := payTrans.GetPayTransByTradeNo()
|
|
|
+ if err != nil {
|
|
|
+ payLog.ErrLog = "查询交易信息错误:" + " err=" + err.Error()
|
|
|
+ payLog.UpdateMerchant()
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ totalFee, err := decimal.NewFromString(wxNotify.Get("total_fee"))
|
|
|
+ if err != nil {
|
|
|
+ payLog.ErrLog = "解析总金额报错:" + "err=" + err.Error()
|
|
|
+ payLog.UpdateMerchant()
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if !totalFee.Equal(payTransInfo.Amount.Mul(decimal.NewFromInt(100))) {
|
|
|
+ payLog.ErrLog = "验证金额报错:total_fee=" + wxNotify.Get("total_fee") + " amount=" + payTransInfo.Amount.String()
|
|
|
+ payLog.UpdateMerchant()
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ timeEnd, err := time.ParseInLocation("20060102150405", wxNotify.Get("time_end"), tools.TimeLocation)
|
|
|
+ if err != nil {
|
|
|
+ payLog.ErrLog = "付款时间解析出错:err=" + err.Error()
|
|
|
+ payLog.UpdateMerchant()
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ payTrans.ThirdTradeNo = wxNotify.Get("transaction_id")
|
|
|
+ payTrans.Status = 2
|
|
|
+ payTrans.PayTime = timeEnd
|
|
|
+ payTrans.AccountStatus = 1
|
|
|
+
|
|
|
+ err = payTrans.UpdatePayTransByTradeNo()
|
|
|
+ if err != nil {
|
|
|
+ payLog.ErrLog = "更新支付状态失败:err=" + err.Error()
|
|
|
+ payLog.UpdateMerchant()
|
|
|
+ c.XML(http.StatusOK, failResp)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ c.XML(http.StatusOK, successResp)
|
|
|
+
|
|
|
+}
|