---
url: "https://pay.weixin.qq.com/doc/v3/merchant/4017151596-java.md"
title: "回复需要即时服务的投诉单-请求示例-java"
doc_id: 4017151596
example_lang: "java"
---

## Java


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

```
package com.java.demo;

import com.java.utils.WXPayUtility; // 引用微信支付工具库，参考：https://pay.weixin.qq.com/doc/v3/merchant/4014931831

import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 回复需要即时服务的投诉单
 */
public class ResponseComplaintImmediateService {
  private static String HOST = "https://api.mch.weixin.qq.com";
  private static String METHOD = "POST";
  private static String PATH = "/v3/merchant-service/complaints-v2/{complaint_id}/response-immediate-service";

  public static void main(String[] args) {
    // TODO: 请准备商户开发必要参数，参考：https://pay.weixin.qq.com/doc/v3/merchant/4013070756
    ResponseComplaintImmediateService client = new ResponseComplaintImmediateService(
      "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"           // 微信支付公钥文件路径，本地文件路径
    );

    ResponseComplaintImmediateServiceRequest request = new ResponseComplaintImmediateServiceRequest();
    request.complaintId = "200201820200101080076610000";
    request.complaintedMchid = "1900000001";
    request.message = new NormalMessage();
    request.message.blocks = new ArrayList<>();
    {
      Block blocksItem = new Block();
      blocksItem.type = BlockType.TEXT;
      blocksItem.text = new Text();
      blocksItem.text.text = "example_text";
      blocksItem.text.color = TextColor.DEFAULT;
      blocksItem.text.isBold = false;
      blocksItem.image = new Image();
      blocksItem.image.mediaId = "example_media_id";
      blocksItem.image.imageStyleType = ImageStyleType.IMAGE_STYLE_TYPE_NARROW;
      blocksItem.link = new Link();
      blocksItem.link.text = "example_text";
      blocksItem.link.action = new ClickAction();
      blocksItem.link.action.actionType = ActionType.ACTION_TYPE_SEND_MESSAGE;
      blocksItem.link.action.jumpUrl = "example_jump_url";
      blocksItem.link.action.miniProgramJumpInfo = new MiniProgramJump();
      blocksItem.link.action.miniProgramJumpInfo.appid = "example_appid";
      blocksItem.link.action.miniProgramJumpInfo.path = "example_path";
      blocksItem.link.action.messageInfo = new MessageInfo();
      blocksItem.link.action.messageInfo.content = "example_content";
      blocksItem.link.action.messageInfo.customData = "example_custom_data";
      blocksItem.link.action.actionId = "example_action_id";
      blocksItem.link.invalidInfo = new InvalidInfo();
      blocksItem.link.invalidInfo.expiredTime = "example_expired_time";
      blocksItem.link.invalidInfo.multiClickable = false;
      blocksItem.faqList = new FaqList();
      blocksItem.faqList.faqs = new ArrayList<>();
      {
        FaqListItem faqsItem = new FaqListItem();
        faqsItem.faqId = "example_faq_id";
        faqsItem.faqTitle = "example_faq_title";
        faqsItem.action = new ClickAction();
        faqsItem.action.actionType = ActionType.ACTION_TYPE_SEND_MESSAGE;
        faqsItem.action.jumpUrl = "example_jump_url";
        faqsItem.action.miniProgramJumpInfo = new MiniProgramJump();
        faqsItem.action.miniProgramJumpInfo.appid = "example_appid";
        faqsItem.action.miniProgramJumpInfo.path = "example_path";
        faqsItem.action.messageInfo = new MessageInfo();
        faqsItem.action.messageInfo.content = "example_content";
        faqsItem.action.messageInfo.customData = "example_custom_data";
        faqsItem.action.actionId = "example_action_id";
        blocksItem.faqList.faqs.add(faqsItem);
      };
      blocksItem.button = new Button();
      blocksItem.button.text = "example_text";
      blocksItem.button.action = new ClickAction();
      blocksItem.button.action.actionType = ActionType.ACTION_TYPE_SEND_MESSAGE;
      blocksItem.button.action.jumpUrl = "example_jump_url";
      blocksItem.button.action.miniProgramJumpInfo = new MiniProgramJump();
      blocksItem.button.action.miniProgramJumpInfo.appid = "example_appid";
      blocksItem.button.action.miniProgramJumpInfo.path = "example_path";
      blocksItem.button.action.messageInfo = new MessageInfo();
      blocksItem.button.action.messageInfo.content = "example_content";
      blocksItem.button.action.messageInfo.customData = "example_custom_data";
      blocksItem.button.action.actionId = "example_action_id";
      blocksItem.button.invalidInfo = new InvalidInfo();
      blocksItem.button.invalidInfo.expiredTime = "example_expired_time";
      blocksItem.button.invalidInfo.multiClickable = false;
      blocksItem.buttonGroup = new ButtonGroup();
      blocksItem.buttonGroup.buttons = new ArrayList<>();
      {
        InnerButton buttonsItem = new InnerButton();
        buttonsItem.text = "example_text";
        buttonsItem.action = new ClickAction();
        buttonsItem.action.actionType = ActionType.ACTION_TYPE_SEND_MESSAGE;
        buttonsItem.action.jumpUrl = "example_jump_url";
        buttonsItem.action.miniProgramJumpInfo = new MiniProgramJump();
        buttonsItem.action.miniProgramJumpInfo.appid = "example_appid";
        buttonsItem.action.miniProgramJumpInfo.path = "example_path";
        buttonsItem.action.messageInfo = new MessageInfo();
        buttonsItem.action.messageInfo.content = "example_content";
        buttonsItem.action.messageInfo.customData = "example_custom_data";
        buttonsItem.action.actionId = "example_action_id";
        blocksItem.buttonGroup.buttons.add(buttonsItem);
      };
      blocksItem.buttonGroup.buttonLayout = ButtonLayout.LAYOUT_UNKNOWN;
      blocksItem.buttonGroup.invalidInfo = new InvalidInfo();
      blocksItem.buttonGroup.invalidInfo.expiredTime = "example_expired_time";
      blocksItem.buttonGroup.invalidInfo.multiClickable = false;
      request.message.blocks.add(blocksItem);
    };
    request.message.senderIdentity = SenderIdentity.UNKNOWN;
    request.message.customData = "example_custom_data";
    request.idempotentId = "550e8400-e29b-41d4-a716-446655440000";
    try {
      ResponseComplaintImmediateServiceResponse response = client.run(request);
        // TODO: 请求成功，继续业务逻辑
        System.out.println(response);
    } catch (WXPayUtility.ApiException e) {
        // TODO: 请求失败，根据状态码执行不同的逻辑
        e.printStackTrace();
    }
  }

  public ResponseComplaintImmediateServiceResponse run(ResponseComplaintImmediateServiceRequest request) {
    String uri = PATH;
    uri = uri.replace("{complaint_id}", WXPayUtility.urlEncode(request.complaintId));
    String reqBody = WXPayUtility.toJson(request);

    Request.Builder reqBuilder = new Request.Builder().url(HOST + uri);
    reqBuilder.addHeader("Accept", "application/json");
    reqBuilder.addHeader("Wechatpay-Serial", wechatPayPublicKeyId);
    reqBuilder.addHeader("Authorization", WXPayUtility.buildAuthorization(mchid, certificateSerialNo,privateKey, METHOD, uri, reqBody));
    reqBuilder.addHeader("Content-Type", "application/json");
    RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), reqBody);
    reqBuilder.method(METHOD, requestBody);
    Request httpRequest = reqBuilder.build();

    // 发送HTTP请求
    OkHttpClient client = new OkHttpClient.Builder().build();
    try (Response httpResponse = client.newCall(httpRequest).execute()) {
      String respBody = WXPayUtility.extractBody(httpResponse);
      if (httpResponse.code() >= 200 && httpResponse.code() < 300) {
        // 2XX 成功，验证应答签名
        WXPayUtility.validateResponse(this.wechatPayPublicKeyId, this.wechatPayPublicKey,
            httpResponse.headers(), respBody);

        // 从HTTP应答报文构建返回数据
        return WXPayUtility.fromJson(respBody, ResponseComplaintImmediateServiceResponse.class);
      } else {
        throw new WXPayUtility.ApiException(httpResponse.code(), respBody, httpResponse.headers());
      }
    } catch (IOException e) {
      throw new UncheckedIOException("Sending request to " + uri + " failed.", e);
    }
  }

  private final String mchid;
  private final String certificateSerialNo;
  private final PrivateKey privateKey;
  private final String wechatPayPublicKeyId;
  private final PublicKey wechatPayPublicKey;

  public ResponseComplaintImmediateService(String mchid, String certificateSerialNo, String privateKeyFilePath, String wechatPayPublicKeyId, String wechatPayPublicKeyFilePath) {
    this.mchid = mchid;
    this.certificateSerialNo = certificateSerialNo;
    this.privateKey = WXPayUtility.loadPrivateKeyFromPath(privateKeyFilePath);
    this.wechatPayPublicKeyId = wechatPayPublicKeyId;
    this.wechatPayPublicKey = WXPayUtility.loadPublicKeyFromPath(wechatPayPublicKeyFilePath);
  }

  public static class ResponseComplaintImmediateServiceRequest {
    @SerializedName("complaint_id")
    @Expose(serialize = false)
    public String complaintId;

    @SerializedName("complainted_mchid")
    public String complaintedMchid;

    @SerializedName("message")
    public NormalMessage message;

    @SerializedName("idempotent_id")
    public String idempotentId;
  }

  public static class ResponseComplaintImmediateServiceResponse {
    @SerializedName("log_id")
    public String logId;
  }

  public static class NormalMessage {
    @SerializedName("blocks")
    public List<Block> blocks;

    @SerializedName("sender_identity")
    public SenderIdentity senderIdentity;

    @SerializedName("custom_data")
    public String customData;
  }

  public static class Block {
    @SerializedName("type")
    public BlockType type;

    @SerializedName("text")
    public Text text;

    @SerializedName("image")
    public Image image;

    @SerializedName("link")
    public Link link;

    @SerializedName("faq_list")
    public FaqList faqList;

    @SerializedName("button")
    public Button button;

    @SerializedName("button_group")
    public ButtonGroup buttonGroup;
  }

  public enum SenderIdentity {
    @SerializedName("UNKNOWN")
    UNKNOWN,
    @SerializedName("MANUAL")
    MANUAL,
    @SerializedName("MACHINE")
    MACHINE
  }

  public enum BlockType {
    @SerializedName("TEXT")
    TEXT,
    @SerializedName("IMAGE")
    IMAGE,
    @SerializedName("LINK")
    LINK,
    @SerializedName("FAQ_LIST")
    FAQ_LIST,
    @SerializedName("BUTTON")
    BUTTON,
    @SerializedName("BUTTON_GROUP")
    BUTTON_GROUP
  }

  public static class Text {
    @SerializedName("text")
    public String text;

    @SerializedName("color")
    public TextColor color;

    @SerializedName("is_bold")
    public Boolean isBold;
  }

  public static class Image {
    @SerializedName("media_id")
    public String mediaId;

    @SerializedName("image_style_type")
    public ImageStyleType imageStyleType;
  }

  public static class Link {
    @SerializedName("text")
    public String text;

    @SerializedName("action")
    public ClickAction action;

    @SerializedName("invalid_info")
    public InvalidInfo invalidInfo;
  }

  public static class FaqList {
    @SerializedName("faqs")
    public List<FaqListItem> faqs;
  }

  public static class Button {
    @SerializedName("text")
    public String text;

    @SerializedName("action")
    public ClickAction action;

    @SerializedName("invalid_info")
    public InvalidInfo invalidInfo;
  }

  public static class ButtonGroup {
    @SerializedName("buttons")
    public List<InnerButton> buttons;

    @SerializedName("button_layout")
    public ButtonLayout buttonLayout;

    @SerializedName("invalid_info")
    public InvalidInfo invalidInfo;
  }

  public enum TextColor {
    @SerializedName("DEFAULT")
    DEFAULT,
    @SerializedName("SECONDARY")
    SECONDARY
  }

  public enum ImageStyleType {
    @SerializedName("IMAGE_STYLE_TYPE_NARROW")
    IMAGE_STYLE_TYPE_NARROW,
    @SerializedName("IMAGE_STYLE_TYPE_WIDE")
    IMAGE_STYLE_TYPE_WIDE
  }

  public static class ClickAction {
    @SerializedName("action_type")
    public ActionType actionType;

    @SerializedName("jump_url")
    public String jumpUrl;

    @SerializedName("mini_program_jump_info")
    public MiniProgramJump miniProgramJumpInfo;

    @SerializedName("message_info")
    public MessageInfo messageInfo;

    @SerializedName("action_id")
    public String actionId;
  }

  public static class InvalidInfo {
    @SerializedName("expired_time")
    public String expiredTime;

    @SerializedName("multi_clickable")
    public Boolean multiClickable;
  }

  public static class FaqListItem {
    @SerializedName("faq_id")
    public String faqId;

    @SerializedName("faq_title")
    public String faqTitle;

    @SerializedName("action")
    public ClickAction action;
  }

  public static class InnerButton {
    @SerializedName("text")
    public String text;

    @SerializedName("action")
    public ClickAction action;
  }

  public enum ButtonLayout {
    @SerializedName("LAYOUT_UNKNOWN")
    LAYOUT_UNKNOWN,
    @SerializedName("LAYOUT_HORIZONTAL")
    LAYOUT_HORIZONTAL,
    @SerializedName("LAYOUT_VERTICAL")
    LAYOUT_VERTICAL
  }

  public enum ActionType {
    @SerializedName("ACTION_TYPE_SEND_MESSAGE")
    ACTION_TYPE_SEND_MESSAGE,
    @SerializedName("ACTION_TYPE_JUMP_URL")
    ACTION_TYPE_JUMP_URL,
    @SerializedName("ACTION_TYPE_JUMP_MINI_PROGRAM")
    ACTION_TYPE_JUMP_MINI_PROGRAM
  }

  public static class MiniProgramJump {
    @SerializedName("appid")
    public String appid;

    @SerializedName("path")
    public String path;
  }

  public static class MessageInfo {
    @SerializedName("content")
    public String content;

    @SerializedName("custom_data")
    public String customData;
  }

}

```
