微信app支付官方开发文档地址:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
以下简单记录调试服务端微信app支付相关信息,有不足之处还望大家指教
一、统一下单
SortedMap<Object, Object> params = new TreeMap(); params.put("appid", 应用ID); params.put("mch_id", 商户号); params.put("nonce_str", 随机字符串); params.put("body", 商品描述); params.put("attach", 附加数据); params.put("out_trade_no",商家订单号);// 商户系统内部订单号,32个字符内、且在同一商户号下唯一 params.put("total_fee",10);// 订单总金额,单位为分 params.put("spbill_create_ip", 终端IP); params.put("notify_url",异步通知地址); params.put("trade_type","APP");// 交易类型 String sign= Util4WxSign.createSign("UTF-8",params);// 签名 params.put("sign",sign); String myTar= Util4WxSign.getRequestXml(params); String myres= Util4WxSign.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", target); Map<String,String> myMap= Util4WxSign.doXMLParse(myres); params.clear(); params.put("appid", 应用ID ); params.put("partnerid", 商户号); params.put("prepayid",myMap.get("prepay_id")); params.put("package","Sign=WXPay"); params.put("noncestr",商家附加参数); params.put("timestamp",时间戳); String my_wx_sign= Util4WxSign.createSign("UTF-8", params); params.put("sign",my_wx_sign);
二、支付回调
Map<String, String> request = Util4WxXML.doXMLParse(req);//解析微信回传的支付信息 boolean verify = Util4WxSign.check(request);//验签 if (verify) { String returnCode = (String)request.get("return_code");// 返回状态码 String returnMsg = (String)request.get("return_msg");//返回信息 if ("SUCCESS".equals(returnCode)) { String app_id = (String)request.get("appid"); String mch_id = (String)request.get("mch_id"); if (Util4WxSign.APP_ID.equals(app_id))//匹配app_id { if (Util4WxSign.MCH_ID.equals(mch_id))//匹配mch_id { //支付成功 开始相关业务处理 } } } }
**************************************我是分割线**************************************************
附上两个工具类(包含签名,封装解析xml):
import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ConnectException; import java.net.URL; import java.util.*; /** * Created by cheng. */ public class Util4WxSign { public static String API_KEY = "你的api_key";//微信app支付 public static String APP_ID = "你的app_id"; public static String MCH_ID = "你的商户号mch_id"; public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){ StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet(); 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=" + API_KEY); String sign = Util4WxMd5.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } public static String getRequestXml(SortedMap<Object,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 k = (String)entry.getKey(); String v = (String)entry.getValue(); if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) { sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">"); }else { sb.append("<"+k+">"+v+"</"+k+">"); } } sb.append("</xml>"); return sb.toString(); } public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) { try { // 创建SSLContext对象,并使用我们指定的信任管理器初始化 TrustManager[] tm = { new Util4WxMyX509TrustManager() }; SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE"); sslContext.init(null, tm, new java.security.SecureRandom()); // 从上述SSLContext对象中得到SSLSocketFactory对象 SSLSocketFactory ssf = sslContext.getSocketFactory(); URL url = new URL(requestUrl); HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setSSLSocketFactory(ssf); 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(); conn.disconnect(); return buffer.toString(); } catch (ConnectException ce) { ce.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } public static String CreateNoncestr() { String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; String res = ""; for (int i = 0; i < 16; i++) { Random rd = new Random(); res += chars.charAt(rd.nextInt(chars.length() - 1)); } return res; } }
import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public class Util4WxXML { /** * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 * @param strxml * @return * @throws JDOMException * @throws IOException */ 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 = Util4WxXML.getChildrenText(children); } m.put(k, v); } //关闭流 in.close(); return m; } /** * 获取子结点的xml * @param children * @return String */ 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(Util4WxXML.getChildrenText(list)); } sb.append(value); sb.append("</" + name + ">"); } } return sb.toString(); } }