This commit is contained in:
Mrx
2026-06-07 14:39:21 +08:00
parent f9ec2e51fd
commit 0dada87a54
6 changed files with 113 additions and 29 deletions

View File

@@ -197,6 +197,20 @@ type xpayOrderStatus struct {
LeftFee int64 `json:"left_fee"`
OrderID string `json:"order_id"`
WxOrderID string `json:"wx_order_id"`
ErrMsg string `json:"err_msg"`
RawOrder string `json:"-"` // query_order 原始 order JSON便于日志排查
}
// XpayAPIError 微信 xpay 接口返回 errcode != 0
type XpayAPIError struct {
URI string
ErrCode int
ErrMsg string
RawBody string
}
func (e *XpayAPIError) Error() string {
return fmt.Sprintf("xpay %s errcode=%d errmsg=%s body=%s", e.URI, e.ErrCode, e.ErrMsg, e.RawBody)
}
func (s *XpayService) callAPI(ctx context.Context, uri, bodyJSON, sessionKey string, needSignature bool) (*xpayAPIResp, error) {
@@ -220,18 +234,32 @@ func (s *XpayService) callAPI(ctx context.Context, uri, bodyJSON, sessionKey str
}
req.Header.Set("Content-Type", "application/json")
logx.WithContext(ctx).Infof("[xpay] req uri=%s env=%d body=%s", uri, s.Env(), bodyJSON)
httpResp, err := http.DefaultClient.Do(req)
if err != nil {
logx.WithContext(ctx).Errorf("[xpay] http err uri=%s err=%v", uri, err)
return nil, err
}
defer httpResp.Body.Close()
respBody, _ := io.ReadAll(httpResp.Body)
respStr := string(respBody)
var apiResp xpayAPIResp
if err := json.Unmarshal(respBody, &apiResp); err != nil {
return nil, fmt.Errorf("解析 xpay 响应失败: %w, body=%s", err, string(respBody))
logx.WithContext(ctx).Errorf("[xpay] parse err uri=%s http=%d body=%s err=%v", uri, httpResp.StatusCode, respStr, err)
return nil, fmt.Errorf("解析 xpay 响应失败: %w, body=%s", err, respStr)
}
logx.WithContext(ctx).Infof("[xpay] resp uri=%s http=%d errcode=%d errmsg=%s body=%s",
uri, httpResp.StatusCode, apiResp.ErrCode, apiResp.ErrMsg, respStr)
if apiResp.ErrCode != 0 {
return &apiResp, &XpayAPIError{
URI: uri,
ErrCode: apiResp.ErrCode,
ErrMsg: apiResp.ErrMsg,
RawBody: respStr,
}
}
logx.WithContext(ctx).Infof("[xpay] call uri=%s body=%s", uri, string(respBody))
return &apiResp, nil
}
@@ -250,11 +278,12 @@ func (s *XpayService) QueryOrder(ctx context.Context, openid, orderNo, sessionKe
// 官方文档query_order 仅需 pay_sig不需用户态 signature
apiResp, err := s.callAPI(ctx, "/xpay/query_order", bodyJSON, "", false)
if err != nil {
if xpayErr, ok := err.(*XpayAPIError); ok {
logx.WithContext(ctx).Errorf("[xpay] query_order FAIL order_no=%s openid=%s errcode=%d errmsg=%s raw=%s",
orderNo, openid, xpayErr.ErrCode, xpayErr.ErrMsg, xpayErr.RawBody)
}
return nil, err
}
if apiResp.ErrCode != 0 {
return nil, fmt.Errorf("query_order errcode=%d errmsg=%s", apiResp.ErrCode, apiResp.ErrMsg)
}
orderRaw := apiResp.Order
if len(orderRaw) == 0 {
@@ -262,8 +291,11 @@ func (s *XpayService) QueryOrder(ctx context.Context, openid, orderNo, sessionKe
}
var status xpayOrderStatus
if len(orderRaw) > 0 {
status.RawOrder = string(orderRaw)
_ = json.Unmarshal(orderRaw, &status)
}
logx.WithContext(ctx).Infof("[xpay] query_order order_no=%s status=%d paid_fee=%d left_fee=%d wx_order_id=%s err_msg=%s raw=%s",
orderNo, status.Status, status.PaidFee, status.LeftFee, status.WxOrderID, status.ErrMsg, status.RawOrder)
return &status, nil
}
@@ -306,11 +338,17 @@ func (s *XpayService) RefundOrder(ctx context.Context, openid, orderNo, refundOr
apiResp, err := s.callAPI(ctx, "/xpay/refund_order", bodyJSON, "", false)
if err != nil {
if xpayErr, ok := err.(*XpayAPIError); ok {
if xpayErr.ErrCode == 268490004 || xpayErr.ErrCode == 268490014 {
logx.WithContext(ctx).Infof("[xpay] refund_order idempotent order_no=%s errcode=%d", orderNo, xpayErr.ErrCode)
return nil
}
logx.WithContext(ctx).Errorf("[xpay] refund_order FAIL order_no=%s errcode=%d errmsg=%s raw=%s",
orderNo, xpayErr.ErrCode, xpayErr.ErrMsg, xpayErr.RawBody)
}
return err
}
if apiResp.ErrCode != 0 && apiResp.ErrCode != 268490004 && apiResp.ErrCode != 268490014 {
return fmt.Errorf("refund_order errcode=%d errmsg=%s", apiResp.ErrCode, apiResp.ErrMsg)
}
_ = apiResp
logx.WithContext(ctx).Infof("[xpay] refund_order OK order_no=%s refund_order_id=%s fee=%d", orderNo, refundOrderID, refundFeeFen)
return nil
}
@@ -330,13 +368,18 @@ func (s *XpayService) NotifyProvideGoods(ctx context.Context, openid, orderNo, w
return err
}
apiResp, err := s.callAPI(ctx, "/xpay/notify_provide_goods", bodyJSON, sessionKey, true)
_, err = s.callAPI(ctx, "/xpay/notify_provide_goods", bodyJSON, sessionKey, true)
if err != nil {
if xpayErr, ok := err.(*XpayAPIError); ok {
if xpayErr.ErrCode == 268490004 {
logx.WithContext(ctx).Infof("[xpay] notify_provide_goods idempotent order_no=%s", orderNo)
return nil
}
logx.WithContext(ctx).Errorf("[xpay] notify_provide_goods FAIL order_no=%s errcode=%d errmsg=%s raw=%s",
orderNo, xpayErr.ErrCode, xpayErr.ErrMsg, xpayErr.RawBody)
}
return err
}
if apiResp.ErrCode != 0 && apiResp.ErrCode != 268490004 {
return fmt.Errorf("notify_provide_goods errcode=%d errmsg=%s", apiResp.ErrCode, apiResp.ErrMsg)
}
logx.WithContext(ctx).Infof("[xpay] notify_provide_goods OK order_no=%s", orderNo)
return nil
}