* 2015-12-04

+ weixin4j-base:【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest,便于二次发起支付。
  
  + weixin4j-base:【重要】添加MchPayRequest的构造函数,便于二次发起支付。
  
  + weixin4j-qy:【重要】第三方应用授权时获取永久授权码覆盖问题。
This commit is contained in:
jinyu 2015-12-04 19:04:05 +08:00
parent f659e8cffe
commit f2af43e46b
9 changed files with 113 additions and 53 deletions

View File

@ -518,3 +518,11 @@
+ weixin4j-[mp|qy]:version upgrade to 1.6.4 + weixin4j-[mp|qy]:version upgrade to 1.6.4
+ weixin4j-server:version upgrade to 1.1.4 + weixin4j-server:version upgrade to 1.1.4
* 2015-12-04
+ weixin4j-base:【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest便于二次发起支付。
+ weixin4j-base:【重要】添加MchPayRequest的构造函数便于二次发起支付。
+ weixin4j-qy:【重要】第三方应用授权时获取永久授权码覆盖问题。

View File

@ -86,3 +86,9 @@
+ 调整PayUtil#createPayJsRequestJson参数位置:从主到次 + 调整PayUtil#createPayJsRequestJson参数位置:从主到次
+ 调整PayUtil#createNativePayRequestURL参数位置:从主到次 + 调整PayUtil#createNativePayRequestURL参数位置:从主到次
* 2015-12-04
+【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest便于二次发起支付。
+【重要】添加MchPayRequest的构造函数便于二次发起支付。

View File

@ -82,12 +82,13 @@ public class PayUtil {
String outTradeNo, double totalFee, String notifyUrl, String outTradeNo, double totalFee, String notifyUrl,
String createIp, WeixinPayAccount weixinAccount) String createIp, WeixinPayAccount weixinAccount)
throws WeixinPayException { throws WeixinPayException {
return createPayJsRequestJson(weixinAccount, openId, body, outTradeNo, return JSON.toJSONString(createPayJsRequest(weixinAccount, openId,
totalFee, notifyUrl, createIp, null, null, null, null, null); body, outTradeNo, totalFee, notifyUrl, createIp, null, null,
null, null, null));
} }
/** /**
* 生成V3.x版本JSAPI支付字符串完整参数 * 生成V3.x版本JSAPI支付对象完整参数
* *
* @param weixinAccount * @param weixinAccount
* 支付配置信息 * 支付配置信息
@ -113,14 +114,17 @@ public class PayUtil {
* 商品标记代金券或立减优惠功能的参数 * 商品标记代金券或立减优惠功能的参数
* @param limitPay * @param limitPay
* 指定支付方式:no_credit--指定不能使用信用卡支付 * 指定支付方式:no_credit--指定不能使用信用卡支付
* @return 支付json串 * @see com.foxinmy.weixin4j.payment.mch.MchPayRequest
* @return MchPayRequest对象<font
* color="red">注意如果要转换为JSON格式请使用fastjson包或者直接用MchPayRequest#
* asPayJsRequestJson方法</font>
* @throws WeixinPayException * @throws WeixinPayException
*/ */
public static String createPayJsRequestJson(WeixinPayAccount weixinAccount, public static MchPayRequest createPayJsRequest(
String openId, String body, String outTradeNo, double totalFee, WeixinPayAccount weixinAccount, String openId, String body,
String notifyUrl, String createIp, String attach, Date timeStart, String outTradeNo, double totalFee, String notifyUrl,
Date timeExpire, String goodsTag, String limitPay) String createIp, String attach, Date timeStart, Date timeExpire,
throws WeixinPayException { String goodsTag, String limitPay) throws WeixinPayException {
MchPayPackage payPackage = new MchPayPackage(weixinAccount, openId, MchPayPackage payPackage = new MchPayPackage(weixinAccount, openId,
body, outTradeNo, totalFee, notifyUrl, createIp, body, outTradeNo, totalFee, notifyUrl, createIp,
TradeType.JSAPI); TradeType.JSAPI);
@ -135,7 +139,7 @@ public class PayUtil {
MchPayRequest jsPayRequest = new MchPayRequest(prePay); MchPayRequest jsPayRequest = new MchPayRequest(prePay);
jsPayRequest.setSignType(SignType.MD5); jsPayRequest.setSignType(SignType.MD5);
jsPayRequest.setPaySign(paysignMd5(jsPayRequest, paySignKey)); jsPayRequest.setPaySign(paysignMd5(jsPayRequest, paySignKey));
return JSON.toJSONString(jsPayRequest); return jsPayRequest;
} }
/** /**

View File

@ -3,8 +3,10 @@ package com.foxinmy.weixin4j.payment.mch;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement; 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; import com.foxinmy.weixin4j.payment.PayRequest;
/** /**
@ -18,7 +20,7 @@ import com.foxinmy.weixin4j.payment.PayRequest;
* NATIVE支付:PayRequest.TradeType=NATIVE * NATIVE支付:PayRequest.TradeType=NATIVE
* </p> * </p>
* *
* @className PayRequest * @className MchPayRequest
* @author jy * @author jy
* @date 2014年8月17日 * @date 2014年8月17日
* @since JDK 1.7 * @since JDK 1.7
@ -30,17 +32,42 @@ public class MchPayRequest extends PayRequest {
private static final long serialVersionUID = -5972173459255255197L; private static final long serialVersionUID = -5972173459255255197L;
@XmlTransient
@JSONField(serialize = false)
private PrePay prePay;
protected MchPayRequest() { protected MchPayRequest() {
// jaxb required // jaxb required
} }
public MchPayRequest(PrePay prePay) throws WeixinPayException { public MchPayRequest(PrePay prePay) {
this.setAppId(prePay.getAppId()); this(prePay.getAppId(), prePay.getPrepayId());
this.prePay = prePay;
}
public MchPayRequest(String appId, String prepayId) {
this.setAppId(appId);
this.setPackageInfo("prepay_id=" + prePay.getPrepayId()); 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 @Override
public String toString() { public String toString() {
return "MchPayRequest [" + super.toString() + "]"; return "MchPayRequest [" + super.toString() + "]";
} }
} }

View File

@ -22,7 +22,7 @@ public class QRParameter implements Serializable {
private static final long serialVersionUID = 6611187606558274253L; private static final long serialVersionUID = 6611187606558274253L;
/** /**
* 临时二维码的有效时间,以秒为单位,最大不超过604800即7天 * 临时二维码的有效时间, 最大不超过2592000即30天此字段如果不填则默认有效期为30秒
*/ */
private int expireSeconds; private int expireSeconds;
/** /**

View File

@ -129,3 +129,7 @@
* 2015-12-01 * 2015-12-01
+ version upgrade to 1.6.3 + version upgrade to 1.6.3
* 2015-12-04
+【重要】第三方应用授权时获取永久授权码覆盖问题。

View File

@ -37,10 +37,6 @@ public class SuiteApi extends QyApi {
* 应用套件ticket * 应用套件ticket
*/ */
private final SuiteTicketHolder suiteTicketHolder; private final SuiteTicketHolder suiteTicketHolder;
/**
* 应用套件永久授权码
*/
private final SuitePerCodeHolder suitePerCodeHolder;
/** /**
* 应用套件pre_code * 应用套件pre_code
*/ */
@ -62,9 +58,6 @@ public class SuiteApi extends QyApi {
new WeixinSuitePreCodeCreator(suiteTokenHolder, new WeixinSuitePreCodeCreator(suiteTokenHolder,
suiteTicketHolder.getSuiteId()), suiteTicketHolder.getSuiteId()),
suiteTicketHolder.getTokenStorager()); suiteTicketHolder.getTokenStorager());
this.suitePerCodeHolder = new SuitePerCodeHolder(
suiteTicketHolder.getSuiteId(),
suiteTicketHolder.getTokenStorager());
} }
/** /**
@ -95,12 +88,16 @@ public class SuiteApi extends QyApi {
} }
/** /**
* 应用套件永久授权码 * 应用套件永久授权码企业号的永久授权码
* *
* @param authCorpid
* 授权方corpid
* @return * @return
*/ */
public SuitePerCodeHolder getPerCodeHolder() { public SuitePerCodeHolder getPerCodeHolder(String authCorpId) {
return this.suitePerCodeHolder; return new SuitePerCodeHolder(authCorpId,
suiteTicketHolder.getSuiteId(),
suiteTicketHolder.getTokenStorager());
} }
/** /**
@ -110,9 +107,9 @@ public class SuiteApi extends QyApi {
* 授权方corpid * 授权方corpid
* @return 企业号token * @return 企业号token
*/ */
public TokenHolder createTokenHolder(String authCorpid) { public TokenHolder createTokenHolder(String authCorpId) {
return new TokenHolder(new WeixinTokenSuiteCreator(authCorpid, return new TokenHolder(new WeixinTokenSuiteCreator(authCorpId,
suitePerCodeHolder, suiteTokenHolder), getPerCodeHolder(authCorpId), suiteTokenHolder),
suiteTicketHolder.getTokenStorager()); suiteTicketHolder.getTokenStorager());
} }
@ -165,6 +162,9 @@ public class SuiteApi extends QyApi {
obj.put("corp_info", obj.remove("auth_corp_info")); obj.put("corp_info", obj.remove("auth_corp_info"));
obj.put("user_info", obj.remove("auth_user_info")); obj.put("user_info", obj.remove("auth_user_info"));
OUserInfo oInfo = JSON.toJavaObject(obj, OUserInfo.class); OUserInfo oInfo = JSON.toJavaObject(obj, OUserInfo.class);
// 微信授权企业号的永久授权码
SuitePerCodeHolder suitePerCodeHolder = getPerCodeHolder(oInfo
.getCorpInfo().getCorpId());
// 缓存微信企业号access_token // 缓存微信企业号access_token
TokenCreator tokenCreator = new WeixinTokenSuiteCreator(null, TokenCreator tokenCreator = new WeixinTokenSuiteCreator(null,
suitePerCodeHolder, suiteTokenHolder); suitePerCodeHolder, suiteTokenHolder);
@ -182,7 +182,7 @@ public class SuiteApi extends QyApi {
/** /**
* 获取企业号的授权信息 * 获取企业号的授权信息
* *
* @param authCorpid * @param authCorpId
* 授权方corpid * 授权方corpid
* @return 授权方信息 * @return 授权方信息
* @throws WeixinException * @throws WeixinException
@ -190,12 +190,13 @@ public class SuiteApi extends QyApi {
* @see <a * @see <a
* 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.E7.9A.84.E6.8E.88.E6.9D.83.E4.BF.A1.E6.81.AF">获取企业号的授权信息</a> * 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.E7.9A.84.E6.8E.88.E6.9D.83.E4.BF.A1.E6.81.AF">获取企业号的授权信息</a>
*/ */
public OUserInfo getOAuthInfo(String authCorpid) throws WeixinException { public OUserInfo getOAuthInfo(String authCorpId) throws WeixinException {
String suite_get_authinfo_uri = getRequestUri("suite_get_authinfo_uri"); String suite_get_authinfo_uri = getRequestUri("suite_get_authinfo_uri");
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId()); obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("auth_corpid", authCorpid); obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", suitePerCodeHolder.getPermanentCode()); obj.put("permanent_code", getPerCodeHolder(authCorpId)
.getPermanentCode());
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
String.format(suite_get_authinfo_uri, String.format(suite_get_authinfo_uri,
suiteTokenHolder.getAccessToken()), obj.toJSONString()); suiteTokenHolder.getAccessToken()), obj.toJSONString());
@ -208,7 +209,7 @@ public class SuiteApi extends QyApi {
/** /**
* 获取企业号应用 * 获取企业号应用
* *
* @param authCorpid * @param authCorpId
* 授权方corpid * 授权方corpid
* @param agentid * @param agentid
* 授权方应用id * 授权方应用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">获取企业号应用</a> * 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">获取企业号应用</a>
* @throws WeixinException * @throws WeixinException
*/ */
public AgentInfo getAgent(String authCorpid, int agentid) public AgentInfo getAgent(String authCorpId, int agentid)
throws WeixinException { throws WeixinException {
String suite_get_agent_uri = getRequestUri("suite_get_agent_uri"); String suite_get_agent_uri = getRequestUri("suite_get_agent_uri");
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId()); obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("auth_corpid", authCorpid); obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", suitePerCodeHolder.getPermanentCode()); obj.put("permanent_code", getPerCodeHolder(authCorpId)
.getPermanentCode());
obj.put("agentid", agentid); obj.put("agentid", agentid);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
String.format(suite_get_agent_uri, String.format(suite_get_agent_uri,
@ -245,7 +247,7 @@ public class SuiteApi extends QyApi {
/** /**
* 设置企业应用的选项设置信息地理位置上报等 * 设置企业应用的选项设置信息地理位置上报等
* *
* @param authCorpid * @param authCorpId
* 授权方corpid * 授权方corpid
* @param agentSet * @param agentSet
* 设置信息 * 设置信息
@ -255,13 +257,14 @@ public class SuiteApi extends QyApi {
* @return 处理结果 * @return 处理结果
* @throws WeixinException * @throws WeixinException
*/ */
public JsonResult setAgent(String authCorpid, AgentSetter agentSet) public JsonResult setAgent(String authCorpId, AgentSetter agentSet)
throws WeixinException { throws WeixinException {
String suite_set_agent_uri = getRequestUri("suite_set_agent_uri"); String suite_set_agent_uri = getRequestUri("suite_set_agent_uri");
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("suite_id", suiteTicketHolder.getSuiteId()); obj.put("suite_id", suiteTicketHolder.getSuiteId());
obj.put("auth_corpid", authCorpid); obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", suitePerCodeHolder.getPermanentCode()); obj.put("permanent_code", getPerCodeHolder(authCorpId)
.getPermanentCode());
obj.put("agent", agentSet); obj.put("agent", agentSet);
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
String.format(suite_set_agent_uri, String.format(suite_set_agent_uri,

View File

@ -15,10 +15,13 @@ import com.foxinmy.weixin4j.token.TokenStorager;
*/ */
public class SuitePerCodeHolder { public class SuitePerCodeHolder {
private final String authCorpId;
private final String suiteId; private final String suiteId;
private final TokenStorager tokenStorager; 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.suiteId = suiteId;
this.tokenStorager = tokenStorager; this.tokenStorager = tokenStorager;
} }
@ -42,11 +45,11 @@ public class SuitePerCodeHolder {
* @return * @return
*/ */
public String getCacheKey() { public String getCacheKey() {
return String.format("qy_suite_percode_%s", suiteId); return String.format("qy_suite_percode_%s:%s", suiteId, authCorpId);
} }
/** /**
* 查找永久二维 * 查找永久授权
* *
* @return * @return
* @throws WeixinException * @throws WeixinException
@ -58,4 +61,8 @@ public class SuitePerCodeHolder {
public String getSuiteId() { public String getSuiteId() {
return this.suiteId; return this.suiteId;
} }
public String getAuthCorpId() {
return this.authCorpId;
}
} }

View File

@ -23,22 +23,22 @@ import com.foxinmy.weixin4j.token.TokenHolder;
public class WeixinTokenSuiteCreator implements TokenCreator { public class WeixinTokenSuiteCreator implements TokenCreator {
private final WeixinRequestExecutor weixinExecutor; private final WeixinRequestExecutor weixinExecutor;
private final String authCorpid; private final String authCorpId;
private final SuitePerCodeHolder perCodeHolder; private final SuitePerCodeHolder perCodeHolder;
private final TokenHolder suiteTokenHolder; private final TokenHolder suiteTokenHolder;
/** /**
* *
* @param suiteSecret * @param authCorpId
* 授权方corpid * 授权方corpid
* @param perCodeHolder * @param perCodeHolder
* 永久授权码 * 永久授权码
* @param suiteTokenHolder * @param suiteTokenHolder
* 套件token * 套件token
*/ */
public WeixinTokenSuiteCreator(String authCorpid, public WeixinTokenSuiteCreator(String authCorpId,
SuitePerCodeHolder perCodeHolder, TokenHolder suiteTokenHolder) { SuitePerCodeHolder perCodeHolder, TokenHolder suiteTokenHolder) {
this.authCorpid = authCorpid; this.authCorpId = authCorpId;
this.perCodeHolder = perCodeHolder; this.perCodeHolder = perCodeHolder;
this.suiteTokenHolder = suiteTokenHolder; this.suiteTokenHolder = suiteTokenHolder;
this.weixinExecutor = new WeixinRequestExecutor(); this.weixinExecutor = new WeixinRequestExecutor();
@ -46,14 +46,15 @@ public class WeixinTokenSuiteCreator implements TokenCreator {
@Override @Override
public String getCacheKey() { public String getCacheKey() {
return String.format("qy_token_suite_%s", perCodeHolder.getSuiteId()); return String.format("qy_token_suite_%s:%s",
perCodeHolder.getSuiteId(), authCorpId);
} }
@Override @Override
public Token createToken() throws WeixinException { public Token createToken() throws WeixinException {
JSONObject obj = new JSONObject(); JSONObject obj = new JSONObject();
obj.put("suite_id", perCodeHolder.getSuiteId()); obj.put("suite_id", perCodeHolder.getSuiteId());
obj.put("auth_corpid", authCorpid); obj.put("auth_corpid", authCorpId);
obj.put("permanent_code", perCodeHolder.getPermanentCode()); obj.put("permanent_code", perCodeHolder.getPermanentCode());
WeixinResponse response = weixinExecutor.post( WeixinResponse response = weixinExecutor.post(
String.format(URLConsts.TOKEN_SUITE_URL, String.format(URLConsts.TOKEN_SUITE_URL,