1、首先分享 微信统一下单接口:
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
微信接口 签名 对比网址:
https://pay.weixin.qq.com/wiki/tools/signverify/
微信小程序 微信支付 网址:
https://mp.weixin.qq.com/debug/wxadoc/dev/api/api-pay.html#wxrequestpaymentobject
2、微信小程序端 代码示例:
1 payment:function(event){ 2 var that = this; 3 console.log(\'去支付按钮点击事件\') 4 wx.request({ 5 url: \'http://192.168.8.50:8080/matouwang/wechat/wechatAppletGolf/createUnifiedOrder\', 6 method: \'POST\', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT 7 // 当method 为POST 时 设置以下 的header 8 header: { \'content-type\': \'application/x-www-form-urlencoded\' }, 9 data: { 10 amount: teamMoney, 11 openid: openId 12 }, 13 success: function (res) { 14 if (res.data.prepayId != \'\'){ 15 console.log(\'微信统一下单接口调用成功 数据包:\' + res.data.prepayId); 16 console.log(\'微信统一下单接口调用成功 订单号:\' + res.data.outTradeNo); 17 console.log(\'调用微信支付接口之前先生成签名\') 18 //保存订单号信息 19 var outTradeNo = res.data.outTradeNo; 20 wx.request({ 21 url: \'http://192.168.8.50:8080/matouwang/wechat/wechatAppletGolf/generateSignature\', 22 method: \'POST\', // OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT 23 // 当method 为POST 时 设置以下 的header 24 header: { \'content-type\': \'application/x-www-form-urlencoded\' }, 25 data: { 26 prepayId: res.data.prepayId 27 }, 28 success: function (paryResult) { 29 if (paryResult.data.sign != \'\') { 30 console.log(\'微信支付接口之前先生成签名成功\') 31 console.log(\'签名:\' + paryResult.data.sign) 32 console.log(\'随机串:\' + paryResult.data.nonceStr) 33 console.log(\'时间戳:\' + paryResult.data.timeStamp) 34 //这个applyId一定要大写 而且签名的参数和调用方法的参数值一定要统一 35 wx.requestPayment({ 36 \'appId\': \'\', 37 \'timeStamp\': paryResult.data.timeStamp, 38 \'nonceStr\': paryResult.data.nonceStr, 39 \'package\': paryResult.data.package, 40 \'signType\': \'MD5\', 41 \'paySign\': paryResult.data.sign, 42 \'success\': function (paymentRes) { 43 console.log(paymentRes) 44 that.setData({ 45 notPay: true, 46 paySuccess: false, 47 teamNotPay: true, 48 button:true, 49 outTradeNo: outTradeNo, 50 payDate:new Date() 51 }) 52 }, 53 \'fail\': function (error) { 54 console.log(error) 55 } 56 }) 57 } else { 58 console.log(\'微信支付接口之前先生成签名失败\') 59 } 60 } 61 }) 62 } 63 } 64 }); 65 },
3、分享微信 统一下单 后台代码示例:
1 @Override 2 public JSONObject createUnifiedOrder(HttpServletRequest request,HttpServletResponse response) { 3 logger.info("微信 统一下单 接口调用"); 4 //设置最终返回对象 5 JSONObject resultJson = new JSONObject(); 6 //创建条件 7 Criteria criteria = new Criteria(); 8 9 //接受参数(金额) 10 String amount = request.getParameter("amount"); 11 //接受参数(openid) 12 String openid = request.getParameter("openid"); 13 //接口调用总金额单位为分换算一下(测试金额改成1,单位为分则是0.01,根据自己业务场景判断是转换成float类型还是int类型) 14 //String amountFen = Integer.valueOf((Integer.parseInt(amount)*100)).toString(); 15 //String amountFen = Float.valueOf((Float.parseFloat(amount)*100)).toString(); 16 String amountFen = "1"; 17 //创建hashmap(用户获得签名) 18 SortedMap<String, String> paraMap = new TreeMap<String, String>(); 19 //设置body变量 (支付成功显示在微信支付 商品详情中) 20 String body = "啦啦啦测试"; 21 //设置随机字符串 22 String nonceStr = Utils.getUUIDString().replaceAll("-", ""); 23 //设置商户订单号 24 String outTradeNo = Utils.getUUIDString().replaceAll("-", ""); 25 26 27 //设置请求参数(小程序ID) 28 paraMap.put("appid", APPLYID); 29 //设置请求参数(商户号) 30 paraMap.put("mch_id", MCHID); 31 //设置请求参数(随机字符串) 32 paraMap.put("nonce_str", nonceStr); 33 //设置请求参数(商品描述) 34 paraMap.put("body", body); 35 //设置请求参数(商户订单号) 36 paraMap.put("out_trade_no", outTradeNo); 37 //设置请求参数(总金额) 38 paraMap.put("total_fee", amountFen); 39 //设置请求参数(终端IP) 40 paraMap.put("spbill_create_ip", WebUtils.getIpAddress(request, response)); 41 //设置请求参数(通知地址) 42 paraMap.put("notify_url", WebUtils.getBasePath()+"wechat/wechatAppletGolf/payCallback"); 43 //设置请求参数(交易类型) 44 paraMap.put("trade_type", "JSAPI"); 45 //设置请求参数(openid)(在接口文档中 该参数 是否必填项 但是一定要注意 如果交易类型设置成\'JSAPI\'则必须传入openid) 46 paraMap.put("openid", openid); 47 //调用逻辑传入参数按照字段名的 ASCII 码从小到大排序(字典序) 48 String stringA = formatUrlMap(paraMap, false, false); 49 //第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。(签名) 50 String sign = MD5Util.MD5(stringA+"&key="+KEY).toUpperCase(); 51 //将参数 编写XML格式 52 StringBuffer paramBuffer = new StringBuffer(); 53 paramBuffer.append("<xml>"); 54 paramBuffer.append("<appid>"+APPLYID+"</appid>"); 55 paramBuffer.append("<mch_id>"+MCHID+"</mch_id>"); 56 paramBuffer.append("<nonce_str>"+paraMap.get("nonce_str")+"</nonce_str>"); 57 paramBuffer.append("<sign>"+sign+"</sign>"); 58 paramBuffer.append("<body>"+body+"</body>"); 59 paramBuffer.append("<out_trade_no>"+paraMap.get("out_trade_no")+"</out_trade_no>"); 60 paramBuffer.append("<total_fee>"+paraMap.get("total_fee")+"</total_fee>"); 61 paramBuffer.append("<spbill_create_ip>"+paraMap.get("spbill_create_ip")+"</spbill_create_ip>"); 62 paramBuffer.append("<notify_url>"+paraMap.get("notify_url")+"</notify_url>"); 63 paramBuffer.append("<trade_type>"+paraMap.get("trade_type")+"</trade_type>"); 64 paramBuffer.append("<openid>"+paraMap.get("openid")+"</openid>"); 65 paramBuffer.append("</xml>"); 66 67 try { 68 //发送请求(POST)(获得数据包ID)(这有个注意的地方 如果不转码成ISO8859-1则会告诉你body不是UTF8编码 就算你改成UTF8编码也一样不好使 所以修改成ISO8859-1) 69 Map<String,String> map = doXMLParse(getRemotePortData(URL, new String(paramBuffer.toString().getBytes(), "ISO8859-1"))); 70 //应该创建 支付表数据 71 if(map!=null){ 72 //清空 73 criteria.clear(); 74 //设置openId条件 75 criteria.put("openId", openid); 76 //获取数据 77 List<WechatAppletGolfPayInfo> payInfoList = appletGolfPayInfoMapper.selectByExample(criteria); 78 //如果等于空 则证明是第一次支付 79 if(CollectionUtils.isEmpty(payInfoList)){ 80 //创建支付信息对象 81 WechatAppletGolfPayInfo appletGolfPayInfo = new WechatAppletGolfPayInfo(); 82 //设置主键 83 appletGolfPayInfo.setPayId(outTradeNo); 84 //设置openid 85 appletGolfPayInfo.setOpenId(openid); 86 //设置金额 87 appletGolfPayInfo.setAmount(Long.valueOf(amount)); 88 //设置支付状态 89 appletGolfPayInfo.setPayStatus("0"); 90 //插入Dao 91 int sqlRow = appletGolfPayInfoMapper.insert(appletGolfPayInfo); 92 //判断 93 if(sqlRow == 1){ 94 logger.info("微信 统一下单 接口调用成功 并且新增支付信息成功"); 95 resultJson.put("prepayId", map.get("prepay_id")); 96 resultJson.put("outTradeNo", paraMap.get("out_trade_no")); 97 return resultJson; 98 } 99 }else{ 100 //判断 是否等于一条 101 if(payInfoList.size() == 1){ 102 //获取 需要更新数据 103 WechatAppletGolfPayInfo wechatAppletGolfPayInfo = payInfoList.get(0); 104 //更新 该条的 金额 105 wechatAppletGolfPayInfo.setAmount(Long.valueOf(amount)); 106 //更新Dao 107 int sqlRow = appletGolfPayInfoMapper.updateByPrimaryKey(wechatAppletGolfPayInfo); 108 //判断 109 if(sqlRow == 1){ 110 logger.info("微信 统一下单 接口调用成功 修改支付信息成功"); 111 resultJson.put("prepayId", map.get("prepay_id")); 112 resultJson.put("outTradeNo", paraMap.get("out_trade_no")); 113 return resultJson; 114 } 115 } 116 } 117 } 118 //将 数据包ID 返回 119 120 System.out.println(map); 121 } catch (UnsupportedEncodingException e) { 122 logger.info("微信 统一下单 异常:"+e.getMessage()); 123 e.printStackTrace(); 124 } catch (Exception e) { 125 logger.info("微信 统一下单 异常:"+e.getMessage()); 126 e.printStackTrace(); 127 } 128 logger.info("微信 统一下单 失败"); 129 return resultJson; 130 }
4、生成 微信支付 签名后台 代码示例:
1 @Override 2 public JSONObject generateSignature(HttpServletRequest request, 3 HttpServletResponse response) { 4 logger.info("微信 支付接口生成签名 方法开始"); 5 //实例化返回对象 6 JSONObject resultJson = new JSONObject(); 7 8 //获得参数(微信统一下单接口生成的prepay_id ) 9 String prepayId = request.getParameter("prepayId"); 10 //创建 时间戳 11 String timeStamp = Long.valueOf(System.currentTimeMillis()).toString(); 12 //创建 随机串 13 String nonceStr = Utils.getUUIDString().replaceAll("-", ""); 14 //创建 MD5 15 String signType = "MD5"; 16 17 //创建hashmap(用户获得签名) 18 SortedMap<String, String> paraMap = new TreeMap<String, String>(); 19 //设置(小程序ID)(这块一定要是大写) 20 paraMap.put("appId", APPLYID); 21 //设置(时间戳) 22 paraMap.put("timeStamp", timeStamp); 23 //设置(随机串) 24 paraMap.put("nonceStr", nonceStr); 25 //设置(数据包) 26 paraMap.put("package", "prepay_id="+prepayId); 27 //设置(签名方式) 28 paraMap.put("signType", signType); 29 30 31 //调用逻辑传入参数按照字段名的 ASCII 码从小到大排序(字典序) 32 String stringA = formatUrlMap(paraMap, false, false); 33 //第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。(签名) 34 String sign = MD5Util.MD5(stringA+"&key="+KEY).toUpperCase(); 35 36 if(StringUtils.isNotBlank(sign)){ 37 //返回签名信息 38 resultJson.put("sign", sign); 39 //返回随机串(这个随机串是新创建的) 40 resultJson.put("nonceStr", nonceStr); 41 //返回时间戳 42 resultJson.put("timeStamp", timeStamp); 43 //返回数据包 44 resultJson.put("package", "prepay_id="+prepayId); 45 46 logger.info("微信 支付接口生成签名 设置返回值"); 47 } 48 logger.info("微信 支付接口生成签名 方法结束"); 49 return resultJson; 50 }
5、签名算法 将key Value 字典排序 代码示例:
1 /** 2 * 3 * 方法用途: 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序),并且生成url参数串<br> 4 * 实现步骤: <br> 5 * 6 * @param paraMap 要排序的Map对象 7 * @param urlEncode 是否需要URLENCODE 8 * @param keyToLower 是否需要将Key转换为全小写 9 * true:key转化成小写,false:不转化 10 * @return 11 */ 12 private static String formatUrlMap(Map<String, String> paraMap, boolean urlEncode, boolean keyToLower){ 13 String buff = ""; 14 Map<String, String> tmpMap = paraMap; 15 try 16 { 17 List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(tmpMap.entrySet()); 18 // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) 19 Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() 20 { 21 @Override 22 public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) 23 { 24 return (o1.getKey()).toString().compareTo(o2.getKey()); 25 } 26 }); 27 // 构造URL 键值对的格式 28 StringBuilder buf = new StringBuilder(); 29 for (Map.Entry<String, String> item : infoIds) 30 { 31 if (StringUtils.isNotBlank(item.getKey())) 32 { 33 String key = item.getKey(); 34 String val = item.getValue(); 35 if (urlEncode) 36 { 37 val = URLEncoder.encode(val, "utf-8"); 38 } 39 if (keyToLower) 40 { 41 buf.append(key.toLowerCase() + "=" + val); 42 } else 43 { 44 buf.append(key + "=" + val); 45 } 46 buf.append("&"); 47 } 48 49 } 50 buff = buf.toString(); 51 if (buff.isEmpty() == false) 52 { 53 buff = buff.substring(0, buff.length() - 1); 54 } 55 } catch (Exception e) 56 { 57 return null; 58 } 59 return buff; 60 }
6、发送远程请求 获得数据 代码示例:
1 2 /** 3 * 方法名: getRemotePortData 4 * 描述: 发送远程请求 获得代码示例 5 * 参数: @param urls 访问路径 6 * 参数: @param param 访问参数-字符串拼接格式, 例:port_d=10002&port_g=10007&country_a= 7 * 创建人: Xia ZhengWei 8 * 创建时间: 2017年3月6日 下午3:20:32 9 * 版本号: v1.0 10 * 返回类型: String 11 */ 12 private String getRemotePortData(String urls, String param){ 13 logger.info("港距查询抓取数据----开始抓取外网港距数据"); 14 try { 15 URL url = new URL(urls); 16 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 17 // 设置连接超时时间 18 conn.setConnectTimeout(30000); 19 // 设置读取超时时间 20 conn.setReadTimeout(30000); 21 conn.setRequestMethod("POST"); 22 if(StringUtil.isNotBlank(param)) { 23 conn.setRequestProperty("Origin", "https://sirius.searates.com");// 主要参数 24 conn.setRequestProperty("Referer", "https://sirius.searates.com/cn/port?A=ChIJP1j2OhRahjURNsllbOuKc3Y&D=567&G=16959&shipment=1&container=20st&weight=1&product=0&request=&weightcargo=1&"); 25 conn.setRequestProperty("X-Requested-With", "XMLHttpRequest");// 主要参数 26 } 27 // 需要输出 28 conn.setDoInput(true); 29 // 需要输入 30 conn.setDoOutput(true); 31 // 设置是否使用缓存 32 conn.setUseCaches(false); 33 // 设置请求属性 34 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 35 conn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接 36 conn.setRequestProperty("Charset", "UTF-8"); 37 38 if(StringUtil.isNotBlank(param)) { 39 // 建立输入流,向指向的URL传入参数 40 DataOutputStream dos=new DataOutputStream(conn.getOutputStream()); 41 dos.writeBytes(param); 42 dos.flush(); 43 dos.close(); 44 } 45 // 输出返回结果 46 InputStream input = conn.getInputStream(); 47 int resLen =0; 48 byte[] res = new byte[1024]; 49 StringBuilder sb=new StringBuilder(); 50 while((resLen=input.read(res))!=-1){ 51 sb.append(new String(res, 0, resLen)); 52 } 53 return sb.toString(); 54 } catch (MalformedURLException e) { 55 e.printStackTrace(); 56 logger.info("港距查询抓取数据----抓取外网港距数据发生异常:" + e.getMessage()); 57 } catch (IOException e) { 58 e.printStackTrace(); 59 logger.info("港距查询抓取数据----抓取外网港距数据发生异常:" + e.getMessage()); 60 } 61 logger.info("港距查询抓取数据----抓取外网港距数据失败, 返回空字符串"); 62 return ""; 63 }
7、XML 转换成 map 对象 代码示例:
1 /** 2 * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 3 * @param strxml 4 * @return 5 * @throws JDOMException 6 * @throws IOException 7 */ 8 @SuppressWarnings("rawtypes") 9 private Map<String,String> doXMLParse(String strxml) throws Exception { 10 if(null == strxml || "".equals(strxml)) { 11 return null; 12 } 13 14 Map<String,String> m = new HashMap<String,String>();
全部评论
请发表评论