微信公众号回调

2021-06-01 15:39
260
0
package abc.controller;

import com.alibaba.fastjson.JSONObject; 
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
 
@RestController
@RequestMapping("/weixin")
@Slf4j
public class WxGZHMsgController
{
    public static final String token = "aadffxxxxxxxx";

    public static String access_token="";

    private StringRedisTemplate stringRedisTemplate;
    private RedisTemplate redisTemplate;

    public static final String wxc_="plzwxc_";

    @Autowired
    public WxGZHMsgController(StringRedisTemplate stringRedisTemplate,RedisTemplate redisTemplate)
    {
        this.stringRedisTemplate = stringRedisTemplate;
        this.redisTemplate = redisTemplate;
        init();
    }

    private void init()
    {
        try
        {
            String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=aadffxxxxxxxx&secret=000xxxxxxsdfsdfsf";
            String ret = HttpUtil.doGet(url);
          /*
          {"access_token":"ACCESS_TOKEN","expires_in":7200}
           */
            JSONObject json = JSONObject.parseObject(ret);
            access_token = json.getString("access_token");
            log.info("get access_token="+access_token);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }

    private String getTicket(String userId)
    {
        String url = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + access_token;
        String postStr = "{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \""+wxc_ + userId + "\"}}}";
        String ret = HttpUtil.doPost(url, postStr);
              /*
              {"ticket":"gQH47joAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xL2taZ2Z3TVRtNzJXV1Brb3ZhYmJJAAIEZ23sUwMEmm
3sUw==","expire_seconds":60,"url":"http://weixin.qq.com/q/kZgfwMTm72WWPkovabbI"}
               */
        JSONObject json = JSONObject.parseObject(ret);
        String ticket = json.getString("ticket");
        String key=wxc_ + userId;
        stringRedisTemplate.opsForValue().set(key, ticket, 604800, TimeUnit.SECONDS);
        return ticket;
    }

    /**
     * 获取用户微信公众号平台扫码传图地址
     * https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQHI8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyOTR5MDFVc0dhemUxUXZFZnh3MVMAAgQf26dgAwQAjScA
     */
    @RequestMapping("/getUserWxcTicketUrl")
    public FormatResult getUserWxcTicketUrl(HttpServletRequest request)
    {
          String userId = UserContext.getUserId(request);

          if(userId==null)
          {
              return new FormatResult(999,"登录超时或未登录");
          }

          String key =wxc_+userId;

          String ticket = stringRedisTemplate.opsForValue().get(key);

          if(ticket==null||ticket.length()>256)
          {
              try
              {
                  ticket = getTicket(userId);
              }
              catch (Exception e)
              {
                  init();
                  ticket = getTicket(userId);
              }
          }

          log.info(userId+")getUserWxcTicketUrl ticket="+ticket);

          /*
                    https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=gQGy8DwAAAAAAAAAAS5odHRwOi8vd2VpeGluLnFxLmNvbS9xLzAyLWpMTzFyc0dhemUxVTdLazF3MXMAAgQHIa1gAwQAjScA
           */

          return new FormatResult("https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+ticket);
    }

    public static final String wxcPicList_="wxcPicList_";

    private boolean checkEchostr(String echostr,HttpServletRequest request, HttpServletResponse resp)
    {
        if(echostr!=null)
        {
            /*
            参数 描述
            signature  微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
            timestamp  时间戳
            nonce  随机数
             */
            String signature=request.getParameter("signature");
            String timestamp=request.getParameter("timestamp");
            String nonce=request.getParameter("nonce");
            log.info("echostr="+echostr);
            log.info("nonce="+nonce);
            log.info("timestamp="+timestamp);
            log.info("token="+token);
            log.info("signature="+signature);
            String source=timestamp+nonce+token;
            String sha1= CTools.getSha1(source);
            log.info("mySha1="+sha1);
            log.info("is Equal?="+sha1.equalsIgnoreCase(signature));
            try
            {
                resp.getWriter().println(echostr);
                resp.getWriter().close();
                request.getInputStream().close();
                return sha1.equalsIgnoreCase(signature);
            }
            catch (Exception e)
            {

            }
        }

        return false;
    }


    @RequestMapping(value = "/receiveMsg")
    public void receiveMsg(HttpServletRequest request, HttpServletResponse resp)
    {
        String echostr=request.getParameter("echostr");
        if(checkEchostr(echostr,request,resp))
        {
            return;
        }

        StringBuilder sb= new StringBuilder();
        byte[] buffer=new byte[512];
        int n =-1;
        try
        {
            while ((n = request.getInputStream().read(buffer)) > 0)
            {
                sb.append(new String(buffer, 0, n));
            }

            String xml=sb.toString();
            log.info(xml);
            Map map =CTools.xmlToMap(xml);
            String FromUserName=(String)map.get("FromUserName");
            String EventKey=(String)map.get("EventKey");
            String PicUrl=(String)map.get("PicUrl");
            if(PicUrl!=null&&PicUrl.startsWith("http"))
            {
                String userId=stringRedisTemplate.opsForValue().get(FromUserName);
                if(userId!=null)
                {
                    String pic=PicUrl;
                    String key=wxcPicList_+userId;
                    List aList=(List)redisTemplate.opsForValue().get(key);

                    if(aList == null)
                    {
                        aList = new ArrayList();
                    }

                    aList.add(PicUrl);

                    redisTemplate.opsForValue().set(key,aList,300,TimeUnit.SECONDS);

                    log.info("key:"+key+";value="+aList);
                }
            }
            else if(EventKey!=null&&EventKey.contains(wxc_))
            {
                int i=EventKey.indexOf(wxc_);
                String userId=EventKey.substring(i+wxc_.length());

                stringRedisTemplate.opsForValue().set(FromUserName,userId,24*60*60,TimeUnit.SECONDS);

                String key=wxcPicList_+userId;
                redisTemplate.delete(key);

                try
                { 
                    OutputStream out=resp.getOutputStream();
                    out.write(getRetXml(FromUserName).getBytes("utf-8"));
                    out.close();
                    request.getInputStream().close();
                    return;
                }catch (Exception e)
                {

                }
           }
            //
        }
        catch (Exception e)
        {
           e.printStackTrace();
        }

        try
        { 
            resp.getWriter().println("SUCCESS");
            resp.getWriter().close();
            request.getInputStream().close();
        }catch (Exception e)
        {

        }
    }

    public String getRetXml(String toUser)
    {
        StringBuilder sb=new StringBuilder();
        sb.append("\n<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<xml>\n<ToUserName><![CDATA[").append(toUser).append("]]></ToUserName>\n<FromUserName><![CDATA[gh_5de2c93ceef9]]></FromUserName><CreateTime>");
        sb.append(System.currentTimeMillis()/1000);
        sb.append("</CreateTime>\n<MsgType><![CDATA[text]]></MsgType>\n<Content><![CDATA[HI,您已开启微信传图模式,点击左下的小键盘图标,发送你需要上传的图片吧。]]></Content>\n</xml>\n\n");
         return sb.toString();
    }
}

 

public static String doPost(String httpUrl, String param)
{

    HttpURLConnection connection = null;
    InputStream is = null;
    OutputStream os = null;
    BufferedReader br = null;
    String result = null;
    try {
        URL url = new URL(httpUrl);
        // 通过远程url连接对象打开连接
        connection = (HttpURLConnection) url.openConnection();
        // 设置连接请求方式
        connection.setRequestMethod("POST");
        // 设置连接主机服务器超时时间:15000毫秒
        connection.setConnectTimeout(15000);
        // 设置读取主机服务器返回数据超时时间:60000毫秒
        connection.setReadTimeout(60000);

        // 默认值为:false,当向远程服务器传送数据/写数据时,需要设置为true
        connection.setDoOutput(true);
        // 默认值为:true,当前向远程服务读取数据时,设置为true,该参数可有可无
        connection.setDoInput(true);
        // 设置传入参数的格式:请求参数应该是 name1=value1&name2=value2 的形式。
        connection.setRequestProperty("Content-Type", "application/json");
        // 设置鉴权信息:Authorization: Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0
        //connection.setRequestProperty("Authorization", "Bearer da3efcbf-0845-4fe3-8aba-ee040be542c0");
        // 通过连接对象获取一个输出流
        os = connection.getOutputStream();
        // 通过输出流对象将参数写出去/传输出去,它是通过字节数组写出的
        os.write(param.getBytes());
        // 通过连接对象获取一个输入流,向远程读取
        if (connection.getResponseCode() == 200) {

            is = connection.getInputStream();
            // 对输入流对象进行包装:charset根据工作项目组的要求来设置
            br = new BufferedReader(new InputStreamReader(is, "UTF-8"));

            StringBuffer sbf = new StringBuffer();
            String temp = null;
            // 循环遍历一行一行读取数据
            while ((temp = br.readLine()) != null) {
                sbf.append(temp);
                sbf.append("\r\n");
            }
            result = sbf.toString();
        }
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        // 关闭资源
        if (null != br) {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (null != os) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (null != is) {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 断开与远程地址url的连接
        connection.disconnect();
    }
    return result;
}

 

public static String getSha1(String str)
{
    if (null == str || 0 == str.length())
    {
        return null;
    }

    char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',

            'a', 'b', 'c', 'd', 'e', 'f'};

    try
    {
        MessageDigest mdTemp = MessageDigest.getInstance("SHA1");

        mdTemp.update(str.getBytes("UTF-8"));

        byte[] md = mdTemp.digest();

        int j = md.length;

        char[] buf = new char[j * 2];

        int k = 0;

        for (int i = 0; i < j; i++)
        {
            byte byte0 = md[i];

            buf[k++] = hexDigits[byte0 >>> 4 & 0xf];

            buf[k++] = hexDigits[byte0 & 0xf];
        }

        return new String(buf);

    } catch (NoSuchAlgorithmException e)
    {
        e.printStackTrace();
    } catch (UnsupportedEncodingException e)
    {
        e.printStackTrace();
    }

    return "";
}


/**
 * XML格式字符串转换为Map
 *
 * @param strXML XML字符串
 * @return XML数据转换后的Map
 * @throws Exception
 */
public static Map<String, String> xmlToMap(String strXML) throws Exception {
    try {
        Map<String, String> data = new HashMap<String, String>();
        DocumentBuilder documentBuilder = newDocumentBuilder();
        InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
        org.w3c.dom.Document doc = documentBuilder.parse(stream);
        doc.getDocumentElement().normalize();
        NodeList nodeList = doc.getDocumentElement().getChildNodes();
        for (int idx = 0; idx < nodeList.getLength(); ++idx) {
            Node node = nodeList.item(idx);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                org.w3c.dom.Element element = (org.w3c.dom.Element) node;
                data.put(element.getNodeName(), element.getTextContent());
            }
        }
        try {
            stream.close();
        } catch (Exception ex) {
            // do nothing
        }
        return data;
    } catch (Exception ex) {
        log.error(strXML+" can't trans to Map error:"+ex.getMessage(),ex);
        throw ex;
    }

}

public static DocumentBuilder newDocumentBuilder() throws ParserConfigurationException {
    DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
    documentBuilderFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
    documentBuilderFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
    documentBuilderFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
    documentBuilderFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
    documentBuilderFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
    documentBuilderFactory.setXIncludeAware(false);
    documentBuilderFactory.setExpandEntityReferences(false);

    return documentBuilderFactory.newDocumentBuilder();
}

public static Document newDocument() throws ParserConfigurationException {
    return newDocumentBuilder().newDocument();
}

全部评论