فهرست منبع

Merge branch 'yun-group-buy' of k.zhang/duoduo into yun-master

k.zhang 1 ماه پیش
والد
کامیت
0ded6619e3
37فایلهای تغییر یافته به همراه4308 افزوده شده و 19 حذف شده
  1. 4 0
      apis/common/post.go
  2. 29 0
      apis/shanghu/account.go
  3. 170 0
      apis/shanghu/active.cash.out.go
  4. 526 0
      apis/shanghu/active.pay.go
  5. 34 1
      apis/shanghu/base.go
  6. 199 0
      apis/shanghu/client.active.draw.log.go
  7. 100 0
      apis/shanghu/client.active.draw.num.go
  8. 961 0
      apis/shanghu/merchant.active.config.go
  9. 111 0
      apis/shanghu/merchant.active.draw.product.go
  10. 132 0
      apis/shanghu/merchant.active.group.buy.go
  11. 78 0
      apis/shanghu/merchant.user.go
  12. 167 0
      apis/shanghu/models/active.config.go
  13. 44 0
      apis/shanghu/models/active.draw.product.go
  14. 71 0
      apis/shanghu/models/active.group.buy.go
  15. 79 0
      apis/shanghu/models/active.pay.go
  16. 44 0
      apis/shanghu/models/client.active.draw.log.go
  17. 16 0
      apis/shanghu/models/client.active.draw.num.go
  18. 10 1
      apis/shanghu/pay.go
  19. 13 4
      conf/conn_ini__test.go
  20. 33 0
      models/shanghu/active.account.log.go
  21. 65 0
      models/shanghu/active.cancel.log.go
  22. 31 0
      models/shanghu/active.cash.out.go
  23. 53 0
      models/shanghu/active.draw.config.go
  24. 48 0
      models/shanghu/active.pay.callback.log.go
  25. 85 0
      models/shanghu/active.user.go
  26. 200 0
      models/shanghu/actvie.client.account.go
  27. 114 0
      models/shanghu/client.active.draw.log.go
  28. 65 0
      models/shanghu/client.active.draw.num.go
  29. 213 0
      models/shanghu/client.active.pay.trans.go
  30. 146 0
      models/shanghu/merchant.account.go
  31. 17 1
      models/shanghu/merchant.account.log.go
  32. 93 0
      models/shanghu/merchant.active.config.go
  33. 153 0
      models/shanghu/merchant.active.draw.product.go
  34. 107 0
      models/shanghu/merchant.active.group.buy.go
  35. 63 0
      models/shanghu/merchant.active.group.buy.project.go
  36. 13 12
      models/shanghu/merchant_user.go
  37. 21 0
      report/cash.out.go

+ 4 - 0
apis/common/post.go

@@ -31,6 +31,10 @@ func Post(inputObj []byte, url string) ([]byte, error) {
 		return nil, err
 	}
 
+	defer resp.Body.Close()
+
+	//fmt.Println("respBytes:", string(respBytes))
+
 	return respBytes, nil
 
 }

+ 29 - 0
apis/shanghu/account.go

@@ -4,6 +4,7 @@ import (
 	"duoduo/apis/shanghu/models"
 	"duoduo/models/shanghu"
 	"duoduo/tools/app"
+	"errors"
 	"github.com/gin-gonic/gin"
 )
 
@@ -45,3 +46,31 @@ func GetAccountAmount(c *gin.Context) {
 	}
 
 }
+
+func GetActiveAmount(c *gin.Context) {
+	var inData models.GetAccountAmountRequest
+	var outData models.GetAccountAmountReply
+	var sqlClientData shanghu.ActiveClientAccount
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	if inData.Type == "client" {
+		sqlClientData.ClientOpenID = inData.OpenId
+		clientAccount, err := sqlClientData.GetActiveAccount()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		outData.Amount = clientAccount.Amount
+		app.OK(c, outData, app.Success)
+		return
+
+	} else {
+		app.Error(c, 500, errors.New("不支持此业务查询"), "不支持此业务查询")
+		return
+	}
+}

+ 170 - 0
apis/shanghu/active.cash.out.go

@@ -0,0 +1,170 @@
+package shanghu
+
+import (
+	"duoduo/apis/common"
+	"duoduo/apis/shanghu/models"
+	"duoduo/models/shanghu"
+	"duoduo/tools/app"
+	"errors"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/go-pay/gopay"
+	"github.com/shopspring/decimal"
+	"time"
+)
+
+func ActiveCashOut(c *gin.Context) {
+	var inData models.PayCashOutRequest
+	var clientAccountSql shanghu.ActiveClientAccount
+	var cashOut shanghu.CashOut
+	var trans []models.TransferDetailList
+	var transDetail models.TransferDetailList
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	_, ok := GlobalCashOutMap[inData.OpenId]
+	if ok {
+		app.OK(c, nil, "正在提现中...")
+		return
+	}
+
+	GlobalCashOutMap[inData.OpenId] = 1
+	defer func() {
+		delete(GlobalCashOutMap, inData.OpenId)
+	}()
+	if inData.Appid == "" { //appid 不能为空
+		app.Error(c, 400, errors.New("AppID不能为空"), "AppID不能为空")
+		return
+	}
+
+	if inData.Amount.Cmp(decimal.NewFromInt(500)) > 0 {
+		app.Error(c, 400, errors.New("单笔金额不能大于500"), "单笔金额不能大于500")
+		return
+	}
+
+	if inData.Amount.Cmp(decimal.NewFromInt(1)) < 0 {
+		app.Error(c, 400, errors.New("单笔金额不能小于1"), "单笔金额不能大于1")
+		return
+	}
+
+	//
+	cashOut.OpenID = inData.OpenId
+	cashOut.AppID = inData.Appid
+	cashOut.Status = 1    //提现中
+	status := []int{1, 3} //提现中、金额待扣减
+
+	cashNum := cashOut.GetCashOutByStatusNum(status)
+	if cashNum > 0 {
+		app.Error(c, 400, errors.New("有一笔交易正在提现中"), "有一笔交易正在提现中")
+		return
+	}
+
+	//校验金额是否够
+	if inData.AccountType == "client" {
+		clientAccountSql.ClientOpenID = inData.OpenId
+		clientAccountInfo, err := clientAccountSql.GetActiveAccount()
+		if err != nil {
+			app.Error(c, 400, err, err.Error())
+			return
+		}
+		if inData.Amount.Cmp(clientAccountInfo.Amount) > 0 {
+			app.Error(c, 400, errors.New("账号余额不够"), "账号余额不够")
+			return
+		}
+		var client shanghu.ActiveUser
+		client.Code = "7jb6"
+		clientInfo, _ := client.GetUserInfoByCode()
+		if clientInfo.OpenID == inData.OpenId {
+			cashOut.Fee = decimal.NewFromInt(0)
+		} else {
+			cashOut.Fee = inData.Amount.Mul(decimal.NewFromFloat32(0.05))
+		}
+
+	} else {
+		app.Error(c, 400, errors.New("账户类型错误"), "账户类型错误")
+		return
+	}
+
+	clientV3, err := NewWechatServiceV3(inData.Appid)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	userName, err := clientV3.V3EncryptText(inData.UserName)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	transDetail.OutDetailNo = common.GetRandomString(32)
+	transDetail.TransferAmount = inData.Amount.Sub(cashOut.Fee).Mul(decimal.NewFromInt(100)).IntPart()
+	transDetail.UserName = userName
+	transDetail.Openid = inData.OpenId
+	transDetail.TransferRemark = "活动提现"
+
+	trans = append(trans, transDetail)
+
+	partnerTradeNo := common.GetRandomString(32)
+	var cashOutCreate shanghu.CashOut
+	//创建提现记录
+	cashOutCreate.AppID = inData.Appid
+	cashOutCreate.Status = 1 //提现中
+	cashOutCreate.OpenID = inData.OpenId
+	cashOutCreate.Amount = inData.Amount
+	cashOutCreate.CreatedAt = time.Now()
+	cashOutCreate.UpdatedAt = time.Now()
+	cashOutCreate.PartnerTradeNo = partnerTradeNo
+	cashOutCreate.Fee = cashOut.Fee
+	cashOutInfo, err := cashOutCreate.Create()
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	var bMap []gopay.BodyMap
+	bm := make(gopay.BodyMap)
+
+	bm.Set("appid", inData.Appid)
+	bm.Set("out_batch_no", partnerTradeNo)
+	bm.Set("batch_name", "活动提现")
+	bm.Set("batch_remark", "活动提现")
+	bm.Set("total_amount", inData.Amount.Sub(cashOut.Fee).Mul(decimal.NewFromInt(100)).IntPart())
+	bm.Set("total_num", 1)
+	bMap = append(bMap, structToMap(&transDetail))
+
+	bm.Set("transfer_detail_list", bMap)
+	bm.Set("transfer_scene_id", "1001")
+
+	fmt.Println(bm.JsonBody())
+
+	reply, err := clientV3.V3Transfer(c, bm)
+	if err != nil {
+		cashOut.ID = cashOutInfo.ID
+		cashOut.FailRes = err.Error()
+		cashOut.Status = 2 //提现失败
+		cashOut.UpdateMerchantStatus()
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	if reply.Code != 0 {
+		cashOut.ID = cashOutInfo.ID
+		cashOut.FailRes = reply.Error
+		cashOut.Status = 2 //提现失败
+		cashOut.UpdateMerchantStatus()
+		app.Error(c, 500, errors.New(reply.Error), reply.Error)
+		return
+	}
+
+	cashOut.WxPartnerTradeNo = reply.Response.BatchId
+	cashOut.PartnerTradeNo = reply.Response.OutBatchNo
+	cashOut.UpdateCashOutWxBachNo()
+
+	app.OK(c, nil, app.Success)
+
+}

+ 526 - 0
apis/shanghu/active.pay.go

@@ -0,0 +1,526 @@
+package shanghu
+
+import (
+	"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/skip2/go-qrcode"
+	"time"
+)
+
+// 待核销金额
+func PendingCancelAmount(c *gin.Context) {
+	var inData models.PendingCancelAmountRequest
+	var activePayTransSql shanghu.ClientActivePayTrans
+	var outData models.PendingCancelAmountReply
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	if inData.Type == 1 { //商家
+		activePayTransSql.MerchantOpenID = inData.OpenId
+		activeAmount, err := activePayTransSql.GetPendingCancelByMerchant()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		outData.Amount = activeAmount.MerchantAmount.String()
+
+	} else if inData.Type == 2 { //个人
+		activePayTransSql.ClientOpenID = inData.OpenId
+		activeAmount, err := activePayTransSql.GetPendingCancelByClient()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		outData.Amount = activeAmount.ClientAmount.String()
+
+	} else {
+		app.Error(c, 500, errors.New("type 类型错误"), err.Error())
+		return
+	}
+
+	app.OK(c, outData, app.Success)
+
+}
+
+// 拼团购买
+func GetGroupBuyPayList(c *gin.Context) {
+	var inData models.GetGroupBuyPayRequest
+	var sqlData shanghu.ClientActivePayTrans
+	var outData []models.GetGroupBuyPayReply
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	//// 不是商家也不是c端客户
+	//if inData.UserType != 1 && inData.UserType != 2 {
+	//	app.Error(c, 500, errors.New("用户类型错误"), err.Error())
+	//	return
+	//}
+	//
+	//// 核销类型错误
+	//if inData.GroupBuyType != 1 && inData.GroupBuyType != 2 {
+	//	app.Error(c, 500, errors.New("核销类型错误"), err.Error())
+	//	return
+	//}
+
+	var pageSize = 10
+	var pageIndex = 1
+
+	if inData.PageSize != 0 {
+		pageSize = inData.PageSize
+	}
+	if inData.PageIndex != 0 {
+		pageIndex = inData.PageIndex
+	}
+
+	activeDrawLogList, count, err := sqlData.GetActivePayTransList(pageSize, pageIndex, inData.OpenId)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	for _, v := range activeDrawLogList {
+		var data models.GetGroupBuyPayReply
+		var activeSql shanghu.MerchantActiveConfig
+		var groupBuySql shanghu.MerchantActiveGroupBuy
+		var groupBuyProductSql shanghu.MerchantActiveGroupByProject
+		var groupBuyProductCancel shanghu.ActiveCancelLog
+		data.MerchantAmount = v.MerchantAmount.String()
+		data.Amount = v.Amount.String()
+		data.ClientAmount = v.ClientAmount.String()
+		data.PayTime = v.PayTime.Format(time.DateTime)
+
+		activeSql.ID = v.ActiveConfigID
+		activeInfo, err := activeSql.GetConfigInfoById()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		data.ActiveName = activeInfo.ActiveName
+		groupBuySql.ID = v.GroupBuyID
+		groupBuyInfo, err := groupBuySql.GetMerchantActiveGroupBuyById()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+
+		groupBuyProductSql.GroupBuyID = v.GroupBuyID
+		groupBuyProductList, _, err := groupBuyProductSql.GetGroupBuyProjectList()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		totalGroupBuyNum := 0
+		for _, v := range groupBuyProductList {
+			totalGroupBuyNum = totalGroupBuyNum + v.CancelNum
+		}
+
+		groupBuyProductCancel.ClientOpenID = inData.OpenId
+		groupBuyProductCancel.ActiveConfigID = v.ActiveConfigID
+		cancelNum := groupBuyProductCancel.GetActiveCancelNum()
+
+		data.GroupBuyName = groupBuyInfo.GroupBuyName
+		data.PayTime = v.PayTime.Format(time.DateTime)
+		data.TradeNo = v.ThirdTradeNo
+		data.TotalCancelNum = totalGroupBuyNum
+		data.PendingCancelNum = totalGroupBuyNum - cancelNum
+		data.Url = groupBuyInfo.GroupBuyUrl
+
+		outData = append(outData, data)
+	}
+	app.PageOK(c, outData, count, pageIndex, pageSize, app.Success)
+
+}
+
+// 拼团核销码
+func GroupBuyPayCode(c *gin.Context) {
+	var inData models.GroupBuyPayCodeRequest
+	var outData models.GroupBuyPayCodeReply
+	var payTransSql shanghu.ClientActivePayTrans
+	var groupBuyProductSql shanghu.MerchantActiveGroupByProject
+	var groupBuyProductCancel shanghu.ActiveCancelLog
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+	//校验核销次数
+	payTransSql.ThirdTradeNo = inData.TradeNo
+	payTransInfo, err := payTransSql.GetPayTransByThirdTradeNo()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	groupBuyProductSql.GroupBuyID = payTransInfo.GroupBuyID
+	groupBuyProductList, _, err := groupBuyProductSql.GetGroupBuyProjectList()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	totalGroupBuyNum := 0
+	for _, v := range groupBuyProductList {
+		totalGroupBuyNum = totalGroupBuyNum + v.CancelNum
+	}
+
+	groupBuyProductCancel.ClientOpenID = payTransInfo.ClientOpenID
+	groupBuyProductCancel.ActiveConfigID = payTransInfo.ActiveConfigID
+	cancelNum := groupBuyProductCancel.GetActiveCancelNum()
+
+	if totalGroupBuyNum <= cancelNum {
+		app.Error(c, 500, errors.New("核销次数用完"), "核销次数用完")
+		return
+	}
+
+	outData.Key = "GROU" + tools.MD5(inData.TradeNo+"zhangkun429@")
+	outData.TradeNo = inData.TradeNo
+
+	str, err := json.Marshal(&outData)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	qr, err := qrcode.Encode(string(str), qrcode.High, 200)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	encodedData := base64.StdEncoding.EncodeToString(qr)
+
+	app.OK(c, encodedData, app.Success)
+}
+
+// 拼团核销详情
+func GroupBuyCancelInfo(c *gin.Context) {
+	var inData models.GroupBuyCancelInfoRequest
+	var outData models.GroupBuyCancelInfoReply
+	var sqlData shanghu.ClientActivePayTrans
+	var activeConfigSql shanghu.MerchantActiveConfig
+	var groupBuySql shanghu.MerchantActiveGroupBuy
+	var groupBuyProjectSql shanghu.MerchantActiveGroupByProject
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	key := "GROU" + tools.MD5(inData.TradeNo+"zhangkun429@")
+	if inData.Key != key {
+		app.Error(c, 500, errors.New("数据错误"), "数据错误")
+		return
+	}
+	sqlData.ThirdTradeNo = inData.TradeNo
+	payTransInfo, err := sqlData.GetPayTransByThirdTradeNo()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	//校验分账类型
+	//if payTransInfo.AccountStatus != shanghu.ClientActivePayTransAccountStatusUnSettle && payTransInfo.AccountStatus != shanghu.ClientActivePayTransAccountStatusSettleFail {
+	//	app.Error(c, 500, errors.New("核销已完成"), "核销已完成")
+	//	return
+	//}
+	// 校验支付类型
+	if payTransInfo.Status != shanghu.ClientActivePayTransStatusPaySuccess {
+		app.Error(c, 500, errors.New("未支付交易不准核销"), "未支付交易不准核销")
+		return
+	}
+
+	// 返回拼团信息
+	outData.Amount = payTransInfo.Amount.String()
+	outData.TradeNo = inData.TradeNo
+	outData.PayTime = payTransInfo.PayTime.Format(time.DateTime)
+	outData.MerchantAmount = payTransInfo.MerchantAmount.String()
+	outData.ClientAmount = payTransInfo.ClientAmount.String()
+
+	activeConfigSql.ID = payTransInfo.ActiveConfigID
+	activeConfigInfo, err := activeConfigSql.GetConfigInfoById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	outData.ActiveName = activeConfigInfo.ActiveName
+	groupBuySql.ID = payTransInfo.GroupBuyID
+	groupBuyInfo, err := groupBuySql.GetMerchantActiveGroupBuyById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	outData.GroupBuyName = groupBuyInfo.GroupBuyName
+	groupBuyProjectSql.GroupBuyID = payTransInfo.GroupBuyID
+	project, _, err := groupBuyProjectSql.GetGroupBuyProjectList()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	for _, v := range project {
+		var projectInfo models.CancelGroupBuyProject
+		var activeCancelSql shanghu.ActiveCancelLog
+		activeCancelSql.ClientOpenID = payTransInfo.ClientOpenID
+		activeCancelSql.ActiveConfigID = payTransInfo.ActiveConfigID
+		activeCancelSql.GroupByProjectID = v.ID
+		num := activeCancelSql.GetActiveCancelNumByProjectID()
+		fmt.Println("num = ", num)
+
+		projectInfo.ProjectName = v.ProjectName
+		projectInfo.TotalCancelNum = v.CancelNum
+		projectInfo.PendingCancelNum = v.CancelNum - num
+		projectInfo.ID = v.ID
+		outData.GroupBuyProject = append(outData.GroupBuyProject, projectInfo)
+	}
+
+	app.OK(c, outData, app.Success)
+}
+
+// 拼团核销
+func GroupBuyCancel(c *gin.Context) {
+	var inData models.GroupBuyCancelRequest
+	var payTrans shanghu.ClientActivePayTrans
+	var activeCancelLogList []shanghu.ActiveCancelLog
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	key := "GROU" + tools.MD5(inData.TradeNo+"zhangkun429@")
+	if inData.Key != key {
+		app.Error(c, 500, errors.New("数据错误"), "数据错误")
+		return
+	}
+
+	//查交易
+	payTrans.ThirdTradeNo = inData.TradeNo
+
+	transInfo, err := payTrans.GetPayTransByThirdTradeNo()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	//校验分账类型
+	//if transInfo.AccountStatus != shanghu.ClientActivePayTransAccountStatusUnSettle && transInfo.AccountStatus != shanghu.ClientActivePayTransAccountStatusSettleFail {
+	//	app.Error(c, 500, errors.New("核销已完成"), "核销已完成")
+	//	return
+	//}
+
+	// 校验支付类型
+	if transInfo.Status != shanghu.ClientActivePayTransStatusPaySuccess {
+		app.Error(c, 500, errors.New("未支付交易不准核销"), "未支付交易不准核销")
+		return
+	}
+
+	if transInfo.AccountStatus == shanghu.ClientActivePayTransAccountStatusSettlePending {
+		app.Error(c, 500, errors.New("正在分账中"), "正在分账中")
+		return
+	}
+
+	//查看核销次数
+	//是否可以核销,默认不可以核销,只要有一个可以核销就为true
+	isCancel := false
+	for _, v := range inData.GroupBuyProject {
+		var projectSql shanghu.MerchantActiveGroupByProject
+		var activeCancel shanghu.ActiveCancelLog
+
+		projectSql.ID = v.ID
+		projectInfo, err := projectSql.GetMerchantActiveGroupBuyProjectByID()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+
+		activeCancel.ClientOpenID = transInfo.ClientOpenID
+		activeCancel.ActiveConfigID = transInfo.ActiveConfigID
+		activeCancel.GroupByProjectID = v.ID
+
+		cancelNum := activeCancel.GetActiveCancelNumByProjectID()
+		fmt.Println("cancelNum = ", cancelNum)
+		fmt.Println("projectInfo.CancelNum = ", projectInfo.CancelNum)
+		fmt.Println("v.CancelNum = ", v.CancelNum)
+
+		if projectInfo.CancelNum >= cancelNum+v.CancelNum && v.CancelNum > 0 {
+			isCancel = true
+			for i := 0; i < v.CancelNum; i++ {
+				var activeCancelLogInfo shanghu.ActiveCancelLog
+				activeCancelLogInfo.ActiveConfigID = transInfo.ActiveConfigID
+				activeCancelLogInfo.ClientOpenID = transInfo.ClientOpenID
+				activeCancelLogInfo.MerchantOpenID = inData.OpenId
+				activeCancelLogInfo.GroupByProjectID = v.ID
+				activeCancelLogInfo.CreatedAt = time.Now()
+				activeCancelLogInfo.UpdatedAt = time.Now()
+
+				activeCancelLogList = append(activeCancelLogList, activeCancelLogInfo)
+			}
+		}
+
+	}
+
+	if !isCancel {
+		app.Error(c, 500, errors.New("核销次数不够"), "核销次数不够")
+		return
+	}
+
+	// 分账
+	if transInfo.AccountStatus == shanghu.ClientActivePayTransAccountStatusSettleSuccess {
+		//不需要分账
+		var activeCancel shanghu.ActiveCancelLog
+		err = activeCancel.TXActiveCancelLogCreate(activeCancelLogList)
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+	} else { // 需要分账
+		// 分账中
+		fmt.Println("分账中...")
+		payTrans.ID = transInfo.ID
+		payTrans.AccountStatus = shanghu.ClientActivePayTransAccountStatusSettlePending
+		err = payTrans.UpdateAccountStatusByID()
+		if err != nil {
+			dataErr := make(map[string]interface{})
+			dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+			dataErr["account_err_log"] = "修改分账中失败:" + err.Error()                           //分账失败日志
+			dataErr["updated_at"] = time.Now()
+			_ = payTrans.UpdateById(dataErr)
+
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+
+		//校验是否被分过,分过后不再分账
+		var merchantAccountLog shanghu.MerchantAccountLog
+		merchantAccountLog.PayTransId = transInfo.ID
+		merchantAccountLog.TransType = shanghu.MerchantAccountLogTransTypeGroupBuy
+		num := merchantAccountLog.GetAccountLogNum()
+		if num > 0 { //交易已经分过账
+			dataErr := make(map[string]interface{})
+			dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+			dataErr["account_err_log"] = "交易已分过账"                                           //分账失败日志
+			dataErr["updated_at"] = time.Now()
+			_ = payTrans.UpdateById(dataErr)
+			app.Error(c, 500, errors.New("交易已分过账"), "交易已分过账")
+			return
+		}
+		//分账校验账号
+		var merchantAccount shanghu.MerchantAccount
+		merchantAccount.MerchantOpenID = transInfo.MerchantOpenID
+		merchantAccountInfo, err := merchantAccount.GetMerchantAccount()
+		if err != nil && err.Error() != "record not found" {
+			dataErr := make(map[string]interface{})
+			dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+			dataErr["account_err_log"] = "商家分账校验账号:" + err.Error()                          //分账失败日志
+			dataErr["updated_at"] = time.Now()
+			_ = payTrans.UpdateById(dataErr)
+
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		if merchantAccountInfo.ID == 0 { //需要创建新账号
+			merchantAccount.MerchantOpenID = transInfo.MerchantOpenID
+			merchantAccount.Version = 1
+			merchantAccount.CreatedAt = time.Now()
+			merchantAccount.UpdatedAt = time.Now()
+			merchantAccount, err = merchantAccount.Create()
+			if err != nil {
+
+				dataErr := make(map[string]interface{})
+				dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+				dataErr["account_err_log"] = "创建新的商家账号:" + err.Error()                          //分账失败日志
+				dataErr["updated_at"] = time.Now()
+				_ = payTrans.UpdateById(dataErr)
+
+				app.Error(c, 500, err, err.Error())
+				return
+			}
+
+		}
+		var clientAccount shanghu.ActiveClientAccount
+		if transInfo.InvitationCode != shanghu.YuanShiMa { //校验c端客户
+			var activeUser shanghu.ActiveUser
+			activeUser.Code = transInfo.InvitationCode
+			activeUserInfo, err := activeUser.GetUserInfoByCode()
+			if err != nil {
+
+				dataErr := make(map[string]interface{})
+				dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail         //分账失败
+				dataErr["account_err_log"] = "根据Code获取c端客户信息:" + transInfo.InvitationCode + err.Error() //分账失败日志
+				dataErr["updated_at"] = time.Now()
+				_ = payTrans.UpdateById(dataErr)
+
+				app.Error(c, 500, err, err.Error())
+				return
+			}
+			clientAccount.ClientOpenID = activeUserInfo.OpenID
+			clientAccountInfo, err := clientAccount.GetActiveAccount()
+			if err != nil && err.Error() != "record not found" {
+
+				dataErr := make(map[string]interface{})
+				dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+				dataErr["account_err_log"] = "获取c端客户账户:" + err.Error()                          //分账失败日志
+				dataErr["updated_at"] = time.Now()
+				_ = payTrans.UpdateById(dataErr)
+
+				app.Error(c, 500, err, err.Error())
+				return
+			}
+
+			if clientAccountInfo.ID == 0 { //需要创建新账号
+				clientAccount.ClientOpenID = activeUserInfo.OpenID
+				clientAccount.Version = 1
+				clientAccount.CreatedAt = time.Now()
+				clientAccount.UpdatedAt = time.Now()
+				clientAccount, err = clientAccount.Create()
+				if err != nil {
+
+					dataErr := make(map[string]interface{})
+					dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+					dataErr["account_err_log"] = "创建c端客户:" + err.Error()                            //分账失败日志
+					dataErr["updated_at"] = time.Now()
+					_ = payTrans.UpdateById(dataErr)
+
+					app.Error(c, 500, err, err.Error())
+					return
+				}
+
+			}
+
+		}
+
+		//分账 根据merchant-openid + activeUserInfo.openid 进行分账
+		//商家分多少钱,客户分多少钱
+		err = merchantAccount.ActiveCancelSettle(activeCancelLogList, merchantAccount, clientAccount, transInfo)
+		if err != nil {
+
+			dataErr := make(map[string]interface{})
+			dataErr["account_status"] = shanghu.ClientActivePayTransAccountStatusSettleFail //分账失败
+			dataErr["account_err_log"] = "分账失败:" + err.Error()                              //分账失败日志
+			dataErr["updated_at"] = time.Now()
+			_ = payTrans.UpdateById(dataErr)
+
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+
+	}
+	app.OK(c, nil, app.Success)
+
+}

+ 34 - 1
apis/shanghu/base.go

@@ -1,6 +1,8 @@
 package shanghu
 
-import "github.com/gin-gonic/gin"
+import (
+	"github.com/gin-gonic/gin"
+)
 
 func InitShangHuRouter(engine *gin.RouterGroup) {
 	v1 := engine.Group("v1")
@@ -69,4 +71,35 @@ func InitShangHuRouter(engine *gin.RouterGroup) {
 		recharge.POST("/merchant/cancel/log", GetMerchantRechargeLog)               // 商家核销记录
 		recharge.POST("/client/cancel/log", GetClientRechargeLog)                   // c端核销记录
 	}
+
+	activeV1 := engine.Group("activeV1")
+	{
+		activeV1.POST("/active/draw/product/create", DrawProductCreate)     //抽奖奖品创建
+		activeV1.POST("/active/group/buy/create", GroupBuyCreate)           //拼团创建
+		activeV1.POST("/active/config/create", ActiveConfigCreate)          //创建活动
+		activeV1.POST("/active/config/list", ActiveConfigList)              //活动列表
+		activeV1.POST("/active/config/info", ActiveConfigInfo)              //活动详情
+		activeV1.POST("/active/draw/product/list", DrawProductList)         //奖品列表
+		activeV1.POST("/active/group/buy/list", GroupBuyList)               //拼团列表
+		activeV1.POST("/active/draw", Draw)                                 //抽奖
+		activeV1.POST("/active/draw/list", DrawLog)                         //中奖列表
+		activeV1.POST("/draw/verification/code", DrawLogVerificationCode)   //奖品核销码                                           //中奖核销码
+		activeV1.POST("/draw/cancel", DrawCancel)                           //核销 奖品与拼团
+		activeV1.POST("/draw/info", DrawCancelInfo)                         //奖品详情
+		activeV1.POST("/active/config/whxy", UpdateActiveConfigWHXY)        //二维码坐标
+		activeV1.POST("/active/qr", GetClientActiveQR)                      //获取二维码
+		activeV1.POST("/active/unified/order", GroupByUnifiedOrder)         //拼团购买
+		activeV1.POST("/active/pay/callback", ActivePayCallBack)            //支付回调
+		activeV1.POST("/active/draw/num", InvitedDrawNum)                   //邀请次数
+		activeV1.POST("/client/user/set", ActiveOpenIdSet)                  //活动 创建用户
+		activeV1.POST("/active/pending.cancel/amount", PendingCancelAmount) //待核销金额  从交易记录里面求和, 扫码后核销,进入可提现余额
+		activeV1.POST("/active/group.buy/cancel", GroupBuyCancel)           //拼团核销&分账,只要核销了一件就分账。根据id核销
+		activeV1.POST("/active/group.buy.cancel/info", GroupBuyCancelInfo)  //核销详情
+		activeV1.POST("/active/group.buy/code", GroupBuyPayCode)            //拼团核销码
+		activeV1.POST("/active/group.buy/pay", GetGroupBuyPayList)          //购买拼团列表
+		activeV1.POST("/active/draw/count", ActiveDrawCount)                //邀请客户数量统计
+		activeV1.POST("/client/user/info", GetActiveUserInfo)               //client 用户信息
+		activeV1.POST("/active/cash/out", ActiveCashOut)                    //c端提现
+		activeV1.POST("/active/client/amount", GetActiveAmount)             //余额
+	}
 }

+ 199 - 0
apis/shanghu/client.active.draw.log.go

@@ -0,0 +1,199 @@
+package shanghu
+
+import (
+	"duoduo/apis/shanghu/models"
+	"duoduo/models/shanghu"
+	"duoduo/tools"
+	"duoduo/tools/app"
+	"encoding/base64"
+	"encoding/json"
+	"errors"
+	"github.com/gin-gonic/gin"
+	"github.com/skip2/go-qrcode"
+	"strconv"
+	"time"
+)
+
+func DrawLog(c *gin.Context) {
+	var inData models.ClientDrawLogRequest
+	var sqlData shanghu.ClientActiveDrawLog
+	var outData []models.ClientDrawLogReply
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	var pageSize = 10
+	var pageIndex = 1
+
+	if inData.PageSize != 0 {
+		pageSize = inData.PageSize
+	}
+	if inData.PageIndex != 0 {
+		pageIndex = inData.PageIndex
+	}
+
+	sqlData.ClientOpenID = inData.ClientOpenID
+	activeDrawLogList, count, err := sqlData.GetClientActiveDrawLogListByOpenId(pageSize, pageIndex)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	for _, v := range activeDrawLogList {
+		//查询商品名称
+		var drawProduct shanghu.MerchantActiveDrawProduct
+		var drawLog models.ClientDrawLogReply
+		drawProduct.ID = v.DrawProductID
+		drawProductInfo, err := drawProduct.GetDrawProductById()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+		drawLog.DrawProductName = drawProductInfo.DrawProductName
+		drawLog.IsPrize = v.IsPrize
+		drawLog.Id = v.ID
+		drawLog.Url = drawProductInfo.DrawUrl
+		drawLog.DrawTime = v.CreatedAt.Format(time.DateTime)
+		outData = append(outData, drawLog)
+	}
+
+	app.PageOK(c, outData, count, pageIndex, pageSize, app.Success)
+
+}
+
+func DrawLogVerificationCode(c *gin.Context) {
+	var inData models.DrawLogVerificationCodeRequest
+	var outData models.DrawLogVerificationCodeReply
+	var sqlData shanghu.ClientActiveDrawLog
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	sqlData.ID = inData.DrawLogId
+	sqlData.ClientOpenID = inData.OpenId
+	drawLog, err := sqlData.GetClientActiveDrawLogListByOpenIdAndId()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	if drawLog.IsPrize == models.NotWon {
+		app.Error(c, 500, errors.New("不需要兑奖"), "不需要兑奖")
+		return
+	}
+
+	outData.Key = "DRAW" + tools.MD5(strconv.FormatInt(inData.DrawLogId, 10)+"zhangkun429@")
+	outData.DrawLogId = inData.DrawLogId
+
+	str, err := json.Marshal(&outData)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	qr, err := qrcode.Encode(string(str), qrcode.High, 200)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	encodedData := base64.StdEncoding.EncodeToString(qr)
+
+	app.OK(c, encodedData, app.Success)
+}
+
+func DrawCancel(c *gin.Context) {
+	var inData models.DrawCancelRequest
+	var sqlData shanghu.ClientActiveDrawLog
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	key := "DRAW" + tools.MD5(strconv.FormatInt(inData.DrawLogId, 10)+"zhangkun429@")
+	if key != inData.Key {
+		app.Error(c, 500, errors.New("数据错误"), "数据错误")
+		return
+	}
+
+	sqlData.ID = inData.DrawLogId
+	drawLog, err := sqlData.GetClientActiveDrawLogListById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	if drawLog.IsPrize != models.NotClaimed {
+		app.Error(c, 500, errors.New("不允许兑奖"), "不允许兑奖")
+		return
+	} else {
+		drawLog.IsPrize = models.Claimed
+		err = drawLog.UpdateDrawPrize()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+	}
+
+	app.OK(c, nil, app.Success)
+
+}
+
+func DrawCancelInfo(c *gin.Context) {
+	var inData models.DrawCancelInfoRequest
+	var sqlData shanghu.ClientActiveDrawLog
+	var activeConfigSql shanghu.MerchantActiveConfig
+	var drawProductSql shanghu.MerchantActiveDrawProduct
+	var outData models.DrawCancelInfoReply
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	key := "DRAW" + tools.MD5(strconv.FormatInt(inData.DrawLogId, 10)+"zhangkun429@")
+	if key != inData.Key {
+		app.Error(c, 500, errors.New("数据错误"), "数据错误")
+		return
+	}
+
+	sqlData.ID = inData.DrawLogId
+	drawLog, err := sqlData.GetClientActiveDrawLogListById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	if drawLog.IsPrize != 2 {
+		app.Error(c, 500, errors.New("未中奖或已兑奖"), "未中奖或已兑奖")
+		return
+	}
+
+	activeConfigSql.ID = drawLog.ActiveConfigID
+	activeInfo, err := activeConfigSql.GetConfigInfoById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+	drawProductSql.ID = drawLog.DrawProductID
+	drawProduct, err := drawProductSql.GetDrawProductById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	outData.DrawUrl = drawProduct.DrawUrl
+	outData.DrawProductName = drawProduct.DrawProductName
+	outData.ActiveConfigName = activeInfo.ActiveName
+	outData.DrawLogId = inData.DrawLogId
+	outData.DrawTime = drawLog.CreatedAt.Format(time.DateTime)
+
+	app.OK(c, outData, app.Success)
+
+}

+ 100 - 0
apis/shanghu/client.active.draw.num.go

@@ -0,0 +1,100 @@
+package shanghu
+
+import (
+	"duoduo/apis/shanghu/models"
+	"duoduo/models/shanghu"
+	"duoduo/tools/app"
+	"github.com/gin-gonic/gin"
+	"time"
+)
+
+// 增加邀请次数
+func InvitedDrawNum(c *gin.Context) {
+	var inData models.InvitedDrawNumRequest
+	var sqlData shanghu.ClientActiveDrawNum
+	var clientSql shanghu.ActiveUser
+	var activeSql shanghu.MerchantActiveConfig
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	if inData.InvitedCode == "yuanshima" {
+		app.OK(c, nil, app.Success)
+		return
+	}
+
+	//查询活动没有抽奖跳过
+	activeSql.ID = inData.ActiveConfigId
+	activeConfigInfo, err := activeSql.GetConfigInfoById()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	if activeConfigInfo.DrawMode == 0 { //不抽奖
+		app.OK(c, nil, app.Success)
+		return
+	}
+
+	clientSql.Code = inData.InvitedCode
+	clientInfo, err := clientSql.GetUserInfoByCode()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	sqlData.ClientOpenID = clientInfo.OpenID
+	sqlData.ActiveConfigID = inData.ActiveConfigId
+	sqlData.ClientOpenIDInvited = inData.OpenId
+	sqlData.CreatedAt = time.Now()
+	sqlData.UpdatedAt = time.Now()
+
+	//校验是否重复打开 同一个用户id 邀请同一个id 同一个活动id
+	count, err := sqlData.GetClientDrawNum()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	//已被邀请过
+	if count > 0 {
+		app.OK(c, nil, app.Success)
+		return
+	}
+
+	_, err = sqlData.Create()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	app.OK(c, nil, app.Success)
+
+}
+
+func ActiveDrawCount(c *gin.Context) {
+	var inData models.ActiveDrawCountRequest
+	var sqlData shanghu.ClientActiveDrawNum
+	var outData models.ActiveDrawCountReply
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	sqlData.ClientOpenID = inData.OpenId
+	sqlData.ActiveConfigID = inData.ActiveConfigId
+	count, err := sqlData.GetClientDrawByOpenID()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	outData.Num = count
+	app.OK(c, outData, app.Success)
+
+}

+ 961 - 0
apis/shanghu/merchant.active.config.go

@@ -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
+		}
+		//校验总概率 总概率相加不能大于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)
+
+}

+ 111 - 0
apis/shanghu/merchant.active.draw.product.go

@@ -0,0 +1,111 @@
+package shanghu
+
+import (
+	"duoduo/apis/shanghu/models"
+	"duoduo/models/shanghu"
+	"duoduo/tools/app"
+	"errors"
+	"github.com/gin-gonic/gin"
+	"time"
+)
+
+// 中奖商品与库存
+func DrawProductCreate(c *gin.Context) {
+	var inData models.CreateDrawProductRequest
+	var sqlData shanghu.MerchantActiveDrawProduct
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	if inData.DrawProductName == "" || inData.DrawUrl == "" || inData.TotalStock <= 0 {
+		app.Error(c, 500, errors.New("必填参数缺失"), "必填参数缺失")
+		return
+	}
+
+	if inData.DrawOdds <= 0 {
+		app.Error(c, 500, errors.New("中奖率需要大于0"), "中奖率需要大于0")
+		return
+	}
+
+	if inData.DrawOdds > 100 {
+		app.Error(c, 500, errors.New("中奖率不能大于100"), "中奖率不能大于100")
+		return
+
+	}
+
+	//if !inData.DrawOdds.GreaterThan(decimal.NewFromFloat(0)) {
+	//	app.Error(c, 500, errors.New("中奖率需要大于0"), "中奖率需要大于0")
+	//	return
+	//}
+
+	sqlData.CreatedAt = time.Now()
+	sqlData.UpdatedAt = time.Now()
+	sqlData.DrawOdds = inData.DrawOdds
+	sqlData.TotalStock = inData.TotalStock
+	sqlData.MerchantOpenID = inData.MerchantOpenID
+	sqlData.DrawProductName = inData.DrawProductName
+	sqlData.Stock = inData.TotalStock
+	sqlData.DrawUrl = inData.DrawUrl
+	sqlData.Version = 0
+	sqlData.IsPrize = inData.IsPrize
+
+	_, err = sqlData.Create()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	app.OK(c, nil, app.Success)
+}
+
+// 奖品商品列表
+func DrawProductList(c *gin.Context) {
+	var inData models.DrawProductListRequest
+	var sqlData shanghu.MerchantActiveDrawProduct
+	var outData []models.DrawProductListReply
+
+	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
+	}
+
+	drawProductList, count, err := sqlData.GetDrawProductListByOpenId(pageSize, pageIndex)
+
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	for _, v := range drawProductList {
+		var drawProductInfo models.DrawProductListReply
+		drawProductInfo.DrawProductName = v.DrawProductName
+		drawProductInfo.DrawOdds = v.DrawOdds
+		drawProductInfo.MerchantOpenID = v.MerchantOpenID
+		drawProductInfo.DrawUrl = v.DrawUrl
+		drawProductInfo.ActiveConfigID = v.ActiveConfigID
+		drawProductInfo.ID = v.ID
+		drawProductInfo.Stock = v.Stock
+		drawProductInfo.TotalStock = v.TotalStock
+		drawProductInfo.IsPrize = v.IsPrize
+
+		outData = append(outData, drawProductInfo)
+	}
+
+	app.PageOK(c, outData, count, pageIndex, pageSize, app.Success)
+
+}

+ 132 - 0
apis/shanghu/merchant.active.group.buy.go

@@ -0,0 +1,132 @@
+package shanghu
+
+import (
+	"duoduo/apis/shanghu/models"
+	"duoduo/models/shanghu"
+	"duoduo/tools/app"
+	"github.com/gin-gonic/gin"
+	"time"
+)
+
+// 拼团与商品一起创建
+func GroupBuyCreate(c *gin.Context) {
+	var inData models.CreateGroupBuyRequest
+	var sqlData shanghu.MerchantActiveGroupBuy
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	sqlData.CreatedAt = time.Now()
+	sqlData.UpdatedAt = time.Now()
+	sqlData.MerchantOpenID = inData.MerchantOpenId
+	sqlData.GroupBuyOneNum = inData.GroupBuyOneNum
+	sqlData.GroupBuyOnePrice = inData.GroupBuyOnePrice
+	sqlData.GroupBuyName = inData.GroupBuyName
+	sqlData.GroupBuyMode = inData.GroupBuyMode
+	sqlData.OriginalPrice = inData.OriginalPrice
+	sqlData.GroupBuyThreePrice = inData.GroupBuyThreePrice
+	sqlData.GroupBuyThreeNum = inData.GroupBuyThreeNum
+	sqlData.GroupBuyTwoPrice = inData.GroupBuyTwoPrice
+	sqlData.GroupBuyTwoNum = inData.GroupBuyTwoNum
+	sqlData.GroupBuyFourPrice = inData.GroupBuyFourPrice
+	sqlData.GroupBuyFourNum = inData.GroupBuyFourNum
+	sqlData.GroupBuyUrl = inData.GroupBuyUrl
+	sqlData.RebateRate = inData.RebateRate
+
+	groupBuyData, err := sqlData.Create()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	for _, v := range inData.GroupBuyProject {
+		projectSql := shanghu.MerchantActiveGroupByProject{
+			GroupBuyID:     groupBuyData.ID,
+			ProjectName:    v.ProjectName,
+			CancelNum:      v.CancelNum,
+			MerchantOpenID: inData.MerchantOpenId,
+			CreatedAt:      time.Now(),
+			UpdatedAt:      time.Now(),
+		}
+		_, err := projectSql.Create()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+	}
+
+	app.OK(c, nil, app.Success)
+
+}
+
+func GroupBuyList(c *gin.Context) {
+	var inData models.GroupBuyListRequest
+	var sqlData shanghu.MerchantActiveGroupBuy
+	var outData []models.GroupBuyListReply
+
+	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
+	}
+
+	groupBuyInfoList, count, err := sqlData.GetGroupBuyListByOpenId(pageSize, pageIndex)
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	for _, v := range groupBuyInfoList {
+		var groupBuyInfo models.GroupBuyListReply
+		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.ID = v.ID
+
+		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.CreateGroupBuyProject
+			groupBuyProjectInfo.ProjectName = v.ProjectName
+			groupBuyProjectInfo.CancelNum = v.CancelNum
+			groupBuyInfo.GroupBuyProject = append(groupBuyInfo.GroupBuyProject, groupBuyProjectInfo)
+		}
+		outData = append(outData, groupBuyInfo)
+
+	}
+
+	app.PageOK(c, outData, count, pageIndex, pageSize, app.Success)
+
+}

+ 78 - 0
apis/shanghu/merchant.user.go

@@ -124,6 +124,62 @@ func ClientOpenIdSet(c *gin.Context) {
 
 }
 
+// 注册用户
+func ActiveOpenIdSet(c *gin.Context) {
+	var inData models.OpenIdSetRequest
+	var outData models.OpenIdSetResponse
+	var sqlData shanghu.ActiveUser
+	//var sql1 bizhi.User
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	url := fmt.Sprintf("https://api.weixin.qq.com/sns/jscode2session?appid=wx43e320d3ffaa4d7b&secret=97d811cde197515ed03b7c7a6e24d4e8&js_code=%s&grant_type=authorization_code", inData.Code)
+
+	val, err := pdd.DuoDuoGet(url)
+	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.Errcode != 0 {
+		app.Error(c, outData.Errcode, err, outData.Errmsg)
+		return
+	}
+	//查询数据
+	sqlData.OpenID = outData.OpenId
+	num := sqlData.GetNum()
+	if num == 0 {
+		//创建用户
+		sqlData.CreatedAt = time.Now()
+		sqlData.UpdatedAt = time.Now()
+		//校验唯一性
+		for _, v := range common.Example(6, 10) {
+			sqlData.Code = v
+			if sqlData.GetCodeNum() <= 0 {
+				break
+			}
+		}
+
+		_, err = sqlData.Create()
+		if err != nil {
+			app.Error(c, 500, err, err.Error())
+			return
+		}
+	}
+
+	app.OK(c, outData, app.Success)
+
+}
+
 func GetUserInfo(c *gin.Context) {
 	var inData models.GetUserInfoRequest
 	var sqlData shanghu.MerchantUser
@@ -168,6 +224,28 @@ func ClientGetUserInfo(c *gin.Context) {
 
 }
 
+func GetActiveUserInfo(c *gin.Context) {
+	var inData models.GetUserInfoRequest
+	var sqlData shanghu.ActiveUser
+
+	err := c.ShouldBindJSON(&inData)
+	if err != nil {
+		app.Error(c, 400, err, err.Error())
+		return
+	}
+
+	//查询数据
+	sqlData.OpenID = inData.OpenId
+	userInfo, err := sqlData.GetUserInfo()
+	if err != nil {
+		app.Error(c, 500, err, err.Error())
+		return
+	}
+
+	app.OK(c, userInfo, app.Success)
+
+}
+
 func MerchantUserCode(c *gin.Context) {
 	var inData models.MerchantUserCodeRequest
 	var sqlData shanghu.MerchantUser

+ 167 - 0
apis/shanghu/models/active.config.go

@@ -0,0 +1,167 @@
+package models
+
+import "github.com/shopspring/decimal"
+
+type CreateActiveConfigRequest struct {
+	MerchantOpenID    string  `json:"merchant_open_id"`
+	DrawOneBiZhong    int64   `json:"draw_one_bi_zhong"`
+	GroupBuyUrl       string  `json:"group_buy_url"`
+	DrawId            []int64 `json:"draw_id"`
+	GroupBuyId        []int64 `json:"group_buy_id"`
+	GroupBuyMode      int     `json:"group_buy_mode"`      // 0-不开团 1-虚拟开团 2-真实开团
+	DrawMode          int     `json:"draw_mode"`           // 抽奖模式 0-不抽奖,1-盲盒
+	ActivityEndTime   string  `json:"activity_end_time"`   // 活动结束时间
+	ActivityStartTime string  `json:"activity_start_time"` // 活动开始时间
+	ActiveName        string  `json:"active_name"`         // 活动名称
+	BackgroundImage   string  `json:"background_image"`    // 海报
+}
+
+type ActiveConfigRequest struct {
+	ActiveConfigId int64  `json:"active_config_id"`
+	MerchantOpenID string `json:"merchant_open_id"`
+	ClientOpenID   string `json:"client_open_id"`
+}
+
+type ActiveConfigReply struct {
+	MerchantName      string             `json:"merchant_name"`       //商家名称
+	DrawOneBiZhong    int64              `json:"draw_one_bi_zhong"`   //
+	GroupBuyUrl       string             `json:"group_buy_url"`       //
+	GroupBuyMode      int                `json:"group_buy_mode"`      // 0-不开团 1-虚拟开团 2-真实开团
+	DrawMode          int                `json:"draw_mode"`           //抽奖模式 0-不抽奖,1-盲盒
+	ActivityEndTime   string             `json:"activity_end_time"`   //活动结束时间
+	ActivityStartTime string             `json:"activity_start_time"` //活动开始时间
+	ActiveName        string             `json:"active_name"`         //活动名称
+	BackgroundImage   string             `json:"background_image"`    // 海报
+	DrawNum           int                `json:"draw_num"`            //抽奖次数
+	DrawProduct       []DrawProduct      `json:"draw_product"`        //中奖商品
+	DrawGroupBuy      []DrawGroupBuyInfo `json:"draw_group_buy"`      //活动拼团
+}
+
+type DrawProduct struct {
+	DrawProductName string `json:"draw_product_name"` // 抽奖名称
+	DrawOdds        int    `json:"draw_odds"`         // 中奖概率
+	Stock           int    `json:"stock"`             // 剩余库存
+	IsPrize         bool   `json:"is_prize"`          // 是否需要兑奖  谢谢惠顾不需要兑奖
+	DrawUrl         string `json:"draw_url"`          // 中奖图片
+	TotalStock      int    `json:"total_stock"`       // 总库存
+
+}
+
+type DrawGroupBuy struct {
+	GroupBuyName       string            `json:"group_buy_name"`        // 拼团名
+	GroupBuyMode       int               `json:"group_buy_mode"`        // 拼团模式 1-真实拼团 2-虚拟拼团
+	MerchantOpenID     string            `json:"merchant_open_id"`      //
+	OriginalPrice      decimal.Decimal   `json:"original_price"`        // 原价
+	GroupBuyOneNum     int               `json:"group_buy_one_num"`     // 人数
+	GroupBuyOnePrice   decimal.Decimal   `json:"group_buy_one_price"`   // 价格
+	GroupBuyTwoNum     int               `json:"group_buy_two_num"`     // 人数
+	GroupBuyTwoPrice   decimal.Decimal   `json:"group_buy_two_price"`   // 价格
+	GroupBuyThreeNum   int               `json:"group_buy_three_num"`   //
+	GroupBuyThreePrice decimal.Decimal   `json:"group_buy_three_price"` //
+	GroupBuyFourNum    int               `json:"group_buy_four_num"`    //
+	GroupBuyFourPrice  decimal.Decimal   `json:"group_buy_four_price"`  //
+	GroupBuyUrl        string            `json:"group_buy_url"`         // 图片
+	ActivityEndTime    string            `json:"activity_end_time"`     // 活动结束时间
+	ActivityStartTime  string            `json:"activity_start_time"`   // 活动开始时间
+	RebateRate         int               `json:"rebate_rate"`           // 佣金比例
+	MaxRebatePrice     decimal.Decimal   `json:"max_rebate_price"`      //最大佣金
+	GroupBuyProject    []GroupBuyProject `json:"group_buy_project"`
+}
+
+type GroupBuyProject struct {
+	ProjectName string `json:"project_name"`
+	CancelNum   int    `json:"cancel_num"`
+}
+
+type DrawGroupBuyInfo struct {
+	GroupBuyId         int64             `json:"group_buy_id"`          //拼团id
+	GroupBuyName       string            `json:"group_buy_name"`        // 拼团名
+	GroupBuyMode       int               `json:"group_buy_mode"`        // 拼团模式 1-真实拼团 2-虚拟拼团
+	MerchantOpenID     string            `json:"merchant_open_id"`      //
+	OriginalPrice      decimal.Decimal   `json:"original_price"`        // 原价
+	GroupBuyOneNum     int               `json:"group_buy_one_num"`     // 人数
+	GroupBuyOnePrice   decimal.Decimal   `json:"group_buy_one_price"`   // 价格
+	GroupBuyTwoNum     int               `json:"group_buy_two_num"`     // 人数
+	GroupBuyTwoPrice   decimal.Decimal   `json:"group_buy_two_price"`   // 价格
+	GroupBuyThreeNum   int               `json:"group_buy_three_num"`   //
+	GroupBuyThreePrice decimal.Decimal   `json:"group_buy_three_price"` //
+	GroupBuyFourNum    int               `json:"group_buy_four_num"`    //
+	GroupBuyFourPrice  decimal.Decimal   `json:"group_buy_four_price"`  //
+	GroupBuyUrl        string            `json:"group_buy_url"`         // 图片
+	ActivityEndTime    string            `json:"activity_end_time"`     // 活动结束时间
+	ActivityStartTime  string            `json:"activity_start_time"`   // 活动开始时间
+	RebateRate         int               `json:"rebate_rate"`           // 佣金比例
+	MaxRebatePrice     decimal.Decimal   `json:"max_rebate_price"`      //最大佣金
+	GroupBuyProject    []GroupBuyProject `json:"group_buy_project"`
+}
+
+type ActiveConfigListRequest struct {
+	OpenId    string `json:"open_id"`
+	PageSize  int    `json:"page_size"`
+	PageIndex int    `json:"page_index"`
+}
+
+type ActiveConfigListReply struct {
+	ID            int64  `json:"id"`             //id
+	ActiveName    string `json:"active_name"`    // 活动名称
+	ActivityEnd   string `json:"activity_end"`   // 活动结束时间
+	ActivityStart string `json:"activity_start"` //活动开始时间
+	CreatedAt     string `json:"created_at"`     //创建时间
+}
+
+// 抽奖
+type DrawRequest struct {
+	ClientOpenID   string `json:"client_open_id"`   //open-id
+	ActiveConfigID int64  `json:"active_config_id"` //活动ID
+}
+
+// 奖品返回
+type DrawReply struct {
+	ID              int64  `json:"id"`                //id
+	DrawUrl         string `json:"draw_url"`          //奖品url
+	DrawProductName string `json:"draw_product_name"` //奖品名称
+	Version         int    `json:"version"`
+}
+
+const (
+	NotWon     = 1 //未中奖
+	NotClaimed = 2 //未兑奖
+	Claimed    = 3 //已兑奖
+)
+
+type ActiveConfigWHXYRequest struct {
+	WHXY           string `json:"whxy"`           //坐标
+	ActiveConfigId int64  `json:"activeConfigId"` //
+}
+
+type ClientActiveQRRequest struct {
+	ActiveConfigId int64  `json:"active_config_id"` //
+	Code           string `json:"code"`             //邀请code
+	OpenId         string `json:"open_id"`
+}
+
+type ClientActiveQRReply struct {
+	Encoded string `json:"encoded"`
+	W       string `json:"w"`
+	H       string `json:"h"`
+	X       string `json:"x"`
+	Y       string `json:"y"`
+}
+
+type GroupBuyUnifiedOrderRequest struct {
+	RequestId      string          `json:"request_id"`      //request id
+	OutTradeNo     string          `json:"out_trade_no"`    //交易id
+	ActiveConfigId int64           `json:"activeConfigId"`  //活动id
+	GroupBuyId     int64           `json:"group_buy_id"`    //团购id
+	ClientOpenId   string          `json:"client_open_id"`  //openid
+	Amount         decimal.Decimal `json:"amount"`          //交易金额
+	InvitationCode string          `json:"invitation_code"` //邀请码
+}
+
+type GroupBuyUnifiedOrderReply struct {
+	Timestamp string `json:"timestamp"` // 时间戳
+	NonceStr  string `json:"nonce_str"` // 随机字符串,长度为32个字符以下
+	Package   string `json:"package"`   // prepay_id 参数值
+	PaySign   string `json:"pay_sign"`  // 签名
+	SignType  string `json:"sign_type"` // 签名类型
+}

+ 44 - 0
apis/shanghu/models/active.draw.product.go

@@ -0,0 +1,44 @@
+package models
+
+import "github.com/shopspring/decimal"
+
+type CreateDrawProductRequest struct {
+	MerchantOpenID  string `json:"merchant_open_id"`
+	DrawProductName string `json:"draw_product_name"` // 抽奖名称
+	DrawOdds        int    `json:"draw_odds"`         // 中奖概率
+	IsPrize         bool   `json:"is_prize"`          // 是否需要兑奖  谢谢惠顾不需要兑奖
+	DrawUrl         string `json:"draw_url"`          // 中奖图片
+	TotalStock      int    `json:"total_stock"`       // 总库存
+}
+
+type DrawProductListRequest struct {
+	OpenId    string `json:"open_id"`
+	PageSize  int    `json:"page_size"`
+	PageIndex int    `json:"page_index"`
+}
+
+type DrawProductListReply struct {
+	//DrawProductInfo []DrawProductInfo `json:"draw_product_info"`
+	ID              int64  `json:"id"`
+	MerchantOpenID  string `json:"merchant_open_id"`
+	DrawProductName string `json:"draw_product_name"` // 抽奖名称
+	DrawOdds        int    `json:"draw_odds"`         // 中奖概率
+	Stock           int    `json:"stock"`             // 剩余库存
+	IsPrize         bool   `json:"is_prize"`          // 是否需要兑奖  谢谢惠顾不需要兑奖
+	DrawUrl         string `json:"draw_url"`          // 中奖图片
+	TotalStock      int    `json:"total_stock"`       // 总库存
+	ActiveConfigID  int64  `json:"active_config_id"`  // 关联活动
+}
+
+type DrawProductInfo struct {
+	ID              int64           `json:"id"`
+	MerchantOpenID  string          `json:"merchant_open_id"`
+	DrawProductName string          `json:"draw_product_name"` // 抽奖名称
+	DrawOdds        decimal.Decimal `json:"draw_odds"`         // 中奖概率
+	Stock           int             `json:"stock"`             // 剩余库存
+	IsPrize         bool            `json:"is_prize"`          // 是否需要兑奖  谢谢惠顾不需要兑奖
+	DrawUrl         string          `json:"draw_url"`          // 中奖图片
+	TotalStock      int             `json:"total_stock"`       // 总库存
+	ActiveConfigID  int64           `json:"active_config_id"`  // 关联活动
+
+}

+ 71 - 0
apis/shanghu/models/active.group.buy.go

@@ -0,0 +1,71 @@
+package models
+
+import "github.com/shopspring/decimal"
+
+type CreateGroupBuyRequest struct {
+	MerchantOpenId     string                  `json:"merchant_open_id"`
+	GroupBuyName       string                  `json:"group_buy_name"`        // 拼团名
+	GroupBuyMode       int                     `json:"group_buy_mode"`        // 拼团模式 1-真实拼团 2-虚拟拼团
+	OriginalPrice      decimal.Decimal         `json:"original_price"`        // 原价
+	GroupBuyOneNum     int                     `json:"group_buy_one_num"`     // 人数
+	GroupBuyOnePrice   decimal.Decimal         `json:"group_buy_one_price"`   // 价格
+	GroupBuyTwoNum     int                     `json:"group_buy_two_num"`     // 人数
+	GroupBuyTwoPrice   decimal.Decimal         `json:"group_buy_two_price"`   // 价格
+	GroupBuyThreeNum   int                     `json:"group_buy_three_num"`   //
+	GroupBuyThreePrice decimal.Decimal         `json:"group_buy_three_price"` //
+	GroupBuyFourNum    int                     `json:"group_buy_four_num"`    //
+	GroupBuyFourPrice  decimal.Decimal         `json:"group_buy_four_price"`  //
+	GroupBuyUrl        string                  `json:"group_buy_url"`         // 图片
+	RebateRate         int                     `json:"rebate_rate"`           //佣金比例
+	GroupBuyProject    []CreateGroupBuyProject `json:"group_buy_project"`
+}
+
+type CreateGroupBuyProject struct {
+	ProjectName string `json:"project_name"`
+	CancelNum   int    `json:"cancel_num"`
+}
+
+type GroupBuyListRequest struct {
+	OpenId    string `json:"open_id"`
+	PageSize  int    `json:"page_size"`
+	PageIndex int    `json:"page_index"`
+}
+
+type GroupBuyListReply struct {
+	//GroupBuyInfo []GroupBuyInfo `json:"group_buy_info"`
+	ID                 int64                   `json:"id"`
+	MerchantOpenId     string                  `json:"merchant_open_id"`
+	GroupBuyName       string                  `json:"group_buy_name"`        // 拼团名
+	GroupBuyMode       int                     `json:"group_buy_mode"`        // 拼团模式 1-真实拼团 2-虚拟拼团
+	OriginalPrice      decimal.Decimal         `json:"original_price"`        // 原价
+	GroupBuyOneNum     int                     `json:"group_buy_one_num"`     // 人数
+	GroupBuyOnePrice   decimal.Decimal         `json:"group_buy_one_price"`   // 价格
+	GroupBuyTwoNum     int                     `json:"group_buy_two_num"`     // 人数
+	GroupBuyTwoPrice   decimal.Decimal         `json:"group_buy_two_price"`   // 价格
+	GroupBuyThreeNum   int                     `json:"group_buy_three_num"`   //
+	GroupBuyThreePrice decimal.Decimal         `json:"group_buy_three_price"` //
+	GroupBuyFourNum    int                     `json:"group_buy_four_num"`    //
+	GroupBuyFourPrice  decimal.Decimal         `json:"group_buy_four_price"`  //
+	GroupBuyUrl        string                  `json:"group_buy_url"`         // 图片
+	RebateRate         int                     `json:"rebate_rate"`           //佣金比例
+	GroupBuyProject    []CreateGroupBuyProject `json:"group_buy_project"`     //
+}
+
+type GroupBuyInfo struct {
+	ID                 int64                   `json:"id"`
+	MerchantOpenId     string                  `json:"merchant_open_id"`
+	GroupBuyName       string                  `json:"group_buy_name"`        // 拼团名
+	GroupBuyMode       int                     `json:"group_buy_mode"`        // 拼团模式 1-真实拼团 2-虚拟拼团
+	OriginalPrice      decimal.Decimal         `json:"original_price"`        // 原价
+	GroupBuyOneNum     int                     `json:"group_buy_one_num"`     // 人数
+	GroupBuyOnePrice   decimal.Decimal         `json:"group_buy_one_price"`   // 价格
+	GroupBuyTwoNum     int                     `json:"group_buy_two_num"`     // 人数
+	GroupBuyTwoPrice   decimal.Decimal         `json:"group_buy_two_price"`   // 价格
+	GroupBuyThreeNum   int                     `json:"group_buy_three_num"`   //
+	GroupBuyThreePrice decimal.Decimal         `json:"group_buy_three_price"` //
+	GroupBuyFourNum    int                     `json:"group_buy_four_num"`    //
+	GroupBuyFourPrice  decimal.Decimal         `json:"group_buy_four_price"`  //
+	GroupBuyUrl        string                  `json:"group_buy_url"`         // 图片
+	RebateRate         int                     `json:"rebate_rate"`           //佣金比例
+	GroupBuyProject    []CreateGroupBuyProject `json:"group_buy_project"`
+}

+ 79 - 0
apis/shanghu/models/active.pay.go

@@ -0,0 +1,79 @@
+package models
+
+type PendingCancelAmountRequest struct {
+	OpenId string `json:"open_id"`
+	Type   int    `json:"type"` //1-商家 2-客户
+}
+
+type PendingCancelAmountReply struct {
+	Amount string `json:"amount"`
+}
+
+type GetGroupBuyPayRequest struct {
+	OpenId    string `json:"open_id"`
+	PageSize  int    `json:"page_size"`
+	PageIndex int    `json:"page_index"`
+	//UserType     int    `json:"user_type"`      //1-商家 2-c端客户
+	//GroupBuyType int    `json:"group_buy_type"` //1-待核销 2-已核销
+}
+
+type GetGroupBuyPayReply struct {
+	ActiveName       string `json:"active_name"`        //活动名称
+	GroupBuyName     string `json:"group_buy_name"`     //拼团名称
+	Amount           string `json:"amount"`             //交易金额
+	MerchantAmount   string `json:"merchant_amount"`    //商家分账金额
+	ClientAmount     string `json:"client_amount"`      //客户分销金额
+	PayTime          string `json:"pay_time"`           //支付时间
+	TradeNo          string `json:"trade_no"`           //交易ID
+	TotalCancelNum   int    `json:"total_cancel_num"`   //总核销次数
+	PendingCancelNum int    `json:"pending_cancel_num"` //待核销次数
+	Url              string `json:"url"`                //url
+
+}
+
+type GroupBuyPayCodeRequest struct {
+	TradeNo string `json:"trade_no"` //交易ID
+}
+
+type GroupBuyPayCodeReply struct {
+	Key     string `json:"key"`      //key
+	TradeNo string `json:"trade_no"` //交易ID
+}
+
+type GroupBuyCancelInfoRequest struct {
+	Key     string `json:"key"`      //key
+	TradeNo string `json:"trade_no"` //交易ID
+}
+
+type GroupBuyCancelInfoReply struct {
+	ActiveName      string                  `json:"active_name"`       //活动名称
+	GroupBuyName    string                  `json:"group_buy_name"`    //拼团名称
+	Amount          string                  `json:"amount"`            //交易金额
+	MerchantAmount  string                  `json:"merchant_amount"`   //商家金额
+	ClientAmount    string                  `json:"client_amount"`     //客户金额
+	PayTime         string                  `json:"pay_time"`          //支付时间
+	TradeNo         string                  `json:"trade_no"`          //交易ID
+	GroupBuyProject []CancelGroupBuyProject `json:"group_buy_project"` //拼团项目
+}
+
+type CancelGroupBuyProject struct {
+	ProjectName      string `json:"project_name"`
+	TotalCancelNum   int    `json:"total_cancel_num"`   //总核销数量
+	PendingCancelNum int    `json:"pending_cancel_num"` //待核销数量
+	ID               int64  `json:"id"`
+}
+
+type GroupBuyCancelRequest struct {
+	Key             string                         `json:"key"`               //key
+	TradeNo         string                         `json:"trade_no"`          //交易ID
+	GroupBuyProject []PendingCancelGroupBuyProject `json:"group_buy_project"` //拼团项目
+	OpenId          string                         `json:"open_id"`           //核销人员
+}
+
+type GroupBuyCancelReply struct {
+}
+
+type PendingCancelGroupBuyProject struct {
+	CancelNum int   `json:"cancel_num"` //数量
+	ID        int64 `json:"id"`
+}

+ 44 - 0
apis/shanghu/models/client.active.draw.log.go

@@ -0,0 +1,44 @@
+package models
+
+type ClientDrawLogRequest struct {
+	ClientOpenID string `json:"client_open_id"` //
+	PageSize     int    `json:"page_size"`
+	PageIndex    int    `json:"page_index"`
+}
+
+type ClientDrawLogReply struct {
+	DrawProductName string `json:"draw_product_name"` //奖品名称
+	IsPrize         int    `json:"is_prize"`          //1-未中奖 2-未兑奖 3-已兑奖
+	Url             string `json:"url"`               //
+	Id              int64  `json:"id"`                //id
+	DrawTime        string `json:"draw_time"`
+}
+
+type DrawLogVerificationCodeRequest struct {
+	DrawLogId int64  `json:"draw_log_id"`
+	OpenId    string `json:"open_id"`
+}
+
+type DrawLogVerificationCodeReply struct {
+	DrawLogId int64  `json:"draw_log_id"`
+	Key       string `json:"key"`
+}
+
+type DrawCancelRequest struct {
+	DrawLogId int64  `json:"draw_log_id"`
+	Key       string `json:"key"`
+}
+
+type DrawCancelInfoRequest struct {
+	DrawLogId int64  `json:"draw_log_id"`
+	Key       string `json:"key"`
+}
+
+// 返回
+type DrawCancelInfoReply struct {
+	ActiveConfigName string `json:"active_config_name"` //配置名称
+	DrawProductName  string `json:"draw_product_name"`  //奖品名称
+	DrawUrl          string `json:"draw_url"`           //图片URL
+	DrawLogId        int64  `json:"draw_log_id"`        //抽奖id
+	DrawTime         string `json:"draw_time"`          //中奖时间
+}

+ 16 - 0
apis/shanghu/models/client.active.draw.num.go

@@ -0,0 +1,16 @@
+package models
+
+type InvitedDrawNumRequest struct {
+	OpenId         string `json:"open_id"`          //被邀请人
+	InvitedCode    string `json:"invited_code"`     //邀请码
+	ActiveConfigId int64  `json:"active_config_id"` //活动id
+}
+
+type ActiveDrawCountRequest struct {
+	OpenId         string `json:"open_id"`          //open-id
+	ActiveConfigId int64  `json:"active_config_id"` //活动id
+}
+
+type ActiveDrawCountReply struct {
+	Num int `json:"num"`
+}

+ 10 - 1
apis/shanghu/pay.go

@@ -60,7 +60,7 @@ func UnifiedOrder(c *gin.Context) {
 	}
 
 	//校验金额
-	// 检查微信相关参数
+	//检查微信相关参数
 	if !inData.Amount.GreaterThan(decimal.NewFromInt(0)) {
 		app.Error(c, 400, errors.New("amount:金额必须大于0"), "amount:金额必须大于0")
 		return
@@ -391,6 +391,15 @@ func NewWechatService() *wechat.Client {
 	return client
 }
 
+func NewWechatServiceTwo(appid, mchId, apiKey string) *wechat.Client {
+
+	client := wechat.NewClient(appid, mchId, apiKey, true)
+	//设置国家
+	client.SetCountry(wechat.China)
+
+	return client
+}
+
 func NewWechatServiceAppid(appid string) *wechat.Client {
 
 	client := wechat.NewClient(appid, "1501641641", "1RKRJBVH4vaRrF0XPW9GX2M3ZSImukIz", true)

+ 13 - 4
conf/conn_ini__test.go

@@ -1,6 +1,7 @@
 package conf
 
 import (
+	"fmt"
 	"testing"
 )
 
@@ -8,10 +9,18 @@ import (
 
 func Test_ConnIni(t *testing.T) {
 
-	conf, err := ConnIni()
-	if err != nil {
-		t.Error(err)
+	//conf, err := ConnIni()
+	//if err != nil {
+	//	t.Error(err)
+	//} else {
+	//	t.Log(conf.MustValue("ubrSet", "ubr_host"))
+	//}
+
+	fmt.Println("fff")
+	var f bool
+	if f {
+		fmt.Println("t")
 	} else {
-		t.Log(conf.MustValue("ubrSet", "ubr_host"))
+		fmt.Println("f")
 	}
 }

+ 33 - 0
models/shanghu/active.account.log.go

@@ -0,0 +1,33 @@
+package shanghu
+
+import (
+	"github.com/shopspring/decimal"
+	"time"
+)
+
+type ActiveClientAccountLog struct {
+	ID                int64           `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`           // 主键
+	ReviewAmountAfter decimal.Decimal `gorm:"column:review_amount_after;type:decimal(10,2)" json:"review_amount_after"` // 审核资金 交易后
+	ReviewAmountPre   decimal.Decimal `gorm:"column:review_amount_pre;type:decimal(10,2)" json:"review_amount_pre"`     // 审核资金 交易前
+	AmountPre         decimal.Decimal `gorm:"column:amount_pre;type:decimal(10,2)" json:"amount_pre"`                   // 交易前
+	AmountAfter       decimal.Decimal `gorm:"column:amount_after;type:decimal(10,2)" json:"amount_after"`               // 交易后
+	TransType         int             `gorm:"column:trans_type;type:int(11)" json:"trans_type"`                         // 交易类型 1-拼团核销入账  2-提现
+	ClientOpenID      string          `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`            // 客户openid
+	CreateBy          int64           `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                        // 创建者
+	UpdateBy          int64           `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                        // 更新者
+	CreatedAt         time.Time       `gorm:"column:created_at;type:datetime(3)" json:"created_at"`                     // 创建时间
+	UpdatedAt         time.Time       `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`                     // 最后更新时间
+	DeletedAt         time.Time       `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"`        // 删除时间
+	Amount            decimal.Decimal `gorm:"column:amount;type:decimal(10,2)" json:"amount"`                           // 交易金额
+	PayTransID        int64           `gorm:"column:pay_trans_id;type:bigint(20)" json:"pay_trans_id"`                  // 交易id
+}
+
+const (
+	ActiveClientAccountLogTransTypeGroupBuy = 1 //拼团入账
+	ActiveClientAccountLogTypeCashOut       = 2 //提现
+	ActiveClientAccountLogTypeCashOutFee    = 3 //提现手续费
+)
+
+func (m *ActiveClientAccountLog) TableName() string {
+	return "active_client_account_log"
+}

+ 65 - 0
models/shanghu/active.cancel.log.go

@@ -0,0 +1,65 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"time"
+)
+
+type ActiveCancelLog struct {
+	ID               int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"` // 主键
+	ClientOpenID     string    `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`
+	MerchantOpenID   string    `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"`
+	ActiveConfigID   int64     `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"`       // 活动id
+	GroupByProjectID int64     `gorm:"column:group_by_project_id;type:bigint(20)" json:"group_by_project_id"` // 拼团商品id
+	SeckillID        int64     `gorm:"column:seckill_id;type:bigint(20)" json:"seckill_id"`                   // 秒杀id
+	UpdateBy         int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`
+	CreateBy         int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`
+	CreatedAt        time.Time `gorm:"column:created_at;type:datetime" json:"created_at"`
+	UpdatedAt        time.Time `gorm:"column:updated_at;type:datetime" json:"updated_at"`
+	DeletedAt        time.Time `gorm:"column:deleted_at;type:datetime;default:null" json:"deleted_at"`
+}
+
+func (m *ActiveCancelLog) TableName() string {
+	return "active_cancel_log"
+}
+
+// 统计cancel数量
+func (m *ActiveCancelLog) GetActiveCancelNum() int {
+	var count int
+
+	tableCount := orm.ShMysql.Table(m.TableName()).Where("active_config_id = ? and client_open_id = ?", m.ActiveConfigID, m.ClientOpenID)
+	tableCount.Count(&count)
+	return count
+}
+
+// 统计cancel数量
+func (m *ActiveCancelLog) GetActiveCancelNumByProjectID() int {
+	var count int
+
+	tableCount := orm.ShMysql.Table(m.TableName()).Where("active_config_id = ? and client_open_id = ? and group_by_project_id = ?", m.ActiveConfigID, m.ClientOpenID, m.GroupByProjectID)
+	tableCount.Count(&count)
+	return count
+}
+
+func (m *ActiveCancelLog) TXActiveCancelLogCreate(log []ActiveCancelLog) error {
+
+	var err error
+	tx := orm.ShMysql.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	for i := 0; i < len(log); i++ {
+		err = tx.Table(log[i].TableName()).Create(&log[i]).Error
+		if err != nil {
+			return err
+		}
+	}
+
+	return nil
+
+}

+ 31 - 0
models/shanghu/active.cash.out.go

@@ -0,0 +1,31 @@
+package shanghu
+
+import (
+	"github.com/shopspring/decimal"
+	"time"
+)
+
+// 活动提现
+type ActiveCashOut struct {
+	ID               int64           `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"` // Id
+	OpenID           string          `gorm:"column:open_id;type:varchar(255)" json:"open_id"`                // Openid
+	AppID            string          `gorm:"column:app_id;type:varchar(255)" json:"app_id"`                  // Appid
+	Status           int             `gorm:"column:status;type:int(11)" json:"status"`                       // 1-提现中 2-提现失败 3-钱已到账待账户扣减  99-提现成功
+	FailRes          string          `gorm:"column:fail_res;type:text" json:"fail_res"`                      // 失败原因
+	PartnerTradeNo   string          `gorm:"column:partner_trade_no;type:varchar(50)" json:"partner_trade_no"`
+	Amount           decimal.Decimal `gorm:"column:amount;type:decimal(10,2)" json:"amount"`                          // 金额
+	CornTime         time.Time       `gorm:"column:corn_time;type:datetime" json:"corn_time"`                         // 定时任务下次查询状态时间
+	CreateBy         int64           `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                       // 创建者
+	UpdateBy         int64           `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                       // 更新者
+	CreatedAt        time.Time       `gorm:"column:created_at;type:datetime(3)" json:"created_at"`                    // 创建时间
+	UpdatedAt        time.Time       `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`                    // 最后更新时间
+	DeletedAt        time.Time       `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"`       // 删除时间
+	Fee              decimal.Decimal `gorm:"column:fee;type:decimal(10,2)" json:"fee"`                                // 手续费
+	WxPartnerTradeNo string          `gorm:"column:wx_partner_trade_no;type:varchar(255)" json:"wx_partner_trade_no"` // 微信批次号
+	AccountStatus    int             `gorm:"column:account_status;type:int(11);default:0" json:"account_status"`      // 分账状态 99-分账成功 2-分账失败 0-未分账 3-分账中
+	AccountFailRes   string          `gorm:"column:account_fail_res;type:varchar(255)" json:"account_fail_res"`       // 分账失败原因
+}
+
+func (m *ActiveCashOut) TableName() string {
+	return "active_cash_out"
+}

+ 53 - 0
models/shanghu/active.draw.config.go

@@ -0,0 +1,53 @@
+package shanghu
+
+//import (
+//	orm "duoduo/database"
+//	"time"
+//)
+//
+//type ClientActiveDrawLog struct {
+//	ID             int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`
+//	ActiveConfigID int64     `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"` // 活动抽奖id
+//	ClientOpenID   string    `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`
+//	DrawProductID  int64     `gorm:"column:draw_product_id;type:bigint(20)" json:"draw_product_id"`     // 中奖商品
+//	CreateBy       int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+//	UpdateBy       int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+//	CreatedAt      time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+//	UpdatedAt      time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+//	DeletedAt      time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+//	IsPrize        int       `gorm:"column:is_prize;type:int(11)" json:"is_prize"`                      // 1-未中奖 2-未兑奖 3-已兑奖
+//}
+//
+//func (m *ClientActiveDrawLog) TableName() string {
+//	return "client_active_draw_log"
+//}
+//
+//func (m *ClientActiveDrawLog) GetClientActiveDrawLogByBiZHong() (int64, error) {
+//	var count int64
+//
+//	table := orm.ShMysql.Table(m.TableName())
+//	table = table.Where("active_config_id = ? and client_open_id = ? and  draw_product_id = ? ",
+//		m.ActiveConfigID, m.ClientOpenID, m.DrawProductID)
+//	if err := table.Count(&count).Error; err != nil {
+//		return 0, nil
+//	}
+//	return count, nil
+//
+//}
+//
+//func (m *ClientActiveDrawLog) Create() (ClientActiveDrawLog, error) {
+//	var doc ClientActiveDrawLog
+//	var err error
+//
+//	doc = *m
+//	err = orm.ShMysql.Table(m.TableName()).Create(&doc).Error
+//	if err != nil {
+//		return doc, err
+//	}
+//
+//	return doc, nil
+//}
+
+//func (m *ClientActiveDrawLog) CreateClientActiveDraw()error  {
+//
+//}

+ 48 - 0
models/shanghu/active.pay.callback.log.go

@@ -0,0 +1,48 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"time"
+)
+
+type ActivePayCallbackLog struct {
+	ID           int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`    //
+	CallBackLog  string    `gorm:"column:call_back_log;type:text" json:"call_back_log"`               //
+	ErrLog       string    `gorm:"column:err_log;type:varchar(255)" json:"err_log"`                   // 处理失败原因
+	OutTradeNo   string    `gorm:"column:out_trade_no;type:varchar(255)" json:"out_trade_no"`         // 交易id
+	ThirdTradeNo string    `gorm:"column:third_trade_no;type:varchar(255)" json:"third_trade_no"`     // 微信交易id
+	CreateBy     int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy     int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt    time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt    time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt    time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+}
+
+func (m *ActivePayCallbackLog) TableName() string {
+	return "active_pay_callback_log"
+}
+
+func (u *ActivePayCallbackLog) Create() (ActivePayCallbackLog, error) {
+	var doc ActivePayCallbackLog
+	var err error
+
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ActivePayCallbackLog) UpdateMerchant() error {
+
+	if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("third_trade_no = ? ", m.ThirdTradeNo).Updates(
+		map[string]interface{}{
+			"err_log":    m.ErrLog,
+			"updated_at": time.Now()}).Error; err != nil {
+		return err
+	}
+
+	return nil
+}

+ 85 - 0
models/shanghu/active.user.go

@@ -0,0 +1,85 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"time"
+)
+
+// 商户账号
+type ActiveUser struct {
+	ID        int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"` // 主键
+	Code      string    `gorm:"column:code;type:varchar(255)" json:"code"`
+	OpenID    string    `gorm:"column:open_id;type:varchar(255)" json:"open_id"`                   // open_id 唯一索引
+	Phone     string    `gorm:"column:phone;type:varchar(24)" json:"phone"`                        // 手机号
+	NickName  string    `gorm:"column:nick_name;type:varchar(255)" json:"nick_name"`               // 微信用户名
+	AvatarUrl string    `gorm:"column:avatar_url;type:varchar(255)" json:"avatar_url"`             // 头像url
+	Admin     int       `gorm:"column:admin;type:int(11)" json:"admin"`                            // 1-管理员  2-销售 3-霸王卡商家 4-店员  5-商家充值 6-商家霸王卡+充值 7-充值店员
+	Pid       string    `gorm:"column:pid;type:varchar(10)" json:"pid"`                            // 上级
+	CreateBy  int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy  int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+}
+
+func (m *ActiveUser) TableName() string {
+	return "active_user"
+}
+
+func (u *ActiveUser) Create() (ActiveUser, error) {
+	var doc ActiveUser
+	var err error
+
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ActiveUser) GetNum() int {
+	var count int
+
+	tableCount := orm.ShMysql.Table(m.TableName()).Where("open_id = ? ", m.OpenID)
+	tableCount.Count(&count)
+	return count
+
+}
+
+func (m *ActiveUser) GetCodeNum() int {
+	var count int
+
+	tableCount := orm.ShMysql.Table(m.TableName()).Where("code = ? ", m.Code)
+	tableCount.Count(&count)
+	return count
+
+}
+
+func (m *ActiveUser) GetUserInfo() (ActiveUser, error) {
+	var doc ActiveUser
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("open_id = ?  ", m.OpenID)
+
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+
+}
+
+func (m *ActiveUser) GetUserInfoByCode() (ActiveUser, error) {
+	var doc ActiveUser
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("code = ?  ", m.Code)
+
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}

+ 200 - 0
models/shanghu/actvie.client.account.go

@@ -0,0 +1,200 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"errors"
+	"github.com/shopspring/decimal"
+	"time"
+)
+
+type ActiveClientAccount struct {
+	ID           int64           `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`    // 主键
+	ClientOpenID string          `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`     //
+	ReviewAmount decimal.Decimal `gorm:"column:review_amount;type:decimal(10,2)" json:"review_amount"`      // 待核销金额
+	Version      int             `gorm:"column:version;type:int(11)" json:"version"`                        // Version
+	Amount       decimal.Decimal `gorm:"column:amount;type:decimal(10,2)" json:"amount"`                    // 可提现金额
+	CreateBy     int64           `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy     int64           `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt    time.Time       `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt    time.Time       `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt    time.Time       `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+}
+
+func (m *ActiveClientAccount) TableName() string {
+	return "active_client_account"
+}
+
+func (m *ActiveClientAccount) GetActiveAccount() (ActiveClientAccount, error) {
+	var doc ActiveClientAccount
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("client_open_id = ?  ", m.ClientOpenID)
+
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+
+}
+
+func (m *ActiveClientAccount) Create() (ActiveClientAccount, error) {
+	var doc ActiveClientAccount
+	var err error
+
+	doc = *m
+	err = orm.ShMysql.Table(m.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+// c端拼个好运提现
+func (m *ActiveClientAccount) SettleSubClient(clientAmount decimal.Decimal, clientOpenId string, cashOutId int64) error {
+	// 使用事务 添加
+	var err error
+	var clientAccount ActiveClientAccount
+	var cashOut CashOut
+	var amountPreClient decimal.Decimal
+	tx := orm.ShMysql.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	err = tx.Table("active_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error
+	if err != nil {
+		return err
+	}
+
+	amountPreClient = clientAccount.Amount
+
+	if clientAccount.Amount.Cmp(clientAmount) < 0 {
+		err = errors.New("账户金额不够")
+		return err
+	}
+
+	clientAmountSub := clientAccount.Amount.Sub(clientAmount)
+	result := tx.Table("active_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates(
+		map[string]interface{}{
+			"amount":     clientAmountSub,
+			"version":    clientAccount.Version + 1,
+			"updated_at": time.Now()})
+	if result.Error != nil {
+		err = result.Error
+		return err
+	}
+
+	if result.RowsAffected <= 0 {
+		err = errors.New("rows is zero")
+		return err
+	}
+
+	var clientAccountLog ActiveClientAccountLog
+
+	clientAccountLog.ClientOpenID = clientOpenId
+	clientAccountLog.UpdatedAt = time.Now()
+	clientAccountLog.AmountPre = amountPreClient
+	clientAccountLog.AmountAfter = clientAmountSub
+	clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount
+	clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount
+	clientAccountLog.Amount = clientAmount
+	clientAccountLog.PayTransID = cashOutId
+	clientAccountLog.TransType = ActiveClientAccountLogTypeCashOut
+
+	err = tx.Table("active_client_account_log").Create(&clientAccountLog).Error
+	if err != nil {
+		return err
+	}
+
+	result = tx.Table("cash_out").Model(&cashOut).Where("id = ? ", cashOutId).Updates(
+		map[string]interface{}{
+			"status":         99, //体现成功
+			"account_status": 99, //分账成功
+			"updated_at":     time.Now()})
+	if result.Error != nil {
+		err = result.Error
+		return err
+	}
+
+	if result.RowsAffected <= 0 {
+		err = errors.New("rows is zero")
+		return err
+	}
+
+	return nil
+
+}
+
+func (m *ActiveClientAccount) SettleAddCashOutFee(amount decimal.Decimal, clientOpenId string, cashOutId int64) error {
+	// 使用事务 添加
+	var err error
+	var clientAccount ActiveClientAccount
+	var amountPreClient decimal.Decimal
+	tx := orm.ShMysql.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	err = tx.Table("active_client_account").Select("*").Where("client_open_id = ?", clientOpenId).Find(&clientAccount).Error
+	if err != nil && err.Error() != "record not found" {
+		return err
+	}
+
+	if clientAccount.ID == 0 {
+		clientAccount.ClientOpenID = clientOpenId
+		clientAccount.Version = 1
+		clientAccount.UpdatedAt = time.Now()
+		clientAccount.CreatedAt = time.Now()
+		err = tx.Table("active_client_account").Create(&clientAccount).Error
+		if err != nil {
+			return err
+		}
+	}
+	amountPreClient = clientAccount.Amount
+
+	clientAmountAdd := clientAccount.Amount.Add(amount)
+	result := tx.Table("active_client_account").Model(&clientAccount).Where("client_open_id = ? and version = ?", clientOpenId, clientAccount.Version).Updates(
+		map[string]interface{}{
+			"amount":     clientAmountAdd,
+			"version":    clientAccount.Version + 1,
+			"updated_at": time.Now()})
+	if result.Error != nil {
+		err = result.Error
+		return err
+	}
+
+	if result.RowsAffected <= 0 {
+		err = errors.New("rows is zero")
+		return err
+	}
+
+	var clientAccountLog ActiveClientAccountLog
+
+	clientAccountLog.ClientOpenID = clientOpenId
+	clientAccountLog.UpdatedAt = time.Now()
+	clientAccountLog.AmountPre = amountPreClient
+	clientAccountLog.AmountAfter = clientAmountAdd
+	clientAccountLog.ReviewAmountAfter = clientAccount.ReviewAmount
+	clientAccountLog.ReviewAmountPre = clientAccount.ReviewAmount
+	clientAccountLog.Amount = amount
+	clientAccountLog.PayTransID = cashOutId
+	clientAccountLog.TransType = ActiveClientAccountLogTypeCashOutFee //服务费
+
+	err = tx.Table("active_client_account_log").Create(&clientAccountLog).Error
+	if err != nil {
+		return err
+	}
+
+	return nil
+
+}

+ 114 - 0
models/shanghu/client.active.draw.log.go

@@ -0,0 +1,114 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"duoduo/tools"
+	"time"
+)
+
+type ClientActiveDrawLog struct {
+	ID             int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`
+	ActiveConfigID int64     `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"`   // 活动抽奖id
+	ClientOpenID   string    `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`     //
+	DrawProductID  int64     `gorm:"column:draw_product_id;type:bigint(20)" json:"draw_product_id"`     // 中奖商品
+	CreateBy       int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy       int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt      time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt      time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt      time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+	IsPrize        int       `gorm:"column:is_prize;type:int(11)" json:"is_prize"`                      // 1-未中奖 2-未兑奖 3-已兑奖
+}
+
+func (m *ClientActiveDrawLog) TableName() string {
+	return "client_active_draw_log"
+}
+
+func (m *ClientActiveDrawLog) GetClientActiveDrawLogByBiZHong() (int64, error) {
+	var count int64
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("active_config_id = ? and client_open_id = ? and  draw_product_id = ? ",
+		m.ActiveConfigID, m.ClientOpenID, m.DrawProductID)
+	if err := table.Count(&count).Error; err != nil {
+		return 0, nil
+	}
+	return count, nil
+
+}
+
+func (m *ClientActiveDrawLog) GetClientActiveDrawLogNum() (int, error) {
+	var count int
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("active_config_id = ? and client_open_id = ? ",
+		m.ActiveConfigID, m.ClientOpenID)
+	if err := table.Count(&count).Error; err != nil {
+		return 0, nil
+	}
+	return count, nil
+
+}
+
+func (m *ClientActiveDrawLog) Create() (ClientActiveDrawLog, error) {
+	var doc ClientActiveDrawLog
+	var err error
+
+	doc = *m
+	err = orm.ShMysql.Table(m.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+func (m *ClientActiveDrawLog) GetClientActiveDrawLogListByOpenId(pageSize int, pageIndex int) ([]ClientActiveDrawLog, int, error) {
+	var doc []ClientActiveDrawLog
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("client_open_id = ? ", m.ClientOpenID)
+	var count int
+	if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *ClientActiveDrawLog) GetClientActiveDrawLogListById() (ClientActiveDrawLog, error) {
+	var doc ClientActiveDrawLog
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("id = ? ", m.ID)
+	if err := table.Select("*").Order("id desc").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ClientActiveDrawLog) GetClientActiveDrawLogListByOpenIdAndId() (ClientActiveDrawLog, error) {
+	var doc ClientActiveDrawLog
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("id = ? and client_open_id = ?", m.ID, m.ClientOpenID)
+	if err := table.Select("*").Order("id desc").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ClientActiveDrawLog) UpdateDrawPrize() error {
+
+	if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("id = ? ", m.ID).Updates(
+		map[string]interface{}{
+			"is_prize":   m.IsPrize,
+			"updated_at": tools.GetCurrntTimeStr()}).Error; err != nil {
+		return err
+	}
+
+	return nil
+}

+ 65 - 0
models/shanghu/client.active.draw.num.go

@@ -0,0 +1,65 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"time"
+)
+
+type ClientActiveDrawNum struct {
+	ID                  int       `gorm:"column:id;type:int(11);primary_key;AUTO_INCREMENT" json:"id"`
+	ActiveConfigID      int64     `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"`
+	ClientOpenID        string    `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`                 // 邀请人
+	ClientOpenIDInvited string    `gorm:"column:client_open_id_invited;type:varchar(255)" json:"client_open_id_invited"` // 被邀请人
+	CreateBy            int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                             // 创建者
+	UpdateBy            int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                             // 更新者
+	CreatedAt           time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`                          // 创建时间
+	UpdatedAt           time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`                          // 最后更新时间
+	DeletedAt           time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"`             // 删除时间
+}
+
+func (m *ClientActiveDrawNum) TableName() string {
+	return "client_active_draw_num"
+}
+
+// 抽奖次数
+func (m *ClientActiveDrawNum) GetDrawNum() (int, error) {
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("client_open_id = ? and active_config_id = ? ", m.ClientOpenID, m.ActiveConfigID)
+	var count int
+	table.Count(&count)
+	return count, nil
+}
+
+func (u *ClientActiveDrawNum) Create() (ClientActiveDrawNum, error) {
+	var doc ClientActiveDrawNum
+	var err error
+
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ClientActiveDrawNum) GetClientDrawNum() (int, error) {
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("client_open_id = ? and active_config_id = ? and client_open_id_invited = ? ", m.ClientOpenID, m.ActiveConfigID, m.ClientOpenIDInvited)
+	var count int
+	table.Count(&count)
+	return count, nil
+}
+
+func (m *ClientActiveDrawNum) GetClientDrawByOpenID() (int, error) {
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("client_open_id = ? and active_config_id = ?  ", m.ClientOpenID, m.ActiveConfigID)
+	var count int
+	table.Count(&count)
+	return count, nil
+}

+ 213 - 0
models/shanghu/client.active.pay.trans.go

@@ -0,0 +1,213 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"github.com/shopspring/decimal"
+	"time"
+)
+
+type ClientActivePayTrans struct {
+	ID             int64           `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`    // 主键
+	RequestID      string          `gorm:"column:request_id;type:varchar(255)" json:"request_id"`             // 请求id,幂等性
+	OutTradeNo     string          `gorm:"column:out_trade_no;type:varchar(255)" json:"out_trade_no"`         // 交易id
+	ActiveConfigID int64           `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"`   // 活动id
+	ClientOpenID   string          `gorm:"column:client_open_id;type:varchar(255)" json:"client_open_id"`     // 客户端openid
+	Status         int             `gorm:"column:status;type:int(11)" json:"status"`                          // 1-未支付 2-支付成功 3-取消支付 4-退款
+	ThirdTradeNo   string          `gorm:"column:third_trade_no;type:varchar(255)" json:"third_trade_no"`     // 微信交易id
+	AccountStatus  int             `gorm:"column:account_status;type:int(11)" json:"account_status"`          // 分账状态 99-分账成功 2-分账失败 1-未分账 3-分账中
+	PayTime        time.Time       `gorm:"column:pay_time;type:datetime(3);default:null" json:"pay_time"`     // 支付时间
+	InvitationCode string          `gorm:"column:invitation_code;type:varchar(25)" json:"invitation_code"`    // 邀请码
+	Amount         decimal.Decimal `gorm:"column:amount;type:decimal(10,2)" json:"amount"`                    // 交易金额
+	AccountErrLog  string          `gorm:"column:account_err_log;type:varchar(255)" json:"account_err_log"`   // 分账err日志
+	GroupBuyID     int64           `gorm:"column:group_buy_id;type:bigint(20)" json:"group_buy_id"`           // 团购id
+	SeckillID      int64           `gorm:"column:seckill_id;type:bigint(20)" json:"seckill_id"`               // 秒杀id
+	CreateBy       int64           `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy       int64           `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt      time.Time       `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt      time.Time       `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt      time.Time       `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+	MerchantAmount decimal.Decimal `gorm:"column:merchant_amount;type:decimal(10,2)" json:"merchant_amount"`  // 商家金额
+	ClientAmount   decimal.Decimal `gorm:"column:client_amount;type:decimal(10,2)" json:"client_amount"`      // 客户分销金额
+	MerchantOpenID string          `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"` // 商家openid
+
+}
+
+const (
+	ClientActivePayTransAccountStatusDef           = 0
+	ClientActivePayTransAccountStatusUnSettle      = 1  //未分账
+	ClientActivePayTransAccountStatusSettleFail    = 2  //分账失败
+	ClientActivePayTransAccountStatusSettlePending = 3  //分账中
+	ClientActivePayTransAccountStatusSettleSuccess = 99 //分账成功
+)
+const (
+	ClientActivePayTransStatusDef        = 0
+	ClientActivePayTransStatusUnPay      = 1 // 未支付
+	ClientActivePayTransStatusPaySuccess = 2 //支付成功
+	ClientActivePayTransStatusPayCancel  = 3 //取消支付
+	ClientActivePayTransStatusRefund     = 4 // 退款
+)
+
+const (
+	YuanShiMa = "yuanshima" //
+)
+
+func (m *ClientActivePayTrans) TableName() string {
+	return "client_active_pay_trans"
+}
+
+func (m *ClientActivePayTrans) GetRequestNum() int {
+	var count int
+
+	tableCount := orm.ShMysql.Table(m.TableName()).Where("request_id = ? ", m.RequestID)
+	tableCount.Count(&count)
+	return count
+
+}
+
+func (m *ClientActivePayTrans) Create() (ClientActivePayTrans, error) {
+	var doc ClientActivePayTrans
+	var err error
+
+	doc = *m
+	err = orm.ShMysql.Table(m.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ClientActivePayTrans) GetPayTransByTradeNo() (ClientActivePayTrans, error) {
+	var doc ClientActivePayTrans
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("out_trade_no = ?  ", m.OutTradeNo)
+
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ClientActivePayTrans) UpdatePayTransByTradeNo() error {
+
+	if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("out_trade_no = ? ", m.OutTradeNo).Updates(
+		map[string]interface{}{
+			"third_trade_no": m.ThirdTradeNo,
+			"pay_time":       m.PayTime,
+			"status":         m.Status,
+			"account_status": m.AccountStatus,
+			"updated_at":     time.Now()}).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (m *ClientActivePayTrans) GetPendingCancelByMerchant() (ClientActivePayTrans, error) {
+	var doc ClientActivePayTrans
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("status = 2 and  account_status = 1 and merchant_open_id = ?", m.MerchantOpenID)
+
+	if err := table.Select("sum(merchant_amount) as merchant_amount").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *ClientActivePayTrans) GetPendingCancelByClient() (ClientActivePayTrans, error) {
+	var doc ClientActivePayTrans
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("status = 2 and  account_status = 1 and client_open_id = ?", m.ClientOpenID)
+
+	if err := table.Select("sum(client_amount) as client_amount").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+// 交易记录
+func (m *ClientActivePayTrans) GetActivePayTransList(pageSize int, pageIndex int, openId string) ([]ClientActivePayTrans, int, error) {
+	var doc []ClientActivePayTrans
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	//if userType == 1 { // 商家
+	//	table = table.Where("merchant_open_id = ?", openId)
+	//
+	//} else if userType == 2 { // c端用户
+	//	table = table.Where("client_open_id = ?", openId)
+	//} else {
+	//	return doc, 0, errors.New("用户类型错误")
+	//}
+	//
+	//if groupBuyType == 1 { // 待核销 核销次数大于0
+	//	table = table.Where("status = 2 and account_status in (1,2)")
+	//} else if groupBuyType == 2 { //已核销
+	//	table = table.Where("status = 2 and account_status = 99")
+	//} else {
+	//	return doc, 0, errors.New("核销类型错误")
+	//}
+	table = table.Where("client_open_id = ? and status = 2 ", openId)
+
+	var count int
+	if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *ClientActivePayTrans) GetPayTransByThirdTradeNo() (ClientActivePayTrans, error) {
+	var doc ClientActivePayTrans
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("third_trade_no = ?  ", m.ThirdTradeNo)
+
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+// 分账
+func (m *ClientActivePayTrans) TXSettle(payInfo ClientActivePayTrans) error {
+	var err error
+
+	tx := orm.ShMysql.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+	//判断是否有这个商家账号,c端用户账号,没有用户需要创建
+
+	//商家加款 c端用户加款
+	return nil
+}
+
+func (m *ClientActivePayTrans) UpdateAccountStatusByID() error {
+
+	if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("id = ? ", m.ID).Updates(
+		map[string]interface{}{
+			"account_status": m.Status,
+			"updated_at":     time.Now()}).Error; err != nil {
+		return err
+	}
+	return nil
+}
+
+func (m *ClientActivePayTrans) UpdateById(data map[string]interface{}) error {
+	err := orm.ShMysql.Table(m.TableName()).Where("id = ?", m.ID).Updates(data).Error
+	if err != nil {
+		return err
+	}
+	return nil
+}

+ 146 - 0
models/shanghu/merchant.account.go

@@ -2,6 +2,8 @@ package shanghu
 
 import (
 	orm "duoduo/database"
+	"errors"
+	"fmt"
 	"github.com/shopspring/decimal"
 	"time"
 )
@@ -36,3 +38,147 @@ func (m *MerchantAccount) GetMerchantAccount() (MerchantAccount, error) {
 	return doc, nil
 
 }
+
+func (m *MerchantAccount) Create() (MerchantAccount, error) {
+	var doc MerchantAccount
+	var err error
+
+	doc = *m
+	err = orm.ShMysql.Table(m.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+// 拼团核销与分账
+func (m *MerchantAccount) ActiveCancelSettle(log []ActiveCancelLog, merchantAccount MerchantAccount, activeClientAccount ActiveClientAccount, payTrans ClientActivePayTrans) error {
+	var err error
+	var merchantAccountLog MerchantAccountLog
+	var clientAccountLog ActiveClientAccountLog
+	fmt.Println("merchantAccount =", merchantAccount)
+	fmt.Println("activeClientAccount =", activeClientAccount)
+
+	err = orm.ShMysql.Table("merchant_account").Select("*").Where("merchant_open_id = ?", merchantAccount.MerchantOpenID).First(&merchantAccount).Error
+	if err != nil {
+		return err
+	}
+
+	if payTrans.InvitationCode != YuanShiMa {
+		err = orm.ShMysql.Table("active_client_account").Select("*").Where("client_open_id = ?", activeClientAccount.ClientOpenID).First(&activeClientAccount).Error
+		if err != nil {
+			return err
+		}
+
+	}
+
+	fmt.Println("merchantAccount =", merchantAccount)
+	fmt.Println("activeClientAccount =", activeClientAccount)
+
+	tx := orm.ShMysql.Begin()
+	defer func() {
+		if err != nil {
+			tx.Rollback()
+		} else {
+			tx.Commit()
+		}
+	}()
+
+	//核销日志
+	for i := 0; i < len(log); i++ {
+		err = tx.Table(log[i].TableName()).Create(&log[i]).Error
+		if err != nil {
+			return err
+		}
+	}
+
+	//分账
+	//商家加款
+	merchantAmountAdd := merchantAccount.Amount.Add(payTrans.MerchantAmount)
+	result := tx.Table("merchant_account").Model(&merchantAccount).Where("merchant_open_id = ? and version = ?", merchantAccount.MerchantOpenID, merchantAccount.Version).Updates(
+		map[string]interface{}{
+			"amount":     merchantAmountAdd,
+			"version":    merchantAccount.Version + 1,
+			"updated_at": time.Now()})
+
+	if result.Error != nil {
+		err = result.Error
+		return err
+	}
+	if result.RowsAffected <= 0 {
+		err = errors.New("rows is zero")
+		return err
+	}
+
+	merchantAccountLog.MerchantOpenID = merchantAccount.MerchantOpenID
+	merchantAccountLog.UpdatedAt = time.Now()
+	merchantAccountLog.AmountPre = merchantAccount.Amount
+	merchantAccountLog.AmountAfter = merchantAmountAdd
+	merchantAccountLog.ReviewAmountAfter = merchantAccount.ReviewAmount
+	merchantAccountLog.ReviewAmountPre = merchantAccount.ReviewAmount
+	merchantAccountLog.Amount = payTrans.MerchantAmount
+	merchantAccountLog.PayTransId = payTrans.ID
+	merchantAccountLog.TransType = MerchantAccountLogTransTypeGroupBuy
+	err = tx.Table("merchant_account_log").Create(&merchantAccountLog).Error
+	if err != nil {
+		return err
+	}
+
+	//err = tx.Table("merchant_account_log").Create(&merchantAccountLog).Error
+	//if err != nil {
+	//	return err
+	//}
+
+	// 客户加款
+	if payTrans.InvitationCode != YuanShiMa && payTrans.InvitationCode != "" {
+		clientAmountAdd := activeClientAccount.Amount.Add(payTrans.ClientAmount)
+		clientResult := tx.Table("active_client_account").Model(&activeClientAccount).Where("client_open_id = ? and version = ?", activeClientAccount.ClientOpenID, activeClientAccount.Version).Updates(
+			map[string]interface{}{
+				"amount":     clientAmountAdd,
+				"version":    activeClientAccount.Version + 1,
+				"updated_at": time.Now()})
+
+		if clientResult.Error != nil {
+			err = clientResult.Error
+			return err
+		}
+		if clientResult.RowsAffected <= 0 {
+			err = errors.New("rows is zero")
+			return err
+		}
+
+		clientAccountLog.ClientOpenID = activeClientAccount.ClientOpenID
+		clientAccountLog.UpdatedAt = time.Now()
+		clientAccountLog.AmountPre = activeClientAccount.Amount
+		clientAccountLog.AmountAfter = clientAmountAdd
+		clientAccountLog.ReviewAmountAfter = activeClientAccount.ReviewAmount
+		clientAccountLog.ReviewAmountPre = activeClientAccount.ReviewAmount
+		clientAccountLog.Amount = payTrans.ClientAmount
+		clientAccountLog.PayTransID = payTrans.ID
+		clientAccountLog.TransType = ActiveClientAccountLogTransTypeGroupBuy
+		err = tx.Table("active_client_account_log").Create(&clientAccountLog).Error
+		if err != nil {
+			return err
+		}
+
+	}
+	//更新状态
+	var activePay ClientActivePayTrans
+	resultPay := tx.Table("client_active_pay_trans").Model(&activePay).Where("id = ? ", payTrans.ID).Updates(
+		map[string]interface{}{
+			"account_status": ClientActivePayTransAccountStatusSettleSuccess,
+			"updated_at":     time.Now()})
+
+	if resultPay.Error != nil {
+		err = resultPay.Error
+		return err
+	}
+	if resultPay.RowsAffected <= 0 {
+		err = errors.New("pay rows is zero")
+		return err
+	}
+
+	return nil
+
+}

+ 17 - 1
models/shanghu/merchant.account.log.go

@@ -1,6 +1,7 @@
 package shanghu
 
 import (
+	orm "duoduo/database"
 	"github.com/shopspring/decimal"
 	"time"
 )
@@ -11,7 +12,7 @@ type MerchantAccountLog struct {
 	ReviewAmountPre   decimal.Decimal `gorm:"column:review_amount_pre;type:decimal(10,2)" json:"review_amount_pre"`     // 审核资金 交易前
 	AmountPre         decimal.Decimal `gorm:"column:amount_pre;type:decimal(10,2)" json:"amount_pre"`                   // 交易前
 	AmountAfter       decimal.Decimal `gorm:"column:amount_after;type:decimal(10,2)" json:"amount_after"`               // 交易后
-	TransType         int             `gorm:"column:trans_type;type:int(11)" json:"trans_type"`                         // 交易类型  0-买卡入账  2-提现
+	TransType         int             `gorm:"column:trans_type;type:int(11)" json:"trans_type"`                         // 交易类型  0-买卡入账 1-拼团入账  2-提现
 	MerchantOpenID    string          `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"`        // 商户openid
 	CreateBy          int64           `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                        // 创建者
 	UpdateBy          int64           `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                        // 更新者
@@ -25,3 +26,18 @@ type MerchantAccountLog struct {
 func (m *MerchantAccountLog) TableName() string {
 	return "merchant_account_log"
 }
+
+const (
+	MerchantAccountLogTransTypeCard     = 0 //霸王卡入账
+	MerchantAccountLogTransTypeGroupBuy = 1 //拼团入账
+	MerchantAccountLogTransTypeCashOut  = 2 //提现
+)
+
+// 获取
+func (m *MerchantAccountLog) GetAccountLogNum() int {
+	var count int
+
+	tableCount := orm.ShMysql.Table(m.TableName()).Where("trans_type = ? and pay_trans_id = ?", m.TransType, m.PayTransId)
+	tableCount.Count(&count)
+	return count
+}

+ 93 - 0
models/shanghu/merchant.active.config.go

@@ -0,0 +1,93 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"duoduo/tools"
+	"time"
+)
+
+// 活动中奖配置,拼团配置,秒杀配置
+type MerchantActiveConfig struct {
+	ID                int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`
+	ConfigMode        int       `gorm:"column:config_mode;type:int(11)" json:"config_mode"`                    // 模式 1-默认模式
+	MerchantOpenID    string    `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"`     // openid
+	DrawMode          int       `gorm:"column:draw_mode;type:int(11);default:0" json:"draw_mode"`              // 抽奖模式 0-不抽奖,1-盲盒
+	DrawOneBiZhong    int64     `gorm:"column:draw_one_bi_zhong;type:bigint(20)" json:"draw_one_bi_zhong"`     // 首次必中抽奖商品ID
+	DrawProduct       string    `gorm:"column:draw_product;type:json" json:"draw_product"`                     // 抽奖商品 商品ID 与中奖率
+	CreateBy          int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                     // 创建者
+	UpdateBy          int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                     // 更新者
+	CreatedAt         time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`                  // 创建时间
+	UpdatedAt         time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`                  // 最后更新时间
+	DeletedAt         time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"`     // 删除时间
+	GroupBuyMode      int       `gorm:"column:group_buy_mode;type:int(11)" json:"group_buy_mode"`              // 0-不开团 1-虚拟开团 2-真实开团
+	GroupBuy          string    `gorm:"column:group_buy;type:json" json:"group_buy"`                           // 开团配置
+	GroupBuyUrl       string    `gorm:"column:group_buy_url;type:varchar(255)" json:"group_buy_url"`           // 介绍图url
+	ActivityEndTime   int64     `gorm:"column:activity_end_time;type:bigint(20)" json:"activity_end_time"`     // 活动结束时间
+	ActivityStartTime int64     `gorm:"column:activity_start_time;type:bigint(20)" json:"activity_start_time"` // 活动开始时间
+	ActiveName        string    `gorm:"column:active_name;type:varchar(255)" json:"active_name"`               // 活动名称
+	W                 string    `gorm:"column:w;type:varchar(255)" json:"w"`                                   //
+	X                 string    `gorm:"column:x;type:varchar(255)" json:"x"`                                   //
+	Y                 string    `gorm:"column:y;type:varchar(255)" json:"y"`                                   //
+	H                 string    `gorm:"column:h;type:varchar(255)" json:"h"`                                   //
+	BackgroundImage   string    `gorm:"column:background_image;type:varchar(255)" json:"background_image"`     // 背景图
+
+}
+
+func (m *MerchantActiveConfig) TableName() string {
+	return "merchant_active_config"
+}
+
+func (u *MerchantActiveConfig) Create() (MerchantActiveConfig, error) {
+	var doc MerchantActiveConfig
+	var err error
+
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *MerchantActiveConfig) GetConfigInfoById() (MerchantActiveConfig, error) {
+	var doc MerchantActiveConfig
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("id = ?  ", m.ID)
+
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (m *MerchantActiveConfig) GetActiveConfigList(pageSize int, pageIndex int) ([]MerchantActiveConfig, int, error) {
+	var doc []MerchantActiveConfig
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("merchant_open_id = ?  ", m.MerchantOpenID)
+	var count int
+	if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *MerchantActiveConfig) UpdateMerchantWHXY() error {
+
+	if err := orm.ShMysql.Table(m.TableName()).Model(&m).Where("id = ? ", m.ID).Updates(
+		map[string]interface{}{
+			"w":          m.W,
+			"h":          m.H,
+			"x":          m.X,
+			"y":          m.Y,
+			"updated_at": tools.GetCurrntTimeStr()}).Error; err != nil {
+		return err
+	}
+
+	return nil
+}

+ 153 - 0
models/shanghu/merchant.active.draw.product.go

@@ -0,0 +1,153 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"duoduo/tools"
+	"errors"
+	"time"
+)
+
+// 中奖活动商品 库存,中奖率
+type MerchantActiveDrawProduct struct {
+	ID              int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`
+	MerchantOpenID  string    `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"`
+	DrawProductName string    `gorm:"column:draw_product_name;type:varchar(255)" json:"draw_product_name"` // 抽奖名称
+	DrawOdds        int       `gorm:"column:draw_odds;type:int(11)" json:"draw_odds"`                      // 中奖概率
+	Stock           int       `gorm:"column:stock;type:int(11)" json:"stock"`                              // 剩余库存
+	Version         int       `gorm:"column:version;type:int(11)" json:"version"`                          // Version
+	IsPrize         bool      `gorm:"column:is_prize;type:tinyint(1)" json:"is_prize"`                     // 是否需要兑奖  谢谢惠顾不需要兑奖
+	DrawUrl         string    `gorm:"column:draw_url;type:varchar(255)" json:"draw_url"`                   // 中奖图片
+	TotalStock      int       `gorm:"column:total_stock;type:int(11)" json:"total_stock"`                  // 总库存
+	ActiveConfigID  int64     `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"`     // 关联活动
+	CreateBy        int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                   // 创建者
+	UpdateBy        int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                   // 更新者
+	CreatedAt       time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`                // 创建时间
+	UpdatedAt       time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`                // 最后更新时间
+	DeletedAt       time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"`   // 删除时间
+}
+
+func (m *MerchantActiveDrawProduct) TableName() string {
+	return "merchant_active_draw_product"
+}
+
+func (u *MerchantActiveDrawProduct) Create() (MerchantActiveDrawProduct, error) {
+	var doc MerchantActiveDrawProduct
+	var err error
+
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (u *MerchantActiveDrawProduct) UpdateConfigId(drawId int64) error {
+	res := orm.ShMysql.Table(u.TableName()).Where("id = ? and active_config_id = 0", drawId).Updates(
+		map[string]interface{}{
+			"active_config_id": u.ActiveConfigID,
+			"updated_at":       time.Now(),
+		})
+	if res.Error != nil {
+		return res.Error
+	}
+	if res.RowsAffected <= 0 {
+		return errors.New("未更新抽奖数据")
+	}
+	return nil
+
+}
+
+// 中奖商品列表
+func (m *MerchantActiveDrawProduct) GetDrawProductList() ([]MerchantActiveDrawProduct, int, error) {
+	var doc []MerchantActiveDrawProduct
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("active_config_id = ?  ", m.ActiveConfigID)
+	var count int
+	if err := table.Select("*").Order("id desc").Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *MerchantActiveDrawProduct) GetDrawProductListByOpenId(pageSize int, pageIndex int) ([]MerchantActiveDrawProduct, int, error) {
+	var doc []MerchantActiveDrawProduct
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("merchant_open_id = ? and  active_config_id = 0", m.MerchantOpenID)
+	var count int
+	if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+// 中奖商品列表
+func (m *MerchantActiveDrawProduct) GetDrawProductListById(idList []int64) ([]MerchantActiveDrawProduct, int, error) {
+	var doc []MerchantActiveDrawProduct
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("id in (?) ", idList)
+	var count int
+	if err := table.Select("*").Order("id desc").Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+// 中奖商品
+func (m *MerchantActiveDrawProduct) GetDrawProductById() (MerchantActiveDrawProduct, error) {
+	var doc MerchantActiveDrawProduct
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("id = ? ", m.ID)
+	var count int
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+	table.Count(&count)
+	return doc, nil
+}
+
+// 奖品列表
+func (m *MerchantActiveDrawProduct) GetDrawProductListByActiveId() ([]MerchantActiveDrawProduct, int, error) {
+	var doc []MerchantActiveDrawProduct
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("active_config_id = ? ", m.ActiveConfigID)
+	var count int
+	if err := table.Select("*").Order("id desc").Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *MerchantActiveDrawProduct) SubStock() error {
+
+	table := orm.ShMysql.Table(m.TableName())
+	result := table.Model(&MerchantActiveDrawProduct{}).Where("id = ? and version = ? ", m.ID, m.Version).Updates(
+		map[string]interface{}{
+			"version":    m.Version + 1,
+			"stock":      m.Stock - 1,
+			"updated_at": tools.GetCurrntTimeStr()})
+
+	if result.Error != nil {
+		return result.Error
+	}
+	if result.RowsAffected <= 0 {
+		err := errors.New("减库存失败,请重新再试。")
+		return err
+	}
+	return nil
+}

+ 107 - 0
models/shanghu/merchant.active.group.buy.go

@@ -0,0 +1,107 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"errors"
+	"github.com/shopspring/decimal"
+	"time"
+)
+
+type MerchantActiveGroupBuy struct {
+	ID                 int64           `gorm:"column:id;type:bigint(20);primary_key" json:"id"`
+	ActiveConfigID     int64           `gorm:"column:active_config_id;type:bigint(20)" json:"active_config_id"` // 关联活动
+	GroupBuyName       string          `gorm:"column:group_buy_name;type:varchar(255)" json:"group_buy_name"`   // 拼团名
+	GroupBuyMode       int             `gorm:"column:group_buy_mode;type:int(11)" json:"group_buy_mode"`        // 拼团模式 1-真实拼团 2-虚拟拼团
+	MerchantOpenID     string          `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"`
+	OriginalPrice      decimal.Decimal `gorm:"column:original_price;type:decimal(10,2)" json:"original_price"`           // 原价
+	GroupBuyOneNum     int             `gorm:"column:group_buy_one_num;type:int(11)" json:"group_buy_one_num"`           // 人数
+	GroupBuyOnePrice   decimal.Decimal `gorm:"column:group_buy_one_price;type:decimal(10,2)" json:"group_buy_one_price"` // 价格
+	GroupBuyTwoNum     int             `gorm:"column:group_buy_two_num;type:int(11)" json:"group_buy_two_num"`           // 人数
+	GroupBuyTwoPrice   decimal.Decimal `gorm:"column:group_buy_two_price;type:decimal(10,2)" json:"group_buy_two_price"` // 价格
+	GroupBuyThreeNum   int             `gorm:"column:group_buy_three_num;type:int(11)" json:"group_buy_three_num"`
+	GroupBuyThreePrice decimal.Decimal `gorm:"column:group_buy_three_price;type:decimal(10,2)" json:"group_buy_three_price"`
+	GroupBuyFourNum    int             `gorm:"column:group_buy_four_num;type:int(11)" json:"group_buy_four_num"`
+	GroupBuyFourPrice  decimal.Decimal `gorm:"column:group_buy_four_price;type:decimal(10,2)" json:"group_buy_four_price"`
+	GroupBuyUrl        string          `gorm:"column:group_buy_url;type:varchar(255)" json:"group_buy_url"`         // 图片
+	GroupBuyBigUrl     string          `gorm:"column:group_buy_big_url;type:varchar(255)" json:"group_buy_big_url"` // 大图
+	CreateBy           int64           `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                   // 创建者
+	UpdateBy           int64           `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                   // 更新者
+	CreatedAt          time.Time       `gorm:"column:created_at;type:datetime(3)" json:"created_at"`                // 创建时间
+	UpdatedAt          time.Time       `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`                // 最后更新时间
+	DeletedAt          time.Time       `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"`   // 删除时间
+	RebateRate         int             `gorm:"column:rebate_rate;type:int(11)" json:"rebate_rate"`                  // 佣金比例
+}
+
+func (m *MerchantActiveGroupBuy) TableName() string {
+	return "merchant_active_group_buy"
+}
+
+func (u *MerchantActiveGroupBuy) Create() (MerchantActiveGroupBuy, error) {
+	var doc MerchantActiveGroupBuy
+	var err error
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+func (u *MerchantActiveGroupBuy) UpdateConfigId(groupBuyId int64) error {
+	res := orm.ShMysql.Table(u.TableName()).Where("id = ? and active_config_id = 0", groupBuyId).Updates(
+		map[string]interface{}{
+			"active_config_id": u.ActiveConfigID,
+			"updated_at":       time.Now(),
+		})
+	if res.Error != nil {
+		return res.Error
+	}
+	if res.RowsAffected <= 0 {
+		return errors.New("未更新拼团数据")
+	}
+	return nil
+
+}
+
+// 中奖商品列表
+func (m *MerchantActiveGroupBuy) GetGroupBuyList() ([]MerchantActiveGroupBuy, int, error) {
+	var doc []MerchantActiveGroupBuy
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("active_config_id = ?  ", m.ActiveConfigID)
+	var count int
+	if err := table.Select("*").Order("id desc").Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *MerchantActiveGroupBuy) GetGroupBuyListByOpenId(pageSize int, pageIndex int) ([]MerchantActiveGroupBuy, int, error) {
+	var doc []MerchantActiveGroupBuy
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("merchant_open_id = ? and  active_config_id = 0", m.MerchantOpenID)
+	var count int
+	if err := table.Select("*").Order("id desc").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *MerchantActiveGroupBuy) GetMerchantActiveGroupBuyById() (MerchantActiveGroupBuy, error) {
+	var doc MerchantActiveGroupBuy
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("id = ? ", m.ID)
+	if err := table.Select("*").Order("id desc").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}

+ 63 - 0
models/shanghu/merchant.active.group.buy.project.go

@@ -0,0 +1,63 @@
+package shanghu
+
+import (
+	orm "duoduo/database"
+	"time"
+)
+
+type MerchantActiveGroupByProject struct {
+	ID             int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"`
+	MerchantOpenID string    `gorm:"column:merchant_open_id;type:varchar(255)" json:"merchant_open_id"` // Open id
+	GroupBuyID     int64     `gorm:"column:group_buy_id;type:bigint(20)" json:"group_buy_id"`           // 关联活动
+	ProjectName    string    `gorm:"column:project_name;type:varchar(255)" json:"project_name"`         // 项目名
+	CancelNum      int       `gorm:"column:cancel_num;type:int(11)" json:"cancel_num"`                  // 核销数量
+	CreateBy       int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy       int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt      time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt      time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt      time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+}
+
+func (m *MerchantActiveGroupByProject) TableName() string {
+	return "merchant_active_group_by_project"
+}
+
+func (u *MerchantActiveGroupByProject) Create() (MerchantActiveGroupByProject, error) {
+	var doc MerchantActiveGroupByProject
+	var err error
+
+	doc = *u
+	err = orm.ShMysql.Table(u.TableName()).Create(&doc).Error
+	if err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}
+
+// 中奖商品列表
+func (m *MerchantActiveGroupByProject) GetGroupBuyProjectList() ([]MerchantActiveGroupByProject, int, error) {
+	var doc []MerchantActiveGroupByProject
+
+	table := orm.ShMysql.Table(m.TableName())
+
+	table = table.Where("group_buy_id = ?  ", m.GroupBuyID)
+	var count int
+	if err := table.Select("*").Order("id desc").Find(&doc).Error; err != nil {
+		return nil, 0, err
+	}
+	table.Count(&count)
+	return doc, count, nil
+}
+
+func (m *MerchantActiveGroupByProject) GetMerchantActiveGroupBuyProjectByID() (MerchantActiveGroupByProject, error) {
+	var doc MerchantActiveGroupByProject
+
+	table := orm.ShMysql.Table(m.TableName())
+	table = table.Where("id = ?  ", m.ID)
+	if err := table.Select("*").First(&doc).Error; err != nil {
+		return doc, err
+	}
+
+	return doc, nil
+}

+ 13 - 12
models/shanghu/merchant_user.go

@@ -7,18 +7,19 @@ import (
 
 // 商户账号
 type MerchantUser struct {
-	ID        int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"` // 主键
-	Code      string    `gorm:"column:code;type:varchar(255)" json:"code"`
-	OpenID    string    `gorm:"column:open_id;type:varchar(255)" json:"open_id"`                   // open_id 唯一索引
-	Phone     string    `gorm:"column:phone;type:varchar(24)" json:"phone"`                        // 手机号
-	NickName  string    `gorm:"column:nick_name;type:varchar(255)" json:"nick_name"`               // 微信用户名
-	AvatarUrl string    `gorm:"column:avatar_url;type:varchar(255)" json:"avatar_url"`             // 头像url
-	Admin     int       `gorm:"column:admin;type:int(11)" json:"admin"`                            // 1-管理员
-	CreateBy  int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
-	UpdateBy  int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
-	CreatedAt time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
-	UpdatedAt time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
-	DeletedAt time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
+	ID          int64     `gorm:"column:id;type:bigint(20);primary_key;AUTO_INCREMENT" json:"id"` // 主键
+	Code        string    `gorm:"column:code;type:varchar(255)" json:"code"`
+	OpenID      string    `gorm:"column:open_id;type:varchar(255)" json:"open_id"`                   // open_id 唯一索引
+	Phone       string    `gorm:"column:phone;type:varchar(24)" json:"phone"`                        // 手机号
+	NickName    string    `gorm:"column:nick_name;type:varchar(255)" json:"nick_name"`               // 微信用户名
+	AvatarUrl   string    `gorm:"column:avatar_url;type:varchar(255)" json:"avatar_url"`             // 头像url
+	Admin       int       `gorm:"column:admin;type:int(11)" json:"admin"`                            // 1-管理员
+	ActiveAdmin int       `gorm:"column:active_admin;type:int(11)" json:"active_admin"`              // 1-管理员
+	CreateBy    int64     `gorm:"column:create_by;type:bigint(20)" json:"create_by"`                 // 创建者
+	UpdateBy    int64     `gorm:"column:update_by;type:bigint(20)" json:"update_by"`                 // 更新者
+	CreatedAt   time.Time `gorm:"column:created_at;type:datetime(3)" json:"created_at"`              // 创建时间
+	UpdatedAt   time.Time `gorm:"column:updated_at;type:datetime(3)" json:"updated_at"`              // 最后更新时间
+	DeletedAt   time.Time `gorm:"column:deleted_at;type:datetime(3);default:null" json:"deleted_at"` // 删除时间
 }
 
 func (m *MerchantUser) TableName() string {

+ 21 - 0
report/cash.out.go

@@ -123,6 +123,27 @@ func CashOutAccount() {
 				accountClient.SettleAddCashOutFee(cashOutInfo.Fee, clientInfo.ClientOpenID, cashOutInfo.ID)
 			}
 
+		} else if cashOutInfo.AppID == "wx8595c589dd736486" { //c端 拼个好运
+			var clientAccount shanghu.ActiveClientAccount
+			err = clientAccount.SettleSubClient(cashOutInfo.Amount, cashOutInfo.OpenID, cashOutInfo.ID)
+			if err != nil {
+				cashOut.AccountStatus = 2 //分账失败
+				cashOut.AccountFailRes = "wx8595c589dd736486-分账失败:" + err.Error()
+				cashOut.ID = cashOutInfo.ID
+				cashOut.UpdateCashOutAccountStatus()
+				continue
+			}
+			var activeUser shanghu.ActiveUser
+			activeUser.Code = "7jb6"
+			activeUserInfo, _ := activeUser.GetUserInfoByCode()
+			if activeUserInfo.OpenID == activeUserInfo.OpenID { //超级管理员钱已经有了不需要收服务费  暂时无效
+				continue
+			} else {
+				var client shanghu.ActiveClientAccount
+				client.SettleAddCashOutFee(cashOutInfo.Fee, activeUserInfo.OpenID, cashOutInfo.ID)
+
+			}
+
 		} else {
 			continue
 		}