微信公众号迁移流程 《openid转换》

6 篇文章 0 订阅

一.总流程图

二.审核通过后,点击迁移之前,拉取旧公众号的openid数据 这里使用weixin4j(也可使用其他工具 或者微信原生sdk)

在这里插入图片描述

     审核通过后管理员收到的通知 收到该通知后先别忙着点确认进行迁移  首先应该把此时旧公众号的openid全部拉出来存到数据库 用于之后的转换openid

1.该表用来储存拉取的旧openid 用来记录对应的新openid

package cn.betatown.member.model.weixin;
 
import java.io.Serializable;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
 
 
import cn.betatown.model.BaseStringEntity;
 
/**
 *
 *旧openid记录表  此表用于记录转换前的旧openid  并记录openid转换情况
 */
@Entity
@Table(name = "M_WEIXIN_OPENID_HIS")
public class WeixinOpenIdHis extends BaseStringEntity implements Serializable {
 
	private static final long serialVersionUID = 5700734079006338566L;
 
	/**
	 * 旧openid
	 */
	@Column(name = "OLD_OPENID",length = 40,nullable = false)
	private String oldOpenId;
	
	/**
	 * 新openid
	 */
	@Column(name = "NEW_OPENID", length = 200)
	private String newOpenId;
	
	/**
	 * 手机号码
	 */
	@Column(name = "MOBILE_NUMBER", length = 40)
	private String mobileNumber;
	
	/**
	 * 会员id
	 */
	@Column(name = "MEMBER_ID", length = 40)
	private String memberId;
 
	public String getOldOpenId() {
		return oldOpenId;
	}
 
	public String getNewOpenId() {
		return newOpenId;
	}
 
	public String getMobileNumber() {
		return mobileNumber;
	}
 
	public String getMemberId() {
		return memberId;
	}
 
	public void setOldOpenId(String oldOpenId) {
		this.oldOpenId = oldOpenId;
	}
 
	public void setNewOpenId(String newOpenId) {
		this.newOpenId = newOpenId;
	}
 
	public void setMobileNumber(String mobileNumber) {
		this.mobileNumber = mobileNumber;
	}
 
	public void setMemberId(String memberId) {
		this.memberId = memberId;
	}
 
	public WeixinOpenIdHis() {
		super();
		// TODO Auto-generated constructor stub
	}
 
	public WeixinOpenIdHis(String oldOpenId) {
		super();
		this.oldOpenId = oldOpenId;
	}
	
}

2.拉取旧公众号的所有openid 存入数据库

package cn.betatown.member.action.member;
 
 
 
import java.util.ArrayList;
import java.util.List;
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
 
import com.bstek.dorado.annotation.Expose;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.WeixinProxy;
import com.foxinmy.weixin4j.mp.model.Following;
 
import cn.betatown.WchatConfig;
import cn.betatown.common.service.ServiceException;
 
import cn.betatown.common.utils.status.StatusHouse;
 
import cn.betatown.common.utils.web.JsonWriter;
import cn.betatown.member.model.weixin.WeixinOpenIdHis;
import cn.betatown.member.service.member.MemberService;
import cn.betatown.security.model.User;
import cn.betatown.security.service.SecurityService;
import net.sf.json.JSONArray;
 
/**
 * 
 * @ClassName: MemberAct
 * @Description: TODO(APP会员视图控制层)
 * @author xuan.yuan
 * @date 2019年5月10日 下午12:06:22
 * 
 */
 
@Controller
public class MemberAct2 {
 
	
	private static Logger logger = LoggerFactory.getLogger(MemberAct2.class);
	
	@Autowired
	private MemberService memberService;
 
	@Autowired
	private SecurityService securityService;
	
	/**
	 * 迁移之前拉取所有openid  存入数据库 以便迁移完成后转换openid
	 * @return
	 * @author xuan.yuan
	 * @date 2019年5月10日 下午3:15:49
	 */
	@Expose
	public String getAllOpenId(){
		try {
			logger.info("executeGetAllopenId(..) start ... ");
			WchatConfig wchatConfig = WchatConfig.getInstance();//weixin4j
			WeixinProxy weixinProxy = wchatConfig.getWeixinProxy();//weixin4j
			List<String> openIds = new ArrayList<String>();
			String nextOpenId = null;
			do{
				Following following = weixinProxy.getFollowingOpenIds(nextOpenId);//weixin4j 获取openids
				int count = following.getCount();//拉取的OPENID个数,最大值为10000
				int total = following.getTotal();//关注总数
				nextOpenId = following.getNextOpenId();//拉取列表的后一个用户的OPENID
				logger.info("关注总数:【"+total+"】本次拉取:【"+count+"】末尾openid:【"+nextOpenId+"】");
				openIds = following.getOpenIds();//列表数据,OPENID的列表
				if(null!=openIds&&openIds.size()>0){
					for (String openId : openIds) {
						WeixinOpenIdHis weixinOpenIdHis = new WeixinOpenIdHis(openId);
						memberService.executeSaveOpenIdHis(weixinOpenIdHis);//将旧openid存入数据库中  用作之后的转换openid源数据
						logger.info(count+".successOpenid【"+openId+"】");
						count--;
					}
				}
			}while(null!=openIds&&openIds.size()>0);
			logger.info("executeGetAllopenId(..) end ... ");
			return "ok";
		} catch (WeixinException e) {
			logger.error(e.getMessage());
			return e.getErrorDesc();
		}catch (Exception e){
			logger.error(e.getMessage());
			return e.getMessage();
		}
	}
	
	
 
 
	/**
	 * 迁移完成后转换openid
	 * @return
	 */
	@Expose
	public String changeAllOpenId(){//		
		User user = securityService.getLoginUser();
		if (user == null) {
			throw new ServiceException(StatusHouse.COMMON_STATUS_NO_LOGIN_OR_TIMEOUT);
		}
		logger.info("executeChangeOpenId(..) start ... ");
		WchatConfig wchatConfig = WchatConfig.getInstance();
		WeixinProxy weixinProxy = wchatConfig.getWeixinProxy();
		try {
			String token = weixinProxy.getTokenManager().getAccessToken();//新公众号的令牌
			List<String> oldOpenIds = memberService.pageWeixinOpenIdHis(100, 1);//分批获取之前存储的旧openid
			int count = 1;
			while(null!=oldOpenIds&&oldOpenIds.size()>0&&count<450){
				logger.info("第"+count+"批开始···size="+oldOpenIds.size());
				String changeUrl = "http://api.weixin.qq.com/cgi-bin/changeopenid?access_token="+token;  //微信提供中的openId转换接口
			    HttpHeaders headers = new HttpHeaders();//请求头  
			    MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8");//这里非常重要 必须是json模式 否则调微信接口报错
			    headers.setContentType(type);
			    jsonChangeOpenid jsonChangeOpenid = new jsonChangeOpenid("wx55ee94e1a6154fb2", oldOpenIds);//此处为原帐号的appid需要转换的openIdS 最大100条,这些必须是旧账号目前关注的才行
			    String requestJson = JsonWriter.toJson(jsonChangeOpenid);
			    logger.info("requestJson==>"+requestJson);
			    HttpEntity<String> httpEntity = new HttpEntity<String>(requestJson,headers);
				RestTemplate restTemplate = new RestTemplate();
				ResponseEntity<String> response = restTemplate.postForEntity(changeUrl, httpEntity,String.class);
				logger.info("微信返回:"+response.getBody());
				net.sf.json.JSONObject jsonObject= net.sf.json.JSONObject.fromObject(response.getBody());
				if(jsonObject.get("errmsg").equals("ok")){
					JSONArray resultList = jsonObject.getJSONArray("result_list");
					for (Object object : resultList) {
						net.sf.json.JSONObject newOpenIdList = net.sf.json.JSONObject.fromObject(object);
						if(newOpenIdList.get("err_msg").equals("ok")){
								try {
									memberService.executeChangeOpenId(newOpenIdList.getString("ori_openid"), newOpenIdList.getString("new_openid"));//根据自己的业务逻辑用新openid 替换 旧openid
									logger.error("success旧openID:"+newOpenIdList.get("ori_openid"));
								} catch (Exception e) {
									logger.error("旧openID:"+newOpenIdList.get("ori_openid")+"失败原因:"+e);
									continue;
								}
						}else{
							logger.error("旧openID:"+newOpenIdList.get("ori_openid")+"失败原因:"+newOpenIdList.get("err_msg"));
						}
					}
				}else{
					logger.error("errorCode:"+jsonObject.get("errcode")+"errmsg:"+jsonObject.get("errmsg"));
					return "errorCode:"+jsonObject.get("errcode")+"errmsg:"+jsonObject.get("errmsg");
				}
				logger.info("第"+count+"批结束···size="+oldOpenIds.size());
				//循环执行
				oldOpenIds = memberService.pageWeixinOpenIdHis(100, 1);
				count++;
			};
			logger.info("executeChangeOpenId(..) end ... ");
			return "ok";
		} catch (WeixinException e) {
			logger.error(e.getMessage());
			return e.getErrorDesc();
		}catch (Exception e) {
			logger.error(e.getMessage());
			return e.getMessage();
		}}
		return "ok";
	}

二.管理员点击确认迁移

1、审核通过后,系统将会下发迁移确认通知给两个帐号管理员的微信号,双方15天内点击确认迁移则自动开启迁移流程(注:必须在审核成功后的15天内确认迁移通知,超时未确认迁移则迁移失败,如需继续迁移需另外申请并支付审核费用;如审核成功后未收到迁移确认通知,可在公众号后台进入帐号迁移页面申请发送通知,每天只可下发一次);

2、双方点击确认迁移后,为保证数据不受影响,原帐号会马上冻结,同时系统下发通知给原账号粉丝,告知迁移事宜,粉丝如有异议,可在1天内取消关注,取消关注的用户不会被迁移;

点击确认迁移后粉丝收到的迁移通知

3、1天后(1天粉丝确认)自动触发迁移,包括粉丝、群发素材、违规记录,耗时时间与数据量大小相关,一般将在1-3个天内完成(1-3天粉丝、群发素材、违规记录迁移),系统给粉丝发送迁移中通知 给管理员发送迁移中通知。

点击确认迁移整整1天后 管理员会收到这个迁移开始通知 此时自动触发迁移

收到上面的通知以后粉丝会陆续收到该通知

4、迁移完成后,新帐号名称同步。微信方面整个迁移流程结束。(迁移完成后没有明确的完成指示,我们公众号粉丝8万左右,一天就完了,只要转换openid接口能调通 说明迁移全部完成了)

三.按照自己的需求配置新公众号各白名单 支付授权目录····等配置信息到服务器
调用上面代码中的openid转换接口转换openid

官方说明:http://kf.qq.com/faq/1901177NrqMr190117nqYJze.html openid转换接口

!!!迁移没完成前调用转换接口会报

!!!公众号id参数给错也会报上面错误

!!! 转换方法请求头类型不是json 也会报 63178:from_appid参数错误,和调用的账号并没有迁移关系

微信公众号openid 转换成 userid,需要先获取微信用户的 access_token,然后调用用户管理接口,即可获取到用户的基本信息,其中包括 userid。 具体步骤如下: 1. 获取 access_token 首先需要获取 access_token,可以通过向以下 URL 发送 GET 请求来获取: ``` https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET ``` 其中,APPID 和 APPSECRET 分别是公众号的 appid 和 appsecret,可以在公众号后台中获取到。 2. 获取用户信息 获取 access_token 后,即可调用用户管理接口,获取用户信息。其中,需要将 openid 作为参数传递给接口。具体接口如下: ``` https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID ``` 其中,ACCESS_TOKEN 是第一步获取到的 access_token,OPENID 是需要转换openid。 3. 获取 userid 调用用户管理接口后,即可获取到用户的基本信息,其中包括 userid。具体的 userid 为用户在公众号中的唯一标识,可以通过如下方式获取: ``` { "subscribe": 1, "openid": "o6_bmjrPTlm6_2sgVt7hMZOPfL2M", "nickname": "Band", "sex": 1, "language": "zh_CN", "city": "广州", "province": "广东", "country": "中国", "headimgurl": "http://wx.qlogo.cn/mmopen/g3MoJvZJyE.../0", "subscribe_time": 1382694957, "unionid": " o6_bmasdasdsad6_2sgVt7hMZOPfL" "remark": "", "groupid": 0, "tagid_list":[128,2], "subscribe_scene": "ADD_SCENE_QR_CODE", "qr_scene": 98765, "qr_scene_str": "" } ``` 其中,userid 对应的 key 为 unionid,可以直接获取到。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值