关于微信支付支付,个人觉得相比支付宝复杂的太多了,但是慢慢理解起来还是很简单的

1,首先准备工作,下方是一个时序图,认真看,图看懂了做起来真的很简单

,

2,第二按照上图说明,开始下单时,调用微信下单接口是需要准备一下几个参数

APIKEY ---------  支付秘钥(微信商户平台可查,需要自己设置)

appid -----   商户ID(微信商户平台可查)

body-------   商品名称

mch_id -----     支付商户号(微信商户平台可查)

nonce_str ---------- 随机字符串

/**
     * 获取随机字符串 Nonce Str
     *
     * @return String 随机字符串
     */
    public static String generateNonceStr() {
        char[] nonceChars = new char[32];
        for (int index = 0 ; index < nonceChars.length ; ++index) {
            nonceChars[index] = SYMBOLS.charAt(RANDOM.nextInt(SYMBOLS.length()));
        }
        return new String(nonceChars);
    }

out_trade_no------------   订单号

spbill_create_ip ------------请求IP

/**
     * 获取用户实际ip
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
            ipAddress = request.getRemoteAddr();
            if (ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")) {
                //根据网卡取本机配置的IP  
                InetAddress inet = null;
                try {
                    inet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                ipAddress = inet.getHostAddress();
            }
        }
        //对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割  
        if (ipAddress != null && ipAddress.length() > 15) { //"***.***.***.***".length() = 15  
            if (ipAddress.indexOf(",") > 0) {
                ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
            }
        }
        return ipAddress;
    }

total_fee------------ //,字符串类型,获取金额,单位分

trade_type -------------------//支付类型,H5就是  "MWEB"

scene_info  -------------------  //{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://www.chujian.live\",\"wap_name\": \"chongzhi\"}}    这个话里面 type就是Wap   wap_url--指的是你们官网地址 ,wap_name 就是网站名称

notify_url   ----------------- //此路径是微信服务器调用支付结果带了一大批参数多次请求

以下就把几个重要的工具类整理一下,后面会用到,建议务必下载微信开发文档,我这里只是把自己整理补充后的放上去

/**
     * 生成签名
     *
     * @param data 待签名数据
     * @param key API密钥
     * @return 签名
     */
    public static String generateSignature(final Map<String, String> data, String key) throws Exception {
        return generateSignature(data, key, SignType.MD5);
    }

/**
     * XML格式字符串转换为Map
     *
     * @param strXML XML字符串
     * @return XML数据转换后的Map
     * @throws Exception
     */
    public static Map<String, String> xmlToMap(String strXML) throws Exception {
        try {
            Map<String, String> data = new HashMap<String, String>();
            DocumentBuilder documentBuilder = WXPayXmlUtil.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) {
                // do nothing
            }
            return data;
        } catch (Exception ex) {
            WXPayUtil.getLogger().warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }

}

/**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        org.w3c.dom.Document document = WXPayXmlUtil.newDocument();
        org.w3c.dom.Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key : data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            org.w3c.dom.Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        } catch (Exception ex) {
        }
        return output;
    }

/**
     * 向指定URL发送GET方法的请求
     * 
     * @param url
     *            发送请求的URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            System.out.println(urlNameString);
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍历所有的响应头字段
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

/**
     * 向指定 URL 发送POST方法的请求
     * 
     * @param url
     *            发送请求的 URL
     * @param param
     *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            URLConnection conn = realUrl.openConnection();
            // 设置通用的请求属性  
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            conn.setRequestProperty("contentType", "text/xml");
            conn.setRequestProperty("Charsert", "utf-8");
            // 发送POST请求必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常!" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return result;
    }
3,接下来废话不多少了,直接上代码了

/**
     * 用户充值金币----------微信H5支付
     */
    @ResponseBody
    @RequestMapping(value = "weixinPayRechargeGold", method = RequestMethod.GET)
    public String weixinPayWap(HttpServletRequest request, HttpServletResponse response, Integer rechargeNumber, String rechargeId) {
        String mweb_url = "";//跳转链接
        //如果是模拟请求则返回null
        boolean bool = rechargeList.contains(rechargeId);
        if (bool == false) {
            return null;
        }
        try {
            //保存充值记录到数据库
           //此处写自己的业务
            //拼接统一下单地址参数
            Map<String, String> paraMap = new HashMap<String, String>();
            //获取请求ip地址
            String ip = WXPayUtil.getIpAddr(request);
            String bodyName = "MEIDAO" + mdRecharge.getNumber();
            Integer money = mdRecharge.getRmb() * 100;//获取金额,单位分
            paraMap.put("appid", WXPayConstants.APPID); //商户ID
            paraMap.put("body", bodyName); //商品名称
            paraMap.put("mch_id", WXPayConstants.MCHID);
            paraMap.put("nonce_str", WXPayUtil.generateNonceStr()); //String 随机字符串
            paraMap.put("out_trade_no", mdRecharge.getNumber());//订单号
            paraMap.put("spbill_create_ip", ip);//请求IP
            paraMap.put("total_fee", money.toString()); //加钱
            paraMap.put("trade_type", "MWEB"); //类型
            paraMap.put("scene_info", "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"https://www.chujian.live\",\"wap_name\": \"yinyinchongzhi\"}}");
            paraMap.put("notify_url", "https://www.chujian.live/faint-service/f/weixin/weixinRechargeGoldResult");// 此路径是微信服务器调用支付结果带了一大批参数多次请求
            String paternerKey = WXPayConstants.APIKEY;
            String sign = WXPayUtil.generateSignature(paraMap, paternerKey);
            paraMap.put("sign", sign);
            String xml = WXPayUtil.mapToXml(paraMap);//将所有参数(map)转xml格式
            // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
            String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            String xmlStr = HttpRequest.sendPost(unifiedorder_url, xml);
            //以下内容是返回前端页面的json数据

if (xmlStr.indexOf("SUCCESS") != -1) {
                Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                mweb_url = (String) map.get("mweb_url");
                //支付完返回浏览器跳转的地址,如跳到查看订单页面
                String redirect_url = "******此处写自己的域名******/faint-service/static/h5/app/successh5.html";
                String redirect_urlEncode = URLEncoder.encode(redirect_url, "utf-8");//对上面地址urlencode
                mweb_url = mweb_url + "&redirect_url=" + redirect_urlEncode;//拼接返回地址
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return mweb_url;
    }

/**
     * 用户充值金币----------微信h5返回结果
     */
    @RequestMapping("weixinRechargeGoldResult")
    public void weixinResult(HttpServletRequest request, HttpServletResponse response) {
        BufferedReader reader;
        try {
            reader = request.getReader();
            String line = "";
            StringBuffer inputString = new StringBuffer();
            while ((line = reader.readLine()) != null) {
                inputString.append(line);
            }
            request.getReader().close();
            Map<String, String> notifyMap = WXPayUtil.xmlToMap(inputString.toString());

if (notifyMap.get("return_code").equals("SUCCESS")) {
                if (notifyMap.get("result_code").equals("SUCCESS")) {
                    String orderSn = notifyMap.get("out_trade_no"); //商户订单号 
                    String amountpaid = notifyMap.get("total_fee");//实际支付的订单金额:单位 分
                    BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);//将分转换成元-实际支付金额:元
                    String openid = notifyMap.get("openid"); //如果有需要可以获取
                  ///此处写自己的业务
                }
            }
            //告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
            response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

如有问题,请指教.有问题也可以给楼主留言

手把手教你完成微信H5支付相关推荐

  1. 实例:用C#.NET手把手教你做微信公众号开发(21)--使用微信支付线上收款:H5方式

    在做线上.线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图: 今天我们来讲一下H5场景支付,使用手机浏览器打开就是H5方式,最常见的推广是短信内置链接,这种场景需要调用微信 ...

  2. 实例:用C#.NET手把手教你做微信公众号开发(20)--使用微信支付线上收款:jsapi方式

    在做线上.线下销售时,可以使用微信便捷支付,通过微信公众号收款有很多种收款方式,如下图: 今天我们来讲一下jsapi支付,场景就是在微信内打开某个页面,完成在线支付,同样一个网页,使用微信打开就是js ...

  3. 解决iOS微信H5支付跳转微信后不返回App问题(Swift-WKWebview)(转)

    解决iOS微信H5支付跳转微信后不返回App问题(Swift-WKWebview)(转) 参考文章: (1)解决iOS微信H5支付跳转微信后不返回App问题(Swift-WKWebview)(转) ( ...

  4. app 访问h5 如何截取_微信H5支付申请相关问题

    之前的文章「微信支付申请相关问题」里说过微信公众号和 APP 申请微信支付,今天来说下微信 H5 支付的申请. 背景介绍 H5 支付是指商户在微信客户端外的移动端网页展示商品或服务,用户在前述页面确认 ...

  5. Android 应用内微信 H5 支付

    一般情况下,要实现应用内支付接入 App 支付 SDK 即可满足业务需求,不过考虑到对于一些类似游戏中心的场景,更多是需要支持 H5 支付.相对微信来说,支付宝的对接简单完善很多,所以本篇文章主要说说 ...

  6. 微信支付—微信H5支付「非微信内部浏览器-QQ/UC浏览器等」

    前言 微信支付-微信H5外部浏览器支付「本文」 微信H5内部浏览器支付「待写」 PC端扫码支付「待写」 一直计划着写一写微信支付相关的文章,希望能加深一下自己的印象,拖了一天又一天- 最近终于空出时间 ...

  7. php根据浏览器调用支付_Android通过外部浏览器调用微信H5支付,Android+PHP详解

    看了好多关于讲解微信H5支付开发的文章,大多数都是通过微信内部浏览器来调用支付接口(其实就是公众号支付),可能是因为H5支付接口刚开放不久吧. 微信官方体验链接:http://wxpay.wxutil ...

  8. php微信h5支付demo,微信h5支付 demo-HTML5微信支付DEMO下载 最新版--pc6下载站

    在微信支付已经霸占了大部分人生活习惯的年代,一个不支持微信支付的商家都不好意思开店了,程序猿们可以下载查看HTML5微信支付DEMO来帮助您熟悉微信支付的代码,马上下载查看微信h5支付demo的内容吧 ...

  9. 微信h5支付,微信外浏览器支付实现

    对接第三方比较重要的点都有什么? 1.按规则 2.单独封装 3.做好出入参 2021-02-07修改 看一下官方文档还是很必要的,知道必不可少的参数是什么:https://pay.weixin.qq. ...

最新文章

  1. LayoutInflater.Factory 妙用
  2. 20145317《网络对抗》shellcode注入Return-to-libc攻击深入
  3. list vue 添加数据方法_一篇文章教会你创建vue项目和使用vue.js实现数据增删改查...
  4. 其他测试用例设计方法-错误推测法与正交实验法
  5. 在linux系统上启动oracle的服务
  6. 2019 互联网月饼哪家强?阿里走情怀;百度最土豪;浪潮最高冷;抖音最创意 .........
  7. 珞珈老师PPT教学-笔记
  8. mariadb登录mysql_MariaDB安装完怎么用root登录
  9. java字符串练习题_java练习题——字符串
  10. 使用npm运行react程序报错The 'mode' option has not been set, webpack will fallback to 'production' for th
  11. flash air java_Flash Air 打包安卓 ane
  12. Android基础入门教程——4.1.2 Activity初窥门径
  13. 从父组件中获取子组件的值
  14. python tutorial json_Python Tutorial - Parse JSON Objects with Python
  15. 面试前紧急补货——网络
  16. 上不了网,代理服务器出现问题
  17. Ubuntu-查看ubuntu系统的版本信息
  18. 中高级Java开发应该要了解!我用2个月的时间破茧成蝶,醍醐灌顶!
  19. Portainer添加远程Docker(Docker API)
  20. tableau 自定义版块地图

热门文章

  1. 电子版药丸,监控你的健康
  2. 计算机技术作文350,网络作文350字
  3. gyp: No Xcode or CLT version detected!问题解决
  4. RISC-V特权级寄存器及指令文档
  5. Python drop方法删除列之inplace参数
  6. 以非耍流氓的方式讨论C++中的面向对象编程
  7. 基于IPSAN的存储典型备份方案
  8. 用计算机收传真,怎么在电脑上发传真 在电脑上接收传真方法介绍【详细步骤】...
  9. 因BIOS设定导致GPU无法使用问题
  10. 独立产品灵感周刊 DecoHack #028 - 如何给你的项目取一个好名字