微信公众号发布信息

一、开发准备

1、公众号的AppID,AppSecret

AppID:

​ 开发者ID是公众号开发识别码,配合开发者密码可调用公众号的接口能力。

AppSecret:

​ 开发者密码是校验公众号开发者身份的密码,具有极高的安全性。切记勿把密码直接交给第三方开发者或直接存储在代码中。如需第三方代开发公众号,请使用授权方式接入

2、在公众号设置中选择功能设置,下载TXT文件放到web服务器的目录下,将域名填写至白名单等
3、获取access_token
public String getSubStableAccessToken() {
        //token有效期为7200s,需要保存起来,先从redis中获取accessToken,没有则请求获取
        String accessToken = stringRedisTemplate.opsForValue().get(WxConstant.SHARE_FLY_SUB_STABLE_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            Map<String, String> params = new HashMap<String, String>();
            params.put("grant_type", "client_credential");
            params.put("appid", userSystemConstant.getWxSubAppId());
            params.put("secret", userSystemConstant.getWxSubSecret());
            String res = null;
            try {
                res = HttpsRequestUtil.httpsRequest("https://api.weixin.qq.com/cgi-bin/stable_token", "POST", null, JSONObject.toJSONString(params));
            } catch (Exception e) {
                e.printStackTrace();
            }
            JSONObject tokenResult = JSONObject.parseObject(res);
            if (res.indexOf("access_token") == -1) {
                log.info("获取公众号access_token有误:{}", tokenResult);
                return null;
            }
            accessToken = tokenResult.getString("access_token");
            long expiresIn = tokenResult.getLong("expires_in");
            //保存进redis
            stringRedisTemplate.opsForValue().set(WxConstant.SHARE_FLY_SUB_STABLE_ACCESS_TOKEN, accessToken, expiresIn, TimeUnit.SECONDS);
            return accessToken;
        }
        return accessToken;
    }
4、OpenID 与 UnionID

OpenID(全局不唯一) :

​ 在关注者与公众号产生消息交互后,公众号可获得关注者的OpenID(加密后的微信号,每个用户对每个公众号的OpenID是唯一的。对于不同公众号,同一用户的OpenID不同)

UnionID(全局唯一) :

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

可以根据UnionID找到对应的微信公众号的UnionID

(1)同步微信公众号用户

实体类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserSubInfoDO implements Serializable {
    private static final long serialVersionUID = 8534660282946889549L;
    private Integer id;
    private String openId;
    private String unionId;
    private String nickName;
    private Integer regStatus;
    private Integer deleted;
    private Date createTime;
    private Date updateTime;

    public UserSubInfoDTO buildUserSbuInfoDTO() {
        return UserSubInfoDTO.builder().openId(openId).unionId(unionId).subscribe(this.deleted == 0 ? 1 : 0).build();
    }
}

service层

@Override
    public ResultBody moveSubUserToTest() {
        String accessToken = this.getSubStableAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + accessToken;
        String jsonStr = HttpsRequestUtil.httpsGet(url, null);
        log.info("all users:{}", jsonStr);
        JSONObject obj = JSONObject.parseObject(jsonStr);
        List<String> lists = JSONArray.parseArray(obj.getJSONObject("data").get("openid").toString(), String.class);
        int count = 0;
        for (String openid : lists) {
            Integer integer = userSubInfoDao.countUserSubInfo(openid);
            if (integer == 0) {
                count++;
                UserSubInfoDO sub = new UserSubInfoDO();
                sub.setOpenId(openid);
                sub.setRegStatus(1);
                sub.setDeleted(0);
                sub.setCreateTime(new Date());
                userSubInfoDao.insertUserSubInfo(sub);
            }
        }
        log.info("User count: {}", count);
        return ResultBody.success();
    }

dao层

<select id="countUserSubInfo" resultType="Integer" parameterType="String">
		select count(*)
		from user_sub_info u
		where u.open_id = #{openId} and is_deleted = 0
	</select>

    <insert id="insertUserSubInfo" useGeneratedKeys="true"
            keyProperty="id" parameterType="com.mmc.iuav.user.entity.UserSubInfoDO">
		insert into user_sub_info
		(
		open_id,union_id,nick_name,reg_status,is_deleted,create_time,update_time
		)
		values
		(
		#{openId},#{unionId},#{nickName},#{regStatus},#{deleted},#{createTime},#{updateTime}
		)
	</insert>

(2)同步微信公众号用户unionId

service层

@Override
    public ResultBody moveSubUserUnionIdToTest() {
        String accessToken = this.getSubStableAccessToken();
        String url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=" + accessToken + "&next_openid=" + "oB6kk6obNektxM62mjj9PJHPtcME";
        String jsonStr = HttpsRequestUtil.httpsGet(url, null);
        log.info("all users:{}", jsonStr);
        JSONObject obj = JSONObject.parseObject(jsonStr);
        List<String> lists = JSONArray.parseArray(obj.getJSONObject("data").get("openid").toString(), String.class);
        int count = 0;
        for (String openid : lists) {
            UserSubInfoDO userSubInfo = userSubInfoDao.getUserSubInfo(openid);
            if (userSubInfo != null) {
                String InfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken + "&openid=" + openid
                        + "&lang=zh_CN";
                String jsonStr1 = HttpsRequestUtil.httpsGet(InfoUrl, null);
                JSONObject obj1 = JSONObject.parseObject(jsonStr1);
                userSubInfo.setUnionId(obj1.getString("unionid"));
                userSubInfo.setRegStatus(1);
                userSubInfoDao.updateUserSubInfo(userSubInfo);
            }
        }
        log.info("User count: {}", count);
        return ResultBody.success();
    }

dao层

<select id="getUserSubInfo" resultMap="userSubInfoResultMap" parameterType="String">
		select u.id,u.open_id,u.union_id,u.nick_name,u.reg_status,
		u.is_deleted,u.create_time,u.update_time
		from user_sub_info u
		where u.open_id = #{openId}
	</select>

<update id="updateUserSubInfo"
            parameterType="com.mmc.iuav.user.entity.UserSubInfoDO">
        update user_sub_info
        <set>
            <if test="unionId != null and unionId != '' ">
                union_id = #{unionId},
            </if>
            <if test="nickName != null">
                nick_name = #{nickName},
            </if>
            <if test="regStatus != null">
                reg_status = #{regStatus},
            </if>
        </set>
        where open_id = #{openId}
    </update>

以上可以通过unionId获取对应的微信公众号中的用户的openId

二、准备关键数据

1、获取touser

touser就是上述获取到的微信公众号中的用户的openId

2、获取模版id(templateId)

(1)、申请模版消息

进入公众号,找到功能-模板消息-我的末班-从模板库中添加,进行新增模板库(需要审核)

得到模版ID

3、获取data数据
public JSONObject spellMsg(String name, String result){
        JSONObject data=new JSONObject();

        //申请项目{{thing3.DATA}}
        JSONObject thing3=new JSONObject();
        thing3.put("value",name);
        data.put("thing3",keyword1);

        //审核时间{{time6.DATA}}
        JSONObject time6=new JSONObject();
        time6.put("value",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        data.put("time6",keyword4);

        //审核结果{{thing5.DATA}}
        JSONObject thing5=new JSONObject();
        thing5.put("value",payAccount);
        data.put("thing5",result);

        return data;
    }

三、相关接口准备

1、实体类
@Builder
@Data
@NoArgsConstructor
@AllArgsConstructor
public class WxMsgVO implements Serializable {
    private static final long serialVersionUID = 107288179600606045L;
    @ApiModelProperty(value = "用户id")
    private Integer userAccountId;
    @ApiModelProperty(value = "公众号的openId")
    private String touser;
    @ApiModelProperty(value = "unionId-全局通用")
    private String unionId;
    @ApiModelProperty(value = "模板id")
    @NotNull(message = "模板id不能为空")
    private String templateId;
    @ApiModelProperty(value = "网页跳转连接")
    private String url;
    @ApiModelProperty(value = "小程序APPID")
    private String wxAppletAppId;
    @ApiModelProperty(value = "小程序跳转连接")
    private String appletPath;
    @ApiModelProperty(value = "标题")
    private MsgData title;
    @ApiModelProperty(value = "消息备注")
    private MsgData remark;
    @ApiModelProperty(value = "按照接口文档传数据")
    private JSONObject dataObject;

    public String buildTemplateMsg() {
        JSONObject msg = new JSONObject();
        msg.put("touser", this.touser);
        msg.put("template_id", this.templateId);
        // 跳转页面
        if (!StringUtils.isBlank(this.url)) {
            msg.put("url", this.url);
        }
        // 跳转小程序页面设置
        if (!StringUtils.isBlank(this.wxAppletAppId) && !StringUtils.isBlank(this.appletPath)) {
            JSONObject mini = new JSONObject();
            mini.put("appid", this.wxAppletAppId);
            mini.put("pagepath", this.appletPath);
            msg.put("miniprogram", mini);
        }
        msg.put("data", this.dataObject);
        return msg.toString();
    }
}
2、service层

获取accessToken

 @Override
    public String getSubStableAccessToken() {
        //token有效期为7200s,需要保存起来,先从redis中获取accessToken,没有则请求获取
        String accessToken = stringRedisTemplate.opsForValue().get(WxConstant.SHARE_FLY_SUB_STABLE_ACCESS_TOKEN);
        if (StringUtils.isBlank(accessToken)) {
            Map<String, String> params = new HashMap<String, String>();
            params.put("grant_type", "client_credential");
            params.put("appid", userSystemConstant.getWxSubAppId());
            params.put("secret", userSystemConstant.getWxSubSecret());
            String res = null;
            try {
                res = HttpsRequestUtil.httpsRequest("https://api.weixin.qq.com/cgi-bin/stable_token", "POST", null, JSONObject.toJSONString(params));
            } catch (Exception e) {
                e.printStackTrace();
            }
            JSONObject tokenResult = JSONObject.parseObject(res);
            if (res.indexOf("access_token") == -1) {
                log.info("获取公众号access_token有误:{}", tokenResult);
                return null;
            }
            accessToken = tokenResult.getString("access_token");
            long expiresIn = tokenResult.getLong("expires_in");
            //保存进redis
            stringRedisTemplate.opsForValue().set(WxConstant.SHARE_FLY_SUB_STABLE_ACCESS_TOKEN, accessToken, expiresIn, TimeUnit.SECONDS);
            return accessToken;
        }
        return accessToken;
    }
@Override
    public ResultBody sendSubTemplateMsg(WxMsgVO ws) {
        String accessToken = null;
        try {
            accessToken = this.getSubStableAccessToken();
            String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
            String param = ws.buildTemplateMsg();
            String result = HttpHelper.httpPost(url, param);
            log.info("模板消息发送结果:{}", result);
        } catch (Exception e) {
            log.error("accessToken获取失败:{}", e.getMessage());
            return ResultBody.error(ResultEnum.WX_ACCESS_TOKEN_ERROR.getResultCode(),
                    ResultEnum.WX_ACCESS_TOKEN_ERROR.getResultMsg() + e.getMessage());
        }
        return ResultBody.success();
    }
3、Http请求
public class HttpHelper {

	// get 请求
	public static String httpGet(String url, Header[] headers) throws Exception {
		HttpUriRequest uriRequest = new HttpGet(url);
		if (null != headers) {
			uriRequest.setHeaders(headers);
		}
		CloseableHttpClient httpClient = null;
		try {
			httpClient = declareHttpClientSSL(url);
			CloseableHttpResponse httpresponse = httpClient.execute(uriRequest);
			HttpEntity httpEntity = httpresponse.getEntity();
			String result = EntityUtils.toString(httpEntity, REQ_ENCODEING_UTF8);
			return result;
		} catch (ClientProtocolException e) {
			out.println(String.format("http请求失败,uri{%s},exception{%s}", new Object[] { url, e }));
		} catch (IOException e) {
			out.println(String.format("IO Exception,uri{%s},exception{%s}", new Object[] { url, e }));
		} finally {
			if (null != httpClient) {
				httpClient.close();
			}
		}
		return null;
	}

	// post 请求
	public static String httpPost(String url, String params) throws Exception {
		HttpPost post = new HttpPost(url);
		post.addHeader("Content-Type", "application/json;charset=" + REQ_ENCODEING_UTF8);
		// 设置传输编码格式
		StringEntity stringEntity = new StringEntity(params, REQ_ENCODEING_UTF8);
		stringEntity.setContentEncoding(REQ_ENCODEING_UTF8);
		post.setEntity(stringEntity);
		HttpResponse httpresponse = null;
		CloseableHttpClient httpClient = null;
		try {
			httpClient = declareHttpClientSSL(url);
			httpresponse = httpClient.execute(post);
			HttpEntity httpEntity = httpresponse.getEntity();
			String result = EntityUtils.toString(httpEntity, REQ_ENCODEING_UTF8);
			return result;
		} catch (ClientProtocolException e) {
			out.println(String.format("http请求失败,uri{%s},exception{%s}", new Object[] { url, e }));
		} catch (IOException e) {
			out.println(String.format("IO Exception,uri{%s},exception{%s}", new Object[] { url, e }));
		} finally {
			if (null != httpClient) {
				httpClient.close();
			}
		}
		return null;
	}

	private static CloseableHttpClient declareHttpClientSSL(String url) {
		if (url.startsWith("https://")) {
			return sslClient();
		} else {
			return HttpClientBuilder.create().setConnectionManager(httpClientConnectionManager).build();
		}
	}

	/**
	 * 设置SSL请求处理
	 *
	 */
	private static CloseableHttpClient sslClient() {
		try {
			SSLContext ctx = SSLContext.getInstance("TLS");
			X509TrustManager tm = new X509TrustManager() {
				@Override
				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}

				@Override
				public void checkClientTrusted(X509Certificate[] xcs, String str) {
				}

				@Override
				public void checkServerTrusted(X509Certificate[] xcs, String str) {
				}
			};
			ctx.init(null, new TrustManager[] { tm }, null);
			SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory();
			return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory).build();
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		} catch (KeyManagementException e) {
			throw new RuntimeException(e);
		}
	}

	private static final String REQ_ENCODEING_UTF8 = "utf-8";
	private static PoolingHttpClientConnectionManager httpClientConnectionManager;

	public HttpHelper() {
		httpClientConnectionManager = new PoolingHttpClientConnectionManager();
		httpClientConnectionManager.setMaxTotal(100);
		httpClientConnectionManager.setDefaultMaxPerRoute(20);
	}

	// get 请求
	public static String httpGet(String url) throws Exception {
		return httpGet(url, null);
	}

四、接口应用

        WxMsgVO ws = new WxMsgVO();
        String unionId = userServiceDao.getUserAccountById(applyInfo.getUserAccountId()).getUnionId();
        // 查询对应的openId(touser)
        String touser = userSubInfoDao.getUserSubInfoByUnionId(unionId).getOpenId();
        JSONObject jsonObject = spellMsg(applyInfo.getName());
        ws.setTouser(touser);
        ws.setTemplateId("y6PHvZownxqR5hf4dSXaa2Lp1jeq3ccytd6G-kUQla4");
        ws.setDataObject(jsonObject);
        wxService.sendSubTemplateMsg(ws);
public JSONObject spellMsg(String name, String result){
        JSONObject data=new JSONObject();

        //申请项目{{thing3.DATA}}
        JSONObject thing3=new JSONObject();
        thing3.put("value",name);
        data.put("thing3",keyword1);

        //审核时间{{time6.DATA}}
        JSONObject time6=new JSONObject();
        time6.put("value",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
        data.put("time6",keyword4);

        //审核结果{{thing5.DATA}}
        JSONObject thing5=new JSONObject();
        thing5.put("value",payAccount);
        data.put("thing5",result);

        return data;
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值