请看清楚你的微信支付是v2还是v3,在这里整理的是v3的,v2的同学请忽略!
前期准备需要用的是商户证书,用的是p12的,设置api密钥(在微信商户端中设置),还需要在微信公众号中设置jsapi授权目录;
1.微信授权获取用户openid
<a href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的微信公众号appid&redirect_uri=授权完回调你的url&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect">点击测试</a>
2.授权回调接口,在接口中解析获取用户openid,如果已经授权的过的,我是通过解析获取到code然后再请求微信得到openid
https://api.weixin.qq.com/sns/oauth2/access_token?appid=你的微信公众号appid&secret="+appsecret+"&code="+code+"&grant_type=authorization_code
3.用户下单提交,分两步,第一步通过统一下单接口获取prepay_id,第二步提交微信支付
前端代码:根据获取的openid提交后端
function wxpayCommit(){ $.ajax({ type : "POST", url : "/wxpayCommit", data :"openid=${openid}", dataType : "json", async : false, success : function(obj) { if(obj.prepay_id ==""){ return; } WeixinJSBridge.invoke('getBrandWCPayRequest',{ "appId" : obj.appid, "timeStamp":obj.timeStamp, "nonceStr" : obj.nonceStr, "package" : "prepay_id="+obj.prepay_id, "signType" : "MD5", "paySign" : obj.paySign },function(res){ alert(res.err_msg); if(res.err_msg == "get_brand_wcpay_request:ok" ) { window.location.href="/index"; }else{ alert("fail"); window.location.href="/wxpayCommit"; } }); }, error : function(msg) { alert("fail"); } });
//统一下单接口获取prepay_id
注意中间遇到签名错误,是你的sign有问题,最好办法在微信官网在线生成签名的比对一样,马上找到错误
SortedMap<String, String> packageParams = new TreeMap<String, String>(); packageParams.put("appid", TenpayConfig.appid); packageParams.put("mch_id", TenpayConfig.partner); packageParams.put("nonce_str", WXUtil.getNonceStr()); packageParams.put("body", "测试"); packageParams.put("out_trade_no", 你的唯一订单号); packageParams.put("total_fee","1"); //银行币种 packageParams.put("spbill_create_ip", request.remoteAddress); //订单生成的机器IP,指用户浏览器端IP packageParams.put("notify_url", 回调的url); packageParams.put("openid", openid); packageParams.put("trade_type", "JSAPI"); RequestHandler reqHandler = new RequestHandler(null, null); reqHandler.init(TenpayConfig.appid, TenpayConfig.appsecret, TenpayConfig.partnerkey); String sign = reqHandler.createSign(packageParams); packageParams.put("sign", sign); String xml = toXml(packageParams); String prepay_id = ""; String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //获取用户的 prepay_id = new GetWxOrderno().getPayNo2(createOrderURL, xml); //生成paysign SortedMap<String, String> payParams = new TreeMap<String, String>(); String non = WXUtil.getNonceStr(); String time = WXUtil.getTimeStamp(); payParams.put("appId", TenpayConfig.appid); payParams.put("nonceStr", non); payParams.put("timeStamp", time); payParams.put("package", "prepay_id="+prepay_id); payParams.put("signType", "MD5"); String paysign = reqHandler.createSign(payParams);
附上其他代码
public static String getNonceStr() { Random random = new Random(); return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)),"GBK"); }
public static String getTimeStamp() { return String.valueOf(System.currentTimeMillis() / 1000); }
public static String getMchBillno(Stringmchid) { SimpleDateFormat shortSdf =new SimpleDateFormat("yyyyMMdd"); String result = mchid+shortSdf.format(new Date())+String.valueOf(System.currentTimeMillis() / 1000); returnresult; }
public String createSign(SortedMap<String, String>packageParams) { 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 (null !=v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k +"=" +v +"&"); } } sb.append("key=" +this.getKey());//api密钥 String sign = MD5Util.MD5Encode(sb.toString(),this.charset) .toUpperCase(); returnsign; }
private static String toXml(SortedMap<String, String>params) { StringBuilder sb = new StringBuilder(); sb.append("<xml>"); for (Map.Entry<String, String>e :params.entrySet()) { sb.append("<" +e.getKey() +">"); sb.append(e.getValue()); sb.append("</" +e.getKey() +">"); } sb.append("</xml>"); returnsb.toString(); }
public static String getPayNo2(Stringurl,StringxmlParam)throws Exception{ KeyStore keyStore = KeyStore.getInstance("PKCS12"); String prepay_id = ""; FileInputStream instream = new FileInputStream(new File("p12的证书路径")); try { keyStore.load(instream, TenpayConfig.partner.toCharArray()); } finally { instream.close(); } // Trust own CA and all self-signed certs SSLContext sslcontext = SSLContexts.custom() .loadKeyMaterial(keyStore, TenpayConfig.partner.toCharArray()) .build(); // Allow TLSv1 protocol only SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext, new String[] { "TLSv1" }, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); CloseableHttpClient httpclient = HttpClients.custom() .setSSLSocketFactory(sslsf) .build(); try { HttpPost httpost= HttpClientConnectionManager.getPostMethod(url); httpost.setEntity(new StringEntity(xmlParam,"UTF-8")); HttpResponse response = httpclient.execute(httpost); String jsonStr = EntityUtils.toString(response.getEntity(),"UTF-8"); if(jsonStr.indexOf("FAIL")!=-1){ return "2"; } Map map = doXMLParse(jsonStr); prepay_id = (String) map.get("prepay_id"); } finally { httpclient.close(); } returnprepay_id; }