java微信支付

1.统一下单(生成预支付的订单):

使用微信的沙盒测试:要先获取key,使用商户id和随机数,sign(签名)通过

https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey

//返回支付结果:微信将支付结果返回到统一下单中的回调地址中

    //try {
       //获取测试用的key
    String nonce_str = WXUtil.getNonceStr();

    SortedMap<String, Object> keyParams = new TreeMap<String, Object>();
    keyParams.put("mch_id",ConstantUtil.Business_name);
    keyParams.put("nonce_str",nonce_str);
    String sandsign = createSign("UTF-8", keyParams);//生成签名
    keyParams.put("sign",sandsign);
    String keyXml = getRequestXml(keyParams);//生成Xml格式的字符串
    //向微信请求沙盒测试的key
    String resultKey = httpsRequest(
            ConstantUtil.GETSandboxKey, "POST",
            keyXml);
    System.out.println(resultKey + "请求到的key");
    Map<String, String> sandMap =  XMLUtil.doXMLParse(resultKey);
     key =  sandMap.get("sandbox_signkey");
    System.out.println(key + "请求到的key");
    SortedMap<String, Object> signParams = new TreeMap<String, Object>();
    //正式环境中需要用户的openid,沙盒测试环境中不需要
        signParams.put("appid", ConstantUtil.APPID);//appid
        signParams.put("mch_id", ConstantUtil.Business_name);//商户号
        signParams.put("nonce_str", nonce_str);
        signParams.put("body", "享窝房费");//商品描述
        signParams.put("out_trade_no", "20190614111714");//订单号
        signParams.put("spbill_create_ip", "127.0.0.1");//终端IP地址
        signParams.put("trade_type", "JSAPI");
        signParams.put("notify_url",ConstantUtil.notify_url);
        LocalDateTime time = LocalDateTime.now().plusMinutes(30);
        Date dateTime = Java8DateUtil.turnToDate(time);
        //订单的开始时间
        signParams.put("time_start", TimeUtil.isTimeSecound(new Date()));
        //订单的结束时间
        signParams.put("time_expire",TimeUtil.isTimeSecound(dateTime));
        //支付费用必须为分,不得带有小数点
        double total_fee = 1.01 *100;
        System.out.println(total_fee);
        int total = (int)total_fee;
        System.out.println(total);
        signParams.put("total_fee",total);//金额为分
        String sign = createSignSand("UTF-8", signParams);//生成签名
        signParams.put("sign", sign);
        //将数据转换成xml形式,微信接受的是xml数据格式
        String requestXml = getRequestXml(signParams);//生成Xml格式的字符串
        System.out.println(requestXml + "........xml");
        //向微信发起统一下单,接受微信返回的数据
        //沙盒测试调用的api接口
        //SAND_PAY_URL: http://api.mch.weixin.qq.com/sandboxnew/pay/unifiedorder
        //正式环境:http://api.mch.weixin.qq.com/pay/unifiedorder
        String result = httpsRequest(
                ConstantUtil.SAND_PAY_URL, "POST",
                requestXml);
        System.out.println(result + "返回的参数");
        Map<String, String> map =  XMLUtil.doXMLParse(result);
        //判断微信返回的状态码是否为success
        if (map.get("return_code").equals("SUCCESS")){
            //判断result_code是否为success
            if (map.get("result_code").equals("SUCCESS")){

            }
        }
        return  map;
   // }catch (Exception e){

   // }
   // return "错误信息";
}

/请求方法(向微信发送消息的工具类)
public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {
    try {
        URL url = new URL(requestUrl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setUseCaches(false);
        // 设置请求方式(GET/POST)
        conn.setRequestMethod(requestMethod);
        conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");
        // 当outputStr不为null时向输出流写数据
        if (null != outputStr) {
            OutputStream outputStream = conn.getOutputStream();
            // 注意编码格式
            outputStream.write(outputStr.getBytes("UTF-8"));
            outputStream.close();
        }
        // 从输入流读取返回内容
        InputStream inputStream = conn.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        String str = null;
        StringBuffer buffer = new StringBuffer();
        while ((str = bufferedReader.readLine()) != null) {
            buffer.append(str);
        }
        // 释放资源
        bufferedReader.close();
        inputStreamReader.close();
        inputStream.close();
        inputStream = null;
        conn.disconnect();
        return buffer.toString();
    } catch (ConnectException ce) {
        System.out.println("连接超时:{}"+ ce);
    } catch (Exception e) {
        System.out.println("https请求异常:{}"+ e);
    }
    return null;
}
//生成签名的工具类
public static String createSign(String characterEncoding,SortedMap<String,Object> parameters){
    StringBuffer sb = new StringBuffer();
    Set es = parameters.entrySet();
    Iterator it = es.iterator();
    while(it.hasNext()) {
        Map.Entry entry = (Map.Entry)it.next();
        String k = (String)entry.getKey();
        Object v = entry.getValue();
        if(null != v && !"".equals(v)
                && !"sign".equals(k) && !"key".equals(k)) {
            sb.append(k + "=" + v + "&");
        }
    }
    sb.append("key=" + ConstantUtil.Business_Key);//最后加密时添加商户密钥,由于key值放在最后,所以不用添加到SortMap里面去,单独处理,编码方式采用UTF-8
    String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
    return sign;
}

//请求xml组装工具类
public static String getRequestXml(SortedMap<String,Object> parameters){
    StringBuffer sb = new StringBuffer();
    sb.append("<xml>");
    Set es = parameters.entrySet();
    Iterator it = es.iterator();
    while(it.hasNext()) {
        Map.Entry entry = (Map.Entry)it.next();
        String key = (String)entry.getKey();
        Object value = entry.getValue();
        if ("attach".equalsIgnoreCase(key)||"body".equalsIgnoreCase(key)||"sign".equalsIgnoreCase(key)) {
            sb.append("<"+key+">"+"<![CDATA["+value+"]]></"+key+">");
        }else {
            sb.append("<"+key+">"+value+"</"+key+">");
        }
    }
    sb.append("</xml>");
    return sb.toString();
}
//将xml转换成map
public static Map doXMLParse(String strxml) throws JDOMException, IOException {
    strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");
    if(null == strxml || "".equals(strxml)) {
        return null;
    }
     
    Map m = new HashMap();
     
    InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
    SAXBuilder builder = new SAXBuilder();
    Document doc = builder.build(in);
    Element root = doc.getRootElement();
    List list = root.getChildren();
    Iterator it = list.iterator();
    while(it.hasNext()) {
        Element e = (Element) it.next();
        String k = e.getName();
        String v = "";
        List children = e.getChildren();
        if(children.isEmpty()) {
            v = e.getTextNormalize();
        } else {
            v = XMLUtil.getChildrenText(children);
        }
         
        m.put(k, v);
    }
     

 

返回支付结果:微信将支付结果返回到统一下单中的回调地址中

 public Object paymentResults(HttpServletRequest request, HttpServletResponse response){
        try{
            System.out.println("微信支付回调");
            PrintWriter writer = response.getWriter();
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            String result = new String(outSteam.toByteArray(), "utf-8");
            System.out.println("微信支付通知结果:" + result);
            Map<String, String> map = null;
            try {
                /**
                 * 解析微信通知返回的信息
                 */
                map = XMLUtil.doXMLParse(result);
            } catch (JDOMException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("=========:"+result);
            // 若支付成功,则告知微信服务器收到通知
            if (map.get("return_code").equals("SUCCESS")) {
                if (map.get("result_code").equals("SUCCESS")) {
                    System.out.println("充值成功!");
                    // PayRecord payRecord=payRecordService.get(Long.valueOf(map.get("out_trade_no")));
                    System.out.println("订单号:"+Long.valueOf(map.get("out_trade_no")));
                    //    System.out.println("payRecord.getPayTime():"+payRecord.getPayTime()==null+","+payRecord.getPayTime());
                    //判断通知是否已处理,若已处理,则不予处理
//                if(payRecord.getPayTime()==null){
//                    System.out.println("通知微信后台");
//                    payRecord.setPayTime(new Date());
//                    String phone=payRecord.getPhone();
//                    AppCustomer appCustomer=appCustomerService.getByPhone(phone);
//                    float balance=appCustomer.getBalance();
//                    balance+=Float.valueOf(map.get("total_fee"))/100;
//                    appCustomer.setBalance(balance);
//                    appCustomerService.update(appCustomer);
//                    payRecordService.update(payRecord);
                    String notifyStr = XMLUtil.setXML("SUCCESS", "");
                    writer.write(notifyStr);
                    writer.flush();
                }
            }

        }catch (Exception e){

        }
        return "";
   }

申请退款:微信申请退款需要下载证书:(如何下载证书具体查看微信支付开发文档)

https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3

 /**
  * 申请退款
  * @param userId
  * @param orderId
  * @return
  */
public Object applicationForRefund(int userId,int orderId) throws  Exception{
    String nonce_str = WXUtil.getNonceStr();
    SortedMap<String, Object> keyParams = new TreeMap<String, Object>();
    keyParams.put("mch_id",ConstantUtil.Business_name);
    keyParams.put("nonce_str",nonce_str);
    String sandsign = createSign("UTF-8", keyParams);//生成签名
    keyParams.put("sign",sandsign);
    String keyXml = getRequestXml(keyParams);//生成Xml格式的字符串
    //向微信请求沙盒测试的key
    String resultKey = httpsRequest(
            ConstantUtil.GETSandboxKey, "POST",
            keyXml);
    System.out.println(resultKey + "请求到的key");
    Map<String, String> sandMap =  XMLUtil.doXMLParse(resultKey);
    key =  sandMap.get("sandbox_signkey");
    System.out.println(key + "请求到的key");
    SortedMap<String, Object> signParams = new TreeMap<String, Object>();
    signParams.put("appid", ConstantUtil.APPID);//appid
    signParams.put("mch_id", ConstantUtil.Business_name);//商户号
    signParams.put("nonce_str", nonce_str);
    signParams.put("out_trade_no", "20190614111714");//订单号
    signParams.put("out_refund_no","20190616110715");//商户退款号
    //支付费用必须为分,不得带有小数点
    double total_fee = 1.01 *100;
    System.out.println(total_fee);
    int total = (int)total_fee;
    System.out.println(total);
    signParams.put("total_fee",total);//金额为分
    signParams.put("refund_fee",total);//退款金额
    String sign = createSignSand("UTF-8", signParams);//生成签名
    signParams.put("sign", sign);
    String requestXml = getRequestXml(signParams);//生成Xml格式的字符串
    System.out.println(requestXml + "........xml");
    //向微信发起退款请求
    //ConstantUtil.sandboxapplicationForRefund:
    //微信沙盒测试退款接口:https://api.mch.weixin.qq.com/sandboxnew/secapi/pay/refund
    //正式环境下的地址: https://api.mch.weixin.qq.com/secapi/pay/refund    
    String result = RefundRequest.httpsRequest(
            ConstantUtil.sandboxapplicationForRefund,requestXml,
            "C:\\work\\install\\Wxchat\\WXCertUtil\\cert\\1538226021_20190619_cert\\apiclient_cert.p12");
    System.out.println(result + "返回的参数");
    Map<String, String> map =  XMLUtil.doXMLParse(result);
    //判断是否申请成功
    if (map.get("return_code").equals("SUCCESS")){

    }
    return  map;
}

证书工具类

public class RefundRequest {
    //连接超时时间,默认10秒
    private static int socketTimeout = 10000;

    //传输超时时间,默认30秒
    private static  int connectTimeout = 30000;

    //请求器的配置
    private static RequestConfig requestConfig;

    //HTTP请求器
    private static CloseableHttpClient httpClient;

    /**
     * 加载证书
     * @param path
     * @throws IOException
     * @throws KeyStoreException
     * @throws UnrecoverableKeyException
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    private static  void initCert(String path) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
        //拼接证书的路径
        KeyStore keyStore = KeyStore.getInstance("PKCS12");

        //加载本地的证书进行https加密传输
        FileInputStream instream = new FileInputStream(new File(path));
        try {
            keyStore.load(instream, ConstantUtil.Business_name.toCharArray());  //加载证书密码,默认为商户ID
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } finally {
            instream.close();
        }

        // Trust own CA and all self-signed certs
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, ConstantUtil.Business_name.toCharArray())       //加载证书密码,默认为商户ID
                .build();
        // Allow TLSv1 protocol only
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[]{"TLSv1"},
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

        httpClient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();

        //根据默认超时限制初始化requestConfig
        requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();

    }


    /**
     * 通过Https往API post xml数据
     * @param url   API地址
     * @param xmlObj   要提交的XML数据对象
     * @param path    当前目录,用于加载证书
     * @return
     * @throws IOException
     * @throws KeyStoreException
     * @throws UnrecoverableKeyException
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public static String httpsRequest(String url, String xmlObj, String path) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
        //加载证书
        initCert(path);

        String result = null;

        HttpPost httpPost = new HttpPost(url);

        //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);

        //设置请求器的配置
        httpPost.setConfig(requestConfig);

        try {
            HttpResponse response = httpClient.execute(httpPost);

            HttpEntity entity = response.getEntity();

            result = EntityUtils.toString(entity, "UTF-8");

        } catch (ConnectionPoolTimeoutException e) {
            System.out.println("http get throw ConnectionPoolTimeoutException(wait time out)");
          //  LogUtils.trace("http get throw ConnectionPoolTimeoutException(wait time out)");

        } catch (ConnectTimeoutException e) {
           // LogUtils.trace("http get throw ConnectTimeoutException");

        } catch (SocketTimeoutException e) {
       //     LogUtils.trace("http get throw SocketTimeoutException");

        } catch (Exception e) {
    //        LogUtils.trace("http get throw Exception");

        } finally {
            httpPost.abort();
        }

        return result;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值