调整TokenCreator设计&公众号新增批量移动、删除用户组接口

This commit is contained in:
jinyu
2015-04-13 11:26:57 +08:00
parent 066546997f
commit f102032379
27 changed files with 529 additions and 116 deletions
+7 -1
View File
@@ -185,4 +185,10 @@ weixin.properties说明
* 2015-04-01
+ 新增[CashApi](./src/main/java/com/foxinmy/weixin4j/mp/api/CashApi.java)发红包、企业付款接口
+ 新增[CashApi](./src/main/java/com/foxinmy/weixin4j/mp/api/CashApi.java)发红包、企业付款接口
* 2015-04-13
+ 新增WeixinTokenCreator与WeixinJSTicketCreator类
+ 新增用户分组批量移动、删除组别接口
@@ -20,6 +20,7 @@ import com.foxinmy.weixin4j.mp.payment.v3.MPPayment;
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult;
import com.foxinmy.weixin4j.mp.payment.v3.Redpacket;
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketSendResult;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.mp.type.BillType;
import com.foxinmy.weixin4j.mp.type.CurrencyType;
import com.foxinmy.weixin4j.mp.type.IdQuery;
@@ -27,8 +28,6 @@ import com.foxinmy.weixin4j.mp.type.IdType;
import com.foxinmy.weixin4j.mp.type.RefundType;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.type.AccountType;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
@@ -52,7 +51,7 @@ public class WeixinPayProxy {
public WeixinPayProxy() {
this(ConfigUtil.getWeixinMpAccount(), new FileTokenHolder(
new WeixinTokenCreator(AccountType.MP)));
new WeixinTokenCreator()));
}
/**
@@ -32,6 +32,7 @@ import com.foxinmy.weixin4j.mp.model.QRParameter;
import com.foxinmy.weixin4j.mp.model.SemQuery;
import com.foxinmy.weixin4j.mp.model.SemResult;
import com.foxinmy.weixin4j.mp.model.User;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.mp.type.DatacubeType;
import com.foxinmy.weixin4j.mp.type.IndustryType;
import com.foxinmy.weixin4j.mp.type.Lang;
@@ -40,8 +41,6 @@ import com.foxinmy.weixin4j.msg.model.MpArticle;
import com.foxinmy.weixin4j.msg.model.Video;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.type.AccountType;
import com.foxinmy.weixin4j.type.MediaType;
/**
@@ -71,7 +70,7 @@ public class WeixinProxy {
* 默认采用文件存放Token信息
*/
public WeixinProxy() {
this(new FileTokenHolder(new WeixinTokenCreator(AccountType.MP)));
this(new FileTokenHolder(new WeixinTokenCreator()));
}
/**
@@ -80,8 +79,7 @@ public class WeixinProxy {
* @param appsecret
*/
public WeixinProxy(String appid, String appsecret) {
this(new FileTokenHolder(new WeixinTokenCreator(appid, appsecret,
AccountType.MP)));
this(new FileTokenHolder(new WeixinTokenCreator(appid, appsecret)));
}
/**
@@ -967,21 +965,54 @@ public class WeixinProxy {
return groupApi.modifyGroup(groupId, name);
}
/**
/**
* 移动用户到分组
*
* @param openId
*
* @param groupId
* 组ID
* @param openId
* 用户对应的ID
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html#.E7.A7.BB.E5.8A.A8.E7.94.A8.E6.88.B7.E5.88.86.E7.BB.84">移动分组</a>
* @see com.foxinmy.weixin4j.mp.model.Group
* @see com.foxinmy.weixin4j.mp.api.GroupApi
*/
*/
public JsonResult moveGroup(int groupId, String openId)
throws WeixinException {
throws WeixinException {
return groupApi.moveGroup(groupId, openId);
}
/**
* 批量移动分组
*
* @param groupId
* 组ID
* @param openIds
* 用户ID列表(不能超过50个)
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/0/56d992c605a97245eb7e617854b169fc.html#.E6.89.B9.E9.87.8F.E7.A7.BB.E5.8A.A8.E7.94.A8.E6.88.B7.E5.88.86.E7.BB.84">批量移动分组</a>
* @see com.foxinmy.weixin4j.mp.model.Group
* @see com.foxinmy.weixin4j.mp.api.GroupApi
*/
public JsonResult moveGroup(int groupId, String... openIds)
throws WeixinException {
return groupApi.moveGroup(groupId, openIds);
}
/**
* 删除用户分组,所有该分组内的用户自动进入默认分组.
*
* @param groupId
* 组ID
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/0/56d992c605a97245eb7e617854b169fc.html#.E5.88.A0.E9.99.A4.E5.88.86.E7.BB.84">删除用户分组</a>
* @see com.foxinmy.weixin4j.mp.model.Group
* @see com.foxinmy.weixin4j.mp.api.GroupApi
*/
public JsonResult deleteGroup(int groupId) throws WeixinException {
return groupApi.deleteGroup(groupId);
}
@@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.mp.api;
import java.util.List;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.JsonResult;
import com.foxinmy.weixin4j.http.Response;
@@ -118,18 +119,18 @@ public class GroupApi extends MpApi {
}
/**
* 移动分组
* 移动用户到分组
*
* @param openId
* 用户对应的ID
* @param groupId
* 组ID
* @param openId
* 用户对应的ID
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/13/be5272dc4930300ba561d927aead2569.html#.E7.A7.BB.E5.8A.A8.E7.94.A8.E6.88.B7.E5.88.86.E7.BB.84">移动分组</a>
* @see com.foxinmy.weixin4j.mp.model.Group
*/
public JsonResult moveGroup(String openId, int groupId)
public JsonResult moveGroup(int groupId, String openId)
throws WeixinException {
String group_move_uri = getRequestUri("group_move_uri");
Token token = tokenHolder.getToken();
@@ -139,4 +140,50 @@ public class GroupApi extends MpApi {
return response.getAsJsonResult();
}
/**
* 批量移动分组
*
* @param groupId
* 组ID
* @param openIds
* 用户ID列表(不能超过50个)
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/0/56d992c605a97245eb7e617854b169fc.html#.E6.89.B9.E9.87.8F.E7.A7.BB.E5.8A.A8.E7.94.A8.E6.88.B7.E5.88.86.E7.BB.84">批量移动分组</a>
* @see com.foxinmy.weixin4j.mp.model.Group
*/
public JsonResult moveGroup(int groupId, String... openIds)
throws WeixinException {
String group_batchmove_uri = getRequestUri("group_batchmove_uri");
Token token = tokenHolder.getToken();
JSONObject obj = new JSONObject();
obj.put("to_groupid", groupId);
obj.put("openid_list", openIds);
Response response = request.post(
String.format(group_batchmove_uri, token.getAccessToken()),
obj.toJSONString());
return response.getAsJsonResult();
}
/**
* 删除用户分组,所有该分组内的用户自动进入默认分组.
*
* @param groupId
* 组ID
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/0/56d992c605a97245eb7e617854b169fc.html#.E5.88.A0.E9.99.A4.E5.88.86.E7.BB.84">删除用户分组</a>
* @see com.foxinmy.weixin4j.mp.model.Group
*/
public JsonResult deleteGroup(int groupId) throws WeixinException {
String group_delete_uri = getRequestUri("group_delete_uri");
Token token = tokenHolder.getToken();
Response response = request.post(
String.format(group_delete_uri, token.getAccessToken()),
String.format("{\"group\":{\"id\":%d}}", groupId));
return response.getAsJsonResult();
}
}
@@ -45,6 +45,10 @@ group_getid_uri={api_cgi_url}/groups/getid?access_token=%s
group_modify_uri={api_cgi_url}/groups/update?access_token=%s
# \u79fb\u52a8\u7528\u6237\u5206\u7ec4
group_move_uri={api_cgi_url}/groups/members/update?access_token=%s
# \u6279\u91cf\u79fb\u52a8\u7528\u6237\u5206\u7ec4
group_batchmove_uri={api_cgi_url}/groups/members/batchupdate?access_token=%s
# \u5220\u9664\u7528\u6237\u5206\u7ec4
group_delete_uri={api_cgi_url}/groups/delete?access_token=%s
# \u83b7\u53d6\u5173\u6ce8\u7740
following_uri={api_cgi_url}/user/get?access_token=%s&next_openid=%s
# \u81ea\u5b9a\u4e49\u83dc\u5355
@@ -0,0 +1,55 @@
package com.foxinmy.weixin4j.mp.token;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.token.TokenHolder;
/**
* 微信公众平台JSTICKET创建者
*
* @className WeixinJSTicketCreator
* @author jy
* @date 2015年1月10日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html#.E9.99.84.E5.BD.951-JS-SDK.E4.BD.BF.E7.94.A8.E6.9D.83.E9.99.90.E7.AD.BE.E5.90.8D.E7.AE.97.E6.B3.95">JS
* TICKET</a>
*/
public class WeixinJSTicketCreator implements TokenCreator {
private final String appid;
private final TokenHolder weixinTokenHolder;
private final HttpRequest request;
/**
* <font color="red">公众平台的access_token</font>
*
* @param weixinTokenHolder
*/
public WeixinJSTicketCreator(String appid, TokenHolder weixinTokenHolder) {
this.appid = appid;
this.weixinTokenHolder = weixinTokenHolder;
this.request = new HttpRequest();
}
@Override
public String getCacheKey() {
return String.format("mp_jsticket_%s", appid);
}
@Override
public Token createToken() throws WeixinException {
Response response = request.get(String.format(Consts.MP_JS_TICKET_URL,
weixinTokenHolder.getToken().getAccessToken()));
JSONObject result = response.getAsJson();
Token token = new Token(result.getString("ticket"));
token.setExpiresIn(result.getIntValue("expires_in"));
token.setTime(System.currentTimeMillis());
return token;
}
}
@@ -0,0 +1,58 @@
package com.foxinmy.weixin4j.mp.token;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.model.WeixinMpAccount;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 微信公众平台TOKEN创建者
*
* @className WeixinTokenCreator
* @author jy
* @date 2015年1月10日
* @since JDK 1.7
* @see <a
* href="http://mp.weixin.qq.com/wiki/11/0e4b294685f817b95cbed85ba5e82b8f.html">微信公众平台获取token说明</a>
* @see com.foxinmy.weixin4j.model.Token
*/
public class WeixinTokenCreator implements TokenCreator {
private final HttpRequest request;
private final String appid;
private final String secret;
public WeixinTokenCreator() {
WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount();
this.appid = weixinAccount.getId();
this.secret = weixinAccount.getSecret();
this.request = new HttpRequest();
}
public WeixinTokenCreator(String appid, String secret) {
this.appid = appid;
this.secret = secret;
this.request = new HttpRequest();
}
@Override
public String getCacheKey() {
return String.format("mp_token_%s", appid);
}
@Override
public Token createToken() throws WeixinException {
String tokenUrl = String.format(Consts.MP_ASSESS_TOKEN_URL, appid,
secret);
Response response = request.get(tokenUrl);
Token token = response.getAsObject(new TypeReference<Token>() {
});
token.setTime(System.currentTimeMillis());
return token;
}
}
@@ -13,9 +13,8 @@ import com.foxinmy.weixin4j.mp.WeixinPayProxy;
import com.foxinmy.weixin4j.mp.payment.coupon.CouponDetail;
import com.foxinmy.weixin4j.mp.payment.coupon.CouponResult;
import com.foxinmy.weixin4j.mp.payment.coupon.CouponStock;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.type.AccountType;
import com.foxinmy.weixin4j.util.DateUtil;
/**
@@ -31,15 +30,12 @@ public class CouponTest {
protected final static WeixinPayProxy WEIXINPAY;
protected final static WeixinMpAccount ACCOUNT;
static {
ACCOUNT = new WeixinMpAccount("公众号的id",
"公众号的secret",
"公众号的支付密钥", "商户平台的id");
ACCOUNT = new WeixinMpAccount("公众号的id", "公众号的secret", "公众号的支付密钥",
"商户平台的id");
WEIXINPAY = new WeixinPayProxy(ACCOUNT, new FileTokenHolder(
new WeixinTokenCreator(ACCOUNT.getId(), ACCOUNT.getSecret(),
AccountType.MP)));
new WeixinTokenCreator(ACCOUNT.getId(), ACCOUNT.getSecret())));
}
protected final File caFile = new File(
"证书文件的路径(*.p12)");
protected final File caFile = new File("证书文件的路径(*.p12)");
@Test
public void sendCoupon() throws WeixinException {
@@ -55,7 +51,7 @@ public class CouponTest {
CouponStock couponStock = WEIXINPAY.queryCouponStock("couponStockId");
System.err.println(couponStock);
}
@Test
public void queryCouponDetail() throws WeixinException {
CouponDetail couponDetail = WEIXINPAY.queryCouponDetail("couponId");
@@ -56,8 +56,21 @@ public class GroupTest extends TokenTest {
@Test
public void move() throws WeixinException {
JsonResult result = groupApi.moveGroup("owGBft_vbBbOaQOmpEUE4xDLeRSU",
100);
JsonResult result = groupApi.moveGroup(100,
"owGBft_vbBbOaQOmpEUE4xDLeRSU");
Assert.assertEquals(0, result.getCode());
}
@Test
public void batchMove() throws WeixinException {
JsonResult result = groupApi.moveGroup(100,
"owGBft_vbBbOaQOmpEUE4xDLeRSU");
Assert.assertEquals(0, result.getCode());
}
@Test
public void delete() throws WeixinException {
JsonResult result = groupApi.deleteGroup(100);
Assert.assertEquals(0, result.getCode());
}
}
@@ -17,12 +17,11 @@ import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
import com.foxinmy.weixin4j.mp.payment.v3.Order;
import com.foxinmy.weixin4j.mp.payment.v3.PayPackageV3;
import com.foxinmy.weixin4j.mp.payment.v3.PrePay;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.mp.type.IdQuery;
import com.foxinmy.weixin4j.mp.type.IdType;
import com.foxinmy.weixin4j.mp.type.TradeType;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.type.AccountType;
public class PayTest {
private final static WeixinPayProxy PAY2;
@@ -30,20 +29,14 @@ public class PayTest {
private final static WeixinMpAccount ACCOUNT2;
private final static WeixinMpAccount ACCOUNT3;
static {
ACCOUNT2 = new WeixinMpAccount(
"请填入v2版本的appid",
"请填入v2版本的appsecret",
"请填入v2版本的paysignkey",
"请填入v2版本的partnerId", "请填入v2版本的partnerKey");
ACCOUNT2 = new WeixinMpAccount("请填入v2版本的appid", "请填入v2版本的appsecret",
"请填入v2版本的paysignkey", "请填入v2版本的partnerId", "请填入v2版本的partnerKey");
PAY2 = new WeixinPayProxy(ACCOUNT2, new FileTokenHolder(
new WeixinTokenCreator(ACCOUNT2.getId(), ACCOUNT2.getSecret(),
AccountType.MP)));
ACCOUNT3 = new WeixinMpAccount("请填入v3版本的appid",
"请填入v3版本的appSecret",
new WeixinTokenCreator(ACCOUNT2.getId(), ACCOUNT2.getSecret())));
ACCOUNT3 = new WeixinMpAccount("请填入v3版本的appid", "请填入v3版本的appSecret",
"请填入v3版本的paysignkey", "请填入v3版本的mchid");
PAY3 = new WeixinPayProxy(ACCOUNT3, new FileTokenHolder(
new WeixinTokenCreator(ACCOUNT3.getId(), ACCOUNT3.getSecret(),
AccountType.MP)));
new WeixinTokenCreator(ACCOUNT3.getId(), ACCOUNT3.getSecret())));
}
@Test
@@ -53,8 +46,7 @@ public class PayTest {
@Test
public void refundV2() throws WeixinException {
File caFile = new File(
"签名文件,如12333.pfx");
File caFile = new File("签名文件,如12333.pfx");
IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO);
System.err.println(PAY2.refundV2(caFile, idQuery, "1422925555037", 16d,
16d, "1221928801", "111111", null, null, null));
@@ -91,8 +83,8 @@ public class PayTest {
@Test
public void refundQueryV3() throws WeixinException {
com.foxinmy.weixin4j.mp.payment.v3.RefundRecord record = PAY3.refundQueryV3(new IdQuery("TT_1427183696238",
IdType.TRADENO));
com.foxinmy.weixin4j.mp.payment.v3.RefundRecord record = PAY3
.refundQueryV3(new IdQuery("TT_1427183696238", IdType.TRADENO));
System.err.println(record);
// 这里的验证签名需要把details循环拼接
String sign = record.getSign();
@@ -117,12 +109,11 @@ public class PayTest {
@Test
public void refundV3() throws WeixinException {
File caFile = new File(
"签名文件如123.p12");
File caFile = new File("签名文件如123.p12");
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
com.foxinmy.weixin4j.mp.payment.v3.RefundResult result = PAY3.refundV3(
caFile, idQuery, "TT_R" + System.currentTimeMillis(), 0.01d, 0.01d,
null, "10020674");
caFile, idQuery, "TT_R" + System.currentTimeMillis(), 0.01d,
0.01d, null, "10020674");
System.err.println(result);
String sign = result.getSign();
result.setSign(null);
@@ -1,14 +1,19 @@
package com.foxinmy.weixin4j.mp.test;
import java.net.URL;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.token.FileTokenHolder;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.type.AccountType;
/**
* token测试
@@ -24,11 +29,26 @@ public class TokenTest {
@Before
public void setUp() {
tokenHolder = new FileTokenHolder(new WeixinTokenCreator(AccountType.MP));
tokenHolder = new FileTokenHolder(new WeixinTokenCreator());
}
@Test
public void test() throws WeixinException {
Assert.assertNotNull(tokenHolder.getToken());
}
public static void main(String[] args) throws Exception {
String wikiUrl = "http://qydev.weixin.qq.com/wiki/index.php?title=%E5%85%A8%E5%B1%80%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E";
// wikiUrl =
// "http://mp.weixin.qq.com/wiki/17/fa4e1434e57290788bde25603fa2fcbd.html";
Document doc = Jsoup.parse(new URL(wikiUrl), 5000);
Elements errors = doc.getElementsByTag("tr");
String node = "<error><code>%s</code><text>%s</text></error>";
StringBuilder xml = new StringBuilder();
for (Element error : errors) {
xml.append(String.format(node, error.child(0).text(), error
.child(1).text()));
}
System.err.println(xml);
}
}