今天要说的是微信推送消息的详细流程,配合微信开发手册一起使用哦,虽然说开发手册有坑,但是毕竟我们需要使用他开发

java推送消息给第三方 java微信推送信息_天才

配置消息推送的接口

我们登陆 微信公众平台在「微信公众平台 - 设置 - 开发设置」页 配置服务器的URL,填写 Token令牌 消息加密密钥 加密方式和数据格式这些基本的信息,数据格式我这里使用的是JSON格式

java推送消息给第三方 java微信推送信息_人才_02


java推送消息给第三方 java微信推送信息_人才_03


这里配置完成一会微信需要验证下你输入的URL,也就是说你需要按照微信的验证规则写一个接口,以下是JAVA片段

public void receiveMsg(){
        String echostr = getPara("echostr");// 随机字符串
        //判断是否为认证 
        if(StringUtils.isBlank(echostr)){
            //否则接收客户发送消息
            responseMsg();
        }else {
            //如果认证去验证
            checkSignature();
        }
    }

这里就是你在微信配置的URL,根据echostr判断是 验证 还是 发图文消息

private void checkSignature() {
        String echostr = getPara("echostr");// 随机字符串
        String signature = getPara("signature");// 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。
        String timestamp = getPara("timestamp");// 时间戳
        String nonce = getPara("nonce");// 随机数
        PrintWriter out = null;
        try {
            out = getResponse().getWriter();
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,否则接入失败
            if (loveHomeSerivce.checkSignature(signature, timestamp, nonce)) {
                out.print(echostr);
                out.flush();//这个地方必须画重点,消息推送配置Token令牌错误校验失败,搞了我很久,必须要刷新!!!!!!!
            }
        } catch (IOException e) {
            e.printStackTrace();
            logger.error("获取Response错误");
        } finally {
            out.close();

        }
    }
public static boolean checkSignature(String signature, String timestamp, String nonce) {

        //与token 比较
        String[] arr = new String[] {TOKEN, timestamp, nonce };

        // 将token、timestamp、nonce三个参数进行字典排序
        Arrays.sort(arr);

        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 = StrUtil.byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }
/**
     * 将字节数组转换为十六进制字符串
     *
     * @param byteArray
     * @return
     */
    public static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

开发者通过检验 signature 对请求进行校验(下面有校验方式)。若确认此次 GET 请求来自微信服务器,请原样返回 echostr 参数内容,则接入生效,成为开发者成功,否则接入失败。加密/校验流程如下:

  1. 将token、timestamp、nonce三个参数进行字典序排序
  2. 将三个参数字符串拼接成一个字符串进行sha1加密
  3. 开发者获得加密后的字符串可与signature对比,标识该请求来源于微信
    验证URL有效性成功后即接入生效,成为开发者。

验证成功后以后访问你在微信配置的URL就是发送图文消息,以上验证只是验证你配置的URL是否正常,下面是发送图文消息的代码

public void responseMsg(){
        PrintWriter out = null;//输入返回内容
        try {
            out = getResponse().getWriter();
            //处理Post请求中的body
            Map<String, String> mapResult = HttpRequestUtil.getPostRequestBody(getRequest());
            String openid = mapResult.get("FromUserName");//发送者的openid
            String title = mapResult.get("Title");//标题
            String pagePath = mapResult.get("PagePath");//小程序页面路径
            String thumbUrl = mapResult.get("ThumbUrl");//封面图片的临时cdn链接
            if(StringUtils.isBlank(openid) || StringUtils.isBlank(title) || StringUtils.isBlank(pagePath) || StringUtils.isBlank(thumbUrl)){
                return;
            }
            JSONObject jsonObject = loveHomeSerivce.sendImgLink(openid, title, pagePath, thumbUrl);
            if(jsonObject == null){
                logger.error("发送客服消息接口返回失败!");
                return;
            }
            logger.error("微信返回请求:errcode="+jsonObject.getIntValue("errcode")+",errmsg="+jsonObject.getString("errmsg"));
        } catch (Exception e) {
            e.printStackTrace();
            logger.error("发送客服消息接口失败!");
        }
        out.print("success");
        out.flush();

这里注意 本人这里测试直接return"success" 是不行的,自己可以尝试下,这就是所谓的微信开发文档的坑吧

public JSONObject sendImgLink(String openid, String title, String pagePath, String thumbUrl) throws IOException {
        //获取接口凭证url
        String getAccessTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET";
        //获取接口凭证
        String accessToken = getAccessToken(getAccessTokenUrl,appId,secret);
        //发送微信请求
        JSONObject PostJson = sendXIRequest(openid, title, pagePath, thumbUrl, accessToken);
        return PostJson;
    }
/**
 1. 获取接口凭证
 */
private String getAccessToken(String url, String appId, String secret) throws IOException {
        HttpClient oHttpClient = new HttpClient();
        //设置传入参数
        url = url.replace("APPID", appId);
        url = url.replace("SECRET", secret);
        //发送获取接口凭证接口
        GetMethod oMethod = new GetMethod(url);
        String sResponsePost = "";//获取接口凭证的结果
        String accessToken = null;//获取接口凭证
        oHttpClient.executeMethod(oMethod);
        //获取访问结果
        sResponsePost = new String(oMethod.getResponseBody(), "UTF-8");
        JSONObject GetJsonResult = JSONObject.parseObject(sResponsePost);
        Map<String,String> mapResult = JSONObject.toJavaObject(GetJsonResult, Map.class);
        accessToken = mapResult.get("access_token");

        if(accessToken == null){
            g_logger.error("发送客服消息接口失败!");
        }
        return accessToken;
    }

获取接口凭证是需要传入三个参数:

  1. grant_type string必填项,固定传入client_credential
  2. appid string必填项,小程序唯一凭证,即 AppID,可在「微信公众平台 - 设置 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
  3. secret string必填项,小程序唯一凭证密钥,即 AppSecret,获取方式同 appid也在 开发设置 中获取
/**
     * @Description //TODO 发送微信请求
     **/
private JSONObject sendXIRequest(String openid, String title, String pagePath, String thumbUrl, String accessToken) {
        //发送请求接口
        Map<String, String> linkMap = getSignUpInfo(title,pagePath,thumbUrl);
        JSONObject wxPar = new JSONObject();
        wxPar.put("touser", openid);
        wxPar.put("msgtype", "link");
        wxPar.put("link", linkMap);
        String requestUrl="https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN";
        requestUrl=requestUrl.replace("ACCESS_TOKEN", accessToken);
        wxPar = WeixinUtil.httpRequest(requestUrl,"POST",wxPar.toString());
        return wxPar;
    }

发送图文消息时传入的参数:

  1. access_token必填项,接口调用凭证 就是上面获取的接口凭证 直接写在URL后面即可
  2. touser必填项,用户的 OpenID 调用接口时传入的参数
  3. msgtype必填项,我们这里发送的是图文消息 填写"link",link 是主要我们分享的图文消息时里面的图片,标题… 下面是拼接的link
public Map<String, String> getSignUpInfo(String title, String pagePath, String imgUrl){
        Map<String, String> map = new HashMap<String, String>();
        if (pagePath != null && pagePath.length() > 1){
            map.put("title", title);
            map.put("description", "打开页面,点击右上角【......】分享");
            Map<String, String> parser = UrlAnalysis.parser(pagePath);
            StringBuffer signUpUrl = new StringBuffer();
            signUpUrl.append(URL);
            map.put("url", signUpUrl.toString());
            map.put("thumb_url", imgUrl);
        }
        return map;
    }

link的拼接参数:

  1. title必填项,消息标题 调用接口时传入的参数
  2. description必填项,图文链接消息 可以自定义
  3. url必填项,图文链接消息被点击后跳转的链接
  4. thumb_url必填项,图文链接消息的图片链接,支持 JPG、PNG 格式,较好的效果为大图 640 X 320,小图 80 X 80

好了这样就可以了,各位大佬,有何不对请指教!