微信公众号关注或取关后再处理我们自己的业务逻辑

业务是:根据扫描不同门店的二维码(上偏博文已经介绍),统计来自各个门店的关注人数。

每个二维码扫描进去都是光大银行的公众号,但是每个门店的二维码中的场景值不一样,要统计通过扫描各个门店进行关注的个数,好判断各个门店的引流情况。

参考博文:https://blog.csdn.net/LiuAustin/article/details/104507369

代码实现:

1.下面WxPublicController代码中,有个get(),post()方法,这两个方法是微信后台自动调用的接口,这个controller的url需要和公众号中配置的url保持一致;

2.由于之前是由(别的公司)PHP写的关于公众号的代码,这次是新增统计各个商户引流情况(我们公司完成java写),所以公众号那边的url不能再进行修改,这下怎么办?

我的思路是:用户关注/取消关注公众号的时候,微信后台会给之前配置好的url中返回一个xml文件,php那边接收到该xml后调用我java这边的接口,进行逻辑处理,由于php那边把xml封装成json了,所以我这边就用@RequestBody JSONObject jsonObject

来接收,然后再进行逻辑处理,其中EventKey就是之前生成的带场景值二维码的场景值,我这边是商户id.

注意:用户扫描二维码,进行关注(Event是subscribe),微信公众号后台才返回EventKey有值,如果是取消关注(Event是unsubscribe),微信公众号后台返回来的EventKey没有值,是空。

/**
 * Copyright (C), 2018-2020, XXX有限公司
 * FileName: WxPublicController
 * Author:   zhanglei
 * Date:     2020/8/11 13:28
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.asyware.game.controller;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author zhanglei
 * @create 2020/8/11
 * @since 1.0.0
 */

import com.asyware.game.entity.Attention;
import com.asyware.game.mapper.AttentionMapper;
import com.asyware.game.service.AttentionService;
import com.asyware.game.utils.SignUtil;
import com.asyware.game.utils.wx.MsgUtil;

import com.asyware.game.utils.wx.TextMsg;
import com.asyware.game.utils.wx.XmlUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author liuqh
 * @date 2019-08-13 16:26
 * @description
 */
@RestController
@RequestMapping(value = "/wx")
@Api(tags = "微信")
public class WxPublicController {

    protected static Logger logger = LoggerFactory.getLogger(WxPublicController.class);
    //填写和公众号后台配置的一样的token
    private static final String TOKENN = "自己公众号的token";
    @Autowired
    private AttentionService attentionService;
    @Autowired
    private AttentionMapper attentionMapper;


    /**
     * 微信公众号appId
     */
    @Value("${APPID}")
    private String publicAppId;
    /**
     * 微信公众号appSecret
     */
    @Value("${APPSECRET}")
    private String publicAppSecret;


    @RequestMapping(method = RequestMethod.GET)
    public void get(HttpServletRequest request, HttpServletResponse response) {
        // 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
        String signature = request.getParameter("signature");
        // 时间戳
        String timestamp = request.getParameter("timestamp");
        // 随机数
        String nonce = request.getParameter("nonce");
        // 随机字符串
        String echostr = request.getParameter("echostr");
        PrintWriter out = null;
        try {
            out = response.getWriter();
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败
            if (SignUtil.checkSignature(TOKENN, signature, timestamp, nonce)) {
                out.print(echostr);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null ) {
                out.close();
            }
        }
    }




 //   @RequestMapping(method = RequestMethod.POST)
 @ApiOperation(value = "PHP那边传入json,进行商户关注人数加减一",notes = "")
 @PostMapping("/parseXml")
    public void post(HttpServletRequest request, HttpServletResponse response,
                     @RequestBody JSONObject jsonObject) throws Exception{
        // 响应消息
        PrintWriter out = null;
        String resMessage = "success";
        try {
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            //把微信返回的xml信息转义成map
    //        Map<String, String> map = XmlUtil.parseXml(request);
            //消息来源用户标识
            String fromUserName = (String)jsonObject.get("FromUserName");
            //消息目的用户标识
            String toUserName = (String)jsonObject.get("ToUserName");
            //消息创建时间(整型)
            String createTime = (String)jsonObject.get("CreateTime");
            //消息类型
            String msgType =(String)jsonObject.get("MsgType");
            //事件类型:subscribe/unsubscribe
            String eventType = (String)jsonObject.get("Event");

            //如果为事件类型
            if(MsgUtil.MSGTYPE_EVENT.equals(msgType)){
                //处理订阅事件
                if(MsgUtil.MESSAGE_SUBSCIBE.equals(eventType)){
                    resMessage = MsgUtil.subscribeForText(toUserName, fromUserName,"欢迎关注,精彩内容不容错过!!!");
                    //TODO 关注的业务逻辑
                    //场景值
                    String eventKey = (String)jsonObject.get("EventKey");
                    List<Attention> list = attentionService.lambdaQuery().eq(Attention::getOpenId, fromUserName).list();
                    if(CollectionUtils.isEmpty(list) && !StringUtils.isEmpty(eventKey)){//没有关注过
                        String[] s = eventKey.split("_");
                        if("1".equals(s[2])){//关注二维码
                            Attention a=new Attention(fromUserName,Integer.valueOf(s[1]));
                            attentionMapper.insert(a);
                        }else{//核销二维码

                        }
                    }
                } else if(MsgUtil.MESSAGE_UNSUBSCIBE.equals(eventType)) { //处理取消订阅消息
                    resMessage = MsgUtil.unsubscribeForText(toUserName, fromUserName);
                    //TODO 取消关注的业务逻辑
                    List<Attention> list = attentionService.lambdaQuery().eq(Attention::getOpenId, fromUserName).list();
                    if(!CollectionUtils.isEmpty(list)){
                        attentionMapper.deleteById(list.get(0).getId());
                    }
                }else if(MsgUtil.MSGTYPE_EVENT.equals(eventType)){//关注之后的扫码消息
                    //场景值
                    String eventKey = (String)jsonObject.get("EventKey");
                    if(!StringUtils.isEmpty(eventKey)){
                        String[] s = eventKey.split("_");
                        if("2".equals(s[2])){//核销二维码

                        }
                    }
                    //todo
                }
                logger.info("eventType:"+eventType+",fromUserName:"+fromUserName+",toUserName:"+toUserName+",msgType:"+msgType+",createTime:"+createTime);
            }
            out = response.getWriter();
            out.println(resMessage);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (out != null ) {
                out.close();
            }
        }
    }
}

2.SignUtil类:

/**
 * Copyright (C), 2018-2020, XXX有限公司
 * FileName: SignUtil
 * Author:   zhanglei
 * Date:     2020/8/11 12:01
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.asyware.game.utils;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author zhanglei
 * @create 2020/8/11
 * @since 1.0.0
 */

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;

/**
 * @author liuqh
 * @date 2019-08-13 16:20
 * @description
 */
public class SignUtil {

    /**
     * 验证签名
     * @param token
     * @param signature 签名用来核实最后的结果是否一致
     * @param timestamp 时间标记
     * @param nonce 随机数字标记
     * @return 一个布尔值确定最后加密得到的是否与signature一致
     */
    public static boolean checkSignature(String token, String signature, String timestamp, String nonce) {
        //将传入参数变成一个String数组然后进行字典排序
        String[] arr = new String[] { token, timestamp, nonce };
        // 将token、timestamp、nonce三个参数进行字典排序
        Arrays.sort(arr);
        //创建一个对象储存排序后三个String的结合体
        StringBuilder content = new StringBuilder();
        for (int i = 0; i < arr.length; i++) {
            content.append(arr[i]);
        }
        MessageDigest md = null;
        String tmpStr = null;

        try {
            md = MessageDigest.getInstance("SHA-1");
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

    /**
     * 将字节数组转换为十六进制字符串
     * @param byteArray
     * @return
     */
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    /**
     * 将每一个字节转换为十六进制字符串
     * @param mByte
     * @return
     */
    private static String byteToHexStr(byte mByte) {
        //转位数参照表
        char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
        char[] tempArr = new char[2];
        tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
        tempArr[1] = Digit[mByte & 0X0F];
        //得到进制码的字符串
        String s = new String(tempArr);
        return s;
    }
}

3.MsgUtil类:

/**
 * Copyright (C), 2018-2020, XXX有限公司
 * FileName: MsgUtil
 * Author:   zhanglei
 * Date:     2020/8/11 13:25
 * Description:
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package com.asyware.game.utils.wx;

/**
 * 〈一句话功能简述〉<br> 
 * 〈〉
 *
 * @author zhanglei
 * @create 2020/8/11
 * @since 1.0.0
 */


import java.util.Date;

/**
 * @author liuqh
 * @date 2020-02-20 10:10
 * @description
 */
public class MsgUtil {

    public static final String MSGTYPE_EVENT = "event";//消息类型--事件
    public static final String MESSAGE_SUBSCIBE = "subscribe";//消息事件类型--订阅事件
    public static final String MESSAGE_UNSUBSCIBE = "unsubscribe";//消息事件类型--取消订阅事件
    public static final String MESSAGE_SCAN = "scan";//消息事件类型--已关注时的扫码事件
    public static final String MESSAGE_TEXT = "text";//消息类型--文本消息

    /**
     * 组装文本消息
     */
    public static String textMsg(String toUserName,String fromUserName,String content){
        TextMsg text = new TextMsg();
        text.setFromUserName(toUserName);
        text.setToUserName(fromUserName);
        text.setMsgType(MESSAGE_TEXT);
        text.setCreateTime(new Date().getTime());
        text.setContent(content);
        return XmlUtil.textMsgToxml(text);
    }

    /**
     * 响应订阅事件--回复文本消息
     */
    public static String subscribeForText(String toUserName,String fromUserName,String content){
        return textMsg(toUserName, fromUserName, content);
    }

    /**
     * 响应取消订阅事件
     */
    public static String unsubscribeForText(String toUserName,String fromUserName){
        System.out.println("用户:"+ fromUserName +"取消关注~");
        return "";
    }
}

猜你喜欢

转载自blog.csdn.net/zhangleiyes123/article/details/107963047