使用公众号发送模板消息

1 篇文章 0 订阅

首先登陆微信的公众号管理平台填写基本配置
URL是和微信校验的重要接口
根据上面的基本配置填写的校验的URL写对应的接口

@RestController
@RequestMapping("/officialAccounts")
public class officialAccounts extends BaseController {

    @Value("${fanlyun.wx.appID}")
    public String appID;


    @Value("${fanlyun.wx.appsecret}")
    public String appsecret;

    private Logger log = LoggerFactory.getLogger(officialAccounts.class);

    @Autowired
    private WxOfficialCheckSignatureService wxOfficialCheckSignatureService;


    /**
     * @Description  验证消息的确来自微信服务器,签名验证
     * @author lst
     * @date 2020-8-18 12:03
     * @return java.lang.String
     */

    @RequestMapping(value = "/check-token", produces = "application/json; charset=utf-8")
    public String checkToken(HttpServletRequest request , HttpSession session) {
        String signature = request.getParameter("signature");
        String timestamp = request.getParameter("timestamp");
        String nonce = request.getParameter("nonce");
        String echostr = request.getParameter("echostr");

        String s = wxOfficialCheckSignatureService.checkSignature(signature, timestamp, nonce, echostr);
        //接受微信的推送(关注和取消关注等)
        try {
            //解析微信返回的xml
            Map<String, String> map = MessageUtil.parseXml(request);
            //测试查看返回的消息
            System.out.println(map.size());
            for (String key : map.keySet()) {
                if("Event".equals(key)){
                    if(map.get(key).equals("subscribe")){
                        //假如是关注事件
                        System.out.println("用户名为:"+map.get("FromUserName"));
                        wxOfficialCheckSignatureService.subscribe(map.get("FromUserName"));
                        break;
                    }
                    if(map.get(key).equals("unsubscribe")){
                        //假如是取消关注事件
                        wxOfficialCheckSignatureService.unsubscribe(map.get("FromUserName"));
                        break;
                    }
                }


            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return s ;
    }
    
}

具体的实现类


@Service
public class WxOfficialCheckSignatureServiceImpl  implements WxOfficialCheckSignatureService {

    @Autowired
    public RedisTemplate redisTemplate;

    @Value("${fanlyun.wx.token}")
    public String token;

    @Value("${fanlyun.wx.getAccessTokenUrl}")
    public String getAccessTokenUrl;

    //公众号ID
    @Value("${fanlyun.wx.appID}")
    public String appID;

    //小程序ID
    @Value("${fanlyun.tencent.miniAppId}")
    private String miniAppId;

    @Value("${fanlyun.wx.appsecret}")
    public String appsecret;

    @Value("${fanlyun.wx.subscribeMessageUrl}")
    private String subscribeMessageUrl;

    @Autowired
    private ISysWxUserInfoService sysWxUserInfoService;

    @Autowired
    private ISysUserService userService;


    @Value("${fanlyun.wx.getPageUserInfoUrl}")
    private String getPageUserInfoUrl;

    private Logger log = LoggerFactory.getLogger(WxOfficialCheckSignatureServiceImpl.class);

    @Override
    public String checkSignature(String signature, String timestamp, String nonce, String echostr) {
        // 1.将token、timestamp、nonce三个参数进行字典序排序
        log.info("signature:{},token:{},timestamp:{},nonce:{}",signature,token,timestamp,nonce);
        String tmpStr = ShaUtil.getSHA1(token,  timestamp,  nonce);
        //TODO 进行对比
        log.info("随机字符串echostr:{}",echostr);
        log.info("tmpStr:{}",tmpStr);
        if (tmpStr.equals(signature.toUpperCase())) {
            return echostr;
        }
        return null;

    }

    /**
     * 获取网页授权凭证
     * @param appID 公众账号的唯一标识
     * @param appsecret 公众账号的密钥
     * @param code
     * @return
     */
    @Override
    public Oauth2Token getOauth2Token(String appID, String appsecret, String code) {
        log.info("获取网页授权凭证 开始...");

        Oauth2Token auth = null;

        //拼接请求地址
        String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
        requestUrl = requestUrl.replace("APPID", appID);
        requestUrl = requestUrl.replace("SECRET", appsecret);
        requestUrl = requestUrl.replace("CODE", code);

        log.info("拼接后的请求地址为:" + requestUrl);

        //获取网页授权凭证
        com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject (HttpUtils.sendGet(requestUrl));

        if(null != jsonObject) {
            try {
                auth = new Oauth2Token();
                auth.setAccessToken(jsonObject.getString("access_token"));
                auth.setExpiresIn(jsonObject.getInteger("expires_in"));
                auth.setRefreshToken("refresh_token");
                auth.setScope("scope");
                auth.setOpenId(jsonObject.getString("openid"));
            }catch(Exception e) {
                auth = null;
                int errorCode = jsonObject.getInteger("errcode");
                String errorMsg = jsonObject.getString("errmsg");
                log.error("获取网页授权凭证失败 errcode:{} errmsg:{}",errorCode,errorMsg);
            }
        }

        log.info("获取网页授权凭证 结束...");
        return auth;
    }


//    /**
//     * 通过网页授权获取用户信息
//     *
//     * @param accessToken 网页授权接口调用凭证
//     * @param openId 用户标识
//     * @return
//     */
//    @Override
//    public WxUserDO getWxUserInfo(String accessToken, String openId) {
//        log.info("获取用户信息 开始...");
//        log.info("网页授权接口访问凭证AccessToken:" + accessToken);
//        log.info("用户标识openId:" + openId);
//
//        WxUserDO wxUserInfo = null;
//
//        // 拼接请求地址
//        String requestUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN";
//        requestUrl = requestUrl.replace("ACCESS_TOKEN", accessToken);
//        requestUrl = requestUrl.replace("OPENID", openId);
//
//        log.info("拼接请求地址:" + requestUrl);
//
//        // 通过网页授权获取用户信息
//        com.alibaba.fastjson.JSONObject jsonObject = JSON.parseObject(HttpUtils.sendGet(requestUrl));
//
//        if (null != jsonObject) {
//            try {
//                wxUserInfo = new WxUserDO();
//                wxUserInfo.setOpenId(jsonObject.getString("openid"));
//                wxUserInfo.setNickname(jsonObject.getString("nickname"));
//                wxUserInfo.setSex(jsonObject.getInteger("sex"));
//                wxUserInfo.setCountry(jsonObject.getString("country"));
//                wxUserInfo.setProvince(jsonObject.getString("province"));
//                wxUserInfo.setCity(jsonObject.getString("city"));
//                wxUserInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
//                //用户授权信息
//                List<String> list = JSON.parseArray(jsonObject.getString("privilege"), String.class);
//                wxUserInfo.setPrivilegeList(list);
//                //与开放平台公用的唯一标识,只有在用户讲公众号绑定到微信开放平台账号后,才会出现该字段
//                wxUserInfo.setUnionid(jsonObject.getString("unionid"));
//            }catch (Exception e) {
//                wxUserInfo = null;
//                int errorCode = jsonObject.getInteger("errcode");
//                String errorMsg = jsonObject.getString("errmsg");
//                log.error("获取用户信息失败  errcode:{} errmsg:{}",errorCode,errorMsg);
//            }
//        }
//
//        log.info("获取用户信息 结束...");
//        return wxUserInfo;
//    }


    /***
     * 发送模板消息
     * @param touser    接收者(用户)的 openid
     * @param template_id   所需下发的订阅模板id
     * @param pagepath  所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏
     * @param data  模板内容,格式形如 { "key1": { "value": any }, "key2": { "value": any } }
     * @param url 模板跳转链接(海外帐号没有跳转能力)
     * @param color 模板内容字体颜色,不填默认为黑色
     * @return
     */
    @Override
    public AjaxResult subscribeMessage(String accessToken, String touser, String template_id, String pagepath, Object data, String url,String color) {
        Map<String, Object> map = new HashMap<>();
        map.put("touser",touser);
        map.put("template_id",template_id);
        map.put("color",color);
        map.put("data",data);
        map.put("url",url);
        if(StringUtils.isEmpty(pagepath)){
            Map<String, Object> miniprogram = new HashMap<>();
            miniprogram.put("appid",miniAppId);
            miniprogram.put("pagepath",pagepath);
            map.put("miniprogram",miniprogram);
        }


        String s = JSONUtils.toJSONString(map);
        log.info("开始发送模板消息,body中的请求参数为:【{}】",s);
        String result = HttpUtils.sendPostWithJson(subscribeMessageUrl+"?access_token="+accessToken, s);
        Map<String,Object> jsonObject = JSON.parseObject(result);
        if (jsonObject.get("errcode").toString().equals("0")) {
            log.info("模板消息发送成功");
            return AjaxResult.success("模板消息发送成功!");
        }else {
            log.info("模板消息发送失败,错误码为:{},错误信息为:{}",jsonObject.get("errcode").toString(),jsonObject.get("errmsg").toString());
            return AjaxResult.error(jsonObject.get("errmsg").toString());
        }
    }


    //发送模板消息
    @Override
    public  void  sendTemplateNews(SysNewTemplate sysNewTemplate,TmsNotice tmsNotice, SysUser sysUser){
        Map<String, HashMap<String, String>> data = getData(tmsNotice,sysNewTemplate);
        String accessToken = getToken();
        AjaxResult ajaxResult = subscribeMessage(accessToken,sysUser.getOfficialOpenId(), sysNewTemplate.getWeixinTemplate(),"",data,"","");
        log.info("发送模板消息后,返回的json为:"+ajaxResult);
    }

    /**
     * 准备data里面的数据
     * @param tmsNotice
     * @param sysNewTemplate
     * @return
     */
    public Map<String, HashMap<String,String>>  getData(TmsNotice tmsNotice, SysNewTemplate sysNewTemplate){
        Map<String,HashMap<String,String>> mapTypes= new HashMap<String, HashMap<String, String>>();
        mapTypes.put(sysNewTemplate.getWxTemplateField1(),new HashMap<String,String>() {
            {
                put("value", tmsNotice.getWxTemplateField1());
            }
        });
        mapTypes.put(sysNewTemplate.getWxTemplateField2(),new HashMap<String,String>() {
            {
                put("value", tmsNotice.getWxTemplateField2());
            }
        });
        mapTypes.put(sysNewTemplate.getWxTemplateField3(),new HashMap<String,String>() {
            {
                put("value", tmsNotice.getWxTemplateField3());
            }
        });
        mapTypes.put(sysNewTemplate.getWxTemplateField4(),new HashMap<String,String>() {
            {
                put("value", tmsNotice.getWxTemplateField4());
            }
        });
        mapTypes.put(sysNewTemplate.getWxTemplateField5(),new HashMap<String,String>() {
            {
                put("value", tmsNotice.getWxTemplateField5());
            }
        });
        mapTypes.put(sysNewTemplate.getWxRemark(),new HashMap<String,String>() {
            {
                put("value", tmsNotice.getWxRemark());
            }
        });
        return mapTypes;
    }

    /***
     * 获取公众号全局唯一后台接口调用凭据(access_token)
     * @return
     */
    @Override
    public  String getToken(){
        //先从Redis中获取Redis中没有则向微信端发送请求
        Object o = redisTemplate.opsForValue().get(Constants.OFFICIAL_TOKEN);
        if (o!=null) {
            return o.toString();
        }

        log.info("======================开始获取公众号中的accessToken==========================");
        String access_token = "";
        String param = "grant_type=client_credential&appid=" + appID + "&secret=" + appsecret;
        String str = HttpUtils.sendGet(getAccessTokenUrl, param);
        Map<String, Object> mapTypes = JSON.parseObject(str);
        for (Object obj : mapTypes.keySet()) {
            if (mapTypes.containsKey("access_token")) {
                access_token = mapTypes.get("access_token").toString();
                redisTemplate.opsForValue().set(Constants.OFFICIAL_TOKEN, access_token, 3600, TimeUnit.SECONDS);
            }
        }

        log.info("======================获取公众号中的accessToken完成,accessToken:【{}】==========================",access_token);
        return access_token;
    }

    //关注事件
    @Override
    public void subscribe(String fromUserName) {
        String token = getToken();
        //拼接链接地址 https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
        String url=getPageUserInfoUrl.replace("ACCESS_TOKEN",token);
         url=url.replace("OPENID",fromUserName);
        String str = HttpUtils.sendGet(url);
        Map<String,Object> mapTypes = JSON.parseObject(str);
        WxUserDO wxUserDO = new WxUserDO();
        wxUserDO.setUnionid(mapTypes.get("unionid").toString());
        List<WxUserDO> lists = sysWxUserInfoService.selectSysWxUserInfoList(wxUserDO);
        //往微信公众号用户信息表中添加数据
        wxUserDO.setOfficialOpenId(fromUserName);
        wxUserDO.setCity(mapTypes.get("city").toString());
        wxUserDO.setCountry(mapTypes.get("country").toString());
        wxUserDO.setHeadimgurl(mapTypes.get("headimgurl").toString());
        wxUserDO.setNickname(mapTypes.get("nickname").toString());
        wxUserDO.setSex(Convert.toInt(mapTypes.get("sex")));
        wxUserDO.setProvince(mapTypes.get("province").toString());
        if(lists==null||lists.size()<=0){
            sysWxUserInfoService.insertSysWxUserInfo(wxUserDO);
        }else {
            String openId = lists.get(0).getOpenId();
            //往微信公众号用户信息表中更新数据
            sysWxUserInfoService.updateByUnionid(wxUserDO);
            userService.updateUserByOpenId(openId,wxUserDO.getOfficialOpenId());
        }

    }

    //取关事件
    @Override
    public void unsubscribe(String fromUserName) {

    }

}

将传送过来的参数排序



public class ShaUtil {


    private static final Logger LOGGER = LoggerFactory.getLogger(ShaUtil.class);




    /**
     * @Description  用SHA1算法验证Token
     * @author lst
     * @date 2020-8-20 11:30
     * @param token url相关的token
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @return java.lang.String
     */
    public static String getSHA1(String token, String timestamp, String nonce){

        String[] arr = new String[] { token, timestamp, nonce };
        Arrays.sort(arr);
        //TODO 2. 将三个参数字符串拼接成一个字符串进行sha1加密
        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");
            // 将三个参数字符串拼接成一个字符串进行sha1加密
            byte[] digest = md.digest(content.toString().getBytes());
            tmpStr = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {

        }

        return tmpStr;
    }

    /**
     * @Description 将字节数组转换为十六进制字符串
     * @author lst
     * @date 2020-8-18 11:56
     * @param byteArray
     * @return java.lang.String
     */
    private static String byteToStr(byte[] byteArray) {
        StringBuilder strDigest = new StringBuilder();
        for (int i = 0; i < byteArray.length; i++) {
            strDigest.append(byteToHexStr(byteArray[i]));
        }
        return strDigest.toString();
    }

    /**
     * @Description  将字节转换为十六进制字符串
     * @author lst
     * @date 2020-8-18 11:57
     * @param mByte
     * @return java.lang.String
     */
    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;
    }


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值