| @@ -36,6 +36,11 @@ | |||||
| <artifactId>testng</artifactId> | <artifactId>testng</artifactId> | ||||
| <scope>test</scope> | <scope>test</scope> | ||||
| </dependency> | </dependency> | ||||
| <dependency> | |||||
| <groupId>org.mockito</groupId> | |||||
| <artifactId>mockito-all</artifactId> | |||||
| <scope>test</scope> | |||||
| </dependency> | |||||
| <dependency> | <dependency> | ||||
| <groupId>com.google.inject</groupId> | <groupId>com.google.inject</groupId> | ||||
| <artifactId>guice</artifactId> | <artifactId>guice</artifactId> | ||||
| @@ -4,6 +4,7 @@ import java.util.List; | |||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.mp.bean.WxMpUserQuery; | 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.WxMpUser; | ||||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | 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_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_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_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> | * <pre> | ||||
| @@ -94,4 +96,17 @@ public interface WxMpUserService { | |||||
| * @param nextOpenid 可选,第一个拉取的OPENID,null为从头开始拉取 | * @param nextOpenid 可选,第一个拉取的OPENID,null为从头开始拉取 | ||||
| */ | */ | ||||
| WxMpUserList userList(String nextOpenid) throws WxErrorException; | 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; | package me.chanjar.weixin.mp.api.impl; | ||||
| import java.util.HashMap; | |||||
| import java.util.List; | import java.util.List; | ||||
| import java.util.Map; | |||||
| import com.google.gson.JsonArray; | |||||
| import com.google.gson.JsonObject; | import com.google.gson.JsonObject; | ||||
| import me.chanjar.weixin.common.error.WxErrorException; | import me.chanjar.weixin.common.error.WxErrorException; | ||||
| import me.chanjar.weixin.mp.api.WxMpService; | import me.chanjar.weixin.mp.api.WxMpService; | ||||
| import me.chanjar.weixin.mp.api.WxMpUserService; | import me.chanjar.weixin.mp.api.WxMpUserService; | ||||
| import me.chanjar.weixin.mp.bean.WxMpUserQuery; | 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.WxMpUser; | ||||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | import me.chanjar.weixin.mp.bean.result.WxMpUserList; | ||||
| import me.chanjar.weixin.mp.util.json.WxMpGsonBuilder; | |||||
| /** | /** | ||||
| * Created by Binary Wang on 2016/7/21. | * Created by Binary Wang on 2016/7/21. | ||||
| @@ -50,6 +55,16 @@ public class WxMpUserServiceImpl implements WxMpUserService { | |||||
| return WxMpUserList.fromJson(responseContent); | 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 | @Override | ||||
| public List<WxMpUser> userInfoList(List<String> openidList) | public List<WxMpUser> userInfoList(List<String> openidList) | ||||
| throws WxErrorException { | 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(WxMpMassTagMessage.class, new WxMpMassTagMessageGsonAdapter()); | ||||
| INSTANCE.registerTypeAdapter(WxMpMassOpenIdsMessage.class, new WxMpMassOpenIdsMessageGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpMassOpenIdsMessage.class, new WxMpMassOpenIdsMessageGsonAdapter()); | ||||
| INSTANCE.registerTypeAdapter(WxMpUser.class, new WxMpUserGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpUser.class, new WxMpUserGsonAdapter()); | ||||
| INSTANCE.registerTypeAdapter(WxMpChangeOpenid.class, new WxMpChangeOpenidGsonAdapter()); | |||||
| INSTANCE.registerTypeAdapter(WxMpUserList.class, new WxUserListGsonAdapter()); | INSTANCE.registerTypeAdapter(WxMpUserList.class, new WxUserListGsonAdapter()); | ||||
| INSTANCE.registerTypeAdapter(WxMpMassVideo.class, new WxMpMassVideoAdapter()); | INSTANCE.registerTypeAdapter(WxMpMassVideo.class, new WxMpMassVideoAdapter()); | ||||
| INSTANCE.registerTypeAdapter(WxMpMassSendResult.class, new WxMpMassSendResultAdapter()); | INSTANCE.registerTypeAdapter(WxMpMassSendResult.class, new WxMpMassSendResultAdapter()); | ||||
| @@ -1,8 +1,13 @@ | |||||
| package me.chanjar.weixin.mp.api.impl; | package me.chanjar.weixin.mp.api.impl; | ||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||
| import java.util.HashMap; | |||||
| import java.util.List; | 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.*; | ||||
| import org.testng.annotations.*; | 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.WxMpUser; | ||||
| import me.chanjar.weixin.mp.bean.result.WxMpUserList; | 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); | 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); | |||||
| } | |||||
| } | |||||
| } | } | ||||