美文网首页Spring-Boot
微信支付(APP支付)之服务端

微信支付(APP支付)之服务端

作者: 王传贺 | 来源:发表于2019-11-22 15:37 被阅读0次

    一: 项目背景

    最近和朋友一起做了一款APP ,涉及到微信支付, 简单记录一下微信支付服务端流程
    微信支付的难点在于没有测试账号,无客服,这点远不如支付宝友好,网上搜索的微信支付千篇一律,对初学者很不友好,因此踩了很多坑。本文从账号的注册,代码的编写详细介绍。

    二: 账号注册

    微信支付是需要审核资质,拥有营业执照的个体户即可申请。值得注意的是,申请账号关联相关身份必须与营业执照一致。
    注册方式开发总结如下,按照流程注册即可
    若app需要接入微信支付,需要先注册并认证开放平台(https://open.weixin.qq.com/)账号,才能生成appid,然后再注册商户平台(https://pay.weixin.qq.com)账号,获取商户号、密钥等,申请成功后,请通过微信支付商户平台发起appid授权绑定(https://kf.qq.com/faq/1801116VJfua1801113QVNVz.html),微信支付开发文档地址为:https://pay.weixin.qq.com/wiki/doc/api/index.html

    三:微信支付接口调试

    注意代码注释结合,微信支付开发文档查看
    常量类

    /**
     * created by wangch on 2019/8/9
     */
    public class ConstantUtil {
    
        /**
         * 微信开发平台应用ID
         */
        public static final String APP_ID="";
        /**
         * 应用对应的凭证
         */
        public static final String APP_SECRET="";
        /**
         * 应用对应的密钥
         */
        public static final String APP_KEY="";
        /**
         * 微信支付商户号
         */
        public static final String MCH_ID="1557353761";
        /**
         * 商品描述
         */
        public static final String BODY="QQ游戏-账户充值";
        /**
         * 商户号对应的密钥
         */
        public static final String PARTNER_key="123466";
    
        /**
         * 商户id
         */
        public static final String PARTNER_ID="";
        /**
         * 常量固定值
         */
        public static final String GRANT_TYPE="client_credential";
        /**
         * 获取预支付id的接口url
         */
        public static String GATEURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        /**
         * 微信服务器回调通知url
         */
        public static String NOTIFY_URL="ip:8080/order/pay/notify";
    }
    

    接口类

    @RestController
    @RequestMapping("/order")
    public class PayController {
    
        private static final Logger LOG = Logger.getLogger(PayController.class);
    
        private static final String ORDER_PAY = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 统一下单
    
        private static final String ORDER_PAY_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery"; // 支付订单查询
    
        private static final String ORDER_REFUND = "https://api.mch.weixin.qq.com/secapi/pay/refund"; // 申请退款
    
        private static final String ORDER_REFUND_QUERY = "https://api.mch.weixin.qq.com/pay/refundquery"; // 申请退款
    
        private static final String APP_ID = ConstantUtil.APP_ID;
    
        private static final String MCH_ID = ConstantUtil.MCH_ID;
    
        private static final String API_SECRET = ConstantUtil.APP_KEY;
    
        @Autowired
        private IOrderService iOrderService;
    
        /**
         * 支付下订单
         *
         * @param request
         * @param response
         * @RequestParam(required = false, defaultValue = "0") Double cashnum, String mercid, String callback
    
         */
        @RequestMapping(value = "/pay", method = RequestMethod.POST)
        public R orderPay(@RequestBody Order order, HttpServletRequest request, HttpServletResponse response) {
            LOG.info("[/order/pay]");
    //        if (!"001".equals(mercid)) {
    //            WebUtil.response(response, WebUtil.packJsonp(callback, JSON
    //                    .toJSONString(new JsonResult(-1, "商品不存在", new ResponseData()), SerializerFeatureUtil.FEATURES)));
    //        }
    
            Map<String, String> restmap = null;
            boolean flag = true; // 是否订单创建成功
            try {
                String total_fee = BigDecimal.valueOf(order.getPrice()).multiply(BigDecimal.valueOf(100))
                        .setScale(0, BigDecimal.ROUND_HALF_UP).toString();
                Map<String, String> parm = new HashMap<String, String>();
                parm.put("appid", APP_ID);
                parm.put("mch_id", MCH_ID);
                parm.put("device_info", "WEB");
                parm.put("nonce_str", PayUtil.getNonceStr());
                parm.put("body", "微信支付");
                parm.put("attach", "wangch");
                // PayUtil.getTradeNo
                parm.put("out_trade_no", order.getCode());
                // String.valueOf(order.getPrice())
                parm.put("total_fee", total_fee);
                parm.put("spbill_create_ip", PayUtil.getRemoteAddrIp(request));
                // "https://www.andy.org/wxpay/order/pay/notify.shtml"
                parm.put("notify_url",ConstantUtil.NOTIFY_URL );
                parm.put("trade_type", "APP");
                parm.put("sign", PayUtil.getSign(parm, API_SECRET));
    
                String restxml = HttpUtils.post(ORDER_PAY, XmlUtil.xmlFormat(parm, false));
                restmap = XmlUtil.xmlParse(restxml);
            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
            }
    
            Map<String, String> payMap = new HashMap<String, String>();
            if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
                payMap.put("appid", APP_ID);
                payMap.put("partnerid", MCH_ID);
                payMap.put("prepayid", restmap.get("prepay_id"));
                payMap.put("package", "Sign=WXPay");
                payMap.put("noncestr", PayUtil.getNonceStr());
                payMap.put("timestamp", PayUtil.payTimestamp());
                try {
                    payMap.put("sign", PayUtil.getSign(payMap, API_SECRET));
                } catch (Exception e) {
                    flag = false;
                }
            }
    
    //        if (flag) {
    //            //return new R().put("获取成功",new ResponseData(null, payMap));
    //            WebUtil.response(response,
    //                    WebUtil.packJsonp("data",
    //                            JSON.toJSONString(new JsonResult(1, "订单获取成功", new ResponseData(null, payMap)),
    //                                    SerializerFeatureUtil.FEATURES)));
    //        } else {
    //            if (CollectionUtil.isNotEmpty(restmap)) {
    //               //return new R().put("订单创建失败",new ResponseData(null, payMap));
    //               LOG.info("订单创建失败:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
    //            }
    //            WebUtil.response(response, WebUtil.packJsonp(order.getCode(), JSON
    //                    .toJSONString(new JsonResult(-1, "订单获取失败", new ResponseData()), SerializerFeatureUtil.FEATURES)));
    //            //return new R().put("订单获取失败",new ResponseData());
    //        }
            R r = new R();
            if (flag){
                return r.put("data",payMap);
            } else {
    
                return R.error("获取失败");
            }
    
        }
    
    
        /**
         * 查询支付结果
         *
         * @param request
         * @param response
         * @param tradeid  微信交易订单号
         * @param tradeno 商品订单号
         * @param callback
         */
        @RequestMapping(value = "/pay/query", method = RequestMethod.POST)
        public R orderPayQuery(HttpServletRequest request, HttpServletResponse response,Integer orderId) {
            LOG.info("[/order/pay/query]");
    //        if (StringUtil.isEmpty(tradeno) && StringUtil.isEmpty(tradeid)) {
    //            WebUtil.response(response, WebUtil.packJsonp(callback, JSON
    //                    .toJSONString(new JsonResult(-1, "订单号不能为空", new ResponseData()), SerializerFeatureUtil.FEATURES)));
    //        }
    
            // 通过id 获取商户订单号与微信订单号
            Map<String,String> map = iOrderService.getOrderInfoByOrderId(orderId);
            Map<String, String> restmap = null;
            try {
                Map<String, String> parm = new HashMap<String, String>();
                parm.put("appid", APP_ID);
                parm.put("mch_id", MCH_ID);
                parm.put("transaction_id", map.get("tradeNo"));
                parm.put("out_trade_no", map.get("code"));
                parm.put("nonce_str", PayUtil.getNonceStr());
                parm.put("sign", PayUtil.getSign(parm, API_SECRET));
    
                String restxml = HttpUtils.post(ORDER_PAY_QUERY, XmlUtil.xmlFormat(parm, false));
                restmap = XmlUtil.xmlParse(restxml);
            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
            }
    
    //        if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
    //            // 订单查询成功 处理业务逻辑
    //            LOG.info("订单查询:订单" + restmap.get("out_trade_no") + "支付成功");
    //            // 将微信订单号存入order 表中
    //
    //            WebUtil.response(response, WebUtil.packJsonp(callback, JSON
    //                    .toJSONString(new JsonResult(1, "订单支付成功", new ResponseData()), SerializerFeatureUtil.FEATURES)));
    //        } else {
    //            if (CollectionUtil.isNotEmpty(restmap)) {
    //                LOG.info("订单支付失败:" + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
    //            }
    //            WebUtil.response(response, WebUtil.packJsonp(callback, JSON
    //                    .toJSONString(new JsonResult(-1, "订单支付失败", new ResponseData()), SerializerFeatureUtil.FEATURES)));
    //        }
            R r = new R();
            if (CollectionUtil.isNotEmpty(restmap) && "SUCCESS".equals(restmap.get("result_code"))) {
                // 订单查询成功 处理业务逻辑
                iOrderService.updateOrderPayByOrderCode(map.get("code"),1);
                return r.ok();
            }else {
                return R.error("支付失败");
            }
        }
    
    
        /**
         * 订单支付微信服务器异步通知
         *
         * @param request
         * @param response
         */
        @RequestMapping("/pay/notify")
        public void orderPayNotify(HttpServletRequest request, HttpServletResponse response) {
            LOG.info("[/order/pay/notify]");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/xml");
            try {
                ServletInputStream in = request.getInputStream();
                String resxml = FileUtil.readInputStream2String(in);
                Map<String, String> restmap = XmlUtil.xmlParse(resxml);
                LOG.info("支付结果通知:" + restmap);
                // 将微信订单号存入order 表中
                iOrderService.insertTradeNo(restmap.get("transaction_id"),restmap.get("out_trade_no"));
                if ("SUCCESS".equals(restmap.get("result_code"))) {
                    // 订单支付成功 业务处理
                    String out_trade_no = restmap.get("out_trade_no"); // 商户订单号
                    // 通过商户订单判断是否该订单已经处理 如果处理跳过 如果未处理先校验sign签名 再进行订单业务相关的处理
                    String sing = restmap.get("sign"); // 返回的签名
                    restmap.remove("sign");
                    String signnow = PayUtil.getSign(restmap, API_SECRET);
                    if (signnow.equals(sing)) {
                        // 进行业务处理
                        LOG.info("订单支付通知: 支付成功,订单号" + out_trade_no);
                        // 支付成功
                        int count = iOrderService.updateOrderPayByOrderCode(out_trade_no,1);
                        // 处理成功后相应给响应xml
                        Map<String, String> respMap = new HashMap<>();
                        respMap = new HashMap<String, String>();
                        respMap.put("return_code", "SUCCESS");  //相应给微信服务器
                        respMap.put("return_msg", "OK");
                        String resXml = XmlUtil.xmlFormat(restmap, true);
                        response.getWriter().write(resXml);
                    } else {
                        LOG.info("订单支付通知:签名错误");
                    }
                } else {
                    LOG.info("订单支付通知:支付失败," + restmap.get("err_code") + ":" + restmap.get("err_code_des"));
                }
            } catch (Exception e) {
                LOG.error(e.getMessage(), e);
            }
        }
    

    工具类
    PayUtil

    **
     * created by wangch on 2019/8/9
     */
    public class PayUtil {
    
        /**
         * 生成订单号
         * 
         * @return
         */
        public static String getTradeNo() {
            // 自增8位数 00000001
            return "TNO" + DatetimeUtil.formatDate(new Date(), DatetimeUtil.TIME_STAMP_PATTERN) + "00000001";
        }
    
        /**
         * 退款单号
         * 
         * @return
         */
        public static String getRefundNo() {
            // 自增8位数 00000001
            return "RNO" + DatetimeUtil.formatDate(new Date(), DatetimeUtil.TIME_STAMP_PATTERN) + "00000001";
        }
    
        /**
         * 退款单号
         * 
         * @return
         */
        public static String getTransferNo() {
            // 自增8位数 00000001
            return "TNO" + DatetimeUtil.formatDate(new Date(), DatetimeUtil.TIME_STAMP_PATTERN) + "00000001";
        }
    
        /**
         * 返回客户端ip
         * 
         * @param request
         * @return
         */
        public static String getRemoteAddrIp(HttpServletRequest request) {
            String ip = request.getHeader("X-Forwarded-For");
            if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
                // 多次反向代理后会有多个ip值,第一个ip才是真实ip
                int index = ip.indexOf(",");
                if (index != -1) {
                    return ip.substring(0, index);
                } else {
                    return ip;
                }
            }
            ip = request.getHeader("X-Real-IP");
            if (StringUtil.isNotEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) {
                return ip;
            }
            return request.getRemoteAddr();
        }
    
        /**
         * 获取服务器的ip地址
         * 
         * @param request
         * @return
         */
        public static String getLocalIp(HttpServletRequest request) {
            return request.getLocalAddr();
        }
    
        public static String getSign(Map<String, String> params, String paternerKey) throws UnsupportedEncodingException {
            return MD5Utils.getMD5(createSign(params, false) + "&key=" + paternerKey).toUpperCase();
        }
    
        /**
         * 构造签名
         * 
         * @param params
         * @param encode
         * @return
         * @throws UnsupportedEncodingException
         */
        public static String createSign(Map<String, String> params, boolean encode) throws UnsupportedEncodingException {
            Set<String> keysSet = params.keySet();
            Object[] keys = keysSet.toArray();
            Arrays.sort(keys);
            StringBuffer temp = new StringBuffer();
            boolean first = true;
            for (Object key : keys) {
                if (key == null || StringUtil.isEmpty(params.get(key))) // 参数为空不参与签名
                    continue;
                if (first) {
                    first = false;
                } else {
                    temp.append("&");
                }
                temp.append(key).append("=");
                Object value = params.get(key);
                String valueStr = "";
                if (null != value) {
                    valueStr = value.toString();
                }
                if (encode) {
                    temp.append(URLEncoder.encode(valueStr, "UTF-8"));
                } else {
                    temp.append(valueStr);
                }
            }
            return temp.toString();
        }
    
        /**
         * 创建支付随机字符串
         * @return
         */
        public static String getNonceStr(){
            String s = RandomUtil.randomString(RandomUtil.LETTER_NUMBER_CHAR, 32);
            return RandomUtil.randomString(RandomUtil.LETTER_NUMBER_CHAR, 32);
        }
        
        /**
         * 支付时间戳
         * @return
         */
        public static String payTimestamp() {
            String s = Long.toString(System.currentTimeMillis() / 1000);
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }
    

    HttpUtils

    **
     * created by wangch on 2019/8/9
     */
    public class HttpUtils {
    
        private static final String DEFAULT_CHARSET = "UTF-8";
        
        private static final int CONNECT_TIME_OUT = 5000; //链接超时时间3秒
        
        private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom().setConnectTimeout(CONNECT_TIME_OUT).build();
        
        private static SSLContext wx_ssl_context = null; //微信支付ssl证书
        
        static{
            Resource resource = new ClassPathResource("wx_apiclient_cert.p12");
            try {
                KeyStore keystore = KeyStore.getInstance("PKCS12");
                char[] keyPassword = ConfigUtil.getProperty("wx.mchid").toCharArray(); //证书密码
                keystore.load(resource.getInputStream(), keyPassword);
                wx_ssl_context = SSLContexts.custom().loadKeyMaterial(keystore, keyPassword).build();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @description 功能描述: get 请求
         * @param url 请求地址
         * @param params 参数
         * @param headers headers参数
         * @return 请求失败返回null
         */
        public static String get(String url, Map<String, String> params, Map<String, String> headers) {
    
            CloseableHttpClient httpClient = null;
            if (params != null && !params.isEmpty()) {
                StringBuffer param = new StringBuffer();
                boolean flag = true; // 是否开始
                for (Entry<String, String> entry : params.entrySet()) {
                    if (flag) {
                        param.append("?");
                        flag = false;
                    } else {
                        param.append("&");
                    }
                    param.append(entry.getKey()).append("=");
                    
                    try {
                        param.append(URLEncoder.encode(entry.getValue(), DEFAULT_CHARSET));
                    } catch (UnsupportedEncodingException e) {
                        //编码失败
                    }
                }
                url += param.toString();
            }
    
            String body = null;
            CloseableHttpResponse response = null;
            try {
                httpClient = HttpClients.custom()
                        .setDefaultRequestConfig(REQUEST_CONFIG)
                        .build();
                HttpGet httpGet = new HttpGet(url);
                response = httpClient.execute(httpGet);
                body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                if (httpClient != null) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return body;
        }
    
        /**
         * @description 功能描述: get 请求
         * @param url 请求地址
         * @return 请求失败返回null
         */
        public static String get(String url) {
            return get(url, null);
        }
    
        /**
         * @description 功能描述: get 请求
         * @param url 请求地址
         * @param params 参数
         * @return 请求失败返回null
         */
        public static String get(String url, Map<String, String> params) {
            return get(url, params, null);
        }
    
        /**
         * @description 功能描述: post 请求
         * @param url 请求地址
         * @param params 参数
         * @return 请求失败返回null
         */
        public static String post(String url, Map<String, String> params) {
            CloseableHttpClient httpClient = null;
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> nameValuePairs = new ArrayList<>();
            if (params != null && !params.isEmpty()) {
                for (Entry<String, String> entry : params.entrySet()) {
                    nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
            }
    
            String body = null;
            CloseableHttpResponse response = null;
            try {
                httpClient = HttpClients.custom()
                        .setDefaultRequestConfig(REQUEST_CONFIG)
                        .build();
                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
                response = httpClient.execute(httpPost);
                body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                if (httpClient != null) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return body;
        }
    
        /**
         * @description 功能描述: post 请求
         * @param url 请求地址
         * @param s 参数xml
         * @return 请求失败返回null
         */
        public static String post(String url, String s) {
            CloseableHttpClient httpClient = null;
            HttpPost httpPost = new HttpPost(url);
            String body = null;
            CloseableHttpResponse response = null;
            try {
                httpClient = HttpClients.custom()
                        .setDefaultRequestConfig(REQUEST_CONFIG)
                        .build();
                httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET));
                response = httpClient.execute(httpPost);
                body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                if (httpClient != null) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return body;
        }
    
        /**
         * @description 功能描述: post https请求,服务器双向证书验证
         * @param url 请求地址
         * @param params 参数
         * @return 请求失败返回null
         */
         public static String posts(String url, Map<String, String> params) {
            CloseableHttpClient httpClient = null;
            HttpPost httpPost = new HttpPost(url);
            List<NameValuePair> nameValuePairs = new ArrayList<>();
            if (params != null && !params.isEmpty()) {
                for (Entry<String, String> entry : params.entrySet()) {
                    nameValuePairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
            }
    
            String body = null;
            CloseableHttpResponse response = null;
            try {
                httpClient = HttpClients.custom()
                        .setDefaultRequestConfig(REQUEST_CONFIG)
                        .setSSLSocketFactory(getSSLConnectionSocket())
                        .build();
                httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs, DEFAULT_CHARSET));
                response = httpClient.execute(httpPost);
                body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                if (httpClient != null) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return body;
        }
        
        /**
         * @description 功能描述: post https请求,服务器双向证书验证
         * @param url 请求地址
         * @param s 参数xml
         * @return 请求失败返回null
         */
        public static String posts(String url, String s) {
            CloseableHttpClient httpClient = null;
            HttpPost httpPost = new HttpPost(url);
            String body = null;
            CloseableHttpResponse response = null;
            try {
                httpClient = HttpClients.custom()
                        .setDefaultRequestConfig(REQUEST_CONFIG)
                        .setSSLSocketFactory(getSSLConnectionSocket())
                        .build();
                httpPost.setEntity(new StringEntity(s, DEFAULT_CHARSET)); 
                response = httpClient.execute(httpPost);
                body = EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (response != null) {
                    try {
                        response.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
    
                if (httpClient != null) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return body;
        }
    
        //获取ssl connection链接
        private static SSLConnectionSocketFactory getSSLConnectionSocket() {
            return new SSLConnectionSocketFactory(wx_ssl_context, new String[] {"TLSv1", "TLSv1.1", "TLSv1.2"}, null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        }
    }
    

    XmlUtil

    **
     * created by wangch on 2019/8/9
     */
    public class XmlUtil {
    
        private static final String PREFIX_XML = "<xml>";
    
        private static final String SUFFIX_XML = "</xml>";
    
        private static final String PREFIX_CDATA = "<![CDATA[";
    
        private static final String SUFFIX_CDATA = "]]>";
    
        /**
         * 转化成xml, 单层无嵌套
         * 
         * @param map
         * @param isAddCDATA
         * @return
         */
        public static String xmlFormat(Map<String, String> parm, boolean isAddCDATA) {
    
            StringBuffer strbuff = new StringBuffer(PREFIX_XML);
            if (CollectionUtil.isNotEmpty(parm)) {
                for (Entry<String, String> entry : parm.entrySet()) {
                    strbuff.append("<").append(entry.getKey()).append(">");
                    if (isAddCDATA) {
                        strbuff.append(PREFIX_CDATA);
                        if (StringUtil.isNotEmpty(entry.getValue())) {
                            strbuff.append(entry.getValue());
                        }
                        strbuff.append(SUFFIX_CDATA);
                    } else {
                        if (StringUtil.isNotEmpty(entry.getValue())) {
                            strbuff.append(entry.getValue());
                        }
                    }
                    strbuff.append("</").append(entry.getKey()).append(">");
                }
            }
            return strbuff.append(SUFFIX_XML).toString();
        }
    
        /**
         * 解析xml
         * 
         * @param xml
         * @return
         * @throws XmlPullParserException
         * @throws IOException
         */
        public static Map<String, String> xmlParse(String xml) throws XmlPullParserException, IOException {
            Map<String, String> map = null;
            if (StringUtil.isNotEmpty(xml)) {
                InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
                XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();
                pullParser.setInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据
                int eventType = pullParser.getEventType();
    
                while (eventType != XmlPullParser.END_DOCUMENT) {
                    switch (eventType) {
                    case XmlPullParser.START_DOCUMENT:
                        map = new HashMap<String, String>();
                        break;
                    case XmlPullParser.START_TAG:
                        String key = pullParser.getName();
                        if (key.equals("xml"))
                            break;
                        String value = pullParser.nextText().trim();
                        map.put(key, value);
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                    }
                    eventType = pullParser.next();
                }
            }
            return map;
        }
    }
    

    MD5Util

    **
     * created by wangch on 2019/8/9
     */
    public class MD5Util {
    
        /**
         * MD5加密
         * @param b
         * @return
         */
        private static String byteArrayToHexString(byte b[]) {
            StringBuffer resultSb = new StringBuffer();
            for (int i = 0; i < b.length; i++)
                resultSb.append(byteToHexString(b[i]));
    
            return resultSb.toString();
        }
    
        private static String byteToHexString(byte b) {
            int n = b;
            if (n < 0)
                n += 256;
            int d1 = n / 16;
            int d2 = n % 16;
            return hexDigits[d1] + hexDigits[d2];
        }
    
        public static String MD5Encode(String origin, String charsetname) {
            String resultString = null;
            try {
                resultString = new String(origin);
                MessageDigest md = MessageDigest.getInstance("MD5");
                if (charsetname == null || "".equals(charsetname))
                    resultString = byteArrayToHexString(md.digest(resultString
                            .getBytes()));
                else
                    resultString = byteArrayToHexString(md.digest(resultString
                            .getBytes(charsetname)));
            } catch (Exception exception) {
            }
            return resultString;
        }
    
        private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5",
                "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
    
    }
    

    四:总结

    上述代码结合微信支付文档很好理解,耐心品味
    参考了andy大神的写法,侵删

    相关文章

      网友评论

        本文标题:微信支付(APP支付)之服务端

        本文链接:https://www.haomeiwen.com/subject/ttcqwctx.html