weixin4j-qy:新增企业号登陆授权API

This commit is contained in:
jinyu 2015-06-12 23:48:55 +08:00
parent dea8ab6252
commit 2275ddd97a
16 changed files with 536 additions and 17 deletions

View File

@ -329,4 +329,6 @@
* 2015-06-12
+ 修缮token实现机制
+ 修缮token实现机制
+ **weixin4j-qy**: 新增企业号[登陆授权](weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/OauthApi.java)API

View File

@ -72,7 +72,7 @@ weixin4j
------
* 公众号第三方服务应用
* 企业号第三方应用 & 企业号登陆授权
* 企业号第三方应用
* 硬件设备 & 摇一摇周边

View File

@ -34,7 +34,7 @@ import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
import com.foxinmy.weixin4j.mp.payment.PayUtil;
import com.foxinmy.weixin4j.mp.payment.conver.ListsuffixResultConverter;
import com.foxinmy.weixin4j.mp.payment.conver.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.mp.payment.v2.Order;
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecord;
import com.foxinmy.weixin4j.mp.payment.v2.RefundResult;
@ -442,7 +442,7 @@ public class Pay2Api extends PayApi {
String sign = PayUtil.paysignMd5(map, weixinAccount.getPartnerKey());
map.put("sign", sign.toLowerCase());
WeixinResponse response = weixinClient.get(refundquery_uri, map);
return ListsuffixResultConverter.containRefundConvert(
return ListsuffixResultDeserializer.containRefundDeserialize(
response.getAsString(), RefundRecord.class);
}

View File

@ -25,7 +25,7 @@ import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
import com.foxinmy.weixin4j.mp.payment.PayUtil;
import com.foxinmy.weixin4j.mp.payment.conver.ListsuffixResultConverter;
import com.foxinmy.weixin4j.mp.payment.conver.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
import com.foxinmy.weixin4j.mp.payment.v3.Order;
import com.foxinmy.weixin4j.mp.payment.v3.RefundRecord;
@ -80,7 +80,7 @@ public class Pay3Api extends PayApi {
String param = XmlStream.map2xml(map);
String orderquery_uri = getRequestUri("orderquery_v3_uri");
WeixinResponse response = weixinClient.post(orderquery_uri, param);
return ListsuffixResultConverter.containCouponConvert(
return ListsuffixResultDeserializer.containCouponDeserialize(
response.getAsString(), Order.class);
}
@ -394,7 +394,7 @@ public class Pay3Api extends PayApi {
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinClient.post(refundquery_uri, param);
return ListsuffixResultConverter.containRefundDetailConvert(
return ListsuffixResultDeserializer.containRefundDetailDeserialize(
response.getAsString(), RefundRecord.class);
}

View File

@ -0,0 +1,33 @@
package com.foxinmy.weixin4j.mp.payment.conver;
/**
* 后缀为_$n xml节点序列化
*
* @className ListsuffixResultSerializer
* @author jy
* @date 2015年3月24日
* @since JDK 1.7
* @see
*/
public class ListsuffixResultSerializer {
/**
* 序列化为json
*
* @param object
* @return json
*/
public String serializeToJSON(Object object) {
return null;
}
/**
* 序列化为xml
*
* @param object
* @return xml
*/
public String serializeToXML(Object object) {
return null;
}
}

View File

@ -84,10 +84,10 @@ public class Order extends ApiResult {
@JSONField(name = "coupon_count")
private Integer couponCount;
/**
* 代金券信息
* 代金券信息 验证签名有点麻烦
*/
@XmlTransient
@JSONField(serialize = false)
@JSONField(serialize = false, deserialize = false)
private List<CouponInfo> couponList;
/**
* 现金支付金额
@ -135,7 +135,7 @@ public class Order extends ApiResult {
protected Order() {
// jaxb required
}
public TradeState getTradeState() {
return tradeState;
}

View File

@ -6,7 +6,7 @@ import java.util.HashMap;
import java.util.Map;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.mp.payment.conver.ListsuffixResultConverter;
import com.foxinmy.weixin4j.mp.payment.conver.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecord;
import com.foxinmy.weixin4j.mp.payment.v3.Order;
import com.foxinmy.weixin4j.xml.XmlStream;
@ -60,7 +60,7 @@ public class XmlstreamTest {
} catch (Exception e) {
}
System.err.println(ListsuffixResultConverter.containCouponConvert(
System.err.println(ListsuffixResultDeserializer.containCouponDeserialize(
sb.toString(), Order.class));
}
@ -77,7 +77,7 @@ public class XmlstreamTest {
} catch (Exception e) {
}
System.err.println(ListsuffixResultConverter.containRefundConvert(
System.err.println(ListsuffixResultDeserializer.containRefundDeserialize(
sb.toString(), RefundRecord.class));
}
@ -94,8 +94,8 @@ public class XmlstreamTest {
} catch (Exception e) {
}
System.err.println(ListsuffixResultConverter
.containRefundDetailConvert(sb.toString(),
System.err.println(ListsuffixResultDeserializer
.containRefundDetailDeserialize(sb.toString(),
com.foxinmy.weixin4j.mp.payment.v3.RefundRecord.class));
}

View File

@ -48,4 +48,8 @@
* 2015-04-13
+ 新增WeixinTokenCreator与WeixinJSTicketCreator类
+ 新增WeixinTokenCreator与WeixinJSTicketCreator类
* 2015-06-12
+ 新增企业号[登陆授权](src/main/java/com/foxinmy/weixin4j/qy/api/OauthApi.java)API

View File

@ -22,6 +22,8 @@ weixin4j-qy
* AgentApi `应用设置API`
* BatchApi `批量操作API`
* OauthApi `oauth授权登陆API`
如何使用
--------

View File

@ -67,7 +67,7 @@ public class WeixinProxy {
/**
* 默认使用weixin4j.properties配置的账号信息
*
* @param tokenStorager
* @param tokenStorager token存储策略
*/
public WeixinProxy(TokenStorager tokenStorager) {
this(tokenStorager, ConfigUtil.getWeixinAccount());

View File

@ -0,0 +1,145 @@
package com.foxinmy.weixin4j.qy.api;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.deserializer.ExtraProcessor;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.qy.model.Corpinfo;
import com.foxinmy.weixin4j.qy.model.OUserInfo;
import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
import com.foxinmy.weixin4j.qy.token.WeixinProviderTokenCreator;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 企业号oauth授权
*
* @className OauthApi
* @author jy
* @date 2015年6月11日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%99%BB%E5%BD%95%E6%8E%88%E6%9D%83">企业号登录授权说明</a>
*/
public class OauthApi extends QyApi {
private final TokenHolder providerTokenHolder;
/**
* 默认使用文件方式保存token使用weixin4j.properties配置的账号信息
*/
public OauthApi() {
this(new FileTokenStorager());
}
/**
* 默认使用weixin4j.properties配置的账号信息
*
* @param tokenStorager
*/
public OauthApi(TokenStorager tokenStorager) {
this(tokenStorager, JSON.parseObject(ConfigUtil.getValue("account"),
WeixinQyAccount.class));
}
/**
*
* @param appid
* @param appsecret
*/
public OauthApi(String corpid, String providerSecret) {
providerTokenHolder = new TokenHolder(new WeixinProviderTokenCreator(
corpid, providerSecret), new FileTokenStorager());
}
/**
*
* @param tokenStorager
* token存储策略
* @param weixinAccount
* 公众号账号信息
*/
public OauthApi(TokenStorager tokenStorager, WeixinQyAccount qyAccount) {
providerTokenHolder = new TokenHolder(new WeixinProviderTokenCreator(
qyAccount), tokenStorager);
}
/**
* @see {@link com.foxinmy.weixin4j.qy.api.OauthApi#getAuthorizeURL(String, String,String)}
*
* @return 请求授权的URL
*/
public String getAuthorizeURL() {
String corpId = ConfigUtil.getWeixinAccount().getId();
String redirectUri = ConfigUtil.getValue("redirect_uri");
return getAuthorizeURL(corpId, redirectUri, "state");
}
/**
* oauth授权
*
* @param corpId
* 企业号提供商的corpid
* @param redirectUri
* 重定向地址
* @param state
* 用于保持请求和回调的状态授权请求后原样带回给第三方
* @return 请求授权的URL
*/
public String getAuthorizeURL(String corpId, String redirectUri,
String state) {
String oauth_uri = getRequestUri("provider_oauth_uri");
try {
return String.format(oauth_uri, corpId,
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state);
} catch (UnsupportedEncodingException e) {
;
}
return "";
}
/**
* 获取企业号管理员登录信息
*
* @param authCode
* oauth2.0授权企业号管理员登录产生的code
* @return 登陆信息
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E4%BC%81%E4%B8%9A%E7%AE%A1%E7%90%86%E5%91%98%E7%99%BB%E5%BD%95%E4%BF%A1%E6%81%AF">授权获取企业号管理员登录信息</a>
* @see com.foxinmy.weixin4j.qy.model.OUserInfo
* @throws WeixinException
*/
public OUserInfo getOUserInfo(String authCode) throws WeixinException {
String oauth_logininfo_uri = getRequestUri("oauth_logininfo_uri");
WeixinResponse response = weixinClient.post(String.format(
oauth_logininfo_uri, providerTokenHolder.getToken()
.getAccessToken()), String.format(
"{\"auth_code\":\"%s\"}", authCode));
return JSON.parseObject(response.getAsString(), OUserInfo.class,
new ExtraProcessor() {
@Override
public void processExtra(Object object, String key,
Object value) {
if (object instanceof Corpinfo) {
Corpinfo corpinfo = (Corpinfo) object;
if (key.equalsIgnoreCase("corp_name")) {
corpinfo.setName(value.toString());
} else if (key
.equalsIgnoreCase("corp_round_logo_url")) {
corpinfo.setRoundLogoUrl(value.toString());
} else if (key
.equalsIgnoreCase("corp_square_logo_url")) {
corpinfo.setSquareLogoUrl(value.toString());
}
}
}
});
}
}

View File

@ -0,0 +1,76 @@
package com.foxinmy.weixin4j.qy.model;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.qy.type.CorpType;
/**
* 授权方企业号信息
*
* @className Corpinfo
* @author jy
* @date 2015年6月12日
* @since JDK 1.7
* @see
*/
public class Corpinfo extends AgentOverview {
private static final long serialVersionUID = 1251033124778972419L;
/**
* 授权方企业号id
*/
private String corpid;
/**
* 授权方企业号类型
*/
@JSONField(name = "corp_type")
private CorpType corpType;
/**
* 授权方企业号用户规模
*/
@JSONField(name = "corp_user_max")
private int corpUserMax;
/**
* 授权方企业号应用规模
*/
@JSONField(name = "corp_agent_max")
private int corpAgentMax;
public String getCorpid() {
return corpid;
}
public void setCorpid(String corpid) {
this.corpid = corpid;
}
public CorpType getCorpType() {
return corpType;
}
public void setCorpType(CorpType corpType) {
this.corpType = corpType;
}
public int getCorpUserMax() {
return corpUserMax;
}
public void setCorpUserMax(int corpUserMax) {
this.corpUserMax = corpUserMax;
}
public int getCorpAgentMax() {
return corpAgentMax;
}
public void setCorpAgentMax(int corpAgentMax) {
this.corpAgentMax = corpAgentMax;
}
@Override
public String toString() {
return "Corpinfo [corpid=" + corpid + ", corpType=" + corpType
+ ", corpUserMax=" + corpUserMax + ", corpAgentMax="
+ corpAgentMax + ", " + super.toString() + "]";
}
}

View File

@ -0,0 +1,147 @@
package com.foxinmy.weixin4j.qy.model;
import java.io.Serializable;
import java.util.List;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.foxinmy.weixin4j.qy.type.AgentAuthType;
/**
* oauth授权登陆信息
*
* @className OUserInfo
* @author jy
* @date 2015年6月12日
* @since JDK 1.7
* @see
*/
public class OUserInfo implements Serializable {
private static final long serialVersionUID = -567063562050171293L;
/**
* 是否系统管理员
*/
@JSONField(name = "is_sys")
private boolean isSysAdmin;
/**
* 是否内部管理员
*/
@JSONField(name = "is_inner")
private boolean isInnerAdmin;
/**
* 登陆管理员信息
*/
@JSONField(name = "user_info")
private User userInfo;
/**
* 授权方企业信息
*/
@JSONField(name = "corp_info")
private Corpinfo corpinfo;
/**
* 该管理员在该提供商中能使用的应用列表
*/
@JSONField(name = "agent")
private List<AgentItem> agentInfo;
/**
* 该管理员拥有的通讯录权限
*/
@JSONField(name = "auth_info")
private JSONObject authInfo;
public boolean isSysAdmin() {
return isSysAdmin;
}
public void setSysAdmin(boolean isSysAdmin) {
this.isSysAdmin = isSysAdmin;
}
public boolean isInnerAdmin() {
return isInnerAdmin;
}
public void setInnerAdmin(boolean isInnerAdmin) {
this.isInnerAdmin = isInnerAdmin;
}
public User getUserInfo() {
return userInfo;
}
public void setUserInfo(User userInfo) {
this.userInfo = userInfo;
}
public Corpinfo getCorpinfo() {
return corpinfo;
}
public void setCorpinfo(Corpinfo corpinfo) {
this.corpinfo = corpinfo;
}
public List<AgentItem> getAgentInfo() {
return agentInfo;
}
public void setAgentInfo(List<AgentItem> agentInfo) {
this.agentInfo = agentInfo;
}
public JSONObject getAuthInfo() {
return authInfo;
}
public void setAuthInfo(JSONObject authInfo) {
this.authInfo = authInfo;
}
@Override
public String toString() {
return "OUserInfo [isSysAdmin=" + isSysAdmin + ", isInnerAdmin="
+ isInnerAdmin + ", userInfo=" + userInfo + ", corpinfo="
+ corpinfo + ", agentInfo=" + agentInfo + ", authInfo="
+ authInfo + "]";
}
public static class AgentItem {
/**
* 应用id
*/
private int agentid;
/**
* 管理员对应用的权限
*/
@JSONField(name = "auth_type")
private AgentAuthType authType;
public int getAgentid() {
return agentid;
}
public void setAgentid(int agentid) {
this.agentid = agentid;
}
public AgentAuthType getAuthType() {
return authType;
}
public void setAuthType(int authType) {
if (authType == 0) {
this.authType = AgentAuthType.USE;
} else if (authType == 1) {
this.authType = AgentAuthType.MANAGE;
}
this.authType = null;
}
@Override
public String toString() {
return "AgentItem [agentid=" + agentid + ", authType=" + authType
+ "]";
}
}
}

View File

@ -0,0 +1,64 @@
package com.foxinmy.weixin4j.qy.token;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinHttpClient;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.Token;
import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
import com.foxinmy.weixin4j.token.TokenCreator;
import com.foxinmy.weixin4j.util.ConfigUtil;
/**
* 微信企业号应用提供商凭证创建
*
* @className WeixinTokenCreator
* @author jy
* @date 2015年1月10日
* @since JDK 1.7
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E8%8E%B7%E5%8F%96%E5%BA%94%E7%94%A8%E6%8F%90%E4%BE%9B%E5%95%86%E5%87%AD%E8%AF%81">获取应用提供商凭证</a>
* @see com.foxinmy.weixin4j.model.Token
*/
public class WeixinProviderTokenCreator implements TokenCreator {
private final WeixinHttpClient httpClient;
private final String corpid;
private final String providersecret;
public WeixinProviderTokenCreator() {
this(JSON.parseObject(ConfigUtil.getValue("account"),
WeixinQyAccount.class));
}
public WeixinProviderTokenCreator(WeixinQyAccount qyAccount) {
this(qyAccount.getId(), qyAccount.getProviderSecret());
}
public WeixinProviderTokenCreator(String corpid, String providersecret) {
this.corpid = corpid;
this.providersecret = providersecret;
this.httpClient = new WeixinHttpClient();
}
@Override
public String getCacheKey() {
return String.format("qy_provider_token_%s", corpid);
}
@Override
public Token createToken() throws WeixinException {
JSONObject obj = new JSONObject();
obj.put("corpid", corpid);
obj.put("provider_secret", providersecret);
WeixinResponse response = httpClient.post(Consts.QY_PROVIDER_TOKEN_URL,
obj.toJSONString());
obj = response.getAsJson();
Token token = new Token(obj.getString("provider_access_token"));
token.setExpiresIn(obj.getIntValue("expires_in"));
token.setTime(System.currentTimeMillis());
return token;
}
}

View File

@ -0,0 +1,21 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 管理员对应用的权限
*
* @className AgentAuthType
* @author jy
* @date 2015年6月12日
* @since JDK 1.7
* @see
*/
public enum AgentAuthType {
/**
* 使用权限
*/
USE,
/**
* 管理权限
*/
MANAGE
}

View File

@ -0,0 +1,25 @@
package com.foxinmy.weixin4j.qy.type;
/**
* 授权方企业号类型
*
* @className CorpType
* @author jy
* @date 2015年6月12日
* @since JDK 1.7
* @see
*/
public enum CorpType {
/**
* 认证号
*/
verified,
/**
* 注册号
*/
unverified,
/**
* 体验号
*/
test;
}