springboot版本:

2.2.0.BUILD-SNAPSHOT

 

可使用场景:企业付款到零钱/提现/微信退款等场景

 

企业提现零钱付款场景下:

下面是能跑通的代码,减少踩坑时间.

两套方案:一套使用注入bean的方式:

("商户号".toCharArray(),商户号就是证书密码)

@Configuration
public class RestTemplateCert {

@Qualifier("RestTemplateWithCert")
@Bean
public RestTemplate getRestTemplateWithCert() {

RestTemplate restTemplate = null;
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");//eg. PKCS12
// 这个之前尝试放在resources目录下来读取,结果这个居然是证书错误的源头,使用下面的直接从路径读取就能成功了,证书读取有问题spring没有报错,大坑
// InputStream cp = this.getClass().getResourceAsStream("apiclient_cert.p12");
FileInputStream instream = new FileInputStream(new File("C:\\extend\\apiclient_cert.p12"));
keyStore.load(instream, "商户号".toCharArray());
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContextBuilder.create()
.loadKeyMaterial(keyStore, "商户号".toCharArray())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, NoopHostnameVerifier.INSTANCE);
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
restTemplate = new RestTemplate(factory);
//将转换器的编码换成utf-8
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("utf-8")));
//System.out.println("restTemplate.hashCode():" + restTemplate.hashCode());
} catch (Exception e) {
e.printStackTrace();
}
return restTemplate;
}

@Primary
@Bean
public RestTemplate getRestTemplate() {
RestTemplate restTemplate = new RestTemplate();

//将转换器的编码换成utf-8
restTemplate.getMessageConverters().set(1, new StringHttpMessageConverter(Charset.forName("utf-8")));
return restTemplate;
}

}

 

携带微信api证书:
@Qualifier("RestTemplateWithCert")
@Resource
private RestTemplate restTemplateWithCert;

常规请求:
@Resource
private

 

微信提现请求:

new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
String body = "xml数据";
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
HttpEntity<String> request = new HttpEntity<>(body, headers);
ResponseEntity<String> res = restTemplateWithCert.postForEntity(url, request, String.class);
System.out.println(res.getBody());

 

第二个解决方案:

需要依赖:

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>

 

public class WxSSLTestTemplate {

public static String TransferRestTemplate(String url, String data) throws KeyStoreException, IOException, UnrecoverableKeyException, KeyManagementException, CertificateException, NoSuchAlgorithmException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("C:\\extend\\apiclient_cert.p12"));
keyStore.load(instream, "商户号".toCharArray());
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContextBuilder.create()
.loadKeyMaterial(keyStore, "商户号".toCharArray())
.build();
// Allow TLSv1 protocol only
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"},
null, hostnameVerifier);

CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();

HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient);
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Connection", "keep-alive");
requestHeaders.add("Accept", "*/*");
requestHeaders.add("Content-Type", "application/x-www-form-urlencoded");
requestHeaders.add("Host", "api.mch.weixin.qq.com");
requestHeaders.add("X-Requested-With", "XMLHttpRequest");
requestHeaders.add("Cache-Control", "max-age=0");
requestHeaders.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");

// 如果使用这个方法,就不能使用下面的这个实例化,而要使用下面第一条使用中的request,否则会报jackson的错误,就算配置忽略bean的检测也没用
// org.springframework.http.HttpEntity<String> requestEntity =
// new org.springframework.http.HttpEntity(new StringEntity(data, "UTF-8"), requestHeaders);

HttpEntity<String> request = new HttpEntity<>(data, requestHeaders);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
return response.getBody();
}

}

 

微信提现请求:

;
String url = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
String result = WxSSLTestTemplate.TransferRestTemplate(url, body);
System.out.println(result);

 

这样就可以完美跑通了