| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961 | 
							- 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
 
- 		}
 
- 		//校验总概率 总概率相加不能大于100
 
- 		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
 
- 	}
 
- 	//必中校验
 
- 	//if inData.DrawOneBiZhong > 0 {
 
- 	//	var checkBZ shanghu.MerchantActiveDrawProduct
 
- 	//	checkBZ.ID = inData.DrawOneBiZhong
 
- 	//	bZInfo, err := checkBZ.GetDrawProductById()
 
- 	//	if err != nil {
 
- 	//		app.Error(c, 500, err, err.Error())
 
- 	//		return
 
- 	//	}
 
- 	//
 
- 	//	if !bZInfo.IsPrize {  //
 
- 	//		app.Error(c, 500, 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
 
- 	//var merchant shanghu.Merchant
 
- 	err := c.ShouldBindJSON(&inData)
 
- 	if err != nil {
 
- 		app.Error(c, 400, err, err.Error())
 
- 		return
 
- 	}
 
- 	//sqlData.MerchantOpenID = inData.MerchantOpenID
 
- 	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
 
- 		//if drawNum+1 < clientDrawNum {
 
- 		//	app.Error(c, 500, errors.New("抽奖次数用完"), "抽奖次数用完")
 
- 		//	return
 
- 		//}
 
- 	}
 
- 	//获取商家信息
 
- 	//merchant.OpenId = inData.MerchantOpenID
 
- 	//merchantInfo, err := merchant.GetMerchant()
 
- 	//if err != nil {
 
- 	//	app.Error(c, 500, err, err.Error())
 
- 	//	return
 
- 	//}
 
- 	//outData.MerchantName = merchantInfo.MerchantName
 
- 	app.OK(c, outData, app.Success)
 
- }
 
- // whxy
 
- 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
 
- 		}
 
- 		// 为0直接中奖 写中奖记录并且返回 查询中奖
 
- 		if count == 0 {
 
- 			//var draw shanghu.ClientActiveDrawLog
 
- 			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)
 
- 			//新建log 减库存
 
- 			err = subStockAddLog(drawProductInfo, inData.ClientOpenID)
 
- 			if err != nil {
 
- 				app.Error(c, 500, err, err.Error())
 
- 				return
 
- 			}
 
- 			//draw.DrawProductID = config.DrawOneBiZhong
 
- 			//draw.ActiveConfigID = inData.ActiveConfigID
 
- 			//draw.ClientOpenID = inData.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 {
 
- 			//	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)
 
- 	}
 
- 	//fmt.Println(prizeList)
 
- 	// 创建抽奖实例
 
- 	lottery := NewLottery(prizeList)
 
- 	// 执行1次抽奖
 
- 	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  // 奖品ID
 
- 	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
 
- 	//var drawProduct shanghu.MerchantActiveDrawProduct
 
- 	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
 
- 	}
 
- 	//	sqlData.ID = inData.ActiveConfigId
 
- 	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
 
- 	}
 
- 	//fmt.Println("val:", val)
 
- 	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 { //根据openid查code
 
- 		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
 
- 	}
 
- 	//err = json.Unmarshal(reply, &getQR)
 
- 	//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
 
- 	}
 
- 	//fmt.Println(string(reply))
 
- 	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
 
- 	}
 
- 	//校验活动id
 
- 	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 //团购id
 
- 	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)
 
- 	//client := NewWechatService()
 
- 	//请求支付下单,成功后得到结果
 
- 	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
 
- 	//merchant, count, err := sqlData.GetOpenIdList(pageSize, pageIndex)
 
- 	//if err != nil {
 
- 	//	app.Error(c, 500, err, err.Error())
 
- 	//	return
 
- 	//}
 
- 	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
 
- 	}
 
- 	//通知回调log
 
- 	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)
 
- }
 
 
  |