微信小程序与公众号打通,实现数据互通

公司因小程序项目先上线,公众号后开发,接到上级的安排实现小程序打通任务,看文档后发现:同一开发者账号只要是在微信开放平台绑定小程序与公众号以后,会有一个唯一的unionid,这个unionid腾讯公司下产品共享。这个unionid就是我们进行打通的关键。

先说一下思路:

1.微信小程序与公众号进行绑定后,在小程序调用wx.login()方法后会自动获取unionid,公众号根据官方文档在获取用户基本信息后会拿到相同的unionid,openid,nickname。。。等相关信息;

2.将小程序拿到的unionid进行数据库的更新操作,公众号拿到的unionid等信息,新建数据库表A进行存储;(注:在这一步,因为我们公司的原因,我们的公众号之前就有人关注了,那么在这之前,我通过公众号获取关注用户列表获取openid的列表,进行循环openid列表,在调用公众号获取用户基本信息列表进行储存数据库表A,循环结束后之前关注的人的信息就储存在数据库A,然后在进行,这一步的操作)

3.通过公众号关注/取关的事件相应,来进行数据库表A的增删操作,维护数据的新鲜度;

4.进行关联查询,到这一步我们会发现,通过unionid进行表的关联后我们已经实现数据的互通了

 

洋洋洒洒的说了一大堆,其实就是公众号的两个接口至关重要(1.关注/取关的事件相应接口     2.获取用户的基本信息接口)

有关于公众号的安全域名配置,服务器域名配置以及获取token就不在这里说了,百度一下一大堆。

代码实现:

第一步,获取公众号用户的openid列表操作,根据opneid进进行用户的基本信息的查询,存入数据库操作(因为我们公司的公众号关注人数只有1000+,所以我只调用了一次获取关注列表的接口)

//主要代码逻辑
//获取token	
AccessToken accessToken=wxUtils.getAccessToken();
	String url="https://api.weixin.qq.com/cgi-bin/user/get?access_token="+accessToken.getAccessToken()+"&next_openid=";//获取所有用户openid
JSONObject jsonObject = httpRequest(url, "GET", null);  
	try {
		if(jsonObject.getString("errcode")!=null){
		}
	}catch(Exception e) {
	}
	WeixinUserList userList = (WeixinUserList)JSONObject.toBean(jsonObject, WeixinUserList.class);
	if(null==userList) {
			return "无用户";
	}
	userList.getTotal();//关注总人数
	//用户openId 列表
	WxOpenidInfo wxOpenidInfo=userList.getData();
	List<String> openIdList=null;
	if(null!=wxOpenidInfo) {
		openIdList=wxOpenidInfo.getOpenid();//公众号返回的openid列表数据	
		if(null!=openIdList && openIdList.size()>0) {
		for(String opendid:openIdList) {
            //获取用户的基本信息(unionid机制)
			 url="https://api.weixin.qq.com/cgi-bin/user/info?       access_token="+accessToken.getAccessToken()+"&openid="+opendid+"&lang=zh_CN";//通过openid获取用户信息
			 jsonObject = httpRequest(url, "GET", null); 
			WeixinUser wxUser=(WeixinUser)JSONObject.toBean(jsonObject, WeixinUser.class);
            //进行数据库表A的储存操作	
			int row = gzhService.addGZHUser(wxUser);
			}
		}
}
			
			
			
			
/**
 * 用户列表  
 * @author 一叶知秋plus
 *
 */
public class WeixinUserList{
	

		 
	    private Integer total;//关注该公众账号的总用户数
	 
	    private Integer count;//拉取的OPENID个数,最大值为10000
	 
	    private WxOpenidInfo data;//列表数据,OPENID的列表
	 
	    private String next_openid;//拉取列表的最后一个用户的OPENID
	 
	    private int errcode;//错误编码
	 
	    private String errmsg="ok";//错误提示
	 
	    public Integer getTotal() {
	        return total;
	    }
	 
	    public void setTotal(Integer total) {
	        this.total = total;
	    }
	 
	    public Integer getCount() {
	        return count;
	    }
	 
	    public void setCount(Integer count) {
	        this.count = count;
	    }
	 
	    public String getNext_openid() {
	        return next_openid;
	    }
	 
	    public void setNext_openid(String next_openid) {
	        this.next_openid = next_openid;
	    }
	 
	    public WxOpenidInfo getData() {
	        return data;
	    }
	 
	    public void setData(WxOpenidInfo data) {
	        this.data = data;
	    }
	 
	    public int getErrcode() {
	        return errcode;
	    }
	 
	    public void setErrcode(int errcode) {
	        this.errcode = errcode;
	    }
	 
	    public String getErrmsg() {
	        return errmsg;
	    }
	 
	    public void setErrmsg(String errmsg) {
	        this.errmsg = errmsg;
	    }
	 
	}
	
	
/**
 * 用户基本信息  
 * @author 一叶知秋plus
 *
 */
	
	public class WeixinUser {
	private String subscribe;//	用户是否订阅该公众号标识,值为0时,代表此用户没有关注该公众号,拉取不到其余信息。
	private String openid;//	用户的标识,对当前公众号唯一
	private String nickname;//	用户的昵称
	private String sex;//	用户的性别,值为1时是男性,值为2时是女性,值为0时是未知
	private String city;//	用户所在城市
	private String country;//	用户所在国家
	private String province;//	用户所在省份
	private String language;//	用户的语言,简体中文为zh_CN
	private List<String> tagid_list;//用户被打上的标签ID列表
	private String unionid;  //用户的unionid
	private String headimgurl;//用户的头像
	
	
	
	
	public String getHeadimgurl() {
		return headimgurl;
	}
	public void setHeadimgurl(String headimgurl) {
		this.headimgurl = headimgurl;
	}
	public String getUnionid() {
		return unionid;
	}
	public void setUnionid(String unionid) {
		this.unionid = unionid;
	}
	public String getSubscribe() {
		return subscribe;
	}
	public void setSubscribe(String subscribe) {
		this.subscribe = subscribe;
	}
	public String getOpenid() {
		return openid;
	}
	public void setOpenid(String openid) {
		this.openid = openid;
	}
	public String getNickname() {
		return nickname;
	}
	public void setNickname(String nickname) {
		this.nickname = nickname;
	}
	public String getSex() {
		return sex;
	}
	public void setSex(String sex) {
		this.sex = sex;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getCountry() {
		return country;
	}
	public void setCountry(String country) {
		this.country = country;
	}
	public String getProvince() {
		return province;
	}
	public void setProvince(String province) {
		this.province = province;
	}
	public String getLanguage() {
		return language;
	}
	public void setLanguage(String language) {
		this.language = language;
	}
	public List<String> getTagid_list() {
		return tagid_list;
	}
	public void setTagid_list(List<String> tagid_list) {
		this.tagid_list = tagid_list;
	}
}


public class WxOpenidInfo {
	private List<String> openid;
	 
    public List<String> getOpenid() {
        return openid;
    }
 
    public void setOpenid(List<String> openid) {
        this.openid = openid;
    }
}




			

步骤二:关注/取关的事件响应接口

/**
 * 请求校验工具类
 */
public class SignUtil {
    // 与接口配置信息中的Token要一致,我的是明文格式
    private static String token = "填写你服务器配置时写的token";

    
    public static boolean checkSignature(String signature, String timestamp,
            String nonce) {
        //从请求中(也就是微信服务器传过来的)拿到的token, timestamp, nonce
        String[] arr = new String[] { token, timestamp, nonce };
        // 将token、timestamp、nonce三个参数进行字典序排序
        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 = byteToStr(digest);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }

        content = null;
        // 将sha1加密后的字符串可与signature对比,标识该请求来源于微信
        return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
    }

  //将加密后的字节数组变成字符串
    private static String byteToStr(byte[] byteArray) {
        String strDigest = "";
        for (int i = 0; i < byteArray.length; i++) {
            strDigest += byteToHexStr(byteArray[i]);
        }
        return strDigest;
    }

    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;
    }
//用于字典排序
    public static void sort(String a[]) {
        for (int i = 0; i < a.length - 1; i++) {
            for (int j = i + 1; j < a.length; j++) {
                if (a[j].compareTo(a[i]) < 0) {
                    String temp = a[i];
                    a[i] = a[j];
                    a[j] = temp;
                }
            }
        }
    }
}


//事件响应的接口
@RequestMapping(value="/GZHConcern.do")
	public void GZHConcern(HttpServletRequest request, HttpServletResponse response) throws IOException {
		String message = "success";
		// 微信加密签名  
		String signature = request.getParameter("signature");  
		// 时间戳  
		String timestamp = request.getParameter("timestamp");  
		// 随机数  
		String nonce = request.getParameter("nonce");  
		// 随机字符串  
		String echostr = request.getParameter("echostr");  
		PrintWriter out = response.getWriter();  
		// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败  
		if (SignUtil.checkSignature(signature, timestamp, nonce)) {  
			out.print(echostr);
			//在这里相应微信的操作
		}  
		
		try {
			Map<String, String> map = XmlUtil.xmlToMap(request);
			String fromUserName = map.get("FromUserName");//消息来源用户标识
			String toUserName = map.get("ToUserName");//消息目的用户标识
			String msgType = map.get("MsgType");//消息类型
			String content = map.get("Content");//消息内容
			
			String eventType = map.get("Event");
			WeixinUser weixinUser = new WeixinUser();
			if(MessageUtil.MSGTYPE_EVENT.equals(msgType)){//如果为事件类型
				if(MessageUtil.MESSAGE_SUBSCIBE.equals(eventType)){//处理订阅事件
					//获取token
					String token = WXUtil.getGZHToken();
					weixinUser = WXUtil.getUnionid(fromUserName, token);
					//进行数据库的操作
					weixinUser.setNickname(weixinUser.getNickname());
					int row = gzhService.addGZHUser(weixinUser);
					//通过openid获取用户的数据
					message = MessageUtil.subscribeForText(toUserName, fromUserName);
				}else if(MessageUtil.MESSAGE_UNSUBSCIBE.equals(eventType)){//处理取消订阅事件
					message = MessageUtil.unsubscribe(toUserName, fromUserName);
					weixinUser.setOpenid(fromUserName);
					//进行数据库的操作
					int row = gzhService.deleteGZHUser(weixinUser);
				}
			}
		} catch (DocumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			out.close();
		}
		out = null;
	}

/*
 * 消息处理工具类
 */
public class MessageUtil {
	public static final String MSGTYPE_EVENT = "event";//消息类型--事件
	public static final String MESSAGE_SUBSCIBE = "subscribe";//消息事件类型--订阅事件
	public static final String MESSAGE_UNSUBSCIBE = "unsubscribe";//消息事件类型--取消订阅事件
	public static final String MESSAGE_TEXT = "text";//消息类型--文本消息
	
	/*
	 * 组装文本消息
	 */
	public static String textMsg(String toUserName,String fromUserName,String content){
		TextMessage text = new TextMessage();
		text.setFromUserName(toUserName);
		text.setToUserName(fromUserName);
		text.setMsgType(MESSAGE_TEXT);
		text.setCreateTime(new Date().getTime());
		text.setContent(content);
		return XmlUtil.textMsgToxml(text);
	}
	
	/*
	 * 响应订阅事件--回复文本消息
	 */
	public static String subscribeForText(String toUserName,String fromUserName){
		return textMsg(toUserName, fromUserName, "欢迎关注,精彩内容不容错过!!!");
	}
	
	/*
	 * 响应取消订阅事件
	 */
	public static String unsubscribe(String toUserName,String fromUserName){
		//TODO 可以进行取关后的其他后续业务处理
		System.out.println("用户:"+ fromUserName +"取消关注~");
		return "";
	}
}


/*
 * xml处理工具类
 */
public class XmlUtil {
	/*
	 * xml转map
	 */
	public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
		HashMap<String, String> map = new HashMap<String,String>();
		SAXReader reader = new SAXReader();
 
		InputStream ins = request.getInputStream();
		Document doc = reader.read(ins);
 
		Element root = doc.getRootElement();
		@SuppressWarnings("unchecked")
		List<Element> list = (List<Element>)root.elements();
 
		for(Element e:list){
			map.put(e.getName(), e.getText());
		}
		ins.close();
		return map;
	}
	/*
	 * 文本消息对象转xml
	 */
	public static String textMsgToxml(TextMessage textMessage){
		XStream xstream = new XStream();
		xstream.alias("xml", textMessage.getClass());
		return xstream.toXML(textMessage);
	}
}

ok,到这一步数据库中有了小程序opneid unionid 公众号opneid  unionid等用户信息,进行关联后就可以进行数据的查询操作,当然小程序也可以发送公众号模板的相应操作了。

 

如果有更好的实现方式,欢迎各位大佬不吝赐教~

 

  • 9
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
微信小程序开发公众号需要进行以下几个步骤: 1. 首先,你需要申请微信公众号和小程序。微信公众号和小程序可以通过微信官方网站进行申请。 2. 接下来,你需要将微信小程序公众号进行关联。这是为了实现消息推送功能。关联的过程需要在微信公众号开发平台进行操作。 3. 在小程序的后端管理界面登录并查看小程序的appid和secret。这些信息将在与微信进行请求交互时使用。 4. 为了实现与微信的请求交互,你需要使用https,并建议使用域名来实现。你还需要准备好对应的https证书,并在小程序的后端开发中配置好外网端口。 5. 如果你想实现微信推送功能,你需要成功关联微信公众号,并将你的IP添加到白名单中,以便获取token。 6. 如果你想实现图片上传功能,建议使用图片服务器,并将图片路径返回给前端。在使用Nginx时,需要注意设置传输大小。 7. 小程序的打包体积不能超过2M,其他资源(包括图片等)应放在后端的静态服务器中。 8. 在进行小程序体验版自测时,你需要在微信管理后台添加相应的开发人员,并在登录小程序时使用开发调试功能。同时,体验版的网络和后端服务的网需要在同一局域网才能进行访问。 9. 如果你想升级和上线小程序,需要提前提交审核申请。初次审核可能需要较长时间,一般需要提前进行准备。在上线前,你需要在微信公众号开发平台添加获取token的白名单,并确保后端服务开启了外网访问权限。 以上是关于微信小程序开发公众号的一些流程和步骤。你可以参考微信官方文档和API文档获取更详细的信息。 #### 引用[.reference_title] - *1* *2* *3* [手记系列之一 ----- 关于微信公众号和小程序的开发流程](https://blog.csdn.net/qazwsxpcm/article/details/127600663)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值