微信扫码支付
来源:互联网 发布:linux pl2303驱动下载 编辑:程序博客网 时间:2024/06/04 19:12
配置文件
package com.nroad.config;import org.apache.commons.configuration.Configuration;import org.apache.commons.configuration.ConfigurationException;import org.apache.commons.configuration.PropertiesConfiguration;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.stereotype.Component;/** * WeixinPayConfig * Created by Administrator on 2017/5/4. * 微信支付配置文件 */@Componentpublic class WeixinPayConfig { private static Log log = LogFactory.getLog(WeixinPayConfig.class); private static Configuration configs; static { WeixinPayConfig.init("weixinpayinfo.properties"); } public static String appid; //微信支付分配的公众账号ID(企业号corpid即为此appId) public static String mch_id; //微信支付分配的商户号 public static String device_info; //设备号,PC网页或公众号内支付可以传"WEB" public static String post_url; //请求路径 public static String query_url; //查询路径 public static String appsecret; public static String mchsecret; //签名时使用的key private WeixinPayConfig() { } private static synchronized void init(String filePath) { if (configs == null) { try { configs = new PropertiesConfiguration(filePath); } catch (ConfigurationException var2) { var2.printStackTrace(); } } if (configs == null) { throw new IllegalStateException("can`t find file by path:" + filePath); } else { appid = configs.getString("appid"); mch_id = configs.getString("mch_id"); device_info = configs.getString("device_info"); post_url = configs.getString("post_url"); query_url = configs.getString("query_url"); appsecret = configs.getString("appsecret"); mchsecret = configs.getString("mchsecret"); log.info("微信支付配置如下: "); log.info("配置文件名: " + filePath); log.info(description()); } } private static String description() { StringBuilder sb = new StringBuilder("Configs{"); sb.append("微信公众账号ID: ").append(appid).append("\n"); sb.append("微信商户号: ").append(mch_id).append("\n"); sb.append("微信设备号: ").append(device_info).append("\n"); sb.append("请求路径: ").append(post_url).append("\n"); sb.append("查询路径: ").append(query_url).append("\n"); sb.append("支付秘钥: ").append(mchsecret).append("\n"); sb.append("}"); return sb.toString(); }
微信支付业务流程
package com.nroad.service.wechat.pay;import com.nroad.config.WeixinPayConfig;import com.nroad.dto.OrderDto;import com.nroad.exception.PayException;import com.nroad.utils.MathUtil;import com.nroad.utils.OrderUtil;import com.nroad.utils.PayCommonUtil;import org.springframework.stereotype.Component;import java.util.Map;import java.util.SortedMap;import java.util.TreeMap;/** * Created by Administrator on 2017/5/4. */@Componentpublic class WeChat { /** * 获取微信支付二维码 * @return */ public String trade_precreate(String cip, OrderDto orderDto,String serverName){ //获取二维码生存周期 String[] QRTime = OrderUtil.QRTime(); //生成随机字符串 String nonce_str = OrderUtil.nonce(); //参数收集 SortedMap<Object,Object> params=new TreeMap<Object, Object>(); params.put("appid", WeixinPayConfig.appid); //公众账号ID params.put("mch_id", WeixinPayConfig.mch_id); //商户号 params.put("device_info", WeixinPayConfig.device_info); //设备号 params.put("nonce_str", nonce_str); //随机字符串 params.put("out_trade_no",orderDto.getOrderNo()); //商户订单号 params.put("body",orderDto.getSubject()); //商品描述 params.put("detail",orderDto.getBody()); //商品详情 params.put("total_fee", MathUtil.movePointRight_s(orderDto.getTotalMoney(),2)); //订单总金额 params.put("spbill_create_ip",cip); //用户端ip params.put("time_start",QRTime[0]); //订单生成时间 params.put("time_expire",QRTime[1]); //订单失效时间 params.put("notify_url","http://"+serverName+":8100/weChat_notify"); //异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 params.put("trade_type","NATIVE"); //交易类型---JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付 //生成签名 String sign = PayCommonUtil.generateSign("UTF-8", params, WeixinPayConfig.mchsecret); params.put("sign",sign); //添加签名信息 //生成xml格式的String String requestXml = PayCommonUtil.generateRequestXml(params); //将xml格式数据发送给微信第三方,通知获取到其反馈信息(也为xml格式) String resXml = null; try { resXml = PayCommonUtil.postData(WeixinPayConfig.post_url, requestXml); } catch (PayException e) { e.printStackTrace(); throw new PayException("微信支付异常"); } //将xml解析为map Map map = PayCommonUtil.doXMLParse(resXml); return (String) map.get("code_url"); } /** * 支付结果结果查询 */ public String resultQuery(WeChatQuery weChatQuery){ SortedMap<Object, Object> requestMap = weChatQuery.getMap(); requestMap.put("nonce_str",OrderUtil.nonce()); String sign = PayCommonUtil.generateSign("UTF-8", requestMap, WeixinPayConfig.mchsecret); requestMap.put("sign",sign); // 生成xml格式的String String requestXml = PayCommonUtil.generateRequestXml(requestMap); //将xml格式数据发送给微信第三方,通知获取到其反馈信息(也为xml格式) String resXml = PayCommonUtil.postData(WeixinPayConfig.query_url, requestXml); //将xml解析为map Map map = PayCommonUtil.doXMLParse(resXml); String result = (String) map.get("trade_state"); System.out.println("微信支付 : " + result); return result; }}
需要使用的工具类
package com.nroad.utils;import java.time.LocalDateTime;/** * Created by Administrator on 2017/5/4. * 订单工具 */public class OrderUtil { public final static String TIME_REGEX = "[-:T.]"; /** * 生成订单号 * @return */ public static String nonce(){ return String.valueOf(System.currentTimeMillis() + (long) (Math.random() * 10000000L)); } /** * 生成商户订单号 * @return */ public static String merchantNo(){ String now = LocalDateTime.now().toString(); return now.replaceAll(TIME_REGEX, "")+"Lb"+(long)(Math.random()*1000000000000L); } /** * 获取交易起始时间和失效时间 * 暂时默认为10分钟 */ public static String[] QRTime(){ LocalDateTime startTime = LocalDateTime.now(); LocalDateTime endTime = startTime.plusMinutes(30L); String start = startTime.toString().split("[.]")[0]; String end = endTime.toString().split("[.]")[0]; return new String[]{start.replaceAll(TIME_REGEX, ""), end.replaceAll(TIME_REGEX, "")}; }}
package com.nroad.utils;import org.apache.commons.lang.StringUtils;import org.jdom.Document;import org.jdom.Element;import org.jdom.JDOMException;import org.jdom.input.SAXBuilder;import java.io.*;import java.net.MalformedURLException;import java.net.URL;import java.net.URLConnection;import java.util.*;/** * Created by Administrator on 2017/5/5. * 支付相关工具 */public class PayCommonUtil { private final static int CONNECT_TIMEOUT = 5000; private final static String DEFAULT_ENCODING = "UTF-8"; /** * 生成签名 * * @param characterEncoding * @param packageParams * @param API_KEY * @return */ public static String generateSign(String characterEncoding, Map<Object, Object> packageParams, String API_KEY) { StringBuffer sb = new StringBuffer(); Set<Map.Entry<Object, Object>> entries = packageParams.entrySet(); Iterator<Map.Entry<Object, Object>> iterator = entries.iterator(); //第一步,生成签名字符串 while (iterator.hasNext()) { Map.Entry entry = iterator.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) { sb.append(key + "=" + value + "&"); } } sb.append("key=" + API_KEY); //通过MD5算法转换 并将其全部转化成大写 String sign = MD5.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); return sign; } /** * 将请求参数转换为xml格式的string * * @param parameters * @return */ public static String generateRequestXml(SortedMap<Object, Object> parameters) { StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set<Map.Entry<Object, Object>> entries = parameters.entrySet(); Iterator<Map.Entry<Object, Object>> iterator = entries.iterator(); while (iterator.hasNext()) { Map.Entry next = iterator.next(); String key = (String) next.getKey(); String value = (String) next.getValue(); if ("".equals(StringUtils.trimToEmpty(value))){ continue; } if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) { sb.append("<" + key + ">" + "<![CDATA[" + value + "]]></" + key + ">"); } else { sb.append("<" + key + ">" + value + "</" + key + ">"); } } sb.append("</xml>"); return sb.toString(); } /** * 将xml数据转换成为 Map类型 * * @param strxml * @return */ public static Map doXMLParse(String strxml) { strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); if (null == strxml || "".equals(strxml)) { return null; } Map m = new HashMap(); InputStream in =null; try { 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 iterator = list.iterator(); while (iterator.hasNext()) { Element e = (Element) iterator.next(); String name = e.getName(); String value = ""; List children = e.getChildren(); //如果存在子节点,继续遍历 if (children.isEmpty()) { value = e.getTextNormalize(); } else { value = PayCommonUtil.getChildrenText(children); } m.put(name, value); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (JDOMException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (in !=null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } } return m; } /** * 获取子节点的xml * @param children * @return */ public static String getChildrenText(List children){ StringBuffer sb =new StringBuffer(); //子节点不为空,迭代子节点 if (!children.isEmpty()){ Iterator iterator = children.iterator(); while (iterator.hasNext()){ Element element = (Element) iterator.next(); String name = element.getName(); String value = element.getTextNormalize(); List list = element.getChildren(); sb.append("<" + name + ">"); if (!list.isEmpty()){ sb.append(PayCommonUtil.getChildrenText(list)); } sb.append(value); sb.append("</" + name +">"); } } return sb.toString(); } /** * 请求数据 * @param url * @param requestXML * @return */ public static String postData(String url, String requestXML) { return postData(url, requestXML, null); } /** * 请求数据,如果成功,获得的是一个xml数据 * @param strUrl * @param data * @param conentType * @return */ private static String postData(String strUrl, String data, String conentType) { BufferedReader reader = null; try { URL url = new URL(strUrl); URLConnection conn = url.openConnection(); conn.setDoOutput(true); conn.setConnectTimeout(CONNECT_TIMEOUT); conn.setReadTimeout(CONNECT_TIMEOUT); if (conentType != null) { conn.setRequestProperty("content-type", conentType); } OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING); if (data == null) { data = ""; } writer.write(data); writer.flush(); writer.close(); reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING)); StringBuffer sb = new StringBuffer(); String line = null; while ((line = reader.readLine()) != null) { sb.append(line); sb.append("\r\n"); } return sb.toString(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) try { reader.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } public static boolean isTenpaySign(String characterEncoding , SortedMap<Object, Object> packageParams, String API_KEY){ StringBuffer sb = new StringBuffer(); Set<Map.Entry<Object, Object>> entries = packageParams.entrySet(); Iterator<Map.Entry<Object, Object>> iterator = entries.iterator(); while (iterator.hasNext()){ Map.Entry entry = (Map.Entry) iterator.next(); String key = (String) entry.getKey(); String value = (String) entry.getValue(); if (!"sign".equalsIgnoreCase(key) && null != value && !"".equals(value)){ sb.append(key + "=" + value +"&"); } } sb.append("key=" + API_KEY); //算出摘要 String mysign = MD5.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); String tenpaySign = ((String)packageParams.get("sign")).toLowerCase(); System.out.println("mysign : "+mysign); System.out.println("tenpaySign : "+tenpaySign); return tenpaySign.equals(mysign); }}
异步通知
@RequestMapping("/weChat_notify") public void weChat_notify(HttpServletRequest request, HttpServletResponse response) { log.info("微信异步通知开始"); //读取参数 InputStream inputStream = null; StringBuffer sb = new StringBuffer(); BufferedReader bufferedReader = null; try { log.info("获取返回参数"); String s = ""; inputStream = request.getInputStream(); bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); while ((s = bufferedReader.readLine()) != null) { sb.append(s); } } catch (IOException e) { log.info("返回参数获取失败"); e.printStackTrace(); } finally { try { if (null != bufferedReader) bufferedReader.close(); if (null != inputStream) inputStream.close(); } catch (IOException e) { log.info("io流关闭失败"); e.printStackTrace(); } } log.info("开始解析xml参数"); //解析xml成map Map<String, String> m = new HashMap<String, String>(); Map map = PayCommonUtil.doXMLParse(sb.toString()); //过滤空 设置 TreeMap log.info("开始过滤空值"); SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); Iterator iterator = map.keySet().iterator(); while (iterator.hasNext()) { String parameter = (String) iterator.next(); String paramterValue = (String) map.get(parameter); String value = ""; //去空格,将NULL 和 "" 转换为"" value = StringUtils.trimToEmpty(paramterValue); packageParams.put(parameter, value); } //判断签名是否正确 log.info("签名验证开始"); if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, WeixinPayConfig.mchsecret)) { log.info("签名验证成功"); //------------------------------ //处理业务开始 //------------------------------ String resXml = ""; if ("SUCCESS".equals((String) packageParams.get("result_code"))) { //这里是支付成功 ///////////////////开始自己的业务/////////////////////// String out_trade_no = (String) packageParams.get("out_trade_no"); save(out_trade_no,"微信"); ///////////////////开始自己的业务/////////////////////// log.info("支付成功"); //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; } else { log.info("支付失败,错误信息:" + packageParams.get("err_code")); resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> "; } //------------------------------ //处理业务完毕 //------------------------------ BufferedOutputStream out = null; try { out = new BufferedOutputStream( response.getOutputStream()); out.write(resXml.getBytes()); } catch (IOException e) { e.printStackTrace(); } finally { try { out.flush(); out.close(); } catch (IOException e) { e.printStackTrace(); } } } else { log.info("通知签名验证失败"); } }
阅读全文
0 0
- 支付宝电脑支付,微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付
- 微信扫码支付-原生支付-流程图
- 微信扫码支付-Native原生支付
- 支付篇—微信扫码支付
- laravel+php+微信扫码支付
- java微信扫码支付
- 微信扫码支付 php代码
- 微信扫码支付开发记录
- datagrid groupview分组新增单选按钮
- Tensorflow学习笔记(二):Deep MNIST for Experts
- java动态代理之自我理解
- 反射修改字段数据
- 000040:在主方法中通过while循环将整数1~10相加,并将结果输出
- 微信扫码支付
- base64网络传输问题
- python学习之——字符串查找 find 和 index方法
- linux从官网安装mysql 5.6
- require时报错:loop or previous error loading module "xxx"
- 中国计算机学会CCF推荐国际学术会议和期刊目录-计算机网络
- js 多文件下载,不错
- IA插件文件编写
- clang++ for centos