---
url: "https://pay.weixin.qq.com/doc/v3/merchant/4012533431-go.md"
title: "查询投诉单列表-请求示例-go"
doc_id: 4012533431
example_lang: "go"
---

## Go


需配合微信支付工具库 wxpay\_utility 使用，请参考 [Go](https://pay.weixin.qq.com/doc/v3/merchant/4015119334.md)

```
package main

import (
	"demo/wxpay_utility" // 引用微信支付工具库，参考 https://pay.weixin.qq.com/doc/v3/merchant/4015119334
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
)

func main() {
	// TODO: 请准备商户开发必要参数，参考：https://pay.weixin.qq.com/doc/v3/merchant/4013070756
	config, err := wxpay_utility.CreateMchConfig(
		"19xxxxxxxx",                 // 商户号，是由微信支付系统生成并分配给每个商户的唯一标识符，商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
		"1DDE55AD98Exxxxxxxxxx",      // 商户API证书序列号，如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
		"/path/to/apiclient_key.pem", // 商户API证书私钥文件路径，本地文件路径
		"PUB_KEY_ID_xxxxxxxxxxxxx",   // 微信支付公钥ID，如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
		"/path/to/wxp_pub.pem",       // 微信支付公钥文件路径，本地文件路径
	)
	if err != nil {
		fmt.Println(err)
		return
	}

	request := &ListComplaintsV2Request{
		Limit:            wxpay_utility.Int64(5),
		Offset:           wxpay_utility.Int64(10),
		BeginDate:        wxpay_utility.String("2019-01-01"),
		EndDate:          wxpay_utility.String("2019-01-01"),
		ComplaintedMchid: wxpay_utility.String("1900012181"),
	}

	response, err := ListComplaintsV2(config, request)
	if err != nil {
		fmt.Printf("请求失败: %+v\n", err)
		// TODO: 请求失败，根据状态码执行不同的处理
		return
	}

	// TODO: 请求成功，继续业务逻辑
	fmt.Printf("请求成功: %+v\n", response)
}

func ListComplaintsV2(config *wxpay_utility.MchConfig, request *ListComplaintsV2Request) (response *ListComplaintsV2Response, err error) {
	const (
		host   = "https://api.mch.weixin.qq.com"
		method = "GET"
		path   = "/v3/merchant-service/complaints-v2"
	)

	reqUrl, err := url.Parse(fmt.Sprintf("%s%s", host, path))
	if err != nil {
		return nil, err
	}
	query := reqUrl.Query()
	if request.Limit != nil {
		query.Add("limit", fmt.Sprintf("%v", *request.Limit))
	}
	if request.Offset != nil {
		query.Add("offset", fmt.Sprintf("%v", *request.Offset))
	}
	if request.BeginDate != nil {
		query.Add("begin_date", *request.BeginDate)
	}
	if request.EndDate != nil {
		query.Add("end_date", *request.EndDate)
	}
	if request.ComplaintedMchid != nil {
		query.Add("complainted_mchid", *request.ComplaintedMchid)
	}
	reqUrl.RawQuery = query.Encode()
	httpRequest, err := http.NewRequest(method, reqUrl.String(), nil)
	if err != nil {
		return nil, err
	}
	httpRequest.Header.Set("Accept", "application/json")
	httpRequest.Header.Set("Wechatpay-Serial", config.WechatPayPublicKeyId())
	authorization, err := wxpay_utility.BuildAuthorization(config.MchId(), config.CertificateSerialNo(), config.PrivateKey(), method, reqUrl.RequestURI(), nil)
	if err != nil {
		return nil, err
	}
	httpRequest.Header.Set("Authorization", authorization)

	client := &http.Client{}
	httpResponse, err := client.Do(httpRequest)
	if err != nil {
		return nil, err
	}
	respBody, err := wxpay_utility.ExtractResponseBody(httpResponse)
	if err != nil {
		return nil, err
	}
	if httpResponse.StatusCode >= 200 && httpResponse.StatusCode < 300 {
		// 2XX 成功，验证应答签名
		err = wxpay_utility.ValidateResponse(
			config.WechatPayPublicKeyId(),
			config.WechatPayPublicKey(),
			&httpResponse.Header,
			respBody,
		)
		if err != nil {
			return nil, err
		}
		response := &ListComplaintsV2Response{}
		if err := json.Unmarshal(respBody, response); err != nil {
			return nil, err
		}

		return response, nil
	} else {
		return nil, wxpay_utility.NewApiException(
			httpResponse.StatusCode,
			httpResponse.Header,
			respBody,
		)
	}
}

type ListComplaintsV2Request struct {
	Limit            *int64  `json:"limit,omitempty"`
	Offset           *int64  `json:"offset,omitempty"`
	BeginDate        *string `json:"begin_date,omitempty"`
	EndDate          *string `json:"end_date,omitempty"`
	ComplaintedMchid *string `json:"complainted_mchid,omitempty"`
}

func (o *ListComplaintsV2Request) MarshalJSON() ([]byte, error) {
	type Alias ListComplaintsV2Request
	a := &struct {
		Limit            *int64  `json:"limit,omitempty"`
		Offset           *int64  `json:"offset,omitempty"`
		BeginDate        *string `json:"begin_date,omitempty"`
		EndDate          *string `json:"end_date,omitempty"`
		ComplaintedMchid *string `json:"complainted_mchid,omitempty"`
		*Alias
	}{
		// 序列化时移除非 Body 字段
		Limit:            nil,
		Offset:           nil,
		BeginDate:        nil,
		EndDate:          nil,
		ComplaintedMchid: nil,
		Alias:            (*Alias)(o),
	}
	return json.Marshal(a)
}

type ListComplaintsV2Response struct {
	Data       []ComplaintInfo `json:"data,omitempty"`
	Limit      *int64          `json:"limit,omitempty"`
	Offset     *int64          `json:"offset,omitempty"`
	TotalCount *int64          `json:"total_count,omitempty"`
}

type ComplaintInfo struct {
	ComplaintId           *string              `json:"complaint_id,omitempty"`
	ComplaintTime         *string              `json:"complaint_time,omitempty"`
	ComplaintDetail       *string              `json:"complaint_detail,omitempty"`
	ComplaintState        *string              `json:"complaint_state,omitempty"`
	PayerPhone            *string              `json:"payer_phone,omitempty"`
	ComplaintOrderInfo    []ComplaintOrderInfo `json:"complaint_order_info,omitempty"`
	ComplaintFullRefunded *bool                `json:"complaint_full_refunded,omitempty"`
	IncomingUserResponse  *bool                `json:"incoming_user_response,omitempty"`
	UserComplaintTimes    *int64               `json:"user_complaint_times,omitempty"`
	ComplaintMediaList    []ComplaintMedia     `json:"complaint_media_list,omitempty"`
	ProblemDescription    *string              `json:"problem_description,omitempty"`
	ProblemType           *ProblemType         `json:"problem_type,omitempty"`
	ApplyRefundAmount     *int64               `json:"apply_refund_amount,omitempty"`
	UserTagList           []UserTag            `json:"user_tag_list,omitempty"`
	ServiceOrderInfo      []ServiceOrderInfo   `json:"service_order_info,omitempty"`
	AdditionalInfo        *AdditionalInfo      `json:"additional_info,omitempty"`
	InPlatformService     *bool                `json:"in_platform_service,omitempty"`
	NeedImmediateService  *bool                `json:"need_immediate_service,omitempty"`
	IsAgentMode           *bool                `json:"is_agent_mode,omitempty"`
}

type ComplaintOrderInfo struct {
	TransactionId *string `json:"transaction_id,omitempty"`
	OutTradeNo    *string `json:"out_trade_no,omitempty"`
	Amount        *int64  `json:"amount,omitempty"`
}

type ComplaintMedia struct {
	MediaType *ComplaintMediaType `json:"media_type,omitempty"`
	MediaUrl  []string            `json:"media_url,omitempty"`
}

type ProblemType string

func (e ProblemType) Ptr() *ProblemType {
	return &e
}

const (
	PROBLEMTYPE_REFUND           ProblemType = "REFUND"
	PROBLEMTYPE_SERVICE_NOT_WORK ProblemType = "SERVICE_NOT_WORK"
	PROBLEMTYPE_OTHERS           ProblemType = "OTHERS"
)

type UserTag string

func (e UserTag) Ptr() *UserTag {
	return &e
}

const (
	USERTAG_TRUSTED   UserTag = "TRUSTED"
	USERTAG_HIGH_RISK UserTag = "HIGH_RISK"
)

type ServiceOrderInfo struct {
	OrderId    *string            `json:"order_id,omitempty"`
	OutOrderNo *string            `json:"out_order_no,omitempty"`
	State      *ServiceOrderState `json:"state,omitempty"`
}

type AdditionalInfo struct {
	Type           *AdditionalType `json:"type,omitempty"`
	SharePowerInfo *SharePowerInfo `json:"share_power_info,omitempty"`
}

type ComplaintMediaType string

func (e ComplaintMediaType) Ptr() *ComplaintMediaType {
	return &e
}

const (
	COMPLAINTMEDIATYPE_USER_COMPLAINT_IMAGE ComplaintMediaType = "USER_COMPLAINT_IMAGE"
	COMPLAINTMEDIATYPE_OPERATION_IMAGE      ComplaintMediaType = "OPERATION_IMAGE"
)

type ServiceOrderState string

func (e ServiceOrderState) Ptr() *ServiceOrderState {
	return &e
}

const (
	SERVICEORDERSTATE_DOING   ServiceOrderState = "DOING"
	SERVICEORDERSTATE_REVOKED ServiceOrderState = "REVOKED"
	SERVICEORDERSTATE_WAITPAY ServiceOrderState = "WAITPAY"
	SERVICEORDERSTATE_DONE    ServiceOrderState = "DONE"
)

type AdditionalType string

func (e AdditionalType) Ptr() *AdditionalType {
	return &e
}

const (
	ADDITIONALTYPE_SHARE_POWER_TYPE AdditionalType = "SHARE_POWER_TYPE"
)

type SharePowerInfo struct {
	ReturnTime              *string            `json:"return_time,omitempty"`
	ReturnAddressInfo       *ReturnAddressInfo `json:"return_address_info,omitempty"`
	IsReturnedToSameMachine *bool              `json:"is_returned_to_same_machine,omitempty"`
}

type ReturnAddressInfo struct {
	ReturnAddress *string `json:"return_address,omitempty"`
	Longitude     *string `json:"longitude,omitempty"`
	Latitude      *string `json:"latitude,omitempty"`
}

```
