|
@@ -0,0 +1,417 @@
|
|
|
|
+package org.rcisoft.aspect.wx.pubnum.wx;
|
|
|
|
+
|
|
|
|
+import java.io.IOException;
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.HashMap;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.Map;
|
|
|
|
+
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
|
+import com.alibaba.fastjson.JSONArray;
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
+import lombok.Data;
|
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
+import org.apache.http.HttpEntity;
|
|
|
|
+import org.apache.http.HttpStatus;
|
|
|
|
+import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
|
+import org.apache.http.client.methods.HttpGet;
|
|
|
|
+import org.apache.http.client.methods.HttpPost;
|
|
|
|
+import org.apache.http.entity.StringEntity;
|
|
|
|
+import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
|
+import org.apache.http.impl.client.HttpClients;
|
|
|
|
+import org.apache.http.util.EntityUtils;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.beans.factory.annotation.Value;
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * 应用模块名称</p>
|
|
|
|
+ * 公众号接口</p>
|
|
|
|
+ * Copyright: Copyright (C) 2023 , Inc. All rights reserved. <p>
|
|
|
|
+ * Company: 成都诚唐科技有限责任公司</p>
|
|
|
|
+ *
|
|
|
|
+ * @author wany
|
|
|
|
+ * @since 2023 /10/25
|
|
|
|
+ */
|
|
|
|
+@Data
|
|
|
|
+@Component
|
|
|
|
+public class WxPublicApi{
|
|
|
|
+
|
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(WxPublicApi.class);
|
|
|
|
+
|
|
|
|
+ // appId
|
|
|
|
+ @Value("${wx.appId:}")
|
|
|
|
+ private String miniApp;
|
|
|
|
+
|
|
|
|
+ // appId
|
|
|
|
+ @Value("${wx.publicNumberAppId:}")
|
|
|
|
+ private String publicApp;
|
|
|
|
+
|
|
|
|
+ // secret
|
|
|
|
+ @Value("${wx.publicNumberSecret:}")
|
|
|
|
+ private String publicSecret;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取公众号token
|
|
|
|
+ */
|
|
|
|
+ private static final String TOKEN_URL =
|
|
|
|
+ "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 发送公众号消息
|
|
|
|
+ */
|
|
|
|
+ private static final String MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=%s";
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 批量获取公众号关注用户列表
|
|
|
|
+ */
|
|
|
|
+ private static final String USER_LIST = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s";
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+ private static final String USER_INFO =
|
|
|
|
+ "https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN";
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 批量获取公众号用户信息
|
|
|
|
+ */
|
|
|
|
+ public static final String BATCH_USER_INFO = "https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token=%s";
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取token
|
|
|
|
+ *
|
|
|
|
+ * @return string
|
|
|
|
+ */
|
|
|
|
+ public String getAccessToken(){
|
|
|
|
+ log.info("------获取公众号token 开始------");
|
|
|
|
+ String getTokenUrl = String.format(TOKEN_URL, publicApp, publicSecret);
|
|
|
|
+ CloseableHttpClient client = null;
|
|
|
|
+ CloseableHttpResponse response = null;
|
|
|
|
+ String token = "";
|
|
|
|
+ try{
|
|
|
|
+ // 创建http GET请求
|
|
|
|
+ HttpGet httpGet = new HttpGet(getTokenUrl);
|
|
|
|
+ client = HttpClients.createDefault();
|
|
|
|
+ // 执行请求
|
|
|
|
+ response = client.execute(httpGet);
|
|
|
|
+ if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
|
|
+ HttpEntity entity = response.getEntity();//得到返回数据
|
|
|
|
+ String result = EntityUtils.toString(entity);
|
|
|
|
+ log.info("请求结果:" + result);
|
|
|
|
+ JSONObject jsonObject = JSON.parseObject(result);
|
|
|
|
+ token = jsonObject.getString("access_token");
|
|
|
|
+ if(StringUtils.isEmpty(token)){
|
|
|
|
+ log.error("数据出错了!");
|
|
|
|
+ } else{
|
|
|
|
+ token = jsonObject.getString("access_token");
|
|
|
|
+ String expires_in = jsonObject.getString("expires_in");
|
|
|
|
+ }
|
|
|
|
+ } else{
|
|
|
|
+ log.error("请求失败:状态码:" + response.getStatusLine().getStatusCode());
|
|
|
|
+ }
|
|
|
|
+ } catch(Exception e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ } finally{
|
|
|
|
+ if(response != null){
|
|
|
|
+ try{
|
|
|
|
+ response.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(client != null){
|
|
|
|
+ try{
|
|
|
|
+ client.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ log.info("------获取公众号token 结束------");
|
|
|
|
+ return token;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 发送模板消息
|
|
|
|
+ *
|
|
|
|
+ * @param openId the open id
|
|
|
|
+ * @param templateId the template id
|
|
|
|
+ * @param path the path
|
|
|
|
+ * @param dataMap the data map
|
|
|
|
+ */
|
|
|
|
+ public void sendMsg(String openId, String templateId, String path, Map<String, Object> dataMap){
|
|
|
|
+ String accessToken = getAccessToken();
|
|
|
|
+ log.info("------发送公众号消息 开始------");
|
|
|
|
+ if(StringUtils.isEmpty(accessToken)){
|
|
|
|
+ log.error("发送公众号消息失败,token为空!");
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ String sendUrl = String.format(MSG_URL, accessToken);
|
|
|
|
+ CloseableHttpClient client = null;
|
|
|
|
+ CloseableHttpResponse response = null;
|
|
|
|
+ try{
|
|
|
|
+ // 创建http post请求
|
|
|
|
+ HttpPost httpPost = new HttpPost(sendUrl);
|
|
|
|
+ client = HttpClients.createDefault();
|
|
|
|
+ //构建请求参数
|
|
|
|
+ JSONObject map = new JSONObject();
|
|
|
|
+ map.put("touser", openId);
|
|
|
|
+ map.put("template_id", templateId);
|
|
|
|
+ Map<String, String> miniProgram = new HashMap<>();
|
|
|
|
+ miniProgram.put("appid", miniApp);
|
|
|
|
+ if(StringUtils.isNotEmpty(path)){
|
|
|
|
+ miniProgram.put("pagepath", path);
|
|
|
|
+ }
|
|
|
|
+ map.put("miniprogram", miniProgram);
|
|
|
|
+ map.put("data", dataMap);
|
|
|
|
+ log.info("请求参数:" + JSON.toJSONString(map));
|
|
|
|
+ StringEntity entity = new StringEntity(map.toString(), StandardCharsets.UTF_8);
|
|
|
|
+ entity.setContentEncoding("UTF-8");
|
|
|
|
+ entity.setContentType("application/json");
|
|
|
|
+ httpPost.setEntity(entity);
|
|
|
|
+ response = client.execute(httpPost);
|
|
|
|
+ if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
|
|
+ String result = EntityUtils.toString(response.getEntity());
|
|
|
|
+ log.info("请求结果:" + result);
|
|
|
|
+ JSONObject jsonObject = JSON.parseObject(result);
|
|
|
|
+ if("ok".equals(jsonObject.getString("errmsg"))){
|
|
|
|
+ log.info("公众号模板消息推送成功---------------------");
|
|
|
|
+ } else{
|
|
|
|
+ log.error("数据出错了!");
|
|
|
|
+ }
|
|
|
|
+ } else{
|
|
|
|
+ log.error("请求失败:状态码:" + response.getStatusLine().getStatusCode());
|
|
|
|
+ }
|
|
|
|
+ } catch(Exception e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ } finally{
|
|
|
|
+ if(response != null){
|
|
|
|
+ try{
|
|
|
|
+ response.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(client != null){
|
|
|
|
+ try{
|
|
|
|
+ client.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ log.info("------发送公众号消息 结束------");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 获取关注用户列表
|
|
|
|
+ *
|
|
|
|
+ * @param nextOpenId the next open id
|
|
|
|
+ * @return object [ ]
|
|
|
|
+ */
|
|
|
|
+ public Object[] getUsersOpenIdList(String nextOpenId){
|
|
|
|
+ String accessToken = getAccessToken();
|
|
|
|
+ Long total = null;
|
|
|
|
+ Long count = null;
|
|
|
|
+ List<String> list = new ArrayList<>();
|
|
|
|
+ if(StringUtils.isEmpty(accessToken)){
|
|
|
|
+ return new Object[]{total, count, list};
|
|
|
|
+ }
|
|
|
|
+ log.info("------批量获取公众号关注用户列表 开始------");
|
|
|
|
+ String url = String.format(USER_LIST, accessToken);
|
|
|
|
+ if(StringUtils.isNotEmpty(nextOpenId)){
|
|
|
|
+ url = url + "&next_openid=" + nextOpenId;
|
|
|
|
+ }
|
|
|
|
+ CloseableHttpClient client = null;
|
|
|
|
+ CloseableHttpResponse response = null;
|
|
|
|
+ try{
|
|
|
|
+ // 创建http GET请求
|
|
|
|
+ HttpGet httpGet = new HttpGet(url);
|
|
|
|
+ client = HttpClients.createDefault();
|
|
|
|
+ //执行请求
|
|
|
|
+ response = client.execute(httpGet);
|
|
|
|
+ if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
|
|
+ //得到返回数据
|
|
|
|
+ HttpEntity entity = response.getEntity();
|
|
|
|
+ String result = EntityUtils.toString(entity);
|
|
|
|
+ log.info("请求结果:" + result);
|
|
|
|
+ JSONObject json = JSON.parseObject(result);
|
|
|
|
+ if(StringUtils.isNotEmpty(json.getString("errmsg")) ||
|
|
|
|
+ StringUtils.isNotEmpty(json.getString("errcode"))){
|
|
|
|
+ //出错了
|
|
|
|
+ log.error("数据出错了!");
|
|
|
|
+ } else{
|
|
|
|
+ total = json.getLong("total");
|
|
|
|
+ count = json.getLong("count");
|
|
|
|
+ JSONObject data = json.getJSONObject("data");
|
|
|
|
+ if(data != null){
|
|
|
|
+ JSONArray openids = data.getJSONArray("openid");
|
|
|
|
+ if(CollectionUtils.isNotEmpty(openids)){
|
|
|
|
+ for(Object o : openids){
|
|
|
|
+ String openId = o.toString();
|
|
|
|
+ if(StringUtils.isNotEmpty(openId)){
|
|
|
|
+ list.add(openId);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else{
|
|
|
|
+ log.error("请求失败:状态码:" + response.getStatusLine().getStatusCode());
|
|
|
|
+ }
|
|
|
|
+ } catch(Exception e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ } finally{
|
|
|
|
+ if(response != null){
|
|
|
|
+ try{
|
|
|
|
+ response.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(client != null){
|
|
|
|
+ try{
|
|
|
|
+ client.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ log.info("------批量获取公众号关注用户列表 结束------");
|
|
|
|
+ return new Object[]{total, count, list};
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public WxPublicUserInfo getUserInfo(String publicOpenId){
|
|
|
|
+ WxPublicUserInfo r = null;
|
|
|
|
+ if(StringUtils.isEmpty(publicOpenId)){
|
|
|
|
+ return r;
|
|
|
|
+ }
|
|
|
|
+ String accessToken = getAccessToken();
|
|
|
|
+ if(StringUtils.isEmpty(accessToken)){
|
|
|
|
+ return r;
|
|
|
|
+ }
|
|
|
|
+ log.info("------获取公众号用户信息 开始------");
|
|
|
|
+ String sendUrl = String.format(USER_INFO, accessToken, publicOpenId);
|
|
|
|
+ CloseableHttpClient client = null;
|
|
|
|
+ CloseableHttpResponse response = null;
|
|
|
|
+ try{
|
|
|
|
+ // 创建http post请求
|
|
|
|
+ HttpGet httpGet = new HttpGet(sendUrl);
|
|
|
|
+ client = HttpClients.createDefault();
|
|
|
|
+ response = client.execute(httpGet);
|
|
|
|
+ if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
|
|
+ String result = EntityUtils.toString(response.getEntity());
|
|
|
|
+ log.info("请求结果:" + result);
|
|
|
|
+ JSONObject json = JSON.parseObject(result);
|
|
|
|
+ if(StringUtils.isNotEmpty(json.getString("errmsg")) ||
|
|
|
|
+ StringUtils.isNotEmpty(json.getString("errcode"))){
|
|
|
|
+ log.error("数据出错了!");
|
|
|
|
+ } else{
|
|
|
|
+ r = WxPublicUserInfo.build(json);
|
|
|
|
+ }
|
|
|
|
+ } else{
|
|
|
|
+ log.error("请求失败:状态码:" + response.getStatusLine().getStatusCode());
|
|
|
|
+ }
|
|
|
|
+ } catch(Exception e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ } finally{
|
|
|
|
+ if(response != null){
|
|
|
|
+ try{
|
|
|
|
+ response.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(client != null){
|
|
|
|
+ try{
|
|
|
|
+ client.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ log.info("------获取公众号用户信息 结束------");
|
|
|
|
+ return r;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public List<WxPublicUserInfo> getUserInfos(List<String> openIds){
|
|
|
|
+ List<WxPublicUserInfo> list = new ArrayList<>();
|
|
|
|
+ if(CollectionUtils.isEmpty(openIds)){
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+ String accessToken = getAccessToken();
|
|
|
|
+ if(StringUtils.isEmpty(accessToken)){
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+ log.info("------批量获取公众号用户信息 开始------");
|
|
|
|
+ String sendUrl = String.format(BATCH_USER_INFO, accessToken);
|
|
|
|
+ CloseableHttpClient client = null;
|
|
|
|
+ CloseableHttpResponse response = null;
|
|
|
|
+ try{
|
|
|
|
+ // 创建http post请求
|
|
|
|
+ HttpPost httpPost = new HttpPost(sendUrl);
|
|
|
|
+ client = HttpClients.createDefault();
|
|
|
|
+ //构建请求参数
|
|
|
|
+ JSONObject map = new JSONObject();
|
|
|
|
+ map.put("user_list", new JSONArray());
|
|
|
|
+ for(int i = 0; i < openIds.size() && i < 100; i++){
|
|
|
|
+ JSONObject user = new JSONObject();
|
|
|
|
+ user.put("openid", openIds.get(i));
|
|
|
|
+ //user.put("lang", "zh_CN");
|
|
|
|
+ map.getJSONArray("user_list").add(user);
|
|
|
|
+ }
|
|
|
|
+ log.info("请求参数:" + JSON.toJSONString(map));
|
|
|
|
+ StringEntity entity = new StringEntity(map.toString(), StandardCharsets.UTF_8);
|
|
|
|
+ entity.setContentEncoding("UTF-8");
|
|
|
|
+ entity.setContentType("application/json");
|
|
|
|
+ httpPost.setEntity(entity);
|
|
|
|
+ response = client.execute(httpPost);
|
|
|
|
+ if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){
|
|
|
|
+ String result = EntityUtils.toString(response.getEntity());
|
|
|
|
+ log.info("请求结果:" + result);
|
|
|
|
+ JSONObject json = JSON.parseObject(result);
|
|
|
|
+ if(StringUtils.isNotEmpty(json.getString("errmsg")) ||
|
|
|
|
+ StringUtils.isNotEmpty(json.getString("errcode"))){
|
|
|
|
+ log.error("数据出错了!");
|
|
|
|
+ } else{
|
|
|
|
+ JSONArray array = json.getJSONArray("user_info_list");
|
|
|
|
+ if(CollectionUtils.isNotEmpty(array)){
|
|
|
|
+ for(Object o : array){
|
|
|
|
+ WxPublicUserInfo user = WxPublicUserInfo.build((JSONObject) o);
|
|
|
|
+ if(user != null){
|
|
|
|
+ list.add(user);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ } else{
|
|
|
|
+ log.error("请求失败:状态码:" + response.getStatusLine().getStatusCode());
|
|
|
|
+ }
|
|
|
|
+ } catch(Exception e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ } finally{
|
|
|
|
+ if(response != null){
|
|
|
|
+ try{
|
|
|
|
+ response.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if(client != null){
|
|
|
|
+ try{
|
|
|
|
+ client.close();
|
|
|
|
+ } catch(IOException e){
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ log.info("------批量获取公众号用户信息 结束------");
|
|
|
|
+ return list;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|