f
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user