小程序发红包实现

(一)controller

    @PostMapping("/sendBizRedPacket")
    public  AjaxResult sendRedPacket(@ApiParam(value = "用户openid") @RequestParam String openid) throws Exception {
        // 1、订单号生成
        String orderNo = getTransid();
        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("mch_billno",orderNo);//订单号
        returnMap.put("re_openid",openid);//用户openid
        //发送红包
        AjaxResult resultMap = wxPayService.sendRedPacket(returnMap);
        return AjaxResult.success("发送成功!",resultMap);
    }

(2)service

 @Override
    public AjaxResult
    sendRedPacket(Map<String, String> returnMap) throws Exception {
        Map<String, String> Map = new HashMap<>();
        //保存订单信息
        returnMap.put("mch_id",wxPaywebConfig.getMchID());//商户号
        returnMap.put("send_name","srzp");//红包发送者名称
        returnMap.put("wxappid",wxPaywebConfig.getAppID());//公众号appid
        returnMap.put("total_amount","1");//付款金额,单位分
        returnMap.put("total_num","1");//红包发放总个数
        returnMap.put("wishing","thank");红包祝福语 最大长度128位
        returnMap.put("client_ip","192.168.0.114");//调用接口的机器Ip地址
        returnMap.put("act_name","asd");//活动名称
      /*  returnMap.put("remark","分享越多得到越多");*/
        returnMap.put("nonce_str", WXPayRedUtil.getNonce_str());
    /*    returnMap.put("key",wxPaywebConfig.getKey());//随机字符串*/
        //生成签名
        Long time = System.currentTimeMillis() / 1000;
        String timestamp = time.toString();
        Map.put("wxappid",wxPaywebConfig.getAppID());//公众账号appid
        Map.put("mch_id",wxPaywebConfig.getMchID());//商户号
        Map.put("device_info","1");
        Map.put("body","test");
        Map.put("nonce_str",WXPayRedUtil.getNonce_str());
        returnMap.put("sign", WXPayRedUtil.createLinkString(returnMap,wxPaywebConfig.getKey()));//生成签名
        String reqStr = WXPayRedUtil.map2Xml(returnMap);
        String resultXml = HttpRedRequest.sendPost(reqStr);
        System.out.println("微信请求返回:"+resultXml);
        //解析微信返回串 如果状态成功 则返回给前端
        if (WXPayRedUtil.getReturnCode(resultXml) != null && WXPayRedUtil.getReturnCode(resultXml).equals("SUCCESS")) {
            //成功
            Map<String, Object> resultMap = new TreeMap<>(
                    new Comparator<String>() {
                        public int compare(String obj1, String obj2) {
                            // 升序排序
                            return obj1.compareTo(obj2);
                        }
                    });

            resultMap.put("appId", wxPaywebConfig.getAppID());
            resultMap.put("nonceStr", WXPayRedUtil.getNonce_str());//解析随机字符串
            resultMap.put("package", reqStr);
            resultMap.put("signType", "MD5");
            resultMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));//时间戳
            String paySign = WXPayRedUtil.getSign(resultMap);
            resultMap.put("paySign", paySign);
            return AjaxResult.success("resultMap",resultMap);
        }else{
            return AjaxResult.error(999, "微信请求支付失败");
        }
    }

(三)工具包(含map转xml文件、解析xml文件获取标签信息)

package com.kdm.project.wx.util;

import com.kdm.common.utils.security.Md5Utils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.NodeList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.util.*;

/**
 * Create by 2021/4/1
 *
 * @Author GZS
 */
public class WXPayRedUtil {
    private final Logger logger = LoggerFactory.getLogger(WXPayRedUtil.class);
    //生成随机字符串
    public static String getNonce_str() {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 15; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    //map转xml 加上签名信息
    public static String map2Xml(Map<String, String> map) throws UnsupportedEncodingException {
        StringBuffer sb = new StringBuffer();
        StringBuilder sb2 = new StringBuilder();
        sb2.append("<xml>");
        for (String key : map.keySet()) {
            sb.append(key);
            sb.append('=');
            sb.append(map.get(key));
            sb.append('&');
            // sb2是用来做请求的xml参数
            sb2.append("<" + key + ">");
//      sb2.append("<![CDATA[" + map.get(key) + "]]>");
            sb2.append(map.get(key));
            sb2.append("</" + key + ">");
        }
        sb.append(System.getenv("signKey"));
      /*  String sign = Md5Utils.hash(sb.toString()).toUpperCase();
        sb2.append("<sign>");
        sb2.append(sign);
        sb2.append("</sign>");*/
        sb2.append("</xml>");
        return sb2.toString();
    }

    //解析微信返回return_code SUCCESS或FILE
    //根据微信返回resultXml再次生成签名
    public static String getSign(Map<String, Object> map) {
        StringBuffer sb = new StringBuffer();
        for (String key : map.keySet()) {
            sb.append(key);
            sb.append('=');
            sb.append(map.get(key));
            sb.append('&');
        }
        sb.append(System.getenv("signKey"));
        System.out.println("第二次签名内容:" + sb);
        System.out.println("第二次签名SING:" + Md5Utils.hash(sb.toString()).toUpperCase());
        return Md5Utils.hash(sb.toString()).toUpperCase();
    }

    //解析微信返回return_code SUCCESS或FILE
    public static String getReturnCode(String resultXml) {

        try {
            Document document = DocumentHelper.parseText(resultXml); //将给定的内容解析为一个xml文档,并返回一个新的Dom Document对象
            Element root = document.getRootElement();//获取根节点
            // 下面开始读取
            Element node=root.element("return_code");
            String info = node.getStringValue();
            return info;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解析微信返回return_msg
    public static String getReturn_msg(String resultXml) {
        String nonceStr;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = dbf.newDocumentBuilder();
            InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
            org.w3c.dom.Document doc = builder.parse(inputStream); //
            // 下面开始读取
            org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
            NodeList nl = root.getElementsByTagName("return_msg");
            org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
            org.w3c.dom.Node nd = el.getFirstChild();
            nonceStr = nd.getNodeValue();
            return nonceStr;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解析微信返回appid
    public static String getAppId(String resultXml) {
        String nonceStr;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = dbf.newDocumentBuilder();
            InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
            org.w3c.dom.Document doc = builder.parse(inputStream); //
            // 下面开始读取
            org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
            NodeList nl = root.getElementsByTagName("appid");
            org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
            org.w3c.dom.Node nd = el.getFirstChild();
            nonceStr = nd.getNodeValue();
            return nonceStr;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解析微信返回mch_id
    public static String getMchId(String resultXml) {
        String nonceStr;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = dbf.newDocumentBuilder();
            InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
            org.w3c.dom.Document doc = builder.parse(inputStream); //
            // 下面开始读取
            org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
            NodeList nl = root.getElementsByTagName("mch_id");
            org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
            org.w3c.dom.Node nd = el.getFirstChild();
            nonceStr = nd.getNodeValue();
            return nonceStr;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解析微信返回nonce_str
    public static String getNonceStr(String resultXml) {
        String nonceStr;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = dbf.newDocumentBuilder();
            InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
            org.w3c.dom.Document doc = builder.parse(inputStream); //
            // 下面开始读取
            org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
            NodeList nl = root.getElementsByTagName("nonce_str");
            org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
            org.w3c.dom.Node nd = el.getFirstChild();
            nonceStr = nd.getNodeValue();
            return nonceStr;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //解析微信返回prepay_id
    public static String getPrepayId(String resultXml) {
        String nonceStr;
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try {
            builder = dbf.newDocumentBuilder();
            InputStream inputStream = new ByteArrayInputStream(resultXml.getBytes());
            org.w3c.dom.Document doc = builder.parse(inputStream); //
            // 下面开始读取
            org.w3c.dom.Element root = doc.getDocumentElement(); // 获取根元素
            NodeList nl = root.getElementsByTagName("prepay_id");
            org.w3c.dom.Element el = (org.w3c.dom.Element) nl.item(0);
            org.w3c.dom.Node nd = el.getFirstChild();
            nonceStr = nd.getNodeValue();
            return nonceStr;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params, String keyee) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        String preStr = "";
        String sign = "";

        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if ("sign".equals(key)) {
                continue;
            }
            if (i == keys.size() - 1) {// 拼接时,不包括最后一个&字符
                preStr = preStr + key + "=" + value;
            } else {
                preStr = preStr + key + "=" + value + "&";
            }
        }
        String msg = preStr+"&key="+keyee;
        sign = encryptMd5(msg.getBytes()).toUpperCase();
        return sign;
    }
    /**
     * 功能:Md5加密
     *
     * @param
     * @return
     */
    public static String encryptMd5(byte[] bytes) {
        StringBuffer sb = new StringBuffer();
        try {
            byte[] md5Str = null;
            MessageDigest mdTemp = MessageDigest.getInstance("MD5");
            mdTemp.update(bytes);
            md5Str = mdTemp.digest();

            for (int i = 0; i < md5Str.length; i++) {
                sb.append(Integer.toHexString(
                        (0x000000ff & md5Str[i]) | 0xffffff00).substring(6));
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return sb.toString();
    }
    /**
     * MD5加密
     * @param
     * @param keys
     * @return
     */
    public static String createSign(Map<String, String> params, String keys){
       /* String sign = "";
        try {
            List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(params.entrySet());
            // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)
            infoIds.sort(new Comparator<Map.Entry<String, String>>() {
                public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                    return (o1.getKey()).compareTo(o2.getKey());
                }
            });
            // 将参数以参数名的字典升序排序
            Map<String, Object> sortParams = new TreeMap<String, String>(params);
            // 构造签名键值对的格式
            StringBuilder sb = new StringBuilder();
            for (Map.Entry<String, String> item : sortParams) {
                if (item.getKey() != null || item.getKey() != "") {
                    String key = item.getKey();
                    String val = (String) item.getValue();
                    if (!(val == "" || val == null)) {
                        sb.append(key + "=" + val + "&");
                    }
                }
            }
            String msg = sb.substring(0,sb.length()-1).toString()+keys;//sb.substring(0,sb.length()-1).toString():截取最后一个&
            //String result = (sb.toString().length()-1)+keys;
            System.out.println("================accsii排序==============="+msg);
            sign = Md5Utils.hash(msg).toUpperCase();//MD5加密,toUpperCase():大小写转换
            System.out.println("================signMD5加密==============="+sign);
        } catch (Exception e) {
            return null;
        }*/
        return "sign";
    }

}

(四)向指定URL发送post请求(附带证书post请求)

package com.kdm.project.wx.util;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.util.List;
import java.util.Map;

/**
 * Create by 2021/4/1
 *
 * @Author GZS
 */
public class HttpRedRequest {
    /**
     * 向指定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;
            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 param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
     * @return 所代表远程资源的响应结果
     */
    public static String sendPost(String param) throws Exception {
        //1.带证书
        KeyStore keyStore  = KeyStore.getInstance("PKCS12");//证书类型
        FileInputStream instream = new FileInputStream(new File("E:\\1602640894_20201102_cert\\apiclient_cert.p12"));//读取文件
        try {
            keyStore.load(instream, "1602640894".toCharArray());
        } finally {
            instream.close();
        }
        //信任自己的ca和所有的签名证书
        SSLContext sslcontext = SSLContexts.custom()
                .loadKeyMaterial(keyStore, "1602640894".toCharArray())
                .build();
        //只允许TLSv1协议
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslcontext,
                new String[] { "TLSv1" },
                null,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        CloseableHttpClient httpclient = HttpClients.custom()
                .setSSLSocketFactory(sslsf)
                .build();
        //2.微信小程序
        String mess = "";
        try {

            HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/mmpaymkttransfers/sendminiprogramhb");

            System.out.println("executing request" + httppost.getRequestLine());
            httppost.setEntity(new StringEntity(param.trim()));
            System.out.println("param+" + param);
            CloseableHttpResponse response = httpclient.execute(httppost);
            try {
                HttpEntity entity = response.getEntity();

                System.out.println("----------------------------------------");
                System.out.println(response.getStatusLine());
                if (entity != null) {
                    System.out.println("Response content length: " + entity.getContentLength());
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent()));
                    String text = "";//返回内容
                    while ((text = bufferedReader.readLine()) != null) {
                        System.out.println(text);
                        mess+=text;
                    }
                    System.out.println("mess="+mess);

                }
                EntityUtils.consume(entity);
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }
        return  mess;
    }
}

(五)使用dom4J操作dom文件获取返回信息


dom4j
dom4j
1.6.1

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值