deal_one_order

This commit is contained in:
lwl0608 2024-02-03 17:23:08 +08:00
parent 13ec1265e3
commit d4011adb92
9 changed files with 217 additions and 9 deletions

View File

@ -42,3 +42,7 @@ type OpCoinOrderListData struct {
type DealOneCoinOrderReq struct {
CoinOrderId string `json:"coin_order_id"`
}
type DealOneOrderReq struct {
OrderId string `json:"order_id"`
}

View File

@ -215,6 +215,7 @@ func Init(r *gin.Engine) {
vasPayGroup.POST("withdraw_send_verifycode", middleware.JSONParamValidator(vasproto.WithdrawSendVerifycodeReq{}), WithdrawSendVerifycode)
vasPayGroup.POST("withdraw_apply", middleware.JSONParamValidator(vasproto.WithdrawApplyReq{}), WithdrawApply)
vasPayGroup.POST("deal_one_coin_order", middleware.JSONParamValidator(vasproto.DealOneCoinOrderReq{}), DealOneCoinOrder)
vasPayGroup.POST("deal_one_order", middleware.JSONParamValidator(vasproto.DealOneOrderReq{}), DealOneOrder)
extVasPayGroup := r.Group("/ext/vas")
extVasPayGroup.POST("alipay_callback", AlipayCallback)

View File

@ -261,9 +261,29 @@ func WithdrawApply(ctx *gin.Context) {
// 处理一个订单
func DealOneCoinOrder(ctx *gin.Context) {
req := ctx.MustGet("client_req").(*vasproto.DealOneCoinOrderReq)
ec := service.DefaultService.DealOneCoinOrder(ctx, req)
ec, err := service.DefaultService.DealOneCoinOrder(ctx, req)
if ec != errcode.ErrCodeVasSrvOk {
logger.Error("DealOneCoinOrder fail, req: %v, ec: %v", util.ToJson(req), ec)
if err != nil {
ReplyErrorMsg(ctx, err.Error())
return
}
ReplyErrCodeMsg(ctx, ec)
return
}
ReplyOk(ctx, nil)
}
// 处理一个订单
func DealOneOrder(ctx *gin.Context) {
req := ctx.MustGet("client_req").(*vasproto.DealOneOrderReq)
ec, err := service.DefaultService.DealOneOrder(ctx, req)
if ec != errcode.ErrCodeVasSrvOk {
logger.Error("DealOneOrder fail, req: %v, ec: %v", util.ToJson(req), ec)
if err != nil {
ReplyErrorMsg(ctx, err.Error())
return
}
ReplyErrCodeMsg(ctx, ec)
return
}

View File

@ -792,6 +792,7 @@ func (v *Vas) OneStepUnlockContact(ctx *gin.Context, req *vasproto.OneStepUnlock
ID: goproto.String(coinOrderId),
Mid: goproto.Int64(req.Mid),
Uid: goproto.Int64(req.Uid),
Oid1: goproto.String(fmt.Sprintf("%d", req.InviterMid)),
ProductId: goproto.String(contactProductId),
Coins: goproto.Int64(coinPrice),
Ct: goproto.Int64(timeNow),
@ -1939,7 +1940,7 @@ func (v *Vas) WithdrawApply(ctx *gin.Context, req *vasproto.WithdrawApplyReq) (t
return
}
// 结算订单
// 结算金币订单
func (v *Vas) DealOneCoinOrder(ctx *gin.Context, coinOrderId string) (err error) {
coinOrder, err := v.store.GetCoinOrderById(ctx, nil, coinOrderId)
if err != nil {
@ -2010,6 +2011,7 @@ func (v *Vas) DealOneCoinOrder(ctx *gin.Context, coinOrderId string) (err error)
BeforeWithdrawDiamonds: goproto.Int64(wallet.GetWithdrawDiamonds()),
AfterWithdrawDiamonds: goproto.Int64(wallet.GetWithdrawDiamonds() + ch.GetChange()),
Change: goproto.Int64(ch.GetChange()),
ProductId: goproto.String(coinOrder.GetProductId()),
}
errIn = v.store.CreateWithdrawDiamondsHis(ctx, tx, h)
if errIn != nil {
@ -2036,6 +2038,139 @@ func (v *Vas) DealOneCoinOrder(ctx *gin.Context, coinOrderId string) (err error)
return
}
// 结算订单
func (v *Vas) DealOneOrder(ctx *gin.Context, orderId string) (err error) {
order, err := v.store.GetOrderById(ctx, nil, orderId)
if err != nil {
logger.Error("GetCoinOrderById fail, id: %v, err: %v", orderId, err)
return
}
if order == nil {
err = errs.ErrVasOrderNotExists
logger.Error("GetCoinOrderById fail nil, id: %v, err: %v", orderId, err)
return
}
// 支付宝查询订单
alipayCli := alipaycli.GetDefaultAlipayClient()
alipayResp, err := alipayCli.QueryOrder(ctx, &alipaycli.QueryOrderParam{
OutTradeNo: orderId,
})
if err != nil {
logger.Error("alipayCli.QueryOrder fail, id: %v, err: %v", orderId, err)
return
}
if alipayResp == nil {
err = errors.New("alipayCli.QueryOrder resp nil")
logger.Error("alipayCli.QueryOrder nil, id: %v, err: %v", orderId, err)
return
}
// 已退款
if alipayResp.Response.TradeStatus == "TRADE_CLOSED" {
// 更新订单状态
err = v.store.UpdateOrderStatus(ctx, nil, order.GetID(), dbstruct.VasOrderStatusPaySuccess, dbstruct.VasOrderStatusRefund)
if err != nil {
logger.Error("UpdateOrderStatus fail, orderId: %v, err: %v", order.GetID(), err)
return
}
err = errors.New("closed order")
return
}
// 判断时间小于7天不处理
if time.Now().Unix()-order.GetCt() < 7*86400 {
logger.Info("DealOneCoinOrder ct fail, order: %v", order.ToString())
return
}
if order.GetOrderStatus() >= dbstruct.VasOrderStatusFinish {
err = errors.New("repeat deal")
logger.Info("DealOneCoinOrder status fail, order: %v", order.ToString())
return
}
// 开启事务
tx, err := v.store.VasBegin(ctx)
if err != nil {
logger.Error("vas begin fail, err: %v", err)
return
}
defer func() {
if err != nil {
logger.Error("global err, order: %v, err: %v", util.ToJson(order), err)
}
errTx := v.store.DealTxCR(tx, err)
if errTx != nil {
logger.Error("DealTxCR fail, err: %v", errTx)
return
}
}()
switch order.GetProductId() {
case dbstruct.ProductIdMembership:
return v.dealOneMembershipOrder(ctx, tx, order)
}
return
}
// 结算会员订单
func (v *Vas) dealOneMembershipOrder(ctx *gin.Context, tx *sqlx.Tx, order *dbstruct.Order) (err error) {
// 把订单对应的收入记录拿出来
chList, err := v.store.GetIncomeCHList(ctx, tx, order.GetID())
if err != nil {
logger.Error("GetIncomeCHList fail, orderId: %v, err: %v", order.GetID(), err)
return
}
// 处理
for _, ch := range chList {
if ch.GetMid() == common.OfficialMid {
continue
}
// 获取钱包
wallet, errIn := v.store.GetWalletForUpdate(ctx, tx, ch.GetMid())
if errIn != nil {
logger.Error("GetWalletForUpdate fail, mid: %v, err: %v", ch.GetMid(), errIn)
err = errIn
return
}
// 添加记录
h := &dbstruct.WithdrawDiamondsHis{
Mid: goproto.Int64(ch.GetMid()),
IncomeChId: goproto.Int64(ch.GetId()),
OrderId: goproto.String(ch.GetOrderId()),
Ct: goproto.Int64(time.Now().Unix()),
BeforeWithdrawDiamonds: goproto.Int64(wallet.GetWithdrawDiamonds()),
AfterWithdrawDiamonds: goproto.Int64(wallet.GetWithdrawDiamonds() + ch.GetChange()),
Change: goproto.Int64(ch.GetChange()),
ProductId: goproto.String(order.GetProductId()),
}
errIn = v.store.CreateWithdrawDiamondsHis(ctx, tx, h)
if errIn != nil {
logger.Error("CreateWithdrawDiamondsHis fail, mid: %v, err: %v", ch.GetMid(), errIn)
err = errIn
return
}
// 更新钱包
errIn = v.store.IncWithdrawDiamonds(ctx, tx, ch.GetMid(), ch.GetChange())
if errIn != nil {
logger.Error("IncWithdrawDiamonds fail, mid: %v, change: %v, err: %v", ch.GetMid(), ch.GetChange(), errIn)
err = errIn
return
}
}
// 更新订单状态
err = v.store.UpdateOrderStatus(ctx, tx, order.GetID(), dbstruct.VasOrderStatusPaySuccess, dbstruct.VasOrderStatusFinish)
if err != nil {
logger.Error("UpdateOrderStatus fail, orderId: %v, err: %v", order.GetID(), err)
return
}
return
}
// 解锁会员资格
func (v *Vas) UnlockMembership(ctx *gin.Context, mid int64, product *dbstruct.Product, order *dbstruct.Order, wallet *dbstruct.Wallet) (orderId string, err error) {

View File

@ -502,11 +502,23 @@ func (s *Service) OpCoinOrderList(ctx *gin.Context, req *vasproto.OpCoinOrderLis
return
}
func (s *Service) DealOneCoinOrder(ctx *gin.Context, req *vasproto.DealOneCoinOrderReq) (ec errcode.ErrCode) {
err := _DefaultVas.DealOneCoinOrder(ctx, req.CoinOrderId)
ec, err = errs.DealVasErr(err)
func (s *Service) DealOneCoinOrder(ctx *gin.Context, req *vasproto.DealOneCoinOrderReq) (ec errcode.ErrCode, err error) {
ec = errcode.ErrCodeVasSrvOk
err = _DefaultVas.DealOneCoinOrder(ctx, req.CoinOrderId)
if err != nil {
logger.Error("DealOneCoinOrder fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeVasSrvFail
return
}
return
}
func (s *Service) DealOneOrder(ctx *gin.Context, req *vasproto.DealOneOrderReq) (ec errcode.ErrCode, err error) {
ec = errcode.ErrCodeVasSrvOk
err = _DefaultVas.DealOneOrder(ctx, req.OrderId)
if err != nil {
logger.Error("DealOneCoinOrder fail, req: %v, err: %v", util.ToJson(req), err)
ec = errcode.ErrCodeVasSrvFail
return
}
return

View File

@ -30,6 +30,7 @@ CREATE TABLE `vas_order`
);
CREATE INDEX out_order_id ON vas_order (out_order_id);
CREATE INDEX ct_status ON vas_order (ct, order_status);
CREATE INDEX ix_ct_productid ON vas_order (ct, product_id);
CREATE TABLE `vas_wallet`
(

View File

@ -804,6 +804,7 @@ type WithdrawDiamondsHis struct {
BeforeWithdrawDiamonds *int64 `json:"before_withdraw_diamonds" db:"before_withdraw_diamonds"`
AfterWithdrawDiamonds *int64 `json:"after_withdraw_diamonds" db:"after_withdraw_diamonds"`
Change *int64 `json:"change" db:"change"`
ProductId *string `json:"product_id" db:"product_id"`
}
func (p *WithdrawDiamondsHis) GetMid() int64 {

View File

@ -34,10 +34,15 @@ func Init(cfg *configcenter.AlipayClientConfig) (err error) {
}
alipayCli.SetNotifyUrl(cfg.NotifyUrl)
//err = alipayCli.SetCertSnByPath(
// "/app/wishpal-ironfan/etc/mix/alipaycert/appCertPublicKey_2021004115647165.crt",
// "/app/wishpal-ironfan/etc/mix/alipaycert/alipayRootCert.crt",
// "/app/wishpal-ironfan/etc/mix/alipaycert/alipayCertPublicKey_RSA2.crt",
//)
err = alipayCli.SetCertSnByPath(
"/app/wishpal-ironfan/etc/mix/alipaycert/appCertPublicKey_2021004115647165.crt",
"/app/wishpal-ironfan/etc/mix/alipaycert/alipayRootCert.crt",
"/app/wishpal-ironfan/etc/mix/alipaycert/alipayCertPublicKey_RSA2.crt",
"/Users/erwin/wishpalv2/service/etc/mix/alipaycert/appCertPublicKey_2021004115647165.crt",
"/Users/erwin/wishpalv2/service/etc/mix/alipaycert/alipayRootCert.crt",
"/Users/erwin/wishpalv2/service/etc/mix/alipaycert/alipayCertPublicKey_RSA2.crt",
)
if err != nil {
logger.Error("SetCertSnByPath fail, cfg: %v, err: %v", util.ToJson(cfg), err)
@ -157,3 +162,19 @@ func (c *AlipayClient) UniTransfer(ctx context.Context, param *UniTransferParam)
logger.Info("alipay UniTransfer param: %v, resp: %v", bm.JsonBody(), util.ToJson(resp))
return
}
// 订单查询
type QueryOrderParam struct {
OutTradeNo string // 商家订单id我们自己的订单id
}
func (c *AlipayClient) QueryOrder(ctx context.Context, param *QueryOrderParam) (resp *alipay.TradeQueryResponse, err error) {
bm := gopay.BodyMap{
"out_trade_no": param.OutTradeNo,
}
resp, err = c.TradeQuery(ctx, bm)
if err != nil {
return
}
return
}

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"os"
"service/bizcommon/util"
"service/library/configcenter"
"service/library/idgenerator"
"testing"
@ -12,7 +13,7 @@ import (
func TestMain(m *testing.M) {
cfg := &configcenter.AlipayClientConfig{
Appid: "2021004115647165",
PrivateKey: "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCeA8ADj0arLzUK5B3R5bqbOkXm8TBe0dI6XpefxnHeNyksEFhQuWTFtQA550lGj/VMyNQC0R+gL6VK/5SdgonzxMx8bC+/1lIWrl3Q8F+JLsAUcNh6C+WzDw7m5YSrG9361f3+i/gPVC4GRTzx91qLdk1ySGZv/GpSVv49k9qtD83gRCbxJq5FY1QA83Wb5xkJoMwl+SlKvFLNxIIzPQh9DvDF+32FTsVQgm3sX1lsArTA4yp7Y4SG3A8mkOanidYX1KiUawMBWaDgZi1CMpQ+Zbb3w0C0txCeZ8ek5JeUw2EYHJ0awMnFE6+vPDm1LNJ0DodkvszGbmLvXQS2eMfVAgMBAAECggEABj1nq7xQshnfIlr3wn4r7E1UzVXg7x2iC6QIoMqZXIkZGyBaHHX1wMjxBVhY0GyG501W8fWIJi87e8az+7RX9kRjPtaW3CB+hV7FXabgXu51r1j1c3xcycFieUO/BXLIRUuGCDNGzHQqjRzW10dJUBCP5l9tjCaPnEjLKWtZS1QwhtmjmAJalC+oQLnhvlmURSWwyvIIgrqK82DZj5DFgXrxlah21Sou/N4xV/W/d0OkaouDxHtQ4Oy/yE/oc2z+vbcBcHrIt+r2g8gymKPdsDFyglUqZeNRlwYnifSUH7Bmn+1uiXAi86RlUdtCYngNUUNoOStB9oC7gidPHyeb0QKBgQDV58AFBOCHdG2gO+VvKiIpbquWMYTbmbRGmCai911G6zX8X/37nawKWZkyk4kIkrohZtwwL5s6AIlD5F9nRBp+Uk1QvlIYokD3vjUuVPyvpC3raASUvTs0WoWbq3gfPH5Qn5vS1C89CQ/68FC+89CYiexxwq7ybX86lzhYGpRXrwKBgQC9HE7e5Cr9akJrUuPW8NjbKATYg2h8s3/FMa4AbeTLPSEPPp20yRGA5P0xPgV1JocfmVd3VC6ivF6YHKKVnKoVbR74InCi4hhriGb3uLz7i6ngjcxysBfOlKA8lOlMAMY4ZrE2zTp2mUKF1Wp3a0IiC0xGPmdh44xvrO8h4UK1uwKBgGkY3Lealdb31YUM6MWdpftFbPj2i5h6BKFK0HDxqNrXZkcBwwCFj6nmK+c1pfaYYOtYZocmXNY6vTamVlmelIXMWkB5wkxoLBONWQPSrfR+bjFjghyyfQxUDaFWtkZiqo1iXmVP64XJlhhtSr8HfE32Nj4OsXZbZk+bTQu8w3XxAoGBAJJg3wvYQQ52uYKpXoJ5WuIIT/fnf3FG35ebpLvgVECcyIIsTZYqLMpAdVswTrknYWAsKW/MUWzVscK8J3z3DxAWruoSfm0V5SEXK9yDuoRazttp5t6/Py5ADOfXu92Am+38Tx/EK4SxjLRbRVW6SC5h4GBe3Vb/8yxeB5uJ6UERAoGAbsCHaS1NW21qYxeWAD8XC1x8B5vLwcVILP0kIt5CPFgKRcRbJPEfnSF8fFC0OKwJrp32+AhMTOEISwJVkR10Jzqn7VU1bu7lHYkiiOIZJCb1cdjfPxYUR60vpIttoKuz+CBIgc0zo1tu3TgCVdCy//coVRCoLeK+JawP43VLJ+g=",
PrivateKey: "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtj6Nu2olEB8c8SDSANExaPbmk8LoYPEGB/APZDskhezO/w4OwPmG1Ak79XDpUUIihdmTZ8i2nBLhhRpFZGU4MMdil4X7a5nYHBm5dkGo3isIInn/qV7AYDqek4pGpMUPI6fbR05NWnUTZ+3AvMjTNBa979MgLyqS3jzpvuK6yXM5RinKVv8IF9KgthRKjH4LHyyRXBGu2cJSA5utjzFCL9KIu/T4XXZ09HOgz+JKPxXDj25Ob5eTtcBDsoJfXChcOvwCA7nxb1jzvGDrkqF36H1CC8KT1aoLRLisBsM+7sjEfNcB4RG5pGHSDGQJwZ0stGAhXf/fuWiLmI/zMOXODAgMBAAECggEAEL7CAuj8w16Iv20r+46QK0i3R42eNsZhf5wD9wYxK5TKal7/rppmLOObIWCrlATtGb7lfg2aj/mpnGEFlvYVDKImh+KYrZ/8lTLupQJQ7SjrDY/VQZPSPo/zZrohWZSSOKkyEg56samcwfc7XKJYa8t3odr9Df4wJDGibrL/z99xrJrz85le+NHBISXUyddS5ojuDNfGwE39wgLu52P74QYxv6s0xZKj2aALXaLXyTzF4ys34nVhhv75gXFtENiUet5/PVRYe7OE4cndcOP9WI3nXP5ojak8N4fY15S0YOm/0NZP8w6nWUemFjUNRXYRY42J+W+/myW8RIppaGuwkQKBgQDYH263Lh8C9EkjGA2po68LUTBhM2fT2L3batzHjXo0jvLT0IR88/9V7xhC3ZQZNcxQCK0xaCYfzFx3UV9veC1zeVRW0i/hyJ8B40w3WXCoGDiHgzQ/kcu/Iaw2qmJyhEFzOwAfrxIgco9EiZBaY7fXyy7YkZLGqXNFcLsuWR5qWwKBgQDNlc19CESIukT31Ap2QBe6t9YNXHZuKTePBRaIUCan3vZwPfZePLJQCgtoVhnCGoHZJ+ZlNhYri9x6DNLZpxCSHZNjccmqFGj3N7xWBqU38gu2dcPdMAxT1ERwf2gdlhgWAhVzD56hsWyrbP9YZACXy7TlevSj7s/5GaNaVuHT+QKBgQC2VZZ3zt51BJnrlLB6LVFRz/ZsGw1+qj5LLpYDeXXff7aYQzRzovsJigVC7GO0/TFZWGid5Us8ypI8TBejGJXn9TXVZdDlwPd9hUFY9QlZl82hbm0XMK7fms4K9KbIDJKXX/CTyoUVgPEkFpcF21lQIuhr6C0XlABfVmNlD+TcPwKBgHJuot2ov3UXsZH8/gHKNSsibswrHmS9HobGPz+K1al1Stk5NCxKPrqcjLL70gSf+ozkT7MggwCkLgnln2u1OV0Lh2HAEY9RIwgQhw2fT1GvseNS873no8T5j0rLMCnfxPJjIItWM2cvOhzFY/BQYaAcrElbwlaJdEvkgG+lkrgJAoGBAInYRdHo9V1exDUS0ucQuraoEtuvgOrqatnCbuNZ9EpgjFJxDbHXOIJYPvgfpyws4amdksNQL0Ux9+p+esJOS+JYYkE1nmCTCrfb6SNKr+PdeUteKtTiHJb4zJhGVC2Lk4uBg9AGa/d7j5apWw4RsZ/R1ky1S6KQUkqItbVrhC8l",
NotifyUrl: "",
}
err := Init(cfg)
@ -37,3 +38,15 @@ func TestAlipayClient_AppPay(t *testing.T) {
}
fmt.Println(paramStr)
}
func TestAlipayClient_QueryOrder(t *testing.T) {
cli := GetDefaultAlipayClient()
resp, err := cli.QueryOrder(context.Background(), &QueryOrderParam{
OutTradeNo: "1750539072771731456",
})
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(util.ToJson(resp))
}