pom.xml
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>retrofit</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.squareup.retrofit2</groupId>
<artifactId>converter-jackson</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.5</version>
</dependency>
Api接口
import com.qbsea.mysboot2shirojwt.test.xml.model.RefundRequest;
import com.qbsea.mysboot2shirojwt.test.xml.model.RefundResponse;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.POST;
public interface WxPayApi {
@POST("apitest/custom/response/3.ajax")
Call<RefundResponse> refund(@Body RefundRequest refund);
}
注入API接口Bean
package com.qbsea.mysboot2shirojwt.test.xml.wxapi;
import com.qbsea.mysboot2shirojwt.test.xml.util.WxPayApiConverterFactory;
import okhttp3.OkHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import retrofit2.Retrofit;
@Configuration
public class ApiConfig {
@Bean
WxPayApi wxPayApi() throws Exception {
OkHttpClient.Builder clientBuilder = new OkHttpClient.Builder();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://qbsea.com/codeGen/")
.client(clientBuilder.build())
.addConverterFactory(new WxPayApiConverterFactory())
.build();
return retrofit.create(WxPayApi.class);
}
}
发送自签名证书
自定义的WxPayApiConverterFactory
1.继承extends Converter.Factory //import retrofit2.Converter;
2.实现两个转换方法
@Nullable
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
return null;
}
@Nullable
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
return null;
}
3.实现Converter的两个类 RequestBodyConverter ResponseBodyConverter
WxPayApiConverterFactory的具体代码
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import retrofit2.Retrofit;
import javax.annotation.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
public class WxPayApiConverterFactory extends Converter.Factory {
@Nullable
@Override//请求体的转换 最终返回一个Converter<?, RequestBody>
public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[]
methodAnnotations, Retrofit retrofit) {
// return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
RequestBodyConverter requestBodyConverter = new RequestBodyConverter<>();
return requestBodyConverter;
}
@Nullable
@Override//响应体的转换 最终返回一个 Converter<ResponseBody, ?>
public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
// return super.responseBodyConverter(type, annotations, retrofit);
ResponseBodyConverter responseBodyConverter = new ResponseBodyConverter<>(type);
return responseBodyConverter;
}
}
RequestBodyConverter转换器
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import retrofit2.Converter;
import java.io.IOException;
public class RequestBodyConverter<T> implements Converter<T, RequestBody> {
private static final MediaType MEDIA_TYPE_XML = MediaType.parse("application/xml; charset=utf-8");
@Override
public RequestBody convert(T t) throws IOException {
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new JaxbAnnotationModule());
xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return RequestBody.create(MEDIA_TYPE_XML, xmlMapper.writeValueAsBytes(t));
}
}
ResponseBodyConverter
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import lombok.RequiredArgsConstructor;
import okhttp3.ResponseBody;
import retrofit2.Converter;
import java.io.IOException;
import java.lang.reflect.Type;
@RequiredArgsConstructor
public class ResponseBodyConverter<T> implements Converter<ResponseBody,T > {
private final Type type;
@Override
public T convert(ResponseBody responseBody) throws IOException {
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(new JaxbAnnotationModule());
xmlMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return xmlMapper.readValue(responseBody.charStream(),new TypeReference<T>(){
@Override
public Type getType() {
return type;
}
});
}
}
参考的返回报文
<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[NfsMFbUFpdbEhPXP]]></nonce_str>
<sign><![CDATA[B7274EB9F8925EB93100DD2085FA56C0]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[1008450740201411110005820873]]></transaction_id>
<out_trade_no><![CDATA[1415757673]]></out_trade_no>
<out_refund_no><![CDATA[1415701182]]></out_refund_no>
<refund_id><![CDATA[2008450740201411110000174436]]></refund_id>
<refund_fee>1</refund_fee>
</xml>
Mode类参考
请求RefundRequest
import lombok.Getter;
import lombok.Setter;
import javax.xml.bind.annotation.XmlElement;
@Getter
@Setter
public class RefundRequest extends WxPayRequest {
@XmlElement(name = "transaction_id")
private String flowNo;
@XmlElement(name = "out_refund_no")
private String refundTradeNo;
@XmlElement(name = "total_fee")
private int totalFee;
@XmlElement(name = "refund_fee")
private int refundFee;
@XmlElement(name = "refund_desc")
private String refundReason;
}
请求WxPayRequest
import lombok.Getter;
import lombok.Setter;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
@Getter
@Setter
@XmlRootElement(name = "xml")
public abstract class WxPayRequest implements Serializable {
@XmlElement(name = "appid")
private String appId;
@XmlElement(name = "mch_id")
private String mchId;
@XmlElement(name = "nonce_str")
private String nonce;
@XmlElement(name = "sign")
private String signature;
@XmlElement(name = "sign_type")
private String signType = "HMAC-SHA256";
}
响应RefundResponse
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import javax.xml.bind.annotation.XmlElement;
@Getter
@Setter
@ToString
public class RefundResponse extends WxPayResponse {
@XmlElement(name = "result_code")
private String resultCode;
@XmlElement(name = "err_code")
private String errorCode;
@XmlElement(name = "err_code_des")
private String errorDesc;
@XmlElement(name = "out_refund_no")
private String refundTradeNo;
@XmlElement(name = "refund_id")
private String refundFlowNo;
public boolean isSuccessful() {
return SUCCESS_CODE.equals(getCode()) && SUCCESS_CODE.equalsIgnoreCase(getResultCode());
}
}
响应WxPayResponse
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlCData;
import lombok.Getter;
import lombok.Setter;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
@Getter
@Setter
@XmlRootElement(name = "xml")
public class WxPayResponse implements Serializable {
public static final String SUCCESS_CODE = "SUCCESS";
public static final String FAILURE_CODE = "FAIL";
@XmlElement(name = "return_code")
@JacksonXmlCData
private String code;
@XmlElement(name = "return_msg")
@JacksonXmlCData
private String message;
public static WxPayResponse success() {
WxPayResponse response = new WxPayResponse();
response.setCode(SUCCESS_CODE);
response.setMessage("OK");
return response;
}
public static WxPayResponse failure(String message) {
WxPayResponse response = new WxPayResponse();
response.setCode(SUCCESS_CODE);
response.setMessage(message);
return response;
}
}