diff --git a/CHANGE.md b/CHANGE.md index 763cb4c7..fc3cee9e 100644 --- a/CHANGE.md +++ b/CHANGE.md @@ -517,4 +517,12 @@ + weixin4j-[mp|qy]:version upgrade to 1.6.4 - + weixin4j-server:version upgrade to 1.1.4 \ No newline at end of file + + weixin4j-server:version upgrade to 1.1.4 + +* 2015-12-04 + + + weixin4j-base:【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest,便于二次发起支付。 + + + weixin4j-base:【重要】添加MchPayRequest的构造函数,便于二次发起支付。 + + + weixin4j-qy:【重要】第三方应用授权时获取永久授权码覆盖问题。 \ No newline at end of file diff --git a/weixin4j-base/CHANGE.md b/weixin4j-base/CHANGE.md index 13b877fe..a8da0023 100644 --- a/weixin4j-base/CHANGE.md +++ b/weixin4j-base/CHANGE.md @@ -85,4 +85,10 @@ + 调整PayUtil#createPayJsRequestJson参数位置:从主到次 - + 调整PayUtil#createNativePayRequestURL参数位置:从主到次 \ No newline at end of file + + 调整PayUtil#createNativePayRequestURL参数位置:从主到次 + +* 2015-12-04 + + +【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest,便于二次发起支付。 + + +【重要】添加MchPayRequest的构造函数,便于二次发起支付。 \ No newline at end of file diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java index 602cdf86..0b8a93fe 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/PayUtil.java @@ -82,12 +82,13 @@ public class PayUtil { String outTradeNo, double totalFee, String notifyUrl, String createIp, WeixinPayAccount weixinAccount) throws WeixinPayException { - return createPayJsRequestJson(weixinAccount, openId, body, outTradeNo, - totalFee, notifyUrl, createIp, null, null, null, null, null); + return JSON.toJSONString(createPayJsRequest(weixinAccount, openId, + body, outTradeNo, totalFee, notifyUrl, createIp, null, null, + null, null, null)); } /** - * 生成V3.x版本JSAPI支付字符串【完整参数】 + * 生成V3.x版本JSAPI支付对象【完整参数】 * * @param weixinAccount * 支付配置信息 @@ -113,14 +114,17 @@ public class PayUtil { * 商品标记,代金券或立减优惠功能的参数 * @param limitPay * 指定支付方式:no_credit--指定不能使用信用卡支付 - * @return 支付json串 + * @see com.foxinmy.weixin4j.payment.mch.MchPayRequest + * @return MchPayRequest对象;注意:如果要转换为JSON格式请使用fastjson包或者直接用MchPayRequest# + * asPayJsRequestJson方法 * @throws WeixinPayException */ - public static String createPayJsRequestJson(WeixinPayAccount weixinAccount, - String openId, String body, String outTradeNo, double totalFee, - String notifyUrl, String createIp, String attach, Date timeStart, - Date timeExpire, String goodsTag, String limitPay) - throws WeixinPayException { + public static MchPayRequest createPayJsRequest( + WeixinPayAccount weixinAccount, String openId, String body, + String outTradeNo, double totalFee, String notifyUrl, + String createIp, String attach, Date timeStart, Date timeExpire, + String goodsTag, String limitPay) throws WeixinPayException { MchPayPackage payPackage = new MchPayPackage(weixinAccount, openId, body, outTradeNo, totalFee, notifyUrl, createIp, TradeType.JSAPI); @@ -135,7 +139,7 @@ public class PayUtil { MchPayRequest jsPayRequest = new MchPayRequest(prePay); jsPayRequest.setSignType(SignType.MD5); jsPayRequest.setPaySign(paysignMd5(jsPayRequest, paySignKey)); - return JSON.toJSONString(jsPayRequest); + return jsPayRequest; } /** diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java index 3f5a0ddc..67be0c44 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/payment/mch/MchPayRequest.java @@ -3,8 +3,10 @@ package com.foxinmy.weixin4j.payment.mch; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; -import com.foxinmy.weixin4j.exception.WeixinPayException; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.annotation.JSONField; import com.foxinmy.weixin4j.payment.PayRequest; /** @@ -18,7 +20,7 @@ import com.foxinmy.weixin4j.payment.PayRequest; * NATIVE支付:PayRequest.TradeType=NATIVE *

* - * @className PayRequest + * @className MchPayRequest * @author jy * @date 2014年8月17日 * @since JDK 1.7 @@ -29,18 +31,43 @@ import com.foxinmy.weixin4j.payment.PayRequest; public class MchPayRequest extends PayRequest { private static final long serialVersionUID = -5972173459255255197L; - + + @XmlTransient + @JSONField(serialize = false) + private PrePay prePay; + protected MchPayRequest() { // jaxb required } - - public MchPayRequest(PrePay prePay) throws WeixinPayException { - this.setAppId(prePay.getAppId()); + + public MchPayRequest(PrePay prePay) { + this(prePay.getAppId(), prePay.getPrepayId()); + this.prePay = prePay; + } + + public MchPayRequest(String appId, String prepayId) { + this.setAppId(appId); this.setPackageInfo("prepay_id=" + prePay.getPrepayId()); } + /** + * 注意:MchPayRequest(String appId, String prepayId) 构造时 为空 + * + * @return 预支付对象 + */ + public PrePay getPrePay() { + return prePay; + } + + @XmlTransient + @JSONField(serialize = false) + public String asPayJsRequestJson() { + return JSON.toJSONString(this); + } + @Override public String toString() { return "MchPayRequest [" + super.toString() + "]"; } + } diff --git a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/QRParameter.java b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/QRParameter.java index f63aef04..1b1aa2de 100644 --- a/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/QRParameter.java +++ b/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/model/QRParameter.java @@ -22,7 +22,7 @@ public class QRParameter implements Serializable { private static final long serialVersionUID = 6611187606558274253L; /** - * 临时二维码的有效时间,以秒为单位,最大不超过604800(即7天) + * 临时二维码的有效时间, 最大不超过2592000(即30天),此字段如果不填,则默认有效期为30秒 */ private int expireSeconds; /** diff --git a/weixin4j-qy/CHANGE.md b/weixin4j-qy/CHANGE.md index c372413a..7ea45e63 100644 --- a/weixin4j-qy/CHANGE.md +++ b/weixin4j-qy/CHANGE.md @@ -129,3 +129,7 @@ * 2015-12-01 + version upgrade to 1.6.3 + +* 2015-12-04 + + +【重要】第三方应用授权时获取永久授权码覆盖问题。 diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java index 04cf1f7d..1f9f4cb4 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/api/SuiteApi.java @@ -37,10 +37,6 @@ public class SuiteApi extends QyApi { * 应用套件ticket */ private final SuiteTicketHolder suiteTicketHolder; - /** - * 应用套件永久授权码 - */ - private final SuitePerCodeHolder suitePerCodeHolder; /** * 应用套件pre_code */ @@ -62,9 +58,6 @@ public class SuiteApi extends QyApi { new WeixinSuitePreCodeCreator(suiteTokenHolder, suiteTicketHolder.getSuiteId()), suiteTicketHolder.getTokenStorager()); - this.suitePerCodeHolder = new SuitePerCodeHolder( - suiteTicketHolder.getSuiteId(), - suiteTicketHolder.getTokenStorager()); } /** @@ -95,12 +88,16 @@ public class SuiteApi extends QyApi { } /** - * 应用套件永久授权码 + * 应用套件永久授权码:企业号的永久授权码 * + * @param authCorpid + * 授权方corpid * @return */ - public SuitePerCodeHolder getPerCodeHolder() { - return this.suitePerCodeHolder; + public SuitePerCodeHolder getPerCodeHolder(String authCorpId) { + return new SuitePerCodeHolder(authCorpId, + suiteTicketHolder.getSuiteId(), + suiteTicketHolder.getTokenStorager()); } /** @@ -110,9 +107,9 @@ public class SuiteApi extends QyApi { * 授权方corpid * @return 企业号token */ - public TokenHolder createTokenHolder(String authCorpid) { - return new TokenHolder(new WeixinTokenSuiteCreator(authCorpid, - suitePerCodeHolder, suiteTokenHolder), + public TokenHolder createTokenHolder(String authCorpId) { + return new TokenHolder(new WeixinTokenSuiteCreator(authCorpId, + getPerCodeHolder(authCorpId), suiteTokenHolder), suiteTicketHolder.getTokenStorager()); } @@ -165,6 +162,9 @@ public class SuiteApi extends QyApi { obj.put("corp_info", obj.remove("auth_corp_info")); obj.put("user_info", obj.remove("auth_user_info")); OUserInfo oInfo = JSON.toJavaObject(obj, OUserInfo.class); + // 微信授权企业号的永久授权码 + SuitePerCodeHolder suitePerCodeHolder = getPerCodeHolder(oInfo + .getCorpInfo().getCorpId()); // 缓存微信企业号access_token TokenCreator tokenCreator = new WeixinTokenSuiteCreator(null, suitePerCodeHolder, suiteTokenHolder); @@ -182,7 +182,7 @@ public class SuiteApi extends QyApi { /** * 获取企业号的授权信息 * - * @param authCorpid + * @param authCorpId * 授权方corpid * @return 授权方信息 * @throws WeixinException @@ -190,12 +190,13 @@ public class SuiteApi extends QyApi { * @see 获取企业号的授权信息 */ - public OUserInfo getOAuthInfo(String authCorpid) throws WeixinException { + public OUserInfo getOAuthInfo(String authCorpId) throws WeixinException { String suite_get_authinfo_uri = getRequestUri("suite_get_authinfo_uri"); JSONObject obj = new JSONObject(); obj.put("suite_id", suiteTicketHolder.getSuiteId()); - obj.put("auth_corpid", authCorpid); - obj.put("permanent_code", suitePerCodeHolder.getPermanentCode()); + obj.put("auth_corpid", authCorpId); + obj.put("permanent_code", getPerCodeHolder(authCorpId) + .getPermanentCode()); WeixinResponse response = weixinExecutor.post( String.format(suite_get_authinfo_uri, suiteTokenHolder.getAccessToken()), obj.toJSONString()); @@ -208,7 +209,7 @@ public class SuiteApi extends QyApi { /** * 获取企业号应用 * - * @param authCorpid + * @param authCorpId * 授权方corpid * @param agentid * 授权方应用id @@ -218,13 +219,14 @@ public class SuiteApi extends QyApi { * href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%94%E7%94%A8%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E#.E8.8E.B7.E5.8F.96.E4.BC.81.E4.B8.9A.E5.8F.B7.E5.BA.94.E7.94.A8">获取企业号应用 * @throws WeixinException */ - public AgentInfo getAgent(String authCorpid, int agentid) + public AgentInfo getAgent(String authCorpId, int agentid) throws WeixinException { String suite_get_agent_uri = getRequestUri("suite_get_agent_uri"); JSONObject obj = new JSONObject(); obj.put("suite_id", suiteTicketHolder.getSuiteId()); - obj.put("auth_corpid", authCorpid); - obj.put("permanent_code", suitePerCodeHolder.getPermanentCode()); + obj.put("auth_corpid", authCorpId); + obj.put("permanent_code", getPerCodeHolder(authCorpId) + .getPermanentCode()); obj.put("agentid", agentid); WeixinResponse response = weixinExecutor.post( String.format(suite_get_agent_uri, @@ -245,7 +247,7 @@ public class SuiteApi extends QyApi { /** * 设置企业应用的选项设置信息,如:地理位置上报等 * - * @param authCorpid + * @param authCorpId * 授权方corpid * @param agentSet * 设置信息 @@ -255,13 +257,14 @@ public class SuiteApi extends QyApi { * @return 处理结果 * @throws WeixinException */ - public JsonResult setAgent(String authCorpid, AgentSetter agentSet) + public JsonResult setAgent(String authCorpId, AgentSetter agentSet) throws WeixinException { String suite_set_agent_uri = getRequestUri("suite_set_agent_uri"); JSONObject obj = new JSONObject(); obj.put("suite_id", suiteTicketHolder.getSuiteId()); - obj.put("auth_corpid", authCorpid); - obj.put("permanent_code", suitePerCodeHolder.getPermanentCode()); + obj.put("auth_corpid", authCorpId); + obj.put("permanent_code", getPerCodeHolder(authCorpId) + .getPermanentCode()); obj.put("agent", agentSet); WeixinResponse response = weixinExecutor.post( String.format(suite_set_agent_uri, diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeHolder.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeHolder.java index 628247a5..74f9640f 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeHolder.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/SuitePerCodeHolder.java @@ -15,10 +15,13 @@ import com.foxinmy.weixin4j.token.TokenStorager; */ public class SuitePerCodeHolder { + private final String authCorpId; private final String suiteId; private final TokenStorager tokenStorager; - public SuitePerCodeHolder(String suiteId, TokenStorager tokenStorager) { + public SuitePerCodeHolder(String authCorpId, String suiteId, + TokenStorager tokenStorager) { + this.authCorpId = authCorpId; this.suiteId = suiteId; this.tokenStorager = tokenStorager; } @@ -42,11 +45,11 @@ public class SuitePerCodeHolder { * @return */ public String getCacheKey() { - return String.format("qy_suite_percode_%s", suiteId); + return String.format("qy_suite_percode_%s:%s", suiteId, authCorpId); } /** - * 查找永久二维码 + * 查找永久授权码 * * @return * @throws WeixinException @@ -58,4 +61,8 @@ public class SuitePerCodeHolder { public String getSuiteId() { return this.suiteId; } + + public String getAuthCorpId() { + return this.authCorpId; + } } diff --git a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java index 244176c7..e9d76881 100644 --- a/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java +++ b/weixin4j-qy/src/main/java/com/foxinmy/weixin4j/qy/suite/WeixinTokenSuiteCreator.java @@ -23,22 +23,22 @@ import com.foxinmy.weixin4j.token.TokenHolder; public class WeixinTokenSuiteCreator implements TokenCreator { private final WeixinRequestExecutor weixinExecutor; - private final String authCorpid; + private final String authCorpId; private final SuitePerCodeHolder perCodeHolder; private final TokenHolder suiteTokenHolder; /** * - * @param suiteSecret + * @param authCorpId * 授权方corpid * @param perCodeHolder * 永久授权码 * @param suiteTokenHolder * 套件token */ - public WeixinTokenSuiteCreator(String authCorpid, + public WeixinTokenSuiteCreator(String authCorpId, SuitePerCodeHolder perCodeHolder, TokenHolder suiteTokenHolder) { - this.authCorpid = authCorpid; + this.authCorpId = authCorpId; this.perCodeHolder = perCodeHolder; this.suiteTokenHolder = suiteTokenHolder; this.weixinExecutor = new WeixinRequestExecutor(); @@ -46,14 +46,15 @@ public class WeixinTokenSuiteCreator implements TokenCreator { @Override public String getCacheKey() { - return String.format("qy_token_suite_%s", perCodeHolder.getSuiteId()); + return String.format("qy_token_suite_%s:%s", + perCodeHolder.getSuiteId(), authCorpId); } @Override public Token createToken() throws WeixinException { JSONObject obj = new JSONObject(); obj.put("suite_id", perCodeHolder.getSuiteId()); - obj.put("auth_corpid", authCorpid); + obj.put("auth_corpid", authCorpId); obj.put("permanent_code", perCodeHolder.getPermanentCode()); WeixinResponse response = weixinExecutor.post( String.format(URLConsts.TOKEN_SUITE_URL,