From 1920418c317cd1411485f79e15be57a511415208 Mon Sep 17 00:00:00 2001 From: lwl0608 Date: Thu, 30 May 2024 09:48:09 +0800 Subject: [PATCH] fix --- app/mix/service/logic/vas.go | 39 ++++++++++++++++- library/payclients/yeepaycli/client.go | 47 ++++++++++++++++++++- library/payclients/yeepaycli/client_test.go | 10 +++++ 3 files changed, 92 insertions(+), 4 deletions(-) diff --git a/app/mix/service/logic/vas.go b/app/mix/service/logic/vas.go index 0248f431..ed2fbc0d 100644 --- a/app/mix/service/logic/vas.go +++ b/app/mix/service/logic/vas.go @@ -3521,7 +3521,7 @@ func (v *Vas) payRefund(ctx *gin.Context, order *dbstruct.Order) error { } case vasproto.PayTypeYeepayAlipayH5, vasproto.PayTypeYeepayWxpayH5: yeepayCli := yeepaycli.GetDefaultYeepayClient() - resp, err := yeepayCli.RefundOne(ctx, &yeepaycli.RefundOneParam{ + resp, refundRequestId, err := yeepayCli.RefundOne(ctx, &yeepaycli.RefundOneParam{ OutTradeNo: orderId, RefundAmount: order.GetPayAmount(), RefundReason: "用户退款", @@ -3530,11 +3530,46 @@ func (v *Vas) payRefund(ctx *gin.Context, order *dbstruct.Order) error { logger.Error("wxpayCli.RefundOne fail, orderId: %v, resp: %v, err: %v", orderId, util.ToJson(resp), err) return err } - if resp.Status != "SUCCESS" { + if resp.Code != "OPR00000" { err = fmt.Errorf("退款失败,请稍后再试") logger.Error("wxpayCli.RefundOne fail, orderId: %v, resp: %v, err: %v", orderId, util.ToJson(resp), err) return err } + + // 轮询退款结果,达到同步退款效果 + var ( + loop = 0 + isRefundSuccess = false + ) + for range time.Tick(time.Second * 1) { + if loop >= 10 { + break + } + qRefundResp, _err := yeepayCli.QueryRefund(ctx, &yeepaycli.QueryRefundParam{ + OutTradeNo: orderId, + RefundRequestId: refundRequestId, + }) + if _err != nil { + logger.Error("loop: %v, yeepayCli.QueryRefund fail, orderId: %v, resp: %v, err: %v", loop, orderId, util.ToJson(qRefundResp), _err) + continue + } + if qRefundResp.Code != "OPR00000" { + logger.Error("loop: %v, yeepayCli.QueryRefund fail, invalid code, orderId: %v, resp: %v", loop, orderId, util.ToJson(qRefundResp)) + continue + } + if qRefundResp.Status == "SUCCESS" { + logger.Info("loop: %v, yeepayCli.QueryRefund ok, orderId: %v, resp: %v", loop, orderId, util.ToJson(qRefundResp)) + isRefundSuccess = true + break + } + loop++ + } + if !isRefundSuccess { + err = fmt.Errorf("退款失败,请稍后再试") + logger.Error("wxpayCli.RefundOne fail, orderId: %v", orderId) + return err + } + logger.Info("wxpayCli.RefundOne success, orderId: %v", orderId) } return nil } diff --git a/library/payclients/yeepaycli/client.go b/library/payclients/yeepaycli/client.go index 7e93fbee..85305841 100644 --- a/library/payclients/yeepaycli/client.go +++ b/library/payclients/yeepaycli/client.go @@ -175,14 +175,15 @@ type RefundOneResp struct { RefundCsFinishDate string `json:"refundCsFinishDate"` } -func (c *YeepayClient) RefundOne(ctx context.Context, param *RefundOneParam) (resp *RefundOneResp, err error) { +func (c *YeepayClient) RefundOne(ctx context.Context, param *RefundOneParam) (resp *RefundOneResp, refundRequestId string, err error) { + refundRequestId = idgenerator.GenYeepayRefundId() req := request.NewYopRequest(constants.POST_HTTP_METHOD, "/rest/v1.0/trade/refund") req.AppId = c.AppId req.IsvPriKey = request.IsvPriKey{Value: c.PrivateKey, CertType: request.RSA2048} req.AddParam("parentMerchantNo", c.ParentMerchantNo) req.AddParam("merchantNo", c.MerchantNo) req.AddParam("orderId", param.OutTradeNo) - req.AddParam("refundRequestId", idgenerator.GenYeepayRefundId()) + req.AddParam("refundRequestId", refundRequestId) req.AddParam("refundAmount", fmt.Sprintf("%.2f", float64(param.RefundAmount)/100.0)) respMeta, err := c.client.Request(req) @@ -198,3 +199,45 @@ func (c *YeepayClient) RefundOne(ctx context.Context, param *RefundOneParam) (re } // 查询退款 +type QueryRefundParam struct { + OutTradeNo string // 商家订单id,我们自己的订单id + RefundRequestId string +} + +type QueryRefundResp struct { + Code string `json:"code"` + Message string `json:"message"` + ParentMerchantNo string `json:"parentMerchantNo"` + MerchantNo string `json:"merchantNo"` + OrderId string `json:"orderId"` + RefundRequestId string `json:"refundRequestId"` + UniqueRefundNo string `json:"uniqueRefundNo"` + Status string `json:"status"` + RefundAmount string `json:"refundAmount"` + RefundRequestDate string `json:"refundRequestDate"` + RefundMerchantFee string `json:"refundMerchantFee"` + RefundAccountDetail string `json:"refundAccountDetail"` + RefundCsFinishDate string `json:"refundCsFinishDate"` +} + +func (c *YeepayClient) QueryRefund(ctx context.Context, param *QueryRefundParam) (resp *QueryRefundResp, err error) { + req := request.NewYopRequest(constants.GET_HTTP_METHOD, "/rest/v1.0/trade/refund/query") + req.AppId = c.AppId + req.ServerRoot = request.SERVER_ROOT + req.IsvPriKey = request.IsvPriKey{Value: c.PrivateKey, CertType: request.RSA2048} + req.AddParam("parentMerchantNo", c.ParentMerchantNo) + req.AddParam("merchantNo", c.MerchantNo) + req.AddParam("orderId", param.OutTradeNo) + req.AddParam("refundRequestId", param.RefundRequestId) + + respMeta, err := c.client.Request(req) + if err != nil { + logger.Error("yeepay RefundOne fail, param: %v, respMeta: %v, err: %v", util.ToJson(req.Params), util.ToJson(respMeta), err) + return + } + resp = new(QueryRefundResp) + b, _ := json.Marshal(respMeta.Result) + _ = json.Unmarshal(b, resp) + logger.Info("yeepay QueryRefund param: %v, resp: %v", util.ToJson(req.Params), util.ToJson(resp)) + return +} diff --git a/library/payclients/yeepaycli/client_test.go b/library/payclients/yeepaycli/client_test.go index 4a8aa243..1ada1838 100644 --- a/library/payclients/yeepaycli/client_test.go +++ b/library/payclients/yeepaycli/client_test.go @@ -61,3 +61,13 @@ func TestYeepayClient_ParseNotify(t *testing.T) { fmt.Println("Payment Info:", paymentInfo) } + +func TestYeepayClient_QueryRefund(t *testing.T) { + cli := GetDefaultYeepayClient() + resp, err := cli.QueryRefund(nil, &QueryRefundParam{ + OutTradeNo: "1795300011844579328", + RefundRequestId: "1795652043868880896", + }) + t.Log(err) + t.Log(util.ToJson(resp)) +}