| @@ -36,6 +36,11 @@ | |||
| <artifactId>testng</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>org.mockito</groupId> | |||
| <artifactId>mockito-all</artifactId> | |||
| <scope>test</scope> | |||
| </dependency> | |||
| <dependency> | |||
| <groupId>com.google.inject</groupId> | |||
| <artifactId>guice</artifactId> | |||
| @@ -4,6 +4,7 @@ import java.util.List; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.mp.bean.WxMpUserQuery; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpChangeOpenid; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | |||
| @@ -17,6 +18,7 @@ public interface WxMpUserService { | |||
| String USER_GET_URL = "https://api.weixin.qq.com/cgi-bin/user/get"; | |||
| String USER_INFO_URL = "https://api.weixin.qq.com/cgi-bin/user/info"; | |||
| String USER_INFO_UPDATE_REMARK_URL = "https://api.weixin.qq.com/cgi-bin/user/info/updateremark"; | |||
| String USER_CHANGE_OPENID_URL = "http://api.weixin.qq.com/cgi-bin/changeopenid"; | |||
| /** | |||
| * <pre> | |||
| @@ -94,4 +96,17 @@ public interface WxMpUserService { | |||
| * @param nextOpenid 可选,第一个拉取的OPENID,null为从头开始拉取 | |||
| */ | |||
| WxMpUserList userList(String nextOpenid) throws WxErrorException; | |||
| /** | |||
| * <pre> | |||
| * 微信公众号主体变更迁移用户 openid | |||
| * 详情请见: http://kf.qq.com/faq/170221aUnmmU170221eUZJNf.html | |||
| * http请求方式: POST | |||
| * 接口地址:https://api.weixin.qq.com/cgi-bin/changeopenid?access_token=ACCESS_TOKEN | |||
| * </pre> | |||
| * | |||
| * @param fromAppid 原公众号的 appid | |||
| * @param openidList 需要转换的openid,这些必须是旧账号目前关注的才行,否则会出错;一次最多100个 | |||
| */ | |||
| List<WxMpChangeOpenid> changeOpenid(String fromAppid, List<String> openidList) throws WxErrorException; | |||
| } | |||
| @@ -1,14 +1,19 @@ | |||
| package me.chanjar.weixin.mp.api.impl; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import com.google.gson.JsonArray; | |||
| import com.google.gson.JsonObject; | |||
| import me.chanjar.weixin.common.error.WxErrorException; | |||
| import me.chanjar.weixin.mp.api.WxMpService; | |||
| import me.chanjar.weixin.mp.api.WxMpUserService; | |||
| import me.chanjar.weixin.mp.bean.WxMpUserQuery; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpChangeOpenid; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | |||
| import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
| /** | |||
| * Created by Binary Wang on 2016/7/21. | |||
| @@ -50,6 +55,16 @@ public class WxMpUserServiceImpl implements WxMpUserService { | |||
| return WxMpUserList.fromJson(responseContent); | |||
| } | |||
| @Override | |||
| public List<WxMpChangeOpenid> changeOpenid(String fromAppid, List<String> openidList) throws WxErrorException { | |||
| Map<String, Object> map = new HashMap<>(); | |||
| map.put("from_appid", fromAppid); | |||
| map.put("openid_list", openidList); | |||
| String responseContent = this.wxMpService.post(USER_CHANGE_OPENID_URL, WxMpGsonBuilder.create().toJson(map)); | |||
| return WxMpChangeOpenid.fromJsonList(responseContent); | |||
| } | |||
| @Override | |||
| public List<WxMpUser> userInfoList(List<String> openidList) | |||
| throws WxErrorException { | |||
| @@ -0,0 +1,34 @@ | |||
| package me.chanjar.weixin.mp.bean.result; | |||
| import com.google.gson.Gson; | |||
| import com.google.gson.JsonObject; | |||
| import com.google.gson.reflect.TypeToken; | |||
| import lombok.Data; | |||
| import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
| import java.io.Serializable; | |||
| import java.lang.reflect.Type; | |||
| import java.util.List; | |||
| /** | |||
| * 主体变更迁移用户 openid 返回. | |||
| * | |||
| * @author 007gzs | |||
| */ | |||
| @Data | |||
| public class WxMpChangeOpenid implements Serializable { | |||
| private static final long serialVersionUID = -8132023284876534743L; | |||
| private String oriOpenid; | |||
| private String newOpenid; | |||
| private String errMsg; | |||
| public static WxMpChangeOpenid fromJson(String json) { | |||
| return WxMpGsonBuilder.create().fromJson(json, WxMpChangeOpenid.class); | |||
| } | |||
| public static List<WxMpChangeOpenid> fromJsonList(String json) { | |||
| Type collectionType = new TypeToken<List<WxMpChangeOpenid>>() { | |||
| }.getType(); | |||
| Gson gson = WxMpGsonBuilder.create(); | |||
| JsonObject jsonObject = gson.fromJson(json, JsonObject.class); | |||
| return gson.fromJson(jsonObject.get("result_list"), collectionType); | |||
| } | |||
| } | |||
| @@ -0,0 +1,25 @@ | |||
| package me.chanjar.weixin.mp.util.json; | |||
| import com.google.gson.JsonDeserializationContext; | |||
| import com.google.gson.JsonDeserializer; | |||
| import com.google.gson.JsonElement; | |||
| import com.google.gson.JsonObject; | |||
| import com.google.gson.JsonParseException; | |||
| import me.chanjar.weixin.common.util.json.GsonHelper; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpChangeOpenid; | |||
| import java.lang.reflect.Type; | |||
| public class WxMpChangeOpenidGsonAdapter implements JsonDeserializer<WxMpChangeOpenid> { | |||
| @Override | |||
| public WxMpChangeOpenid deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { | |||
| JsonObject o = json.getAsJsonObject(); | |||
| WxMpChangeOpenid changeOpenid = new WxMpChangeOpenid(); | |||
| changeOpenid.setOriOpenid(GsonHelper.getString(o, "ori_openid")); | |||
| changeOpenid.setNewOpenid(GsonHelper.getString(o, "new_openid")); | |||
| changeOpenid.setErrMsg(GsonHelper.getString(o, "err_msg")); | |||
| return changeOpenid; | |||
| } | |||
| } | |||
| @@ -25,6 +25,7 @@ public class WxMpGsonBuilder { | |||
| INSTANCE.registerTypeAdapter(WxMpMassTagMessage.class, new WxMpMassTagMessageGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(WxMpMassOpenIdsMessage.class, new WxMpMassOpenIdsMessageGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(WxMpUser.class, new WxMpUserGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(WxMpChangeOpenid.class, new WxMpChangeOpenidGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(WxMpUserList.class, new WxUserListGsonAdapter()); | |||
| INSTANCE.registerTypeAdapter(WxMpMassVideo.class, new WxMpMassVideoAdapter()); | |||
| INSTANCE.registerTypeAdapter(WxMpMassSendResult.class, new WxMpMassSendResultAdapter()); | |||
| @@ -1,8 +1,13 @@ | |||
| package me.chanjar.weixin.mp.api.impl; | |||
| import java.util.ArrayList; | |||
| import java.util.HashMap; | |||
| import java.util.List; | |||
| import java.util.Map; | |||
| import me.chanjar.weixin.mp.api.WxMpUserService; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpChangeOpenid; | |||
| import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||
| import org.testng.*; | |||
| import org.testng.annotations.*; | |||
| @@ -15,6 +20,9 @@ import me.chanjar.weixin.mp.bean.WxMpUserQuery; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUser; | |||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | |||
| import static org.mockito.Mockito.mock; | |||
| import static org.mockito.Mockito.when; | |||
| /** | |||
| * 测试用户相关的接口 | |||
| * | |||
| @@ -75,4 +83,50 @@ public class WxMpUserServiceImplTest { | |||
| System.out.println(wxMpUserList); | |||
| } | |||
| public void testChangeOpenid() throws WxErrorException { | |||
| List<String> openids = new ArrayList<>(); | |||
| openids.add(this.configProvider.getOpenid()); | |||
| List<WxMpChangeOpenid> wxMpChangeOpenidList = this.wxService.getUserService() | |||
| .changeOpenid("原公众号appid", openids); | |||
| Assert.assertNotNull(wxMpChangeOpenidList); | |||
| Assert.assertEquals(1, wxMpChangeOpenidList.size()); | |||
| WxMpChangeOpenid wxMpChangeOpenid = wxMpChangeOpenidList.get(0); | |||
| Assert.assertNotNull(wxMpChangeOpenid); | |||
| Assert.assertEquals(this.configProvider.getOpenid(), wxMpChangeOpenid.getOriOpenid()); | |||
| System.out.println(wxMpChangeOpenid); | |||
| } | |||
| public static class MockTest { | |||
| private WxMpService wxService = mock(WxMpService.class); | |||
| @Test | |||
| public void testMockChangeOpenid() throws WxErrorException { | |||
| List<String> openids = new ArrayList<>(); | |||
| openids.add("oEmYbwN-n24jxvk4Sox81qedINkQ"); | |||
| openids.add("oEmYbwH9uVd4RKJk7ZZg6SzL6tTo"); | |||
| String fromAppid = "old_appid"; | |||
| Map<String, Object> map = new HashMap<>(); | |||
| map.put("from_appid", fromAppid); | |||
| map.put("openid_list", openids); | |||
| String returnJson = "{\"errcode\": 0,\"errmsg\": \"ok\",\"result_list\": [{\"ori_openid\": \"oEmYbwN-n24jxvk4Sox81qedINkQ\",\"new_openid\": \"o2FwqwI9xCsVadFah_HtpPfaR-X4\",\"err_msg\": \"ok\"},{\"ori_openid\": \"oEmYbwH9uVd4RKJk7ZZg6SzL6tTo\",\"err_msg\": \"ori_openid error\"}]}"; | |||
| when(wxService.post(WxMpUserService.USER_CHANGE_OPENID_URL, WxMpGsonBuilder.create().toJson(map))).thenReturn(returnJson); | |||
| List<WxMpChangeOpenid> wxMpChangeOpenidList = this.wxService.getUserService() | |||
| .changeOpenid(fromAppid, openids); | |||
| Assert.assertNotNull(wxMpChangeOpenidList); | |||
| Assert.assertEquals(2, wxMpChangeOpenidList.size()); | |||
| WxMpChangeOpenid wxMpChangeOpenid = wxMpChangeOpenidList.get(0); | |||
| Assert.assertNotNull(wxMpChangeOpenid); | |||
| Assert.assertEquals("oEmYbwN-n24jxvk4Sox81qedINkQ", wxMpChangeOpenid.getOriOpenid()); | |||
| Assert.assertEquals("o2FwqwI9xCsVadFah_HtpPfaR-X4", wxMpChangeOpenid.getNewOpenid()); | |||
| Assert.assertEquals("ok", wxMpChangeOpenid.getErrMsg()); | |||
| wxMpChangeOpenid = wxMpChangeOpenidList.get(1); | |||
| Assert.assertNotNull(wxMpChangeOpenid); | |||
| Assert.assertEquals("oEmYbwH9uVd4RKJk7ZZg6SzL6tTo", wxMpChangeOpenid.getOriOpenid()); | |||
| Assert.assertNull(wxMpChangeOpenid.getNewOpenid()); | |||
| Assert.assertEquals("ori_openid error", wxMpChangeOpenid.getErrMsg()); | |||
| System.out.println(wxMpChangeOpenid); | |||
| } | |||
| } | |||
| } | |||