微信扫带参数二维码,微信回调

先申请公众号的测试账号:微信公众平台

在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的openid不同)。公众号可通过本接口来根据OpenID获取用户基本信息,包括昵称、头像、性别、所在城市、语言和关注时间。

请注意,如果开发者有在多个公众号,或在公众号、移动应用之间统一用户帐号的需求,需要前往微信开放平台(open.weixin.qq.com)绑定公众号后,才可利用UnionID机制来满足上述需求。

重点:想获取用户的unionID,就需要将这个测试公众号,配置到微信开放平台

 url:填写后点击提交微信会请求,所以你项目需要先部署,并且微信服务器可以访问到

token:随便填写,代码中会使用到

 @RequestMapping("/weChatCallBack")
    public String weChatCallBack(HttpServletRequest request) throws Exception {
        String msgSignature = request.getParameter("signature");
        String msgTimestamp = request.getParameter("timestamp");
        String msgNonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");
        String encrypt = request.getParameter("encrypt");
        if (StringUtils.isNotBlank(echostr)) {
            //第一次填写回调地址使用,回调地址通过,后面微信就不会请求了
            if (WXPublicUtils.verifyUrl(msgSignature, msgTimestamp, msgNonce, encrypt)) {
                return echostr;
            }
        } else {

//这个是处理逻辑
            String msg = weChatService.weChatCallBack(request);
        }
        return "success";
    }

 验证过程

 /**
     * 验证Token
     *
     * @param msgSignature 签名串,对应URL参数的signature
     * @param timeStamp    时间戳,对应URL参数的timestamp
     * @param nonce        随机数
     * @return 是否为安全签名
     * @throws AesException 执行失败,请查看该异常的错误码和具体的错误信息
     */
    public static boolean verifyUrl(String msgSignature, String timeStamp, String nonce, String encrypt)
            throws AesException {
        // 这里的 WXPublicConstants.TOKEN 填写你自己设置的Token就可以了
      
        String signature = SHA1Util.getSHA1("此处填写你在页面中的token", timeStamp, nonce, encrypt);
       
        if (!signature.equals(msgSignature)) {
            throw new AesException(AesException.ValidateSignatureError);
        }
        return true;
    }



 /**
     * 用SHA1算法生成安全签名
     *
     * @param token     票据
     * @param timestamp 时间戳
     * @param nonce     随机字符串
     * @param encrypt   密文
     * @return 安全签名
     */
    public static String getSHA1(String token, String timestamp, String nonce, String encrypt) throws AesException {
        try {
            String[] array = new String[]{token, timestamp, nonce};
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            Arrays.sort(array);
            for (int i = 0; i < array.length; i++) {
                sb.append(array[i]);
            }
            String str = sb.toString();
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AesException(AesException.ComputeSignatureError);
        }
    }






public class AesException extends Exception {

    public final static int OK = 0;
    public final static int ValidateSignatureError = -40001;
    public final static int ParseXmlError = -40002;
    public final static int ComputeSignatureError = -40003;
    public final static int IllegalAesKey = -40004;
    public final static int ValidateAppidError = -40005;
    public final static int EncryptAESError = -40006;
    public final static int DecryptAESError = -40007;
    public final static int IllegalBuffer = -40008;


    private int code;

    private static String getMessage(int code) {
        switch (code) {
            case ValidateSignatureError:
                return "签名验证错误";
            case ParseXmlError:
                return "xml解析失败";
            case ComputeSignatureError:
                return "sha加密生成签名失败";
            case IllegalAesKey:
                return "SymmetricKey非法";
            case ValidateAppidError:
                return "appid校验失败";
            case EncryptAESError:
                return "aes加密失败";
            case DecryptAESError:
                return "aes解密失败";
            case IllegalBuffer:
                return "解密后得到的buffer非法";

            default:
                return null; // cannot be
        }
    }

    public int getCode() {
        return code;
    }

    public AesException(int code) {
        super(getMessage(code));
        this.code = code;
    }

}

这个是微信回调

public String weChatCallBack(HttpServletRequest request) {
        // 获得微信端返回的xml数据
        StringBuilder returnXml = new StringBuilder();
        Map<String, String> map = new HashMap<>(8);
        try (InputStream is = request.getInputStream(); InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr)) {
            String str;
            while ((str = br.readLine()) != null) {
                //返回的是xml数据
                returnXml.append(str);
            }

            log.info("微信传来消息:{}", returnXml.toString());
            map = WXPublicUtils.xmlToMap(returnXml.toString());
        } catch (Exception e) {
            log.error("处理微信公众号请求信息,失败", e);
        }
        // 区分消息类型
        String msgType = map.get("MsgType");
        // 普通消息
        if ("text".equals(msgType)) {
            // 暂不开发 处理文本消息
        } else if ("image".equals(msgType)) {
            // 暂不开发 处理图片消息
        } else if ("voice".equals(msgType)) {
            // 暂不开发 处理语音消息
        } else if ("video".equals(msgType)) {
            // 暂不开发 处理视频消息
        } else if ("shortvideo".equals(msgType)) {
            // 暂不开发 处理小视频消息
        } else if ("location".equals(msgType)) {
            // 暂不开发 处理地理位置消息
        } else if ("link".equals(msgType)) {
            // 暂不开发 处理链接消息
        }
        // 事件推送
        else if ("event".equals(msgType)) {
            // 事件消息
            String event = map.get("Event");
            //带参数的二维码中的参数 scene_6ba76c65-7825-4507-a79c-84260ca1f087
            String eventKey = map.get("EventKey");
            String openId = map.get("FromUserName");
            if (eventKey.startsWith(Consts.QRSCENE)) {
                eventKey = eventKey.split("_")[1];
            }
           
            //根据openId换subscribe信息
            String jdbAppId = "微信appid";
            String accessToken = "获取微信accessToken";
            WeChatSubscribe subscribe = weChatApi.isSubscribeByOpenId(accessToken, openId);
           
            if ("subscribe".equals(event)) {
                log.info("订阅事件或未关注扫描二维码事件");
               
            } else if ("unsubscribe".equals(event)) { // 取消订阅事件
                log.info("处理取消订阅事件,暂时不做任何处理");
            } else if ("SCAN".equals(event)) {
                log.info("已关注扫描二维码事件");
               
            } else if ("LOCATION".equals(event)) {
                // 暂不开发 处理上报地理位置事件
            } else if ("CLICK".equals(event)) {
                // 暂不开发 处理点击菜单拉取消息时的事件推送事件
            } else if ("VIEW".equals(event)) {
                // 暂不开发 处理点击菜单跳转链接时的事件推送
            }
        }
        return "success";
    }


/**
     * 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<>();
            DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
            InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
            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.warn("Invalid XML, can not convert to map. Error message: {}. XML content: {}", ex.getMessage(), strXML);
            throw ex;
        }
    }

    /**
     * 将Map转换为XML格式的字符串
     *
     * @param data Map类型数据
     * @return XML格式的字符串
     * @throws Exception
     */
    public static String mapToXml(Map<String, String> data) throws Exception {
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
        Document document = documentBuilder.newDocument();
        Element root = document.createElement("xml");
        document.appendChild(root);
        for (String key : data.keySet()) {
            String value = data.get(key);
            if (value == null) {
                value = "";
            }
            value = value.trim();
            Element filed = document.createElement(key);
            filed.appendChild(document.createTextNode(value));
            root.appendChild(filed);
        }
        TransformerFactory tf = TransformerFactory.newInstance();
        Transformer transformer = tf.newTransformer();
        DOMSource source = new DOMSource(document);
        transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        transformer.setOutputProperty(OutputKeys.INDENT, "yes");
        StringWriter writer = new StringWriter();
        StreamResult result = new StreamResult(writer);
        transformer.transform(source, result);
        String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
        try {
            writer.close();
        } catch (Exception ex) {

        }
        return output;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值