1.后端提供前端调起支付所需要的参数
/** * 微信公众号支付 * *
@param trade_no 订单号 *
@param totalAmount 支付金额 *
@param description 文字内容说明 *
@param attach 自定义参数 length=127 *
@param openId 微信公众号openId *
@param wxnotify 回调地址 * @param request - *
@return - */
public static SortedMap
WxPublicPay(String appId, String mchId, String trade_no, BigDecimal totalAmount, String description, String attach, String openId, String wxnotify, HttpServletRequest request) { Map
map = weixinPrePay(appId, mchId, trade_no, totalAmount, description, attach, openId, wxnotify, request); SortedMap
finalpackage = new TreeMap<>(); finalpackage.put("appId", appId);
finalpackage.put("timeStamp", System.currentTimeMillis() / 1000);
finalpackage.put("nonceStr", getRandomString(32));
finalpackage.put("package", "prepay_id=" + map.get("prepay_id"));
finalpackage.put("signType", "MD5");
String sign = createSign(finalpackage); finalpackage.put("paySign", sign);
return finalpackage;
}
/** * 微信下单 * * @param trade_no 订单号 ‘
@param totalAmount 支付金额 *
@param description 文字内容说明 *
@param attach 自定义参数 length=127 *
@param openid 微信公众号openId *
@param wxnotify 回调地址 *
@param request - *
@return - *
@appId appId 支付appid *
@appId mchId 商户号mchId */
private static Map
weixinPrePay(String appId, String mchId, String trade_no, BigDecimal totalAmount, String description, String attach, String openid, String wxnotify, HttpServletRequest request) { SortedMap
parameterMap = new TreeMap<>(); parameterMap.put("appid", appId);
parameterMap.put("mch_id", mchId);
parameterMap.put("nonce_str", getRandomString(32));
parameterMap.put("body", description);
// parameterMap.put("attach", attach);
parameterMap.put("out_trade_no", trade_no);
parameterMap.put("fee_type", "CNY");
BigDecimal total = totalAmount.multiply(new BigDecimal(100));
java.text.DecimalFormat df = new java.text.DecimalFormat("0"); System.out.println(df.format(total)); parameterMap.put("total_fee", df.format(total));
parameterMap.put("spbill_create_ip", request.getRemoteAddr());
parameterMap.put("notify_url", wxnotify);
parameterMap.put("sign_type", "MD5");
parameterMap.put("trade_type", "JSAPI");
parameterMap.put("product_id", "qqq12355");
//trade_type为JSAPI是 openid为必填项 parameterMap.put("openid", openid);// parameterMap.put("trade_type", "APP");
String sign = createSign(parameterMap);
System.out.println(sign); parameterMap.put("sign", sign);
// boolean flg = isTenpaySign(parameterMap);
String requestXML = getRequestXml(parameterMap);
String result = httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", requestXML);
System.out.println(result);
Map
map = null; try {
map = doXMLParse(result);
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
/** * length表示生成字符串的长度 * *
@param length *
@return */
private static String getRandomString(int length) {
//length表示生成字符串的长度 //DATO
String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; Random random = new Random();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
//生成签名
private static String createSign(SortedMap
parameters) { StringBuilder sb = new StringBuilder();
Set
> es = parameters.entrySet(); for (Map.Entry
entry : es) { String k = (String) entry.getKey();
Object v = entry.getValue();
if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k).append("=").append(v).append("&"); }
}
System.out.println(CacheUtil.getHospConfig().getWxAppKey()); sb.append("key=").append(CacheUtil.getHospConfig().getWxAppKey()); System.out.println(sb.toString());
return MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
}
//请求xml组装
private static String getRequestXml(SortedMap
parameters) { StringBuilder sb = new StringBuilder(); sb.append("
"); Set
> es = parameters.entrySet(); for (Map.Entry
entry : es) { String key = (String) entry.getKey();
String value = (String) entry.getValue();
if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) { sb.append("<").append(key).append(">").append("").append(key).append(">");
} else { sb.append("<").append(key).append(">").append(value).append("").append(key).append(">");
}
}
sb.append(""); return sb.toString();
}
//请求方法private 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;
StringBuilder buffer = new StringBuilder();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
// 释放资源 bufferedReader.close();
inputStreamReader.close();
inputStream.close();
conn.disconnect();
return buffer.toString();
} catch (ConnectException ce) {
System.out.println("连接超时:{}" + ce);
} catch (Exception e) {
System.out.println("https请求异常:{}" + e); } return null;
}
//xml解析
public static Map
doXMLParse(String strxml) throws Exception { 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(); for (Object aList : list) {
Element e = (Element) aList; 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;
}
private static String getChildrenText(List
children) { StringBuilder sb = new StringBuilder();
if (!children.isEmpty()) {
for (Element e : children) {
String name = e.getName();
String value = e.getTextNormalize();
List
list = e.getChildren(); sb.append("<").append(name).append(">");
if (!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("").append(name).append(">");
}
}
return sb.toString();}
2.前端调起支付
onBridgeReady: function (obj) {
WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
"appId": obj.appId, //公众号名称,由商户传入 //时间戳,自1970年以来的秒数 "
timeStamp": obj.timeStamp,
"nonceStr": obj.nonceStr, //随机串
"package": obj.package,
"signType": obj.signType, //微信签名方式:
"paySign": obj.paySign //微信签名
}, function (res) {
if (res.err_msg == "get_brand_wcpay_request:ok") {
location.href = `succPay.html?OrderNo=` + obj.orderNo; // 使用以上方式判断前端返回,微信团队郑重提示: // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
} else {
// alert(res.err_msg); }
});