create order. add paytype: coin

This commit is contained in:
lwl0608 2024-06-04 17:44:06 +08:00
parent b35e2ac7a3
commit 8bf8e9357f
4 changed files with 137 additions and 24 deletions

View File

@ -32,11 +32,13 @@ const (
PayTypeWxpayNative = "wxpay_native" // 微信 native
PayTypeWxpayJsapi = "wxpay_jsapi" // 微信 jsapi
PayTypeWxpayH5 = "wxpay_h5" // 微信支付 h5
PayTypeCoin = "coin" // 金币支付
)
const (
CallBackPayTypeAlipay = "alipay"
CallBackPayTypeWxpay = "wxpay"
CallBackPayTypeCoin = "coin"
)
const (

View File

@ -296,6 +296,8 @@ func (v *Vas) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data
return
}
req.Oid3 = wxpayCli.AppId
case vasproto.PayTypeCoin:
return v.CreateOrderByCoin(ctx, req, product)
}
// 添加订单
@ -344,6 +346,110 @@ func (v *Vas) CreateOrder(ctx *gin.Context, req *vasproto.CreateOrderReq) (data
return
}
func (v *Vas) CreateOrderByCoin(ctx *gin.Context, req *vasproto.CreateOrderReq, product *dbstruct.Product) (data *vasproto.CreateOrderData, err error) {
var (
order *dbstruct.Order
orderId = idgenerator.GenOrderId() // 订单id
priceCoin = product.GetRealPriceCoin()
)
// 开启事务
tx, err := v.store.VasBegin(ctx)
if err != nil {
logger.Error("vas begin fail, err: %v", err)
return nil, err
}
defer func() {
if err != nil {
logger.Error("global err, req: %v, order: %v, err: %v", util.ToJson(req), util.ToJson(order), err)
}
errTx := v.store.DealTxCR(tx, err)
if errTx != nil {
logger.Error("DealTxCR fail, err: %v", errTx)
return
}
}()
// 检查钱包
wallet, exists := v.CheckWalletExist(ctx, tx, req.Mid)
if !exists {
err = errs.ErrVasWalletNotExist
logger.Error("CheckWalletExist fail, mid: %v, err: %v", req.Mid, err)
return
}
if wallet.GetCoins() <= priceCoin {
err = errs.ErrVasNoEnoughCoin
logger.Error("not enough coin, mid: %v, coins: %v, err: %v", req.Mid, wallet.Coins, err)
return
}
// 扣金币
err = v.store.DecCoins(ctx, tx, req.Mid, priceCoin)
if err != nil {
logger.Error("DecCoins fail, mid: %v, priceCoin: %v, err: %v", req.Mid, priceCoin, err)
return
}
// 添加订单
var (
timeNow = time.Now().Unix()
)
order = &dbstruct.Order{
ID: goproto.String(orderId),
Mid: goproto.Int64(req.Mid),
Uid: goproto.Int64(req.Uid),
Oid1: goproto.String(req.Oid1),
Oid2: goproto.String(req.Oid2),
Oid3: goproto.String(req.Oid3),
ProductId: goproto.String(req.ProductId),
PayType: goproto.String(req.PayType),
PayAmount: goproto.Int64(product.RealPrice),
Coins: goproto.Int64(product.ValueCoins),
OrderStatus: goproto.Int32(dbstruct.VasOrderStatusInit),
OrderFrom: goproto.String(req.From),
Ct: goproto.Int64(timeNow),
Ut: goproto.Int64(timeNow),
Operator: goproto.String(req.Operator),
Did: goproto.String(req.Did),
Version: goproto.String(req.Version),
OsVersion: goproto.String(req.Version),
DevType: goproto.Int32(req.DevType),
Channel: goproto.String(req.Channel),
Model: goproto.String(req.Model),
NetType: goproto.String(req.NetType),
Ip: goproto.String(req.Ip),
}
err = v.store.CreateOrder(ctx, tx, order)
if err != nil {
logger.Error("CreateOrder fail, order: %v, err: %v", util.ToJson(order), err)
return
}
// 提交事务
errTx := v.store.DealTxCR(tx, err)
if errTx != nil {
logger.Error("DealTxCR fail, err: %v", errTx)
err = errTx
return
}
// 手动回调
err = v.PayCallback(ctx, &vasproto.PayCallbackParamIn{
OrderId: orderId,
OutOrderId: fmt.Sprintf("%s_bycoin", orderId),
CallbackPayType: vasproto.CallBackPayTypeCoin,
})
if err != nil {
logger.Error("PayCallback fail, err: %v", err)
return
}
data = &vasproto.CreateOrderData{
OrderId: orderId,
}
return
}
func (v *Vas) CheckWalletExist(ctx *gin.Context, tx *sqlx.Tx, mid int64) (wallet *dbstruct.Wallet, exist bool) {
wallet, err := v.store.GetWalletByMid(ctx, tx, mid)
switch err {
@ -1249,7 +1355,7 @@ func (v *Vas) GetUserWechatUnlock(ctx *gin.Context, mid, uid int64) (uu *dbstruc
}
// 【支付】回调
func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) (err error) {
var (
orderId = p.OrderId
outOrderId = p.OutOrderId
@ -1261,16 +1367,16 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
checkOrder, err := v.store.GetOrderById(ctx, nil, orderId)
if err != nil {
logger.Error("GetOrderById fail, p: %v, err: %v", util.ToJson(p), err)
return
return err
}
if checkOrder == nil {
logger.Warn("GetOrderById nil, p: %v", util.ToJson(p))
return
return err
}
// 是否已处理过的订单
if checkOrder.GetOrderStatus() != dbstruct.VasOrderStatusInit {
logger.Error("repeat deal, p: %v", util.ToJson(p))
return
return err
}
// out_order_id检查
@ -1281,29 +1387,29 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
}
if err != nil {
logger.Error("GetOrderByOutOrderId fail, p: %v, err: %v", util.ToJson(p), err)
return
return err
}
if outOrder != nil {
logger.Error("out order exists, p: %v", util.ToJson(p))
return
return err
}
// 获取商品
product, err := v.store.GetProductById(ctx, checkOrder.GetProductId())
if err != nil {
logger.Error("GetProductById fail, id: %v, err: %v", checkOrder.GetProductId(), err)
return
return err
}
if product == nil {
logger.Error("GetProductById nil, id: %v", checkOrder.GetProductId())
return
return err
}
// 钱包
_, hasWallet := v.CheckWalletExist(ctx, nil, checkOrder.GetMid())
if !hasWallet {
logger.Error("CheckWalletExist fail, mid: %v", checkOrder.GetMid())
return
return err
}
// 解锁信息
@ -1313,7 +1419,7 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
_, hasZoneUnlock := v.CheckZoneUnlockExist(ctx, nil, mid, zid)
if !hasZoneUnlock {
logger.Error("CheckZoneUnlockExist fail, mid: %v, zid: %v", mid, zid)
return
return err
}
}
@ -1321,7 +1427,7 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
tx, err := v.store.VasBegin(ctx)
if err != nil {
logger.Error("vas begin fail, err: %v", err)
return
return err
}
defer func() {
_ = v.AddOplogOrder(
@ -1368,7 +1474,7 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
order, err := v.store.GetOrderByIdForUpdate(ctx, tx, orderId)
if err != nil {
logger.Error("GetOrderByIdForUpdate fail, p: %v", util.ToJson(p))
return
return err
}
// 锁住钱包
@ -1403,14 +1509,14 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
err = v.store.CreateConsumeHistory(ctx, tx, ch)
if err != nil {
logger.Error("CreateConsumeHistory fail, ch: %v, err: %v", util.ToJson(ch), err)
return
return err
}
// 更新状态
err = v.store.UpdateOrderStatus(ctx, tx, orderId, dbstruct.VasOrderStatusInit, dbstruct.VasOrderStatusPaySuccess)
if err != nil {
logger.Error("UpdateOrderStatus fail, p: %v", util.ToJson(p))
return
return err
}
afterStatus = dbstruct.VasOrderStatusPaySuccess
@ -1418,7 +1524,7 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
err = v.store.UpdateOutOrderId(ctx, tx, orderId, outOrderId)
if err != nil {
logger.Error("UpdateOutOrderId fail, p: %v", util.ToJson(p))
return
return err
}
// 商品判断
@ -1428,12 +1534,12 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
err = v.store.IncCoins(ctx, tx, order.GetMid(), order.GetCoins())
if err != nil {
logger.Error("IncCoins fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
err = v.store.UpdateOrderStatus(ctx, tx, orderId, dbstruct.VasOrderStatusPaySuccess, dbstruct.VasOrderStatusFinish)
if err != nil {
logger.Error("UpdateOrderStatus fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
afterStatus = dbstruct.VasOrderStatusFinish
case product.Id == dbstruct.ProductIdH5ContactWechat:
@ -1441,32 +1547,32 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
err = v.store.IncCoins(ctx, tx, order.GetMid(), order.GetCoins())
if err != nil {
logger.Error("IncCoins fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
case product.Id == dbstruct.ProductIdMembership:
// 解锁会员资格
_, err = v.UnlockMembership(ctx, tx, util.DerefInt64(order.Mid), product, order, wallet)
if err != nil {
logger.Error("UnlockMembership fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
case product.Id == dbstruct.ProductIdH5ZoneMoment:
err = v.UnlockZoneMoment(ctx, tx, order)
if err != nil {
logger.Error("UnlockZoneMoment fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
case product.Id == dbstruct.ProductIdH5ZoneAdmission:
err = v.UnlockZoneAdmission(ctx, tx, order, dbstruct.ZoneUnlockTypePay)
if err != nil {
logger.Error("UnlockZoneAdmission fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
case product.Id == dbstruct.ProductIdH5ZoneSuperfanship:
err = v.UnlockZoneSuperfanship(ctx, tx, order, dbstruct.ZoneUnlockTypePay)
if err != nil {
logger.Error("UnlockZoneSuperfanship fail, order: %v, err: %v", util.ToJson(order), err)
return
return err
}
}
@ -1474,8 +1580,9 @@ func (v *Vas) PayCallback(ctx *gin.Context, p *vasproto.PayCallbackParamIn) {
_err := v.UnlockZoneIronfanshipReachConsume(ctx, tx, order.GetMid(), order.GetZid(), order.GetUid())
if _err != nil {
logger.Error("UnlockZoneIronfanshipReachConsume fail, order: %v, err: %v", util.ToJson(order), _err)
return
return err
}
return err
}
func (v *Vas) GetCoinOrderById(ctx *gin.Context, id string) (*dbstruct.CoinOrder, error) {

View File

@ -499,7 +499,7 @@ func (s *Service) H5DirectUnlockWechat(ctx *gin.Context, req *vasproto.H5DirectU
// 支付回调
func (s *Service) PayCallback(ctx *gin.Context, req *vasproto.PayCallbackParamIn) (data *vasproto.H5DirectUnlockWechatData, ec errcode.ErrCode) {
_DefaultVas.PayCallback(ctx, req)
_ = _DefaultVas.PayCallback(ctx, req)
return
}

View File

@ -96,3 +96,7 @@ type Product struct {
Images []*ToCImage `json:"images"`
Videos []*ToCVideo `json:"videos"`
}
func (p Product) GetRealPriceCoin() int64 {
return p.RealPrice / 10
}