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);
        }


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

    勿在浮沙筑高台 ——个人浅见,难免有误导之处,麻烦请指出。
  • 相关阅读:
    Palindrome Partitioning
    Minimum Path Sum
    Maximum Depth of Binary Tree
    Minimum Depth of Binary Tree
    Unique Binary Search Trees II
    Unique Binary Search Trees
    Merge Intervals
    Merge Sorted Array
    Unique Paths II
    C++ Primer Plus 笔记第九章
  • 原文地址:https://www.cnblogs.com/liufeichn/p/11961658.html
Copyright © 2011-2022 走看看