操作之前建议查看官方文档熟悉名词解释
链接: 微信支付app官方文档
坐标–>
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
微信配置参数–>
(小插曲,安卓接wx_package的时候使用’='号切割 但是由于这个字段的特殊性 最后采用的是安卓写死…)
//appId
private String appId = "123456";
//商户id
private String mchId = "123456";
//商户密钥
private String key = "123456";
// AppSecret
private String appSecret = "123456";
//证书存放地址
private String certPath = "";
//HTTP链接超时时间
private int httpConnectTimeoutMs = 8000;
//HTTP读取数据超时时间
private int httpReadTimeoutMs = 10000;
//微信支付异步通知地址
private String payNotifyUrl = "123456";
private String wx_package ="Sign=WXPay";
支付下单–>
下单接口是个大坑,参数必须保持顺序否则会报出签名异常
链接: 微信检测签名.
还需要注意的是:再请求完下单接口后,需要进行二次签名才能返给app调起支付,否则一直会报参数异常
//1.参数封装
public String create(PayElementVO vo) throws Exception {
Map data = new HashMap();
data.put("appid", weixinConfig.getAppId());//公众账号ID
if (StringUtils.isNotEmpty(vo.getSubject())) {
data.put("body", vo.getSubject());
}
data.put("mch_id", weixinConfig.getMchId());//商户
data.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
data.put("notify_url", weixinConfig.getPayNotifyUrl());
data.put("out_trade_no", vo.getOrderId());//交易订单号
data.put("spbill_create_ip", "111,111,1,1");//服务器IP
data.put("total_fee", yuan.toString());//金额(分)
data.put("trade_type", "APP");//交易类型
try {
String xmlParam = WXPayUtil.generateSignedXml(data, weixinConfig.getKey());
System.out.println("请求的参数:" + xmlParam);
Map<String, String> stringMap = WXPayUtil.xmlToMap(xmlParam);
//2.发送请求
String xmlResult = HttpClientUtil.postXML(WXPayConstants.UNIFIEDORDER_URL, xmlParam);
Map<String, String> mapResult = WXPayUtil.xmlToMap(xmlResult);
//3.组装返回给安卓的数据 需要二次签名
Map map = new LinkedHashMap<String, String>();
map.put("appid", mapResult.get("appid"));
map.put("partnerid", mapResult.get("mch_id"));
map.put("prepayid", mapResult.get("prepay_id"));
map.put("noncestr", mapResult.get("nonce_str"));
map.put("timestamp", String.valueOf(new Date().getTime()).substring(0, 10));
map.put("package", "Sign=WXPay");
String signature = WXPayUtil.generateSignature(map, weixinConfig.getKey());
String resultString = "{\"appid\":\"" + mapResult.get("appid") + "\",\"partnerid\":\"" + mapResult.get("mch_id") + "\",\"package\":\"Sign=WXPay\"," +
"\"noncestr\":\"" + mapResult.get("nonce_str") + "\",\"timestamp\":" + map.get("timestamp") + "," +
"\"prepayid\":\"" + mapResult.get("prepay_id") + "\",\"sign\":\"" + signature + "\"}";
return resultString;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return "";
}
}
查询订单交易情况
链接: 微信查询订单状态.
/**
* 查询订单消费情况
*/
public Map queryPayStatus(String transactionId) {
// Order order = orderMapper.selectById(orderId);
// BigDecimal amount = order.getAmount();
//1.封装参数
Map param = new HashMap();
param.put("appid", weixinConfig.getAppId());
param.put("mch_id", weixinConfig.getMchId());
param.put("nonce_str", WXPayUtil.generateNonceStr());
param.put("transaction_id", transactionId);
try {
String xmlParam = WXPayUtil.generateSignedXml(param, weixinConfig.getKey());
//2.发送请求
String xmlResult = HttpClientUtil.postXML(WXPayConstants.ORDERQUERY_URL, xmlParam);
Map<String, String> map = WXPayUtil.xmlToMap(xmlResult);
// if (amount.compareTo(new BigDecimal(map.get("settlement_total_fee"))) != 0) {
// return new HashMap();
// }
log.info("【微信查詢訂單】xmlParam={}", xmlParam);
return map;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
微信回调
由于业务问题,使用的回调 没使用查单进行操作
需要额外注意的是回调接口必须外网可访问
可以使用公司服务器 或者使用小工具ngrok内网穿透 本地调试起来不要太方便!
/**
* 微信回调
*/
public void WXPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map<String, String> params = getRequestMap(request, params);
String orderId = params.get("out_trade_no");
boolean signatureValid = false;
try {
signatureValid = WXPayUtil.isSignatureValid(params, weixinConfig.getKey());
} catch (Exception e) {
log.error("【微信异步通知】微信回调通知失败 e={} params={}", e, params);
responseBody(response, "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![回调通知失败]></return_msg></xml>");
return;
}
if (signatureValid == false) {
log.error("【微信异步通知】验证签名错误 params={}",params);
responseBody(response, "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![验证签名错误]></return_msg></xml>");
return;
}
//向微信发送成功接收通知
responseBody(response, "<xml><return_code><![CDATA[SUEECSS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
return;
}
private Map<String, String> getRequestMap(HttpServletRequest request, Map<String, String> params) {
String inputLine = null;
// 接收到的数据
StringBuffer recieveData = new StringBuffer();
BufferedReader in = null;
try {
in = new BufferedReader(new InputStreamReader(
request.getInputStream(), "UTF-8"));
while ((inputLine = in.readLine()) != null) {
recieveData.append(inputLine);
}
} catch (IOException e) {
} finally {
try {
if (null != in) {
in.close();
}
} catch (IOException e) {
}
}
try {
params= WXPayUtil.xmlToMap(recieveData.toString());//微信jdk 中一个XML转MAP的工具
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return params;
}
httpClient工具类–>
package com.ftsino.huntingalliance.common.utils;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
@Component
public class httpClientUtils{
private static final Log logger = LogFactory.getLog(httpClientUtils.class);
private static final int timeout = 5000;
public static final String DEFAULT_CHARSET = "UTF-8";
/**
* 获取一个HttpClient对象
*
* @return
*/
public static HttpClient getHttpClient() {
HttpClient client = new HttpClient();
client.getHttpConnectionManager().getParams().setConnectionTimeout(timeout);
client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, DEFAULT_CHARSET);
return client;
}
/**
* 提交xml
*
* @param url 地址
* @param xmlFile xml文件
* @return
*/
public static String postXML(String url, String xmlFile) {
return postXML(url, xmlFile, getHttpClient());
}
/**
* 提交xml
*
* @param url 地址
* @param xml xml内容
* @param client
* @return
*/
public static String postXML(String url, String xml, HttpClient client) {
String resp = null;
PostMethod post = new PostMethod(url);
try {
RequestEntity requestEntity = new StringRequestEntity(xml, "text/xml", DEFAULT_CHARSET);
post.setRequestEntity(requestEntity);
// 指定请求内容的类型
post.setRequestHeader("Content-type", "application/xml; charset=" + DEFAULT_CHARSET);
client.executeMethod(post);
resp = post.getResponseBodyAsString();
} catch (Exception e) {
logger.error("提交xml失败", e);
throw new RuntimeException("提交xml失败");
} finally {
post.releaseConnection();
}
return resp;
}
}
使用微信中遇到的问题(支付以及回调)
请参考 微信支付以及回调问题.
.