微信App支付开发历程
微信开放平台账号配置
查看详情得到对应的AppID和AppSecret(不可再次查看,创建App应用时保存好),对应的接口信息中注意开通微信支付
app支付核心代码如下:
//微信支付 String now_ip=Utils.getIP(request); //得到用户ip String nonce_str=Utils.getCharAndNum(32); //得到32位随机数 int inputIntFee=1; String total_fee=inputIntFee+""; //total_fee="1";// String prepay_id=null; Map<String,String> paraMap=new HashMap<>(); paraMap.put("appid", PayConfigUtils.getWx_app_id()); paraMap.put("attach", description); paraMap.put("body", body); paraMap.put("mch_id", PayConfigUtils.getWx_mch_id()); paraMap.put("nonce_str", nonce_str); paraMap.put("notify_url", PayConfigUtils.getWx_pay_notify_url()); paraMap.put("out_trade_no", passengerOrder.getPay_num()); paraMap.put("spbill_create_ip", now_ip); paraMap.put("total_fee", total_fee); paraMap.put("trade_type", "APP"); List<String> keys =new ArrayList<>(paraMap.keySet()); Collections.sort(keys); StringBuilder authInfo = new StringBuilder(); for (int i=0;i<keys.size()-1; i++) { String value = paraMap.get(keys.get(i)); authInfo.append(keys.get(i)+"="+value+"&"); } authInfo.append(keys.get(keys.size()-1)+"="+paraMap.get(keys.get(keys.size()-1))); String stringA=authInfo.toString()+"&key="+PayConfigUtils.getWx_app_secret_key(); String sign=Utils.encode("MD5",stringA).toUpperCase(); //封装xml String paras="<xml>\n" + " <appid>"+PayConfigUtils.getWx_app_id()+"</appid>\n" + " <attach>"+description+"</attach>\n" + " <body>"+body+"</body>\n" + " <mch_id>"+PayConfigUtils.getWx_mch_id()+"</mch_id>\n" + " <nonce_str>"+nonce_str+"</nonce_str>\n" + " <notify_url>"+PayConfigUtils.getWx_pay_notify_url()+"</notify_url>\n" + " <out_trade_no>"+passengerOrder.getPay_num()+"</out_trade_no>\n" + " <spbill_create_ip>"+now_ip+"</spbill_create_ip>\n" + " <total_fee>"+total_fee+"</total_fee>\n" + " <trade_type>APP</trade_type>\n" + " <sign>"+sign+"</sign>\n" + "</xml>"; try { String content=senPost(paras); if(content!=null){ prepay_id=Utils.readStringXml(content); } if(prepay_id!=null){ String current_noncestr=Utils.getCharAndNum(32); String current_sign=null; long current_timestamp=System.currentTimeMillis()/1000; result.put("appid",PayConfigUtils.getWx_app_id()); result.put("partnerid",PayConfigUtils.getWx_mch_id()); result.put("prepayid",prepay_id); result.put("package","Sign=WXPay"); result.put("noncestr",current_noncestr); result.put("timestamp",current_timestamp); //加密算法 String nowStringA="appid="+PayConfigUtils.getWx_app_id()+"&noncestr="+current_noncestr+"&package=Sign=WXPay&partnerid="+PayConfigUtils.getWx_mch_id()+"&prepayid="+prepay_id+"×tamp="+current_timestamp+"&key="+PayConfigUtils.getWx_app_secret_key(); current_sign=Utils.encode("MD5",nowStringA).toUpperCase(); result.put("sign",current_sign); } } catch (Exception e) { e.printStackTrace(); }
工具类Utils具体代码如下:
package com.now.do.utilities; import org.apache.commons.lang.StringUtils; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import redis.clients.jedis.Jedis; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.FileOutputStream; import java.io.InputStream; import java.security.MessageDigest; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; public class Utils { public static String getCurrentTime() { Date inputDate = new Date(); SimpleDateFormat outputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String datetime = outputFormat.format(inputDate); return datetime; } public static String getTimestamp() { Long timestamp = System.currentTimeMillis(); return timestamp.toString(); } public static long getCurrenTimeStamp(){ long time = System.currentTimeMillis(); return time; } //加密算法 public static String encode(String algorithm, String str) { String ALGORITHM = "MD5"; char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; if (str == null) { return null; } try { MessageDigest messageDigest = MessageDigest.getInstance(algorithm); messageDigest.update(str.getBytes("utf-8")); return getFormattedText(messageDigest.digest()); } catch (Exception e) { throw new RuntimeException(e); } } private static String getFormattedText(byte[] bytes) { int len = bytes.length; StringBuilder buf = new StringBuilder(len * 2); char[] HEX_DIGITS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; // 把密文转换成十六进制的字符串形式 for (int j = 0; j < len; j++) { buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]); buf.append(HEX_DIGITS[bytes[j] & 0x0f]); } return buf.toString(); } public static String getIP(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){ //多次反向代理后会有多个ip值,第一个ip才是真实ip int index = ip.indexOf(","); if(index != -1){ return ip.substring(0,index); }else{ return ip; } } ip = request.getHeader("X-Real-IP"); if(StringUtils.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)){ return ip; } return request.getRemoteAddr(); } //产生8位随机数 public static String random(int n){ int[] i=new int[n]; int count=0; String randomNum=""; while(count<n){ int t=(int)(Math.random()*9);//抽取的数值小于char类型的“z”(122) if((t>=0&t<=9)){ i[count]=t; count++; } }for(int k=0;k<n;k++){ if(i[k]>=0&i[k]<=9) randomNum=randomNum+i[k]; else randomNum=randomNum+(char)i[k]; } return randomNum; } public static String getCharAndNum(int length) { String val = ""; Random random = new Random(); for (int i = 0; i < length; i++) { // 输出字母还是数字 String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 字符串 if ("char".equalsIgnoreCase(charOrNum)) { // 取得大写字母还是小写字母 int choice = random.nextInt(2) % 2 == 0 ? 65 : 97; val += (char) (choice + random.nextInt(26)); } else if ("num".equalsIgnoreCase(charOrNum)) { // 数字 val += String.valueOf(random.nextInt(10)); } } return val; } public static void getUpperWord(){ String key="851wordW"; System.out.println(key.toUpperCase()); } //随机生成一个在一定范围内的随机数 public static int getRandomNum(int limit){ int randomNum=(int)(Math.random()*(limit+1));//抽取的数值小于char类型的“z”(122) return randomNum; } public static String readStringXml( String xml) { Document doc ; String result=null; try { doc = DocumentHelper.parseText(xml); // 将字符串转为XML Element rootElt = doc.getRootElement(); // 获取根节点 Iterator return_code = rootElt.elementIterator("return_code"); // 获取根节点下的子节点return_code // 获取根节点下的子节点return_code String is_success=null; // 遍历head节点 while (return_code.hasNext()) { Element recordEle = (Element) return_code.next(); is_success = recordEle.getText(); // 拿到return_code返回值 //System.out.println("return_code:" + is_success); } if(is_success!=null&&is_success.equals("SUCCESS")){ Iterator prepay_id = rootElt.elementIterator("prepay_id"); while (prepay_id.hasNext()) { Element recordEle = (Element) prepay_id.next(); result = recordEle.getText(); // 拿到prepay_id返回值 //System.out.println("prepay_id:" + result); } } } catch (DocumentException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return result; } public static void getDoubleValue(){ String time=Utils.getCurrentTime(); System.out.println(time.substring(0,time.length()-3)); } }
剩下的工作就是把得到的吊起微信支付的参数,即上面的JsonObject(result)发送到前台就ok了!