@@ -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); | |||||
} | |||||
} | |||||
} | } |