之前写过一个APP支付宝支付,一直没有时间写APP微信支付。在写微信支付的时候,和前端调了好久,其实不是后端的事。我是觉得只要拿到了,预支付ID(prepay_id),前端就应该能调起来的。所以以后遇到说什么后端的事,简直就是坑爹啊。
下面就直接上代码了++++++++++++++++++++++++++++++++
下面的是APP支付的一些参数,最好先封装好,方便使用
public class WechatPayConstantWx {
/**
* APP微信支付
*/
public static String API_KEY = "**************";
public static String APPID = "&&&&&&&&&&&&&&&";
public static String MCH_ID = "***********";
public static String trade_type = "APP";
public static String body = "……………………………………";
public static String wxnotify = "http://fg4dap.natappfree.cc/项目的名字/order-pay-wei-xin-notify-controller";// 微信回调地址
}
// 生成签名
@SuppressWarnings("rawtypes")
public static String createSign(String characterEncoding, SortedMap<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + WechatPayConstantWx.API_KEY);// 最后加密时添加商户密钥,由于key值放在最后,所以不用添加到SortMap里面去,单独处理,编码方式采用UTF-8
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
上面的是,生成签名的,这是第一次生成签名。后面还会有一次的————————————————————
请求XML封装
// 请求xml组装
@SuppressWarnings("rawtypes")
public static String getRequestXml(SortedMap<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value;
if (key.equals("total_fee")) {
value = String.valueOf(entry.getValue());
} else {
value = (String) entry.getValue();
}
if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) {
sb.append("<" + key + ">" + "<![CDATA[" + value + "]]></" + key + ">");
} else {
sb.append("<" + key + ">" + value + "</" + key + ">");
}
}
sb.append("</xml>");
return sb.toString();
}
请求方法
// 请求方法
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
System.out.println("连接超时:{}" + ce);
} catch (Exception e) {
System.out.println("https请求异常:{}" + e);
}
return null;
}
XML解析
// xml解析
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if (children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
// 关闭流
in.close();
return m;
}
第一次就是,把订单信息根据微信给的文档加签,在就是XML封装好,在就是发送请求,请求之后,就解析XML,拿到预支付ID(prepay_id)
如果你没有拿到预支付ID,就看一下文档,是不是有什么错误的 是吧。》》》》》》》》》》》》》》》》》
private static Map<String, String> weixinPrePay(String trade_no, int actualPayMoney, String description,
HttpServletRequest httpServletRequest) {
SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();
parameterMap.put("appid", WechatPayConstantWx.APPID);
parameterMap.put("body", description);
parameterMap.put("mch_id", WechatPayConstantWx.MCH_ID);
parameterMap.put("nonce_str",PayCommonUtil.getRandomString(32));
parameterMap.put("notify_url", WechatPayConstantWx.wxnotify);
parameterMap.put("out_trade_no", trade_no);
parameterMap.put("fee_type", "CNY"); // 货币类型
parameterMap.put("spbill_create_ip", httpServletRequest.getRemoteAddr());// 终端IP
System.out.println("===========================================" + httpServletRequest.getRemoteAddr());
parameterMap.put("total_fee", actualPayMoney);
parameterMap.put("trade_type", WechatPayConstantWx.trade_type);
String sign = PayCommonUtil.createSign("UTF-8", parameterMap);
System.out.println("======================================================================" + sign);
parameterMap.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameterMap);
System.err.println(requestXML);
String result = PayCommonUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST",
requestXML);
System.err.println(result);
Map<String, String> map = null;
try {
map = PayCommonUtil.doXMLParse(result);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return map;
}
之后还需要在加签一次——————————————————————————————————
@Transactional
@RequestMapping(value = "/wei-xin-order-pay-controller", method = { RequestMethod.POST })
public String OrderPay(@RequestBody String body, HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws Exception {
log.info("微信支付接口 ");
httpServletResponse.setContentType("text/html;charset=utf-8");
Request request = getRequest(body);
Response response = getResponse(request);
response.setUrl("wei-xin-order-pay-controller");
// 请求业务参数
OrderPayRequest orderPayRequest = JSONObject.parseObject(request.getBizContent(), OrderPayRequest.class);
String trade_no = orderPayRequest.getOrderCode();// 商户订单号
String actualPayMoneys = orderPayRequest.getActualPayMoney();
Map<String, String> map =weixinPrePay(trade_no, actualPayMoneys, httpServletRequest);
SortedMap<String, Object> finalpackage = new TreeMap<String, Object>();
finalpackage.put("appid", WechatPayConstantWx.APPID);
finalpackage.put("noncestr", PayCommonUtil.getRandomString(32));
finalpackage.put("package", "Sign=WXPay");
finalpackage.put("partnerid", WechatPayConstantWx.MCH_ID);// 商户号
finalpackage.put("prepayid", map.get("prepay_id"));
finalpackage.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
System.err.println("=================================================" + map.get("prepay_id"));
String sign = PayCommonUtil.createSign("UTF-8", finalpackage);
finalpackage.put("sign", sign);
response.setResult(finalpackage);
System.err.println("============================================="+toFastJson(response));
httpServletResponse.getWriter().print(toFastJson(response));
return null;
}
toFastJson(response)++++++++++把这个直接给前端,他们去调微信支付=============
下面的就是直接把response转化为JSON>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
public String toFastJson(Object obj) {
String objStr = com.alibaba.fastjson.JSONObject.toJSONString(obj,
SerializerFeature.WriteDateUseDateFormat,
SerializerFeature.WriteMapNullValue);
return objStr;
}
还有下面的两个方法,大家可以要,也可以不要>>>>>>>>>>>>>>>>>>>>
我也是为 做个笔记<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**
* 微信MD5加签
* @author xyl
*
*/
public class MD5Util {
private static String byteArrayToHexString(byte b[]) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++)
resultSb.append(byteToHexString(b[i]));
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n += 256;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
public static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if (charsetname == null || "".equals(charsetname))
resultString = byteArrayToHexString(md.digest(resultString
.getBytes()));
else
resultString = byteArrayToHexString(md.digest(resultString
.getBytes(charsetname)));
} catch (Exception exception) {
}
return resultString;
}
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
}
public class PayCommonUtil {
// 微信参数配置
//public static String API_KEY = "b5c5345c033c5445e13ade6e10c2c796";
// 随机字符串生成 wxbe50da3d99876bc4
public static String getRandomString(int length) { // length表示生成字符串的长度
String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
// 请求xml组装
@SuppressWarnings("rawtypes")
public static String getRequestXml(SortedMap<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set es = parameters.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String key = (String) entry.getKey();
String value;
if (key.equals("total_fee")) {
value = String.valueOf(entry.getValue());
} else {
value = (String) entry.getValue();
}
if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) {
sb.append("<" + key + ">" + "<![CDATA[" + value + "]]></" + key + ">");
} else {
sb.append("<" + key + ">" + value + "</" + key + ">");
}
}
sb.append("</xml>");
return sb.toString();
}
// 生成签名
@SuppressWarnings("rawtypes")
public static String createSign(String characterEncoding, SortedMap<String, Object> parameters) {
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + WechatPayConstantWx.API_KEY);// 最后加密时添加商户密钥,由于key值放在最后,所以不用添加到SortMap里面去,单独处理,编码方式采用UTF-8
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
/**
* 验证回调签名
*
* @param packageParams
* @param key
* @param charset
* @return
*/
@SuppressWarnings("rawtypes")
public static boolean isTenpaySign(Map<String, String> map) {
String charset = "utf-8";
String signFromAPIResponse = map.get("sign");
if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
return false;
}
System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);
// 过滤空 设置 TreeMap
SortedMap<String, String> packageParams = new TreeMap<>();
for (String parameter : map.keySet()) {
String parameterValue = map.get(parameter);
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
StringBuffer sb = new StringBuffer();
Set es = packageParams.entrySet();
Iterator it = es.iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = (String) entry.getValue();
if (!"sign".equals(k) && null != v && !"".equals(v)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + WechatPayConstantWx.API_KEY);
// 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
// 算出签名
String resultSign = "";
String tobesign = sb.toString();
if (null == charset || "".equals(charset)) {
resultSign = MD5Util.MD5Encode(tobesign, "UTF8").toUpperCase();
} else {
resultSign = MD5Util.MD5Encode(tobesign, "UTF8").toUpperCase();
}
String tenpaySign = ((String) packageParams.get("sign")).toUpperCase();
return tenpaySign.equals(resultSign);
}
// 请求方法
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
try {
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
// 设置请求方式(GET/POST)
conn.setRequestMethod(requestMethod);
conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
// 当outputStr不为null时向输出流写数据
if (null != outputStr) {
OutputStream outputStream = conn.getOutputStream();
// 注意编码格式
outputStream.write(outputStr.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
System.out.println("连接超时:{}" + ce);
} catch (Exception e) {
System.out.println("https请求异常:{}" + e);
}
return null;
}
// xml解析
@SuppressWarnings({ "unchecked", "rawtypes" })
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
if (null == strxml || "".equals(strxml)) {
return null;
}
Map m = new HashMap();
InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
List list = root.getChildren();
Iterator it = list.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if (children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = getChildrenText(children);
}
m.put(k, v);
}
// 关闭流
in.close();
return m;
}
@SuppressWarnings("rawtypes")
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if (!children.isEmpty()) {
Iterator it = children.iterator();
while (it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}
return sb.toString();
}
}