zoukankan      html  css  js  c++  java
  • java进行微信h5支付开发

    最近在做微信支付开发用的框架是 srpingMVC mybatis spring

    下面是开发流程图

    微信内网页支付时序图

    我们只需要开发红色标记的模块就可以了。

    具体参数详情可以查看微信开发者文档。

    新手第一次写,写的不好。

    1.下面是下单接口

    @RequestMapping(value = "/down/order.spr")
        @ResponseBody
        public Object downOrder(HttpServletRequest request, HttpServletResponse response,
                @RequestParam("appointment_id") String appointment_id) {
            // 生成随机数字符串
            String nonceStr = getRandomString();
            // 获取商品订单号
            String out_trade_no = UUID.randomUUID().toString().replace("-", "");
            // 获取终端 IP
            String spbill_create_ip = request.getRemoteAddr();
            // 获取微信 openid
            WeiXinUserInfo userInfo = (WeiXinUserInfo) request.getSession().getAttribute("weixinUser");
            // 组装请求数据
            Map<String, String> paramsMap = new HashMap<String, String>();
            // 获取签名
            String sign = "";
            try {
                paramsMap.put("openid", userInfo.getOpenid());
                paramsMap.put("appid", APP_ID);
                paramsMap.put("mch_id", MCH_ID);
                paramsMap.put("nonce_str", nonceStr);
                paramsMap.put("body", body);
                paramsMap.put("out_trade_no", out_trade_no);
                paramsMap.put("fee_type", FEE_TYPE);
                paramsMap.put("total_fee", total_fee);
                paramsMap.put("spbill_create_ip", spbill_create_ip);
                paramsMap.put("notify_url", NOTIFY_URL);
                paramsMap.put("trade_type", TRADE_TYPE);
                sign = getPayCustomSign(paramsMap, paykey);
                paramsMap.put("sign", sign);
            } catch (Exception e) {
                log.debug("生成请求签名失败");
            }
            // map 转 xml 字符串
            String paramsXml = mapToXml(paramsMap);
            // 发送订单请求
            String result = sendPost(DOWN_ORDER, paramsXml);
            // 将返回的 xml 转化成 map
            Map<String, String> resultMap = null;
            // 获取预支付交易会话标识
            String prepay_id = "";
            if (result.indexOf("SUCCESS") != -1) {
                try {
                    resultMap = xmlToMap(result);
                    prepay_id = resultMap.get("prepay_id");
                } catch (JDOMException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                // 进行填充数据库
                saveOrder(appointment_id);
            }
            // 封装 h5 页面调用参数
            Map<String, Object> returnSignMap = new HashMap<String, Object>();
            String returnSign = "";
            try {
                returnSignMap.put("appid", APP_ID);
                returnSignMap.put("timeStamp", System.currentTimeMillis());
                returnSignMap.put("nonce_str", nonceStr);
                returnSignMap.put("package", "prepay_id=" + prepay_id);
                returnSignMap.put("signType", "MD5");
                returnSign = getPayCustomSign(returnSignMap, paykey);
                returnSignMap.put("sign", returnSign);
            } catch (Exception e) {
                log.debug("生成返回签名失败");
            }

            return new ResponseWrapper(ExceptionCode.SUCCESS, null, returnSignMap);
        }

    比较麻烦是签名的获取:以下是代码(摘自网络

    /**
         * 获取支付所需签名
         *
         * @param bizObj
         * @param key
         * @return
         * @throws Exception
         */
        private String getPayCustomSign(Map map, String key) throws Exception {
            String bizString = FormatBizQueryParaMap(map, false);
            return sign(bizString, key);
        }

        /**
         * 进行字典排序
         *
         * @param paraMap
         * @param urlencode
         * @return
         * @throws Exception
         */
        private String FormatBizQueryParaMap(Map paraMap, boolean urlencode) throws Exception {
            String sf = "";

            try {
                List<Entry> infoIds = new ArrayList<Entry>(paraMap.entrySet());
                Collections.sort(infoIds, new Comparator<Entry>() {
                    public int compare(Map.Entry o1, Map.Entry o2) {
                        return (o1.getKey().toString().compareTo(o2.getKey().toString()));
                    }
                });
                for (int i = 0; i < infoIds.size(); i++) {
                    Map.Entry entryItem = infoIds.get(i);
                    if (entryItem.getKey() != "") {
                        String key = (String) entryItem.getKey();
                        String value = (String) entryItem.getValue();
                        if (urlencode) {
                            value = URLEncoder.encode(value, "utf-8");
                        }
                        sf += key + "=" + value + "&";
                    }
                }
                if (sf.isEmpty() == false) {
                    sf = sf.substring(0, sf.length() - 1);
                }
            } catch (Exception e) {
                throw new Exception(e.getMessage());
            }

            return sf;
        }

        /**
         * 生成 签名
         *
         * @param content
         * @param key
         * @return
         */
        private String sign(String content, String key) {
            String signStr = content + "&key=" + key;
            return MD5(signStr).toUpperCase();
        }

        /**
         * MD5 加密
         *
         * @param str
         * @return
         */
        private final String MD5(String str) {
            char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

            try {
                byte[] btInput = str.getBytes();
                MessageDigest mdInst = MessageDigest.getInstance("MD5");
                mdInst.update(btInput);
                byte[] md = mdInst.digest();
                int j = md.length;
                char str2[] = new char[j * 2];
                int k = 0;
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    str2[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    str2[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(str2);
            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }


    生成随机数

        /**
         * 随机生成 32 位的字符串
         *
         * @return
         */
        private String getRandomString() {
            Random random = new Random();
            StringBuffer nonceStrSf = new StringBuffer();
            for (int i = 0; i < 32; i++) {
                nonceStrSf.append(nonce_str.charAt(random.nextInt(nonce_str.length() - 1)));
            }
            return nonceStrSf.toString();
        }

    map转xml

        /**
         * map 转 xml
         *
         * @param map
         * @return
         */
        private String mapToXml(Map<String, String> map) {
            StringBuffer sf = new StringBuffer("<xml>");
            Iterator<Entry<String, String>> iterator = map.entrySet().iterator();

            while (iterator.hasNext()) {
                Entry<String, String> entry = iterator.next();
                String key = entry.getKey();
                String value = entry.getValue();
                sf.append("<" + key + ">" + value + "</" + key + ">");
            }
            sf.append("</xml>");

            return sf.toString();
        }


    2.接受微信通知结果接口

        /**
         * 接受通知
         *
         * @param request
         * @param response
         * @return
         * @throws IOException
         */
        @RequestMapping(value = "/acceptance/notify.spt")
        public void acceptanceNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {

            // 接受微信返回通知
            String content = RequestUtil.getRequestContent(request);
            // 设置发送请求参数
            Map<String, String> resultMap = new HashMap<String, String>();
            try {
                resultMap = xmlToMap(content);
            } catch (JDOMException e) {
                e.printStackTrace();
            }
            // 进行数据存库,交易成功则存库,否则不存
            saveOrderLog(content, resultMap);

            Map<String, String> returnMap = new HashMap<String, String>();
            returnMap.put("return_code", resultMap.get("return_code"));
            returnMap.put("return_msg", resultMap.get("return_msg"));

            String toXml = mapToXml(returnMap);
            response.getWriter().write(toXml);
        }


    第一次写这么长的博客,不足之处请留言告之便于本人成长,再次感谢你的阅读。

    勿在浮沙筑高台 ——个人浅见,难免有误导之处,麻烦请指出。
  • 相关阅读:
    leetcode 190 Reverse Bits
    vs2010 单文档MFC 通过加载位图文件作为客户区背景
    leetcode 198 House Robber
    记忆化搜索(DP+DFS) URAL 1183 Brackets Sequence
    逆序数2 HDOJ 1394 Minimum Inversion Number
    矩阵连乘积 ZOJ 1276 Optimal Array Multiplication Sequence
    递推DP URAL 1586 Threeprime Numbers
    递推DP URAL 1167 Bicolored Horses
    递推DP URAL 1017 Staircases
    01背包 URAL 1073 Square Country
  • 原文地址:https://www.cnblogs.com/liufeichn/p/11961658.html
Copyright © 2011-2022 走看看