微信公众号推送小程序模板消息的实现

微信公众号推送小程序模板消息的实现

准备:
微信小程序认证
微信公众号认证
微信开发平台认证(绑定微信小程序和公众号(unionid))
unionid:同一用户,对同一个微信开放平台下的不同应用,unionid是相同的
思路:
1. 获取小程序信息(用户openid小程序用户唯一ID)
将小程序与公众号绑定(绑定后才可获取unionid)

    /**
     * 小程序用户登录授权
     */
    @GetMapping("/getUserOpenId")
    public AjaxResult getUserOpenId(String code){
        if (StringUtils.isEmpty(code)){
            return AjaxResult.error("请输入code");
        }
        Map<String, Object> result = new LinkedHashMap();
        String oAuth = WxAppletUserInfo.getOAuth(code, userAppId, userSecret);
        JSONObject jsonObject = JSONObject.fromObject(oAuth);
        //获取openId和sessionKey
        String openid = jsonObject.get("openid").toString();
        String session_key = jsonObject.get("session_key").toString();
        String unionid= jsonObject.get("unionid").toString();
		......
    }

2.获取公众号的openid(公众号用户唯一ID)


--公众号回调
https://open.weixin.qq.com/connect/oauth2/authorize?appid=&redirect_uri=https%3A%2F%2Fty.breezedi.com%2Fadmin%2Fapi%2Fwx%2FscanQRCode&response_type=code&scope=snsapi_userinfo&state=0078d70e-68c#wechat_redirect



     /**
     * 微信授权回调
     * @param request
     * @param resp
     * @throws IOException
     */
    @RequestMapping(value = "/scanQRCode", method = {RequestMethod.GET,RequestMethod.POST})
    public void scanQRCode(HttpServletRequest request,HttpServletResponse resp) throws IOException {
        String code = request.getParameter("code");
        if (null == code || code.trim().equals("")){
            log.info("***********code为空************");
        }
        String state = request.getParameter("state");
        if (null != state || !code.trim().equals("")){
            log.info("state参数:{}",state);
        }
        //根据code获取token
        String accessTokenCode = WxAppletUserInfo.getAccessTokenCode(code);
        //获取openid
        JSONObject jsonObject = JSONObject.fromObject(accessTokenCode);
        log.info("微信回调后获取公众号参数:{}",jsonObject);
        //获取openid和session_key
        String openid = jsonObject.get("openid").toString();
        String accessToken = jsonObject.get("access_token").toString();
        //获取用户信息网页授权
        String wxUserInfo = WxAppletUserInfo.getWxUserInfo(accessToken,openid);
        log.info("用户信息{}",wxUserInfo);
        JSONObject fromObject = JSONObject.fromObject(wxUserInfo);
        String nickName = fromObject.getString("nickname");
        String sex = fromObject.getString("sex");
        String province = fromObject.getString("province");
        String city = fromObject.getString("city");
        String country = fromObject.getString("country");
        String headImgUrl = fromObject.getString("headimgurl");
        String privilege = fromObject.getString("privilege");
        String unionId = fromObject.getString("unionid");
        TyWxPatform patform = new TyWxPatform();
        //授权判断用户是否关注公众号
        //获取用户信息所需要的token
        String token = WxAppletUserInfo.getAccessToken();
        String infoSub = WxAppletUserInfo.getWxUserInfoSub(token, openid);
        JSONObject json = JSONObject.fromObject(infoSub);
        String  subscribe = json.getString("subscribe");
       //业务方法........
    }

获取小程序公众号信息

package com.ty.common.wx;

import com.ty.common.utils.http.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.AlgorithmParameters;
import java.security.Key;
import java.security.Security;

@Slf4j
public class WxAppletUserInfo {

    //获取小程序登录信息
    private final static String GET_CODE_SESSION_URL="https://api.weixin.qq.com/sns/jscode2session";

    // 算法名
    private static final String KEY_NAME = "AES";

    // ECB模式只用密钥即可对数据进行加密解密,CBC模式需要添加一个iv 加解密算法/模式/填充方式
    private static final String CIPHER_ALGORITHM = "AES/CBC/PKCS7Padding";

    //公众号AppID
    private static final String appId = "";

    //公众号秘钥
    private static final String appSecret = "";

    //通过code换取网页授权access_token
    private static final String wxAuthLoginUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";

    //公众号网页登陆url
    private static final String urlToken = "https://api.weixin.qq.com/cgi-bin/token";

    //获取微信公众号信息--是否关注
    private static final String userInfoSub = "https://api.weixin.qq.com/cgi-bin/user/info";

    //获取微信公众号信息--网页授权 拉取用户信息
    private static final String userInfo = "https://api.weixin.qq.com/sns/userinfo";

    /**
     * 获取小程序用户登陆信息
     * @param code
     * @param appId
     * @param secret
     * @return
     */
    public static String getOAuth(String code,String appId,String secret) {
        StringBuffer url = new StringBuffer(GET_CODE_SESSION_URL);
        url.append("?appid="+appId).append("&secret="+secret)
                .append("&js_code="+code)
                .append("&grant_type=authorization_code");
        return HttpUtils.sendGet(url.toString());
    }

    /**
     * 微信 数据解密<br/>
     * 对称解密使用的算法为 AES-128-CBC,数据采用PKCS#7填充<br/>
     * 对称解密的目标密文:encrypted=Base64_Decode(encryptData)<br/>
     * 对称解密秘钥:key = Base64_Decode(session_key),aeskey是16字节<br/>
     * 对称解密算法初始向量:iv = Base64_Decode(iv),同样是16字节<br/>
     *
     * @param encryptedData 目标密文
     * @param session_key 会话ID
     * @param iv 加密算法的初始向量
     */
    public static JSONObject wxDecrypt(String encryptedData, String session_key, String iv) {
        log.info("手机号解密所需要的数据:\n{},\n{},\n{}\n",encryptedData,session_key,iv);
        String json = null;
        byte[] encrypted64 = Base64.decodeBase64(encryptedData);
        byte[] key64 = Base64.decodeBase64(session_key);
        byte[] iv64 = Base64.decodeBase64(iv);
        byte[] data;
        try {
            init();
            json = new String(decrypt(encrypted64, key64, generateIV(iv64)));
        } catch (Exception e) {
            log.error("*********解密微信手机号失败:**********" + e.getMessage());
        }
        return JSONObject.fromObject(json);
    }

    /**
     * 初始化密钥
     */
    public static void init() throws Exception {
        Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
        KeyGenerator.getInstance(KEY_NAME).init(128);
    }

    /**
     * 生成iv
     */
    public static AlgorithmParameters generateIV(byte[] iv) throws Exception {
        // iv 为一个 16 字节的数组,这里采用和 iOS 端一样的构造方法,数据全为0
        // Arrays.fill(iv, (byte) 0x00);
        AlgorithmParameters params = AlgorithmParameters.getInstance(KEY_NAME);
        params.init(new IvParameterSpec(iv));
        return params;
    }

    /**
     * 生成解密
     */
    public static byte[] decrypt(byte[] encryptedData, byte[] keyBytes, AlgorithmParameters iv)throws Exception {
        Key key = new SecretKeySpec(keyBytes, KEY_NAME);
        Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
        // 设置为解密模式
        cipher.init(Cipher.DECRYPT_MODE, key, iv);
        return cipher.doFinal(encryptedData);
    }

    /**
     * 获取模板消息所需要的access_token(获取微信公众号的access_token(7200秒有效))
     * @param
     * @return
     */
    public static String getAccessToken() {
        StringBuffer url = new StringBuffer(urlToken);
        url.append("?appid="+appId)
                .append("&secret="+appSecret)
                .append("&grant_type=client_credential");
        String token = HttpUtils.sendGet(url.toString());
        log.info("获取模板消息所的认证参数access_token:{}",token);
        JSONObject Json = JSONObject.fromObject(token);
        String access_token = String.valueOf(Json.get("access_token").toString());
        return access_token;
    }

    /**
     * 公众号
     * 根据code获取到网页授权access_token
     * @param code
     * @return  微信回调后带有的参数code值
     */
    public static String getAccessTokenCode(String code) {
        StringBuffer url = new StringBuffer(wxAuthLoginUrl);
        url.append("?appid="+appId)
                .append("&secret="+appSecret)
                .append("&code="+code)
                .append("&grant_type=authorization_code");
        log.info("根据code获取到网页授权access_token:{}",url.toString());
        return HttpUtils.sendGet(url.toString());
    }

    /**
     * 公众号
     * 获取微信用户 (判断有无关注)获取用户信息
     * @param accessToken
     * @param openId
     * @return
     */
    public static String getWxUserInfoSub(String accessToken,String openId) {
        StringBuffer url = new StringBuffer(userInfoSub);
        url.append("?access_token="+accessToken)
                .append("&openid="+openId)
                .append("&lang=zh_CN");
        log.info("获取微信用户信息(是否关注公众号):{}",url.toString());
        return HttpUtils.sendGet(url.toString());
    }

    /**
     * 公众号
     * 获取微信用户--网页授权获取用户信息
     * @param accessToken
     * @param openId
     * @return
     */
    public static String getWxUserInfo(String accessToken,String openId) {
        StringBuffer url = new StringBuffer(userInfo);
        url.append("?access_token="+accessToken)
                .append("&openid="+openId)
                .append("&lang=zh_CN");
        String urlUserInfo = url.toString();
        log.info("获取微信用户信息url:{}",urlUserInfo);
        return HttpUtils.sendGet(urlUserInfo);
    }

}

HTTPUtils

 /**
     *
     * @Title: get
     * @Description: TODO(get请求)
     * @param @param url
     * @param @return    设定文件
     * @return String    返回类型
     * @throws
     */
    public static String sendGet(String url) {
        String result = "";
        // 设置请求配置
        RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.STANDARD)
                .setConnectionRequestTimeout(10000).setConnectTimeout(10000).setSocketTimeout(50000). build();
        // 打开浏览器
        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(globalConfig).build();
        HttpGet httpGet = new HttpGet(url);
        RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();
        httpGet.setConfig(requestConfig);
        httpGet.addHeader("Content-type", "application/json;charset=utf-8");
        httpGet.setHeader("Accept", "application/json");
        // 设置头
        httpGet.addHeader("User-Agent",
                "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.152 Safari/537.36");
        httpGet.addHeader("Cookie", "_gat=1; nsfw-click-load=off; gif-click-load=on; _ga=GA1.2.1861846600.1423061484");
        // 收到回复
        CloseableHttpResponse response;
        try {
            response = httpClient.execute(httpGet);
            log.info("HTTPGet请求状态,status:{}" , response.getStatusLine().getStatusCode());
            result = EntityUtils.toString(response.getEntity(), "utf-8");
            EntityUtils.consume(response.getEntity());
            response.close();
            httpGet.releaseConnection();
            httpClient.close();
        } catch (ClientProtocolException e) {
            log.info("发送GET请求出现异常!" + e);
            e.printStackTrace();
        } catch (IOException e) {
            log.info("发送GET请求出现异常!" + e);
            e.printStackTrace();
        }
        return result;
    }

3.推送消息服务
公众号模板申请:一个月只能有三次,审核7-15个工作日

//1.获取access_token
https请求方式: GET 
urlToken = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET'
  
String TemplateId = "";  

//2.模板消息类
//openid 是用户公众号的openid
  public static JSONObject packJsonDoctorMsg(String openid,String AppId,String pagePath){
        //医生发送公众号模板消息
        WechatTemplate wechatTemplate = new WechatTemplate();
        wechatTemplate.setTouser(openid);
        wechatTemplate.setTemplate_id(TemplateId);
        MiniprogramData miniprogramData = new MiniprogramData();
        miniprogramData.setAppid(AppId);
        miniprogramData.setPagepath(pagePath);//所需跳转到小程序的具体页面路径,支持带参数,(示例index?foo=bar),要求该小程序已发布,暂不支持小游戏
        wechatTemplate.setMiniprogram(miniprogramData);
        Map<String,TemplateData> dataMap = new HashMap<>();
        TemplateData title = new TemplateData();
        title.setValue("所发送消息内容");
        title.setColor("#000000");
        dataMap.put("title",title);
        TemplateData first = new TemplateData();
        first.setValue("所发送消息内容";
        first.setColor("#000000");
        dataMap.put("first",first);
        TemplateData keyword = new TemplateData();
        keyword.setValue("所发送消息内容");
        keyword.setColor("#000000");
        dataMap.put("keyword",keyword);
        TemplateData keyword = new TemplateData();
        keyword.setValue("所发送消息内容");
        keyword.setColor("#000000");
        dataMap.put("keyword", keyword);
        TemplateData keyword = new TemplateData();
        keyword.setValue("所发送消息内容");
        keyword.setColor("#000000");
        dataMap.put("keyword", keyword);
        TemplateData keyword = new TemplateData();
        keyword.setValue("所发送消息内容");
        keyword.setColor("#000000");
        dataMap.put("keyword", keyword);
        TemplateData remark = new TemplateData();
        remark.setValue("所发送消息内容");
        remark.setColor("#000000");
        dataMap.put("remark", remark);
        wechatTemplate.setData(dataMap);
        JSONObject json = JSONObject.fromObject(wechatTemplate);
        return json;
    }

//3.用户发送模板消息
JSONObject userMsgDate = MessageModel.packJsonUserMsg(openid, AppId, userPagePath);

JSONObject jsonobjUser = HttpUtils.httpRequest(send+WxAppUserInfo.getAccessToken(urlToken,appId,appSecret),"POST",userMsgDate.toString());
               

over~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值