第三方支付——微信web端支付(java)
大概思路:将参数组装为一个map集合,签名后发送http请求给微信,微信会返回一个xml字符串,将这个xml字符串解析并验签,得到code_url参数,传给前台,前台将这个code_url生成一个二维码,就可以了。
1、创建支付
/** * 微信支付 * @param model * @param order_id * @return * @throws Exception */ @RequestMapping(value = "/doWechatPay", method = RequestMethod.POST)@ResponseBody public Map createWechatPay(Model model, Integer order_id,HttpServletRequest request) throws Exception {Map json = new HashMap(); User user = (User) model.asMap().get("user"); ShareOrderInfo order = orderInfoMapper.selectByPrimaryKey(order_id); //生成一笔预付订单流水 String trad_no = "PC_WECHAT" + OrderNoUtil.leadsNo();//订单流水号 ShareUserTrad trad = new ShareUserTrad(); trad.setResourceTradId(-1); trad.setUserId(user.getId()); trad.setCreatedBy(user.getId()); trad.setLastUpdBy(user.getId()); trad.setOnlineOfflineFlag("0");//线上 trad.setOrderNo(order.getOrderNo()); trad.setUserTradAmount(order.getToBePaid()); trad.setTradMethod("4");//支付宝 trad.setPayReceiveFlag("2");//支出 trad.setSuccessFlag("0");//交易进行中 trad.setTradType("1");//订单支付 trad.setTradNo(trad_no); trad.setModifyNum(0); shareUserTradMapper.insertSelective(trad); //随机字符串 String nonce_str = PayUtil.getRandomString(32); String UTF8 = "UTF-8"; Map<String,String> map = new HashMap<String,String>(); map.put("body","订单["+order.getOrderNo()+"]支付"); map.put("trade_type","NATIVE"); map.put("mch_id",Config.wechat_mch_id); map.put("sign_type","MD5"); map.put("nonce_str",nonce_str); map.put("fee_type","CNY"); map.put("device_info","WEB"); map.put("out_trade_no",trad_no); map.put("total_fee",order.getToBePaid().multiply(new BigDecimal(100)).toBigInteger().toString()); // map.put("total_fee","1");//测试 map.put("appid",Config.wechat_app_id); map.put("notify_url",Config.wechat_notify_url); map.put("spbill_create_ip",PayUtil.getIp(request)); String sign = PayUtil.getWechatSign(map); String reqBody = "<xml>" +"<body>"+map.get("body")+"</body>" +"<trade_type>"+map.get("trade_type")+"</trade_type>" +"<mch_id>"+map.get("mch_id")+"</mch_id>" +"<sign_type>"+map.get("sign_type")+"</sign_type>" +"<nonce_str>"+map.get("nonce_str")+"</nonce_str>" +"<detail />"+"<fee_type>"+map.get("fee_type")+"</fee_type>" +"<device_info>"+map.get("device_info")+"</device_info>" +"<out_trade_no>"+map.get("out_trade_no")+"</out_trade_no>" +"<total_fee>"+map.get("total_fee")+"</total_fee>" +"<appid>"+map.get("appid")+"</appid>" +"<notify_url>"+map.get("notify_url")+"</notify_url>" +"<sign>"+sign+"</sign>" +"<spbill_create_ip>"+map.get("spbill_create_ip")+"</spbill_create_ip>" +"</xml>"; URL httpUrl = new URL(Config.wechat_url); HttpURLConnection httpURLConnection = (HttpURLConnection) httpUrl.openConnection(); httpURLConnection.setRequestProperty("Host", "api.mch.weixin.qq.com"); httpURLConnection.setDoOutput(true); httpURLConnection.setRequestMethod("POST"); httpURLConnection.setConnectTimeout(10*1000); httpURLConnection.setReadTimeout(10*1000); httpURLConnection.connect(); OutputStream outputStream = httpURLConnection.getOutputStream(); outputStream.write(reqBody.getBytes(UTF8)); //获取内容 InputStream inputStream = httpURLConnection.getInputStream(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8)); final StringBuffer stringBuffer = new StringBuffer(); String line = null; while ((line = bufferedReader.readLine()) != null) {stringBuffer.append(line); }String resp = stringBuffer.toString(); if (stringBuffer!=null) {try {bufferedReader.close(); } catch (IOException e) {e.printStackTrace(); }}if (inputStream!=null) {try {inputStream.close(); } catch (IOException e) {e.printStackTrace(); }}if (outputStream!=null) {try {outputStream.close(); } catch (IOException e) {e.printStackTrace(); }}Map<String, String> respData = PayUtil.xmlToMap(resp); String return_code = ""; if (respData.containsKey("return_code")) {return_code = respData.get("return_code"); }if("SUCCESS".equals(return_code)){if (respData.containsKey("sign") ) {String respSign = respData.get("sign"); if(respData.get("sign").equals(PayUtil.getWechatSign(respData))){json.put("code_url",respData.get("code_url")); }}}System.out.println(resp); return json; }
respData.get("code_url")
这个就是我们要的二维码内容。
PayUtil:
import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.servlet.http.HttpServletRequest; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.security.MessageDigest; import java.util.*; public class PayUtil {/** * MD5加密 * @param data * @return * @throws Exception */ public static String MD5(String data) throws Exception {java.security.MessageDigest md = MessageDigest.getInstance("MD5"); byte[] array = md.digest(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); }return sb.toString().toUpperCase(); }/** * XML转MAP * @param strXML * @return * @throws Exception */ public static Map<String, String> xmlToMap(String strXML) throws Exception {try {Map<String, String> data = new HashMap<String, String>(); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); org.w3c.dom.Document doc = documentBuilder.parse(stream); doc.getDocumentElement().normalize(); NodeList nodeList = doc.getDocumentElement().getChildNodes(); for (int idx = 0; idx < nodeList.getLength(); ++idx) {Node node = nodeList.item(idx); if (node.getNodeType() == Node.ELEMENT_NODE) {org.w3c.dom.Element element = (org.w3c.dom.Element) node; data.put(element.getNodeName(), element.getTextContent()); }}try {stream.close(); } catch (Exception ex) {ex.printStackTrace(); }return data; } catch (Exception ex) {ex.printStackTrace(); return null; }}/** * 获取随机字符串 * @param length * @return */ public static String getRandomString(int length) { //length表示生成字符串的长度 String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuffer sb = new StringBuffer(); for (int i = 0; i < length; i++) {int number = random.nextInt(base.length()); sb.append(base.charAt(number)); }return sb.toString(); }/** * 获取IP地址 * @param request * @return */ public static String getIp(HttpServletRequest request){String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP"); }if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP"); }if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP"); }if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR"); }if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr(); }return ip; }/** * 获取微信支付签名 * @param map * @return * @throws Exception */ public static String getWechatSign(Map<String,String> map) throws Exception{Set<String> keySet = map.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) {if (k.equals("sign")) {continue; }if (map.get(k).trim().length() > 0) {// 参数值为空,则不参与签名 sb.append(k).append("=").append(map.get(k).trim()).append("&"); }}sb.append("key=").append(Config.wechat_key); return PayUtil.MD5(sb.toString()).toUpperCase(); }/** * * Map转xml数据 */ public static String mapToXML(Map<String,String> param){StringBuffer sb = new StringBuffer(); sb.append("<xml>"); for (Map.Entry<String,String> entry : param.entrySet()) {sb.append("<"+ entry.getKey() +">"); sb.append(entry.getValue()); sb.append("</"+ entry.getKey() +">"); }sb.append("</xml>"); return sb.toString(); } }
2、前台根据code_url生成支付二维码
这里我使用了第三方js控件qrcode来生成二维码。
function toWechatPay(){var data = "order_id=" + ${id}; $.ajax({url: rootPath + '/pay/doWechatPay', type: "post", data: data, processData: true, success: function (result) {var json = eval('('+result+')'); $("#wechatQrcode").qrcode({render: "table", //table方式 width: 200, //宽度 height:200, //高度 text: json.code_url //任意内容 }); $(document).ready(function () {setInterval("ajaxstatus()", 3000); }); }, error: function (XMLHttpRequest, error, errorThrown) {layer.msg("支付失败,原因:保存预支付交易流水失败"); }}); }
因为二维码为静态的,所以设置一个三秒的定时任务查询订单的状态,来改变页面。
function ajaxstatus() {var data = "order_id=" + ${id}; $.ajax({url: rootPath + '/pay/getPayStatus', type: "GET", dataType:"json", data: data, success: function (data) {if (data.status == "3") { //订单状态为3表示支付成功 layer.msg("支付成功,请刷新页面~",{shift: -1,time:2000},function(){var index = parent.layer.getFrameIndex(window.name); parent.layer.close(index); }); }}, error: function () {layer.msg("请求订单状态出错"); }}); }
3、异步通知
/** * 微信支付异步通知 * @param request * @param response * @throws Exception */ @RequestMapping(value = "/wechatPayNo", method = RequestMethod.POST)@ResponseBody public void wechatPayNotify(HttpServletRequest request,HttpServletResponse response) throws Exception {ServletInputStream instream = request.getInputStream(); StringBuffer sb = new StringBuffer(); int len = -1; byte[] buffer = new byte[1024]; while((len = instream.read(buffer)) != -1){sb.append(new String(buffer,0,len)); }instream.close(); Map<String,String> requestMap = PayUtil.xmlToMap(sb.toString());//接受微信的通知参数 String return_code = ""; String returnXml = ""; // BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); if (requestMap.containsKey("return_code")) {return_code = requestMap.get("return_code"); }else{returnXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[return_code不存在]]></return_msg>" + "</xml> "; // out.write(returnXml.getBytes()); }if("SUCCESS".equals(return_code)){if (requestMap.containsKey("sign") ) {String respSign = requestMap.get("sign"); if(respSign.equals(PayUtil.getWechatSign(requestMap))){DealUserTradModel dealUserTradModel = new DealUserTradModel(); dealUserTradModel.setOut_trad_no(requestMap.get("transaction_id")); dealUserTradModel.setTrad_no(requestMap.get("out_trade_no")); dealUserTradModel.setCompany_amount(new BigDecimal(requestMap.get("total_fee")).divide(new BigDecimal("100")));//微信以分为单位,除以100…… dealUserTradModel.setPay_amount(new BigDecimal(requestMap.get("total_fee")).divide(new BigDecimal("100"))); dealUserTradModel.setUser_account(requestMap.get("openid")); dealUserTradModel.setUser_account_name(requestMap.get("openid")); payService.dealTrad(dealUserTradModel); // returnXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" // + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; // out.write(returnXml.getBytes()); String msg = "success"; response.setContentType("text/xml"); response.getWriter().println(msg); }else{returnXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[sign不正确]]></return_msg>" + "</xml> "; // out.write(returnXml.getBytes()); }}else{returnXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[sign不正确]]></return_msg>" + "</xml> "; // out.write(returnXml.getBytes()); }}else{returnXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[return_code不正确]]></return_msg>" + "</xml> "; // out.write(returnXml.getBytes()); } // out.flush(); // out.close(); }
校验参数,并修改数据库的订单状态,同时返回success,否则微信会重复通知。
String msg = "success"; response.setContentType("text/xml"); response.getWriter().println(msg);
第三方支付——微信web端支付(java)相关推荐
- Flask后端实践 连载十六 Flask实现微信Web端及APP端登录注册
Flask后端实践 连载十六 Flask实现微信Web端及APP端登录注册 tips: 本文将实现微信Web端和APP端登陆注册 本文基于python3编写 代码仓库 项目场景 某天,项目经理说,项目 ...
- 由于内核久,腾讯云的webrtc服务在微信web端尚无法使用此功能(客服已解释)
以下内容是我的提问里面的内荣,文章后面的客服内容则是新增的: 添加描述 这个是pc端微信 demo打开的界面 很明显那个select没有渲染出来,而且也没有alert出来是否支持webrtc 添加描述 ...
- JSAPI网页授权-微信支付-微信退款-商户平台Java对接
简介: 首先,对接微信支付要知道需要什么参数,然后等我们拿到这些需要的参数.就要开始怎么去做.微信有专门的支付dome,可惜我才疏学浅,没怎么看懂(哭泣~).不过里面的有一些工具类是我们所需要的. 这 ...
- h5通过php微信支付宝支付,用H5调用支付微信公众号支付的解析
这篇文章主要为大家详细介绍了微信公众号支付H5调用支付,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 最近项目需要微信支付,然后看了下微信公众号支付,虽然不难,但是细节还是需要注意的,用了大半天时 ...
- 支付宝手机网站支付,app支付,PC端支付流程以及服务端php支付下单,回调流程详解
一.支付宝支付相关文档地址: 支付宝支付相关的文档地址:https://open.alipay.com/api 电脑网站支付:https://opendocs.alipay.com/open/270/ ...
- android 微信跨境支付,微信跨境支付.pdf
微信跨境支付 WeChat Cross-border Payment 1 (1) Business Overview (1) , We cooperate with China Tencent tec ...
- 微信小程序php后台支付,微信小程序 支付功能实现PHP实例详解
微信小程序 支付功能实现PHP实例详解 前端代码: wx.request({ url: 'https://www.yourhost.com/weixin/WeiActivity/payJoinfee' ...
- 梦行扫码付(收银台条码支付 微信钱包条码支付 支付宝二维码支付 手机APP钱包支付 PHP扫码支付 )
适用于:各行各业(如,超市 餐厅 收费站 等各类收费处) 平台管理员篇 扫码付管理 (收银台条码支付) 全站收款账号 (微信钱包条码支付) 全站收款记录 (支付宝二维码支付) 商家篇 我的扫码付 (支 ...
- 微信web端生成支付二维码
需要准备: WxPay.Config.php appid(绑定支付的appid), mechID(商户号), key(用户支付密码), appsecert(公众号账号secert) 证书(也可以不需要 ...
- 微信网页端支付功能(前端)详解
微信支付功能其实与登录授权功能是有相通之处的,都是调用微信的JSAPI,直接搜索JSAPI就可以看见微信支付的文档.接下来我说一下支付功能我的思路. 首先 : 用户登录进入页面,支付调取统一下单接口, ...
最新文章
- lora和nbiot的相同点,它们之间有何区别和联系?
- SED单行脚本快速参考(Unix流编辑器)
- axios的get与post
- MVC UpdateModel的未能更新XXXXX的类型模型
- ssl1202-滑雪【记忆化搜索法】
- CodeSite日志使用
- 设计师学习HTML/CSS之路-11
- 【Cocos2dX(2.x)_Lua开发之三】
- (8)FPGA面试题触发器满足建立时间和保持时间的原因
- 《互联网理财一册通》一一第1章 做好互联网理财前的准备工作
- 利用python获取nginx服务的ip以及流量统计信息
- Context 使用不当造成内存泄露
- 导图速读《高性能MySQL》
- 强化狼群等级制度的灰狼优化算法-附代码
- VS2019安装QT5.14.1全过程
- 安装西门子博图一直重启_博图软件常见错误解决方法
- 关于代付和分账系统的区别
- 计算机双系统,细说如何给电脑安装双系统
- python定义一个复数类complex_定义一个复数类Complex,使得下面的代码能够工作
- 十八、绘制游戏背景图片
热门文章
- 书摘—松下幸之助全传
- ESP8266开发之旅 网络篇④ Station——ESP8266WiFiSTA库的使用
- BREDR之inquiry及page
- Linux命令行设置行数,Linux设置history命令显示行数以及时间
- 查询历史使用过的命令并使用(history)
- 上海内推 | 微软亚洲研究院(上海)AI-ML组招聘AI实习生
- 软件是计算机所需要的程序,软件是指电脑运行所需要的各种程序及其有关资料.doc...
- 密码学写作论文排版操作手册,latex模板cryptocode
- 投票程序c语言论文,c语言投票程序摘要.doc
- Linux之磁盘与文件系统管理