parent
4420adca99
commit
0356484f44
@ -164,4 +164,8 @@
|
|||||||
|
|
||||||
+ type包拆分card/mch
|
+ type包拆分card/mch
|
||||||
|
|
||||||
+ 新增card卡券相关类
|
+ 新增card卡券相关类
|
||||||
|
|
||||||
|
* 2016-08-22
|
||||||
|
|
||||||
|
+ 删除`Weixin4jSettings`配置类
|
||||||
@ -1,7 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.api;
|
package com.foxinmy.weixin4j.api;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -48,8 +46,6 @@ public class CashApi extends MchApi {
|
|||||||
/**
|
/**
|
||||||
* 发放红包 企业向微信用户个人发现金红包
|
* 发放红包 企业向微信用户个人发现金红包
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param redpacket
|
* @param redpacket
|
||||||
* 红包信息
|
* 红包信息
|
||||||
* @return 发放结果
|
* @return 发放结果
|
||||||
@ -63,27 +59,16 @@ public class CashApi extends MchApi {
|
|||||||
* 发放裂变红包接口</a>
|
* 发放裂变红包接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public RedpacketSendResult sendRedpack(InputStream certificate,
|
public RedpacketSendResult sendRedpack(Redpacket redpacket)
|
||||||
Redpacket redpacket) throws WeixinException {
|
throws WeixinException {
|
||||||
super.declareMerchant(redpacket);
|
super.declareMerchant(redpacket);
|
||||||
JSONObject obj = (JSONObject) JSON.toJSON(redpacket);
|
JSONObject obj = (JSONObject) JSON.toJSON(redpacket);
|
||||||
obj.put("wxappid", obj.remove("appid"));
|
obj.put("wxappid", obj.remove("appid"));
|
||||||
obj.put("sign", weixinSignature.sign(obj));
|
obj.put("sign", weixinSignature.sign(obj));
|
||||||
String param = XmlStream.map2xml(obj);
|
String param = XmlStream.map2xml(obj);
|
||||||
WeixinResponse response = null;
|
WeixinResponse response = createSSLRequestExecutor()
|
||||||
try {
|
.post(redpacket.getTotalNum() > 1 ? getRequestUri("groupredpack_send_uri")
|
||||||
response = createSSLRequestExecutor(certificate)
|
: getRequestUri("redpack_send_uri"), param);
|
||||||
.post(redpacket.getTotalNum() > 1 ? getRequestUri("groupredpack_send_uri")
|
|
||||||
: getRequestUri("redpack_send_uri"), param);
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String text = response.getAsString()
|
String text = response.getAsString()
|
||||||
.replaceFirst("<wxappid>", "<appid>")
|
.replaceFirst("<wxappid>", "<appid>")
|
||||||
.replaceFirst("</wxappid>", "</appid>");
|
.replaceFirst("</wxappid>", "</appid>");
|
||||||
@ -93,8 +78,6 @@ public class CashApi extends MchApi {
|
|||||||
/**
|
/**
|
||||||
* 查询红包记录
|
* 查询红包记录
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param outTradeNo
|
* @param outTradeNo
|
||||||
* 商户发放红包的商户订单号
|
* 商户发放红包的商户订单号
|
||||||
* @return 红包记录
|
* @return 红包记录
|
||||||
@ -107,26 +90,15 @@ public class CashApi extends MchApi {
|
|||||||
* 查询裂变红包接口</a>
|
* 查询裂变红包接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public RedpacketRecord queryRedpack(InputStream certificate,
|
public RedpacketRecord queryRedpack(String outTradeNo)
|
||||||
String outTradeNo) throws WeixinException {
|
throws WeixinException {
|
||||||
Map<String, String> para = createBaseRequestMap(null);
|
Map<String, String> para = createBaseRequestMap(null);
|
||||||
para.put("bill_type", "MCHT");
|
para.put("bill_type", "MCHT");
|
||||||
para.put("mch_billno", outTradeNo);
|
para.put("mch_billno", outTradeNo);
|
||||||
para.put("sign", weixinSignature.sign(para));
|
para.put("sign", weixinSignature.sign(para));
|
||||||
String param = XmlStream.map2xml(para);
|
String param = XmlStream.map2xml(para);
|
||||||
WeixinResponse response = null;
|
WeixinResponse response = createSSLRequestExecutor().post(
|
||||||
try {
|
getRequestUri("redpack_query_uri"), param);
|
||||||
response = createSSLRequestExecutor(certificate).post(
|
|
||||||
getRequestUri("redpack_query_uri"), param);
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response.getAsObject(new TypeReference<RedpacketRecord>() {
|
return response.getAsObject(new TypeReference<RedpacketRecord>() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -143,8 +115,6 @@ public class CashApi extends MchApi {
|
|||||||
* <li>每个用户每天最多可付款10次,可以在商户平台--API安全进行设置
|
* <li>每个用户每天最多可付款10次,可以在商户平台--API安全进行设置
|
||||||
* <li>给同一个用户付款时间间隔不得低于15秒
|
* <li>给同一个用户付款时间间隔不得低于15秒
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param payment
|
* @param payment
|
||||||
* 付款信息
|
* 付款信息
|
||||||
* @return 付款结果
|
* @return 付款结果
|
||||||
@ -155,27 +125,16 @@ public class CashApi extends MchApi {
|
|||||||
* 企业付款接口</a>
|
* 企业付款接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public CorpPaymentResult sendCorpPayment(InputStream certificate,
|
public CorpPaymentResult sendCorpPayment(CorpPayment payment)
|
||||||
CorpPayment payment) throws WeixinException {
|
throws WeixinException {
|
||||||
super.declareMerchant(payment);
|
super.declareMerchant(payment);
|
||||||
JSONObject obj = (JSONObject) JSON.toJSON(payment);
|
JSONObject obj = (JSONObject) JSON.toJSON(payment);
|
||||||
obj.put("mchid", obj.remove("mch_id"));
|
obj.put("mchid", obj.remove("mch_id"));
|
||||||
obj.put("mch_appid", obj.remove("appid"));
|
obj.put("mch_appid", obj.remove("appid"));
|
||||||
obj.put("sign", weixinSignature.sign(obj));
|
obj.put("sign", weixinSignature.sign(obj));
|
||||||
String param = XmlStream.map2xml(obj);
|
String param = XmlStream.map2xml(obj);
|
||||||
WeixinResponse response = null;
|
WeixinResponse response = createSSLRequestExecutor().post(
|
||||||
try {
|
getRequestUri("corppayment_send_uri"), param);
|
||||||
response = createSSLRequestExecutor(certificate).post(
|
|
||||||
getRequestUri("corppayment_send_uri"), param);
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String text = response.getAsString()
|
String text = response.getAsString()
|
||||||
.replaceFirst("<mch_appid>", "<appid>")
|
.replaceFirst("<mch_appid>", "<appid>")
|
||||||
.replaceFirst("</mch_appid>", "</appid>")
|
.replaceFirst("</mch_appid>", "</appid>")
|
||||||
@ -187,8 +146,6 @@ public class CashApi extends MchApi {
|
|||||||
/**
|
/**
|
||||||
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param outTradeNo
|
* @param outTradeNo
|
||||||
* 商户调用企业付款API时使用的商户订单号
|
* 商户调用企业付款API时使用的商户订单号
|
||||||
* @return 付款记录
|
* @return 付款记录
|
||||||
@ -198,8 +155,8 @@ public class CashApi extends MchApi {
|
|||||||
* 企业付款查询接口</a>
|
* 企业付款查询接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public CorpPaymentRecord queryCorpPayment(InputStream certificate,
|
public CorpPaymentRecord queryCorpPayment(String outTradeNo)
|
||||||
String outTradeNo) throws WeixinException {
|
throws WeixinException {
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("nonce_str", RandomUtil.generateString(16));
|
obj.put("nonce_str", RandomUtil.generateString(16));
|
||||||
obj.put("mch_id", weixinAccount.getMchId());
|
obj.put("mch_id", weixinAccount.getMchId());
|
||||||
@ -207,19 +164,8 @@ public class CashApi extends MchApi {
|
|||||||
obj.put("partner_trade_no", outTradeNo);
|
obj.put("partner_trade_no", outTradeNo);
|
||||||
obj.put("sign", weixinSignature.sign(obj));
|
obj.put("sign", weixinSignature.sign(obj));
|
||||||
String param = XmlStream.map2xml(obj);
|
String param = XmlStream.map2xml(obj);
|
||||||
WeixinResponse response = null;
|
WeixinResponse response = createSSLRequestExecutor().post(
|
||||||
try {
|
getRequestUri("corppayment_query_uri"), param);
|
||||||
response = createSSLRequestExecutor(certificate).post(
|
|
||||||
getRequestUri("corppayment_query_uri"), param);
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response.getAsObject(new TypeReference<CorpPaymentRecord>() {
|
return response.getAsObject(new TypeReference<CorpPaymentRecord>() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.api;
|
package com.foxinmy.weixin4j.api;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
@ -21,7 +19,8 @@ import com.foxinmy.weixin4j.xml.XmlStream;
|
|||||||
* @author jinyu(foxinmy@gmail.com)
|
* @author jinyu(foxinmy@gmail.com)
|
||||||
* @date 2015年3月25日
|
* @date 2015年3月25日
|
||||||
* @since JDK 1.6
|
* @since JDK 1.6
|
||||||
* @see <a href="https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_1">代金券</a>
|
* @see <a
|
||||||
|
* href="https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_1">代金券</a>
|
||||||
*/
|
*/
|
||||||
public class CouponApi extends MchApi {
|
public class CouponApi extends MchApi {
|
||||||
|
|
||||||
@ -32,8 +31,6 @@ public class CouponApi extends MchApi {
|
|||||||
/**
|
/**
|
||||||
* 发放代金券(需要证书)
|
* 发放代金券(需要证书)
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param couponStockId
|
* @param couponStockId
|
||||||
* 代金券批次id
|
* 代金券批次id
|
||||||
* @param partnerTradeNo
|
* @param partnerTradeNo
|
||||||
@ -48,9 +45,8 @@ public class CouponApi extends MchApi {
|
|||||||
* href="https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_3">发放代金券接口</a>
|
* href="https://pay.weixin.qq.com/wiki/doc/api/tools/sp_coupon.php?chapter=12_3">发放代金券接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public CouponResult sendCoupon(InputStream certificate,
|
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
|
||||||
String couponStockId, String partnerTradeNo, String openId,
|
String openId, String opUserId) throws WeixinException {
|
||||||
String opUserId) throws WeixinException {
|
|
||||||
Map<String, String> map = createBaseRequestMap(null);
|
Map<String, String> map = createBaseRequestMap(null);
|
||||||
map.put("coupon_stock_id", couponStockId);
|
map.put("coupon_stock_id", couponStockId);
|
||||||
map.put("partner_trade_no", partnerTradeNo);
|
map.put("partner_trade_no", partnerTradeNo);
|
||||||
@ -66,19 +62,8 @@ public class CouponApi extends MchApi {
|
|||||||
map.put("type", "XML");
|
map.put("type", "XML");
|
||||||
map.put("sign", weixinSignature.sign(map));
|
map.put("sign", weixinSignature.sign(map));
|
||||||
String param = XmlStream.map2xml(map);
|
String param = XmlStream.map2xml(map);
|
||||||
WeixinResponse response = null;
|
WeixinResponse response = createSSLRequestExecutor().post(
|
||||||
try {
|
getRequestUri("coupon_send_uri"), param);
|
||||||
response = createSSLRequestExecutor(certificate).post(
|
|
||||||
getRequestUri("coupon_send_uri"), param);
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return response.getAsObject(new TypeReference<CouponResult>() {
|
return response.getAsObject(new TypeReference<CouponResult>() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
package com.foxinmy.weixin4j.api;
|
package com.foxinmy.weixin4j.api;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -55,10 +58,22 @@ public class MchApi extends BaseApi {
|
|||||||
* @return
|
* @return
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
protected WeixinRequestExecutor createSSLRequestExecutor(
|
protected WeixinRequestExecutor createSSLRequestExecutor()
|
||||||
InputStream certificate) throws WeixinException {
|
throws WeixinException {
|
||||||
|
InputStream certificateFile;
|
||||||
|
try {
|
||||||
|
File certificate = new File(weixinAccount.getCertificateFile());
|
||||||
|
if (!certificate.exists() || !certificate.isFile()) {
|
||||||
|
throw new WeixinException("invalid certificate file : "
|
||||||
|
+ certificate.toString());
|
||||||
|
}
|
||||||
|
certificateFile = new FileInputStream(
|
||||||
|
weixinAccount.getCertificateFile());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new WeixinException("IO Error on createSSLRequestExecutor", e);
|
||||||
|
}
|
||||||
return weixinExecutor.createSSLRequestExecutor(
|
return weixinExecutor.createSSLRequestExecutor(
|
||||||
weixinAccount.getCertificateKey(), certificate);
|
weixinAccount.getCertificateKey(), certificateFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -2,11 +2,9 @@ package com.foxinmy.weixin4j.api;
|
|||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@ -213,7 +211,7 @@ public class PayApi extends MchApi {
|
|||||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
||||||
* </a>
|
* </a>
|
||||||
*/
|
*/
|
||||||
public String createNativePayRequestURL(String productId) {
|
public String createNativePayRequest(String productId) {
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
String timestamp = DateUtil.timestamp2string();
|
String timestamp = DateUtil.timestamp2string();
|
||||||
String noncestr = RandomUtil.generateString(16);
|
String noncestr = RandomUtil.generateString(16);
|
||||||
@ -435,8 +433,6 @@ public class PayApi extends MchApi {
|
|||||||
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
|
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
@ -458,36 +454,28 @@ public class PayApi extends MchApi {
|
|||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
|
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||||
String outRefundNo, double totalFee, double refundFee,
|
double totalFee, double refundFee, CurrencyType refundFeeType,
|
||||||
CurrencyType refundFeeType, String opUserId) throws WeixinException {
|
String opUserId) throws WeixinException {
|
||||||
WeixinResponse response = null;
|
WeixinResponse response = null;
|
||||||
try {
|
Map<String, String> map = createBaseRequestMap(idQuery);
|
||||||
Map<String, String> map = createBaseRequestMap(idQuery);
|
map.put("out_refund_no", outRefundNo);
|
||||||
map.put("out_refund_no", outRefundNo);
|
map.put("total_fee",
|
||||||
map.put("total_fee", Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
|
Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
|
||||||
map.put("refund_fee", Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
|
map.put("refund_fee",
|
||||||
if (StringUtil.isBlank(opUserId)) {
|
Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
|
||||||
opUserId = weixinAccount.getMchId();
|
if (StringUtil.isBlank(opUserId)) {
|
||||||
}
|
opUserId = weixinAccount.getMchId();
|
||||||
map.put("op_user_id", opUserId);
|
|
||||||
if (refundFeeType == null) {
|
|
||||||
refundFeeType = CurrencyType.CNY;
|
|
||||||
}
|
|
||||||
map.put("refund_fee_type", refundFeeType.name());
|
|
||||||
map.put("sign", weixinSignature.sign(map));
|
|
||||||
String param = XmlStream.map2xml(map);
|
|
||||||
response = createSSLRequestExecutor(certificate).post(
|
|
||||||
getRequestUri("refund_apply_uri"), param);
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
map.put("op_user_id", opUserId);
|
||||||
|
if (refundFeeType == null) {
|
||||||
|
refundFeeType = CurrencyType.CNY;
|
||||||
|
}
|
||||||
|
map.put("refund_fee_type", refundFeeType.name());
|
||||||
|
map.put("sign", weixinSignature.sign(map));
|
||||||
|
String param = XmlStream.map2xml(map);
|
||||||
|
response = createSSLRequestExecutor().post(
|
||||||
|
getRequestUri("refund_apply_uri"), param);
|
||||||
return response.getAsObject(new TypeReference<RefundResult>() {
|
return response.getAsObject(new TypeReference<RefundResult>() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -495,8 +483,6 @@ public class PayApi extends MchApi {
|
|||||||
/**
|
/**
|
||||||
* 退款申请(全额退款)
|
* 退款申请(全额退款)
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
@ -504,12 +490,11 @@ public class PayApi extends MchApi {
|
|||||||
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
||||||
* @param totalFee
|
* @param totalFee
|
||||||
* 订单总金额,单位为元
|
* 订单总金额,单位为元
|
||||||
* @see {@link #applyRefund(InputStream, IdQuery, String, double, double,CurrencyType, String)}
|
* @see {@link #applyRefund(IdQuery, String, double, double,CurrencyType, String)}
|
||||||
*/
|
*/
|
||||||
public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
|
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||||
String outRefundNo, double totalFee) throws WeixinException {
|
double totalFee) throws WeixinException {
|
||||||
return applyRefund(certificate, idQuery, outRefundNo, totalFee,
|
return applyRefund(idQuery, outRefundNo, totalFee, totalFee, null, null);
|
||||||
totalFee, null, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -518,8 +503,6 @@ public class PayApi extends MchApi {
|
|||||||
* 如需实现相同功能请调用退款接口</font></br> <font
|
* 如需实现相同功能请调用退款接口</font></br> <font
|
||||||
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
|
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
@ -527,25 +510,14 @@ public class PayApi extends MchApi {
|
|||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public MerchantResult reverseOrder(InputStream certificate, IdQuery idQuery)
|
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException {
|
||||||
throws WeixinException {
|
Map<String, String> map = createBaseRequestMap(idQuery);
|
||||||
try {
|
map.put("sign", weixinSignature.sign(map));
|
||||||
Map<String, String> map = createBaseRequestMap(idQuery);
|
String param = XmlStream.map2xml(map);
|
||||||
map.put("sign", weixinSignature.sign(map));
|
WeixinResponse response = createSSLRequestExecutor().post(
|
||||||
String param = XmlStream.map2xml(map);
|
getRequestUri("order_reverse_uri"), param);
|
||||||
WeixinResponse response = createSSLRequestExecutor(certificate)
|
return response.getAsObject(new TypeReference<MerchantResult>() {
|
||||||
.post(getRequestUri("order_reverse_uri"), param);
|
});
|
||||||
return response.getAsObject(new TypeReference<MerchantResult>() {
|
|
||||||
});
|
|
||||||
} finally {
|
|
||||||
if (certificate != null) {
|
|
||||||
try {
|
|
||||||
certificate.close();
|
|
||||||
} catch (IOException e) {
|
|
||||||
;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -614,17 +586,16 @@ public class PayApi extends MchApi {
|
|||||||
* @param billType
|
* @param billType
|
||||||
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
||||||
* REFUND,返回当日退款订单
|
* REFUND,返回当日退款订单
|
||||||
* @param billPath
|
* @param outputStream
|
||||||
* 对账单保存路径
|
* 输出流
|
||||||
* @return excel表格
|
|
||||||
* @since V3
|
* @since V3
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">
|
* "http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">
|
||||||
* 下载对账单API</a>
|
* 下载对账单API</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public File downloadBill(Date billDate, BillType billType, String billPath)
|
public void downloadBill(Date billDate, BillType billType,
|
||||||
throws WeixinException {
|
OutputStream outputStream) throws WeixinException {
|
||||||
if (billDate == null) {
|
if (billDate == null) {
|
||||||
Calendar now = Calendar.getInstance();
|
Calendar now = Calendar.getInstance();
|
||||||
now.add(Calendar.DAY_OF_MONTH, -1);
|
now.add(Calendar.DAY_OF_MONTH, -1);
|
||||||
@ -634,14 +605,6 @@ public class PayApi extends MchApi {
|
|||||||
billType = BillType.ALL;
|
billType = BillType.ALL;
|
||||||
}
|
}
|
||||||
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
|
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
|
||||||
String fileName = String.format("weixin4j_bill_%s_%s_%s.txt",
|
|
||||||
formatBillDate, billType.name().toLowerCase(),
|
|
||||||
weixinAccount.getId());
|
|
||||||
File file = new File(String.format("%s%s%s", billPath, File.separator,
|
|
||||||
fileName));
|
|
||||||
if (file.exists()) {
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
Map<String, String> map = createBaseRequestMap(null);
|
Map<String, String> map = createBaseRequestMap(null);
|
||||||
map.put("bill_date", formatBillDate);
|
map.put("bill_date", formatBillDate);
|
||||||
map.put("bill_type", billType.name());
|
map.put("bill_type", billType.name());
|
||||||
@ -653,8 +616,8 @@ public class PayApi extends MchApi {
|
|||||||
BufferedReader reader = null;
|
BufferedReader reader = null;
|
||||||
BufferedWriter writer = null;
|
BufferedWriter writer = null;
|
||||||
try {
|
try {
|
||||||
writer = new BufferedWriter(new OutputStreamWriter(
|
writer = new BufferedWriter(new OutputStreamWriter(outputStream,
|
||||||
new FileOutputStream(file), Consts.UTF_8));
|
Consts.UTF_8));
|
||||||
reader = new BufferedReader(new InputStreamReader(
|
reader = new BufferedReader(new InputStreamReader(
|
||||||
response.getBody(), Consts.UTF_8));
|
response.getBody(), Consts.UTF_8));
|
||||||
String line = null;
|
String line = null;
|
||||||
@ -676,7 +639,6 @@ public class PayApi extends MchApi {
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return file;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -21,6 +21,18 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
|||||||
private final File tmpdir;
|
private final File tmpdir;
|
||||||
private final String SEPARATOR = File.separator;
|
private final String SEPARATOR = File.separator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认缓存路径:java.io.tmpdir
|
||||||
|
*/
|
||||||
|
public FileCacheStorager() {
|
||||||
|
this(System.getProperty("java.io.tmpdir"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param path
|
||||||
|
* 缓存文件报错
|
||||||
|
*/
|
||||||
public FileCacheStorager(String path) {
|
public FileCacheStorager(String path) {
|
||||||
this.tmpdir = new File(String.format("%s%s%s", path, SEPARATOR, ALLKEY));
|
this.tmpdir = new File(String.format("%s%s%s", path, SEPARATOR, ALLKEY));
|
||||||
this.tmpdir.mkdirs();
|
this.tmpdir.mkdirs();
|
||||||
@ -28,14 +40,17 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T lookup(String key) {
|
public T lookup(String key) {
|
||||||
File cacheFile = new File(String.format("%s%s%s", tmpdir.getAbsolutePath(), SEPARATOR, key));
|
File cacheFile = new File(String.format("%s%s%s",
|
||||||
|
tmpdir.getAbsolutePath(), SEPARATOR, key));
|
||||||
try {
|
try {
|
||||||
if (cacheFile.exists()) {
|
if (cacheFile.exists()) {
|
||||||
T cache = SerializationUtils.deserialize(new FileInputStream(cacheFile));
|
T cache = SerializationUtils.deserialize(new FileInputStream(
|
||||||
|
cacheFile));
|
||||||
if (cache.getCreateTime() < 0) {
|
if (cache.getCreateTime() < 0) {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
if ((cache.getCreateTime() + cache.getExpires() - CUTMS) > System.currentTimeMillis()) {
|
if ((cache.getCreateTime() + cache.getExpires() - CUTMS) > System
|
||||||
|
.currentTimeMillis()) {
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -48,8 +63,10 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
|||||||
@Override
|
@Override
|
||||||
public void caching(String key, T cache) {
|
public void caching(String key, T cache) {
|
||||||
try {
|
try {
|
||||||
SerializationUtils.serialize(cache,
|
SerializationUtils.serialize(
|
||||||
new FileOutputStream(new File(String.format("%s%s%s", tmpdir.getAbsolutePath(), SEPARATOR, key))));
|
cache,
|
||||||
|
new FileOutputStream(new File(String.format("%s%s%s",
|
||||||
|
tmpdir.getAbsolutePath(), SEPARATOR, key))));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@ -58,10 +75,12 @@ public class FileCacheStorager<T extends Cacheable> implements CacheStorager<T>
|
|||||||
@Override
|
@Override
|
||||||
public T evict(String key) {
|
public T evict(String key) {
|
||||||
T cache = null;
|
T cache = null;
|
||||||
File cacheFile = new File(String.format("%s%s%s", tmpdir.getAbsolutePath(), SEPARATOR, key));
|
File cacheFile = new File(String.format("%s%s%s",
|
||||||
|
tmpdir.getAbsolutePath(), SEPARATOR, key));
|
||||||
try {
|
try {
|
||||||
if (cacheFile.exists()) {
|
if (cacheFile.exists()) {
|
||||||
cache = SerializationUtils.deserialize(new FileInputStream(cacheFile));
|
cache = SerializationUtils.deserialize(new FileInputStream(
|
||||||
|
cacheFile));
|
||||||
cacheFile.delete();
|
cacheFile.delete();
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@ -124,8 +124,7 @@ public class WeixinRequestExecutor {
|
|||||||
* @return 微信响应
|
* @return 微信响应
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public WeixinResponse doRequest(HttpRequest request)
|
public WeixinResponse doRequest(HttpRequest request) throws WeixinException {
|
||||||
throws WeixinException {
|
|
||||||
try {
|
try {
|
||||||
if (logger.isEnabled(InternalLogLevel.DEBUG)) {
|
if (logger.isEnabled(InternalLogLevel.DEBUG)) {
|
||||||
logger.debug("weixin request >> " + request.getMethod() + " "
|
logger.debug("weixin request >> " + request.getMethod() + " "
|
||||||
@ -227,6 +226,12 @@ public class WeixinRequestExecutor {
|
|||||||
new java.security.SecureRandom());
|
new java.security.SecureRandom());
|
||||||
return createSSLRequestExecutor(sslContext);
|
return createSSLRequestExecutor(sslContext);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (IOException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
throw new WeixinException("Key load error", e);
|
throw new WeixinException("Key load error", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,10 +95,6 @@ public class Token implements Cacheable {
|
|||||||
return extra;
|
return extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setExtra(Map<String, String> extra) {
|
|
||||||
this.extra = extra;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Token pushExtra(String name, String value) {
|
public Token pushExtra(String name, String value) {
|
||||||
this.extra.put(name, value);
|
this.extra.put(name, value);
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@ -21,11 +21,11 @@ public class WeixinAccount implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* 唯一的身份标识
|
* 唯一的身份标识
|
||||||
*/
|
*/
|
||||||
private String id;
|
private final String id;
|
||||||
/**
|
/**
|
||||||
* 调用接口的密钥
|
* 调用接口的密钥
|
||||||
*/
|
*/
|
||||||
private String secret;
|
private final String secret;
|
||||||
|
|
||||||
@JSONCreator
|
@JSONCreator
|
||||||
public WeixinAccount(@JSONField(name = "id") String id,
|
public WeixinAccount(@JSONField(name = "id") String id,
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package com.foxinmy.weixin4j.model;
|
|||||||
import com.alibaba.fastjson.annotation.JSONCreator;
|
import com.alibaba.fastjson.annotation.JSONCreator;
|
||||||
import com.alibaba.fastjson.annotation.JSONField;
|
import com.alibaba.fastjson.annotation.JSONField;
|
||||||
import com.foxinmy.weixin4j.util.StringUtil;
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
|
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信支付账户
|
* 微信支付账户
|
||||||
@ -19,20 +20,23 @@ public class WeixinPayAccount extends WeixinAccount {
|
|||||||
/**
|
/**
|
||||||
* 公众号支付请求中用于加密的密钥
|
* 公众号支付请求中用于加密的密钥
|
||||||
*/
|
*/
|
||||||
private String paySignKey;
|
private final String paySignKey;
|
||||||
/**
|
/**
|
||||||
* 微信支付分配的商户号
|
* 微信支付分配的商户号
|
||||||
*/
|
*/
|
||||||
private String mchId;
|
private final String mchId;
|
||||||
/**
|
/**
|
||||||
* 加载支付证书文件的密码(默认为商户号)
|
* 加载支付证书文件的密码(默认为商户号)
|
||||||
*/
|
*/
|
||||||
private String certificateKey;
|
private String certificateKey;
|
||||||
|
/**
|
||||||
|
* 商户证书文件(默认加载classpath:ca.p12)
|
||||||
|
*/
|
||||||
|
private String certificateFile;
|
||||||
/**
|
/**
|
||||||
* 微信支付分配的设备号
|
* 微信支付分配的设备号
|
||||||
*/
|
*/
|
||||||
private String deviceInfo;
|
private String deviceInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 财付通商户身份的标识
|
* 财付通商户身份的标识
|
||||||
*/
|
*/
|
||||||
@ -58,7 +62,27 @@ public class WeixinPayAccount extends WeixinAccount {
|
|||||||
* 微信支付分配的商户号(必填)
|
* 微信支付分配的商户号(必填)
|
||||||
*/
|
*/
|
||||||
public WeixinPayAccount(String id, String paySignKey, String mchId) {
|
public WeixinPayAccount(String id, String paySignKey, String mchId) {
|
||||||
this(id, null, paySignKey, mchId, null, null, null, null, null);
|
this(id, paySignKey, mchId, mchId, "classpath:ca.p12");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付商户信息
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* 公众号唯一的身份ID(必填)
|
||||||
|
* @param paySignKey
|
||||||
|
* 支付密钥字符串(必填)
|
||||||
|
* @param mchId
|
||||||
|
* 微信支付分配的商户号(必填)
|
||||||
|
* @param certificateKey
|
||||||
|
* 加载支付证书文件的密码(默认为商户号)
|
||||||
|
* @param certificateFile
|
||||||
|
* 商户证书文件(默认加载classpath:ca.p12)
|
||||||
|
*/
|
||||||
|
public WeixinPayAccount(String id, String paySignKey, String mchId,
|
||||||
|
String certificateKey, String certificateFile) {
|
||||||
|
this(id, null, paySignKey, mchId, certificateKey, certificateFile,
|
||||||
|
null, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -74,6 +98,8 @@ public class WeixinPayAccount extends WeixinAccount {
|
|||||||
* 微信支付分配的商户号(必填)
|
* 微信支付分配的商户号(必填)
|
||||||
* @param certificateKey
|
* @param certificateKey
|
||||||
* 加载支付证书文件的密码(默认为商户号)
|
* 加载支付证书文件的密码(默认为商户号)
|
||||||
|
* @param certificateFile
|
||||||
|
* 商户证书文件(默认加载classpath:ca.p12)
|
||||||
* @param deviceInfo
|
* @param deviceInfo
|
||||||
* 微信支付分配的设备号(非必填)
|
* 微信支付分配的设备号(非必填)
|
||||||
* @param partnerId
|
* @param partnerId
|
||||||
@ -89,6 +115,7 @@ public class WeixinPayAccount extends WeixinAccount {
|
|||||||
@JSONField(name = "paySignKey") String paySignKey,
|
@JSONField(name = "paySignKey") String paySignKey,
|
||||||
@JSONField(name = "mchId") String mchId,
|
@JSONField(name = "mchId") String mchId,
|
||||||
@JSONField(name = "certificateKey") String certificateKey,
|
@JSONField(name = "certificateKey") String certificateKey,
|
||||||
|
@JSONField(name = "certificateFile") String certificateFile,
|
||||||
@JSONField(name = "deviceInfo") String deviceInfo,
|
@JSONField(name = "deviceInfo") String deviceInfo,
|
||||||
@JSONField(name = "partnerId") String partnerId,
|
@JSONField(name = "partnerId") String partnerId,
|
||||||
@JSONField(name = "subId") String subId,
|
@JSONField(name = "subId") String subId,
|
||||||
@ -97,6 +124,7 @@ public class WeixinPayAccount extends WeixinAccount {
|
|||||||
this.paySignKey = paySignKey;
|
this.paySignKey = paySignKey;
|
||||||
this.mchId = mchId;
|
this.mchId = mchId;
|
||||||
this.certificateKey = certificateKey;
|
this.certificateKey = certificateKey;
|
||||||
|
this.certificateFile = certificateFile;
|
||||||
this.deviceInfo = deviceInfo;
|
this.deviceInfo = deviceInfo;
|
||||||
this.partnerId = partnerId;
|
this.partnerId = partnerId;
|
||||||
this.subId = subId;
|
this.subId = subId;
|
||||||
@ -131,12 +159,40 @@ public class WeixinPayAccount extends WeixinAccount {
|
|||||||
return subMchId;
|
return subMchId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCertificateKey(String certificateKey) {
|
||||||
|
this.certificateKey = certificateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertificateFile() {
|
||||||
|
return Weixin4jConfigUtil.replaceClassPathValue(certificateFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertificateFile(String certificateFile) {
|
||||||
|
this.certificateFile = certificateFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeviceInfo(String deviceInfo) {
|
||||||
|
this.deviceInfo = deviceInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPartnerId(String partnerId) {
|
||||||
|
this.partnerId = partnerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubId(String subId) {
|
||||||
|
this.subId = subId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubMchId(String subMchId) {
|
||||||
|
this.subMchId = subMchId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "WeixinPayAccount [" + super.toString() + ", paySignKey="
|
return "WeixinPayAccount [" + super.toString() + ", paySignKey="
|
||||||
+ paySignKey + ", mchId=" + mchId + ", certificateKey="
|
+ paySignKey + ", mchId=" + mchId + ", certificateKey="
|
||||||
+ certificateKey + ", deviceInfo=" + deviceInfo
|
+ certificateKey + ",certificateFile =" + certificateFile
|
||||||
+ ", partnerId=" + partnerId + ", subId=" + subId
|
+ ", deviceInfo=" + deviceInfo + ", partnerId=" + partnerId
|
||||||
+ ", subMchId=" + subMchId + "]";
|
+ ", subId=" + subId + ", subMchId=" + subMchId + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,7 +23,7 @@ public class MediaCounter implements Serializable {
|
|||||||
@JSONField(name = "total_count")
|
@JSONField(name = "total_count")
|
||||||
private int totalCount;
|
private int totalCount;
|
||||||
/**
|
/**
|
||||||
* 文件素材总数目(企业号都有)
|
* 文件素材总数目(企业号独有)
|
||||||
*/
|
*/
|
||||||
@JSONField(name = "file_count")
|
@JSONField(name = "file_count")
|
||||||
private int fileCount;
|
private int fileCount;
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
package com.foxinmy.weixin4j.payment;
|
package com.foxinmy.weixin4j.payment;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.OutputStream;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
@ -37,7 +35,6 @@ import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
|
|||||||
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
|
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
|
||||||
import com.foxinmy.weixin4j.payment.mch.RefundResult;
|
import com.foxinmy.weixin4j.payment.mch.RefundResult;
|
||||||
import com.foxinmy.weixin4j.payment.mch.SettlementRecord;
|
import com.foxinmy.weixin4j.payment.mch.SettlementRecord;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
||||||
import com.foxinmy.weixin4j.type.CurrencyType;
|
import com.foxinmy.weixin4j.type.CurrencyType;
|
||||||
import com.foxinmy.weixin4j.type.CustomsCity;
|
import com.foxinmy.weixin4j.type.CustomsCity;
|
||||||
@ -73,32 +70,34 @@ public class WeixinPayProxy {
|
|||||||
*/
|
*/
|
||||||
private final CustomsApi customsApi;
|
private final CustomsApi customsApi;
|
||||||
/**
|
/**
|
||||||
* 配置信息
|
* 商户信息
|
||||||
*/
|
*/
|
||||||
private final Weixin4jSettings<WeixinPayAccount> settings;
|
private final WeixinPayAccount weixinPayAccount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用weixin4j.properties配置的支付账号信息
|
* 微信支付接口实现(使用weixin4j.properties配置的account商户信息)
|
||||||
*/
|
*/
|
||||||
public WeixinPayProxy() {
|
public WeixinPayProxy() {
|
||||||
this(
|
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
|
||||||
new Weixin4jSettings<WeixinPayAccount>(JSON.parseObject(
|
WeixinPayAccount.class));
|
||||||
Weixin4jConfigUtil.getValue("account"),
|
|
||||||
WeixinPayAccount.class)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 微信支付接口实现
|
||||||
* @param settings
|
*
|
||||||
* 支付相关配置信息
|
* @param weixinPayAccount
|
||||||
* @see com.foxinmy.weixin4j.setting.Weixin4jSettings
|
* 微信商户信息
|
||||||
*/
|
*/
|
||||||
public WeixinPayProxy(Weixin4jSettings<WeixinPayAccount> settings) {
|
public WeixinPayProxy(WeixinPayAccount weixinPayAccount) {
|
||||||
this.settings = settings;
|
if (weixinPayAccount == null) {
|
||||||
this.payApi = new PayApi(settings.getAccount());
|
throw new IllegalArgumentException(
|
||||||
this.couponApi = new CouponApi(settings.getAccount());
|
"weixinPayAccount must not be empty");
|
||||||
this.cashApi = new CashApi(settings.getAccount());
|
}
|
||||||
this.customsApi = new CustomsApi(settings.getAccount());
|
this.weixinPayAccount = weixinPayAccount;
|
||||||
|
this.payApi = new PayApi(weixinPayAccount);
|
||||||
|
this.couponApi = new CouponApi(weixinPayAccount);
|
||||||
|
this.cashApi = new CashApi(weixinPayAccount);
|
||||||
|
this.customsApi = new CustomsApi(weixinPayAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,7 +106,7 @@ public class WeixinPayProxy {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinPayAccount getWeixinPayAccount() {
|
public WeixinPayAccount getWeixinPayAccount() {
|
||||||
return settings.getAccount();
|
return weixinPayAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,8 +226,8 @@ public class WeixinPayProxy {
|
|||||||
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
* "https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一
|
||||||
* </a>
|
* </a>
|
||||||
*/
|
*/
|
||||||
public String createNativePayRequestURL(String productId) {
|
public String createNativePayRequest(String productId) {
|
||||||
return payApi.createNativePayRequestURL(productId);
|
return payApi.createNativePayRequest(productId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -431,8 +430,6 @@ public class WeixinPayProxy {
|
|||||||
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
|
* ,要采用原来的退款单号。总退款金额不能超过用户实际支付金额。
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
@ -456,11 +453,11 @@ public class WeixinPayProxy {
|
|||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public RefundResult applyRefund(InputStream certificate, IdQuery idQuery,
|
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||||
String outRefundNo, double totalFee, double refundFee,
|
double totalFee, double refundFee, CurrencyType refundFeeType,
|
||||||
CurrencyType refundFeeType, String opUserId) throws WeixinException {
|
String opUserId) throws WeixinException {
|
||||||
return payApi.applyRefund(certificate, idQuery, outRefundNo, totalFee,
|
return payApi.applyRefund(idQuery, outRefundNo, totalFee, refundFee,
|
||||||
refundFee, refundFeeType, opUserId);
|
refundFeeType, opUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -468,13 +465,11 @@ public class WeixinPayProxy {
|
|||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*
|
*
|
||||||
* @see {@link #applyRefund(InputStream, IdQuery, String, double, double, String,CurrencyType)}
|
* @see {@link #applyRefund(IdQuery, String, double, double, String,CurrencyType)}
|
||||||
*/
|
*/
|
||||||
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
public RefundResult applyRefund(IdQuery idQuery, String outRefundNo,
|
||||||
double totalFee) throws WeixinException, IOException {
|
double totalFee) throws WeixinException {
|
||||||
return payApi.applyRefund(
|
return payApi.applyRefund(idQuery, outRefundNo, totalFee);
|
||||||
new FileInputStream(settings.getCertificateFile0()), idQuery,
|
|
||||||
outRefundNo, totalFee);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -512,7 +507,7 @@ public class WeixinPayProxy {
|
|||||||
* @param billType
|
* @param billType
|
||||||
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
|
||||||
* REFUND,返回当日退款订单
|
* REFUND,返回当日退款订单
|
||||||
* @return excel表格
|
* @para outputStream 输出流
|
||||||
* @since V2 & V3
|
* @since V2 & V3
|
||||||
* @see com.foxinmy.weixin4j.api.PayApi
|
* @see com.foxinmy.weixin4j.api.PayApi
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
@ -520,9 +515,9 @@ public class WeixinPayProxy {
|
|||||||
* 下载对账单API</a>
|
* 下载对账单API</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public File downloadBill(Date billDate, BillType billType)
|
public void downloadBill(Date billDate, BillType billType,
|
||||||
throws WeixinException {
|
OutputStream outputStream) throws WeixinException {
|
||||||
return payApi.downloadBill(billDate, billType, settings.getTmpdir0());
|
payApi.downloadBill(billDate, billType, outputStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -531,8 +526,6 @@ public class WeixinPayProxy {
|
|||||||
* 如需实现相同功能请调用退款接口</font></br> <font
|
* 如需实现相同功能请调用退款接口</font></br> <font
|
||||||
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
|
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font> </br>
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 证书文件(V2版本后缀为*.pfx,V3版本后缀为*.p12)
|
|
||||||
* @param idQuery
|
* @param idQuery
|
||||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||||
* transaction_id> out_trade_no
|
* transaction_id> out_trade_no
|
||||||
@ -541,25 +534,8 @@ public class WeixinPayProxy {
|
|||||||
* @since V3
|
* @since V3
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public MerchantResult reverseOrder(InputStream certificate, IdQuery idQuery)
|
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException {
|
||||||
throws WeixinException {
|
return payApi.reverseOrder(idQuery);
|
||||||
return payApi.reverseOrder(certificate, idQuery);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 冲正撤销
|
|
||||||
*
|
|
||||||
* @param idQuery
|
|
||||||
* transaction_id、out_trade_no 二选一
|
|
||||||
* @return 撤销结果
|
|
||||||
* @see {@link #reverseOrder(InputStream, IdQuery)}
|
|
||||||
* @throws WeixinException
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public MerchantResult reverseOrder(IdQuery idQuery) throws WeixinException,
|
|
||||||
IOException {
|
|
||||||
return payApi.reverseOrder(
|
|
||||||
new FileInputStream(settings.getCertificateFile0()), idQuery);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -634,8 +610,6 @@ public class WeixinPayProxy {
|
|||||||
/**
|
/**
|
||||||
* 发放代金券(需要证书)
|
* 发放代金券(需要证书)
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param couponStockId
|
* @param couponStockId
|
||||||
* 代金券批次id
|
* 代金券批次id
|
||||||
* @param partnerTradeNo
|
* @param partnerTradeNo
|
||||||
@ -652,23 +626,10 @@ public class WeixinPayProxy {
|
|||||||
* 发放代金券接口</a>
|
* 发放代金券接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public CouponResult sendCoupon(InputStream certificate,
|
|
||||||
String couponStockId, String partnerTradeNo, String openId,
|
|
||||||
String opUserId) throws WeixinException {
|
|
||||||
return couponApi.sendCoupon(certificate, couponStockId, partnerTradeNo,
|
|
||||||
openId, opUserId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发放代金券
|
|
||||||
*
|
|
||||||
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#sendCoupon(InputStream, String, String, String, String)}
|
|
||||||
*/
|
|
||||||
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
|
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
|
||||||
String openId) throws WeixinException, IOException {
|
String openId, String opUserId) throws WeixinException {
|
||||||
return couponApi.sendCoupon(
|
return couponApi.sendCoupon(couponStockId, partnerTradeNo, openId,
|
||||||
new FileInputStream(settings.getCertificateFile0()),
|
opUserId);
|
||||||
couponStockId, partnerTradeNo, openId, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -710,8 +671,6 @@ public class WeixinPayProxy {
|
|||||||
/**
|
/**
|
||||||
* 发放红包 企业向微信用户个人发现金红包
|
* 发放红包 企业向微信用户个人发现金红包
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param redpacket
|
* @param redpacket
|
||||||
* 红包信息
|
* 红包信息
|
||||||
* @return 发放结果
|
* @return 发放结果
|
||||||
@ -726,27 +685,14 @@ public class WeixinPayProxy {
|
|||||||
* 发放裂变红包接口</a>
|
* 发放裂变红包接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public RedpacketSendResult sendRedpack(InputStream certificate,
|
|
||||||
Redpacket redpacket) throws WeixinException {
|
|
||||||
return cashApi.sendRedpack(certificate, redpacket);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 发放红包
|
|
||||||
*
|
|
||||||
* @see {@link #sendRedpack(InputStream, Redpacket)}
|
|
||||||
*/
|
|
||||||
public RedpacketSendResult sendRedpack(Redpacket redpacket)
|
public RedpacketSendResult sendRedpack(Redpacket redpacket)
|
||||||
throws WeixinException, IOException {
|
throws WeixinException {
|
||||||
return cashApi.sendRedpack(
|
return cashApi.sendRedpack(redpacket);
|
||||||
new FileInputStream(settings.getCertificateFile0()), redpacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询红包记录
|
* 查询红包记录
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param outTradeNo
|
* @param outTradeNo
|
||||||
* 商户发放红包的商户订单号
|
* 商户发放红包的商户订单号
|
||||||
* @return 红包记录
|
* @return 红包记录
|
||||||
@ -760,22 +706,9 @@ public class WeixinPayProxy {
|
|||||||
* 查询裂变红包接口</a>
|
* 查询裂变红包接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public RedpacketRecord queryRedpack(InputStream certificate,
|
|
||||||
String outTradeNo) throws WeixinException {
|
|
||||||
return cashApi.queryRedpack(certificate, outTradeNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 查询红包
|
|
||||||
*
|
|
||||||
* @see {@link #queryRedpack(InputStream,String)}
|
|
||||||
*/
|
|
||||||
public RedpacketRecord queryRedpack(String outTradeNo)
|
public RedpacketRecord queryRedpack(String outTradeNo)
|
||||||
throws WeixinException, IOException {
|
throws WeixinException {
|
||||||
return cashApi
|
return cashApi.queryRedpack(outTradeNo);
|
||||||
.queryRedpack(
|
|
||||||
new FileInputStream(settings.getCertificateFile0()),
|
|
||||||
outTradeNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -790,8 +723,6 @@ public class WeixinPayProxy {
|
|||||||
* <li>每个用户每天最多可付款10次,可以在商户平台--API安全进行设置
|
* <li>每个用户每天最多可付款10次,可以在商户平台--API安全进行设置
|
||||||
* <li>给同一个用户付款时间间隔不得低于15秒
|
* <li>给同一个用户付款时间间隔不得低于15秒
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param payment
|
* @param payment
|
||||||
* 付款信息
|
* 付款信息
|
||||||
* @return 付款结果
|
* @return 付款结果
|
||||||
@ -803,27 +734,14 @@ public class WeixinPayProxy {
|
|||||||
* 企业付款接口</a>
|
* 企业付款接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public CorpPaymentResult sendCorpPayment(InputStream certificate,
|
|
||||||
CorpPayment payment) throws WeixinException {
|
|
||||||
return cashApi.sendCorpPayment(certificate, payment);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 企业付款
|
|
||||||
*
|
|
||||||
* @see {@link #sendCorpPayment(InputStream, CorpPayment)}
|
|
||||||
*/
|
|
||||||
public CorpPaymentResult sendCorpPayment(CorpPayment payment)
|
public CorpPaymentResult sendCorpPayment(CorpPayment payment)
|
||||||
throws WeixinException, IOException {
|
throws WeixinException {
|
||||||
return cashApi.sendCorpPayment(
|
return cashApi.sendCorpPayment(payment);
|
||||||
new FileInputStream(settings.getCertificateFile0()), payment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
||||||
*
|
*
|
||||||
* @param certificate
|
|
||||||
* 后缀为*.p12的证书文件
|
|
||||||
* @param outTradeNo
|
* @param outTradeNo
|
||||||
* 商户调用企业付款API时使用的商户订单号
|
* 商户调用企业付款API时使用的商户订单号
|
||||||
* @return 付款记录
|
* @return 付款记录
|
||||||
@ -834,22 +752,9 @@ public class WeixinPayProxy {
|
|||||||
* 企业付款查询接口</a>
|
* 企业付款查询接口</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public CorpPaymentRecord queryCorpPayment(InputStream certificate,
|
|
||||||
String outTradeNo) throws WeixinException {
|
|
||||||
return cashApi.queryCorpPayment(certificate, outTradeNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 企业付款查询
|
|
||||||
*
|
|
||||||
* @see {@link #CorpPaymentRecord(InputStream, String)}
|
|
||||||
*/
|
|
||||||
public CorpPaymentRecord queryCorpPayment(String outTradeNo)
|
public CorpPaymentRecord queryCorpPayment(String outTradeNo)
|
||||||
throws WeixinException, IOException {
|
throws WeixinException {
|
||||||
return cashApi
|
return cashApi.queryCorpPayment(outTradeNo);
|
||||||
.queryCorpPayment(
|
|
||||||
new FileInputStream(settings.getCertificateFile0()),
|
|
||||||
outTradeNo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,97 +0,0 @@
|
|||||||
package com.foxinmy.weixin4j.setting;
|
|
||||||
|
|
||||||
import com.foxinmy.weixin4j.cache.CacheStorager;
|
|
||||||
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
|
||||||
import com.foxinmy.weixin4j.model.Token;
|
|
||||||
import com.foxinmy.weixin4j.util.StringUtil;
|
|
||||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信配置相关
|
|
||||||
*
|
|
||||||
* @className Weixin4jSettings
|
|
||||||
* @author jinyu(foxinmy@gmail.com)
|
|
||||||
* @date 2016年1月28日
|
|
||||||
* @since JDK 1.6
|
|
||||||
* @see
|
|
||||||
*/
|
|
||||||
public class Weixin4jSettings<T> {
|
|
||||||
/**
|
|
||||||
* 账号信息
|
|
||||||
*/
|
|
||||||
private final T account;
|
|
||||||
/**
|
|
||||||
* 系统临时目录
|
|
||||||
*/
|
|
||||||
private String tmpdir;
|
|
||||||
/**
|
|
||||||
* Token的存储方式 默认为FileCacheStorager
|
|
||||||
*/
|
|
||||||
private CacheStorager<Token> cacheStorager;
|
|
||||||
/**
|
|
||||||
* 支付接口需要的证书文件(*.p12)
|
|
||||||
*/
|
|
||||||
private String certificateFile;
|
|
||||||
|
|
||||||
public Weixin4jSettings(T account) {
|
|
||||||
this.account = account;
|
|
||||||
}
|
|
||||||
|
|
||||||
public T getAccount() {
|
|
||||||
return account;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTmpdir() {
|
|
||||||
return tmpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTmpdir(String tmpdir) {
|
|
||||||
this.tmpdir = tmpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTmpdir0() {
|
|
||||||
if (StringUtil.isBlank(tmpdir)) {
|
|
||||||
return Weixin4jConfigUtil.getValue("weixin4j.tmpdir",
|
|
||||||
System.getProperty("java.io.tmpdir"));
|
|
||||||
}
|
|
||||||
return tmpdir;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CacheStorager<Token> getCacheStorager() {
|
|
||||||
return cacheStorager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CacheStorager<Token> getCacheStorager0() {
|
|
||||||
if (cacheStorager == null) {
|
|
||||||
return new FileCacheStorager<Token>(getTmpdir0());
|
|
||||||
}
|
|
||||||
return cacheStorager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCacheStorager(CacheStorager<Token> cacheStorager) {
|
|
||||||
this.cacheStorager = cacheStorager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertificateFile() {
|
|
||||||
return certificateFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getCertificateFile0() {
|
|
||||||
if (StringUtil.isBlank(certificateFile)) {
|
|
||||||
return Weixin4jConfigUtil.getClassPathValue(
|
|
||||||
"weixin4j.certificate.file", "classpath:ca.p12");
|
|
||||||
}
|
|
||||||
return certificateFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCertificateFile(String certificateFile) {
|
|
||||||
this.certificateFile = certificateFile;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Weixin4jSettings [account=" + account + ", tmpdir=" + tmpdir
|
|
||||||
+ ", cacheStorager=" + cacheStorager + ", certificateFile="
|
|
||||||
+ certificateFile + "]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -13,10 +13,10 @@ import com.foxinmy.weixin4j.model.Token;
|
|||||||
* @date 2015年6月12日
|
* @date 2015年6月12日
|
||||||
* @since JDK 1.6
|
* @since JDK 1.6
|
||||||
* @see TokenCreator
|
* @see TokenCreator
|
||||||
|
* @see com.foxinmy.weixin4j.token.TokenCreator
|
||||||
* @see com.foxinmy.weixin4j.cache.CacheStorager
|
* @see com.foxinmy.weixin4j.cache.CacheStorager
|
||||||
*/
|
*/
|
||||||
public class TokenManager extends CacheManager<Token> {
|
public class TokenManager extends CacheManager<Token> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param tokenCreator
|
* @param tokenCreator
|
||||||
|
|||||||
@ -20,7 +20,8 @@ public class Weixin4jConfigUtil {
|
|||||||
private final static String CLASSPATH_VALUE;
|
private final static String CLASSPATH_VALUE;
|
||||||
private static ResourceBundle weixinBundle;
|
private static ResourceBundle weixinBundle;
|
||||||
static {
|
static {
|
||||||
CLASSPATH_VALUE = Thread.currentThread().getContextClassLoader().getResource("").getPath();
|
CLASSPATH_VALUE = Thread.currentThread().getContextClassLoader()
|
||||||
|
.getResource("").getPath();
|
||||||
try {
|
try {
|
||||||
weixinBundle = ResourceBundle.getBundle(Consts.WEIXIN4J);
|
weixinBundle = ResourceBundle.getBundle(Consts.WEIXIN4J);
|
||||||
} catch (MissingResourceException e) {
|
} catch (MissingResourceException e) {
|
||||||
@ -77,7 +78,7 @@ public class Weixin4jConfigUtil {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getClassPathValue(String key) {
|
public static String getClassPathValue(String key) {
|
||||||
return getValue(key).replaceFirst(CLASSPATH_PREFIX, CLASSPATH_VALUE);
|
return replaceClassPathValue(getValue(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,7 +88,11 @@ public class Weixin4jConfigUtil {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static String getClassPathValue(String key, String defaultValue) {
|
public static String getClassPathValue(String key, String defaultValue) {
|
||||||
return getValue(key, defaultValue).replaceFirst(CLASSPATH_PREFIX, CLASSPATH_VALUE);
|
return replaceClassPathValue(getValue(key, defaultValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String replaceClassPathValue(String value) {
|
||||||
|
return value.replaceFirst(CLASSPATH_PREFIX, CLASSPATH_VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,11 +103,14 @@ public class Weixin4jConfigUtil {
|
|||||||
public static WeixinAccount getWeixinAccount() {
|
public static WeixinAccount getWeixinAccount() {
|
||||||
WeixinAccount account = null;
|
WeixinAccount account = null;
|
||||||
try {
|
try {
|
||||||
account = JSON.parseObject(getValue("account"), WeixinAccount.class);
|
account = JSON
|
||||||
|
.parseObject(getValue("account"), WeixinAccount.class);
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
System.err.println("'weixin4j.account' key not found in weixin4j.properties.");
|
System.err
|
||||||
|
.println("'weixin4j.account' key not found in weixin4j.properties.");
|
||||||
} catch (MissingResourceException e) {
|
} catch (MissingResourceException e) {
|
||||||
System.err.println("'weixin4j.account' key not found in weixin4j.properties.");
|
System.err
|
||||||
|
.println("'weixin4j.account' key not found in weixin4j.properties.");
|
||||||
}
|
}
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.base.test;
|
package com.foxinmy.weixin4j.base.test;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -28,43 +25,39 @@ import com.foxinmy.weixin4j.util.Consts;
|
|||||||
public class CashTest extends PayTest {
|
public class CashTest extends PayTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendRedpacket() throws WeixinException, IOException {
|
public void sendRedpacket() throws WeixinException {
|
||||||
Redpacket redpacket = new Redpacket("HB001", "无忧钱庄",
|
Redpacket redpacket = new Redpacket("HB001", "无忧钱庄",
|
||||||
"oyFLst1bqtuTcxK-ojF8hOGtLQao", 1d, 1, "红包测试", "127.0.0.1",
|
"oyFLst1bqtuTcxK-ojF8hOGtLQao", 1d, 1, "红包测试", "127.0.0.1",
|
||||||
"快来领取红包吧!", "来就送钱");
|
"快来领取红包吧!", "来就送钱");
|
||||||
RedpacketSendResult result = PAY.sendRedpack(
|
RedpacketSendResult result = PAY.sendRedpack(redpacket);
|
||||||
new FileInputStream(caFile), redpacket);
|
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queryRedpacket() throws WeixinException, IOException {
|
public void queryRedpacket() throws WeixinException {
|
||||||
String outTradeNo = "HB001";
|
String outTradeNo = "HB001";
|
||||||
RedpacketRecord result = PAY.queryRedpack(new FileInputStream(caFile),
|
RedpacketRecord result = PAY.queryRedpack(outTradeNo);
|
||||||
outTradeNo);
|
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendCorpPayment() throws WeixinException, IOException {
|
public void sendCorpPayment() throws WeixinException {
|
||||||
CorpPayment payment = new CorpPayment("MP001",
|
CorpPayment payment = new CorpPayment("MP001",
|
||||||
"ofW1gwok9vZIyle0YbA-eQe83Uk8",
|
"ofW1gwok9vZIyle0YbA-eQe83Uk8",
|
||||||
CorpPaymentCheckNameType.NO_CHECK, "企业付款测试", 1d, "127.0.0.1");
|
CorpPaymentCheckNameType.NO_CHECK, "企业付款测试", 1d, "127.0.0.1");
|
||||||
CorpPaymentResult result = PAY.sendCorpPayment(new FileInputStream(
|
CorpPaymentResult result = PAY.sendCorpPayment(payment);
|
||||||
caFile), payment);
|
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queryCorpPayment() throws WeixinException, IOException {
|
public void queryCorpPayment() throws WeixinException {
|
||||||
CorpPaymentRecord result = PAY.queryCorpPayment(new FileInputStream(caFile),
|
CorpPaymentRecord result = PAY.queryCorpPayment("MP001");
|
||||||
"MP001");
|
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
|
|||||||
@ -1,7 +1,5 @@
|
|||||||
package com.foxinmy.weixin4j.base.test;
|
package com.foxinmy.weixin4j.base.test;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
@ -26,11 +24,11 @@ import com.foxinmy.weixin4j.util.DateUtil;
|
|||||||
public class CouponTest extends PayTest {
|
public class CouponTest extends PayTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void sendCoupon() throws WeixinException, IOException {
|
public void sendCoupon() throws WeixinException {
|
||||||
String partnerTradeNo = String.format("%s%s%s", ACCOUNT.getMchId(),
|
String partnerTradeNo = String.format("%s%s%s", ACCOUNT.getMchId(),
|
||||||
DateUtil.fortmat2yyyyMMdd(new Date()), "1");
|
DateUtil.fortmat2yyyyMMdd(new Date()), "1");
|
||||||
CouponResult result = PAY.sendCoupon(new FileInputStream(caFile),
|
CouponResult result = PAY.sendCoupon("123", partnerTradeNo,
|
||||||
"123", partnerTradeNo, "oyFLst1bqtuTcxK-ojF8hOGtLQao", null);
|
"oyFLst1bqtuTcxK-ojF8hOGtLQao", null);
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
package com.foxinmy.weixin4j.base.test;
|
package com.foxinmy.weixin4j.base.test;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.FileOutputStream;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@ -20,12 +20,12 @@ import com.foxinmy.weixin4j.payment.mch.Order;
|
|||||||
import com.foxinmy.weixin4j.payment.mch.PrePay;
|
import com.foxinmy.weixin4j.payment.mch.PrePay;
|
||||||
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
|
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
|
||||||
import com.foxinmy.weixin4j.payment.mch.RefundResult;
|
import com.foxinmy.weixin4j.payment.mch.RefundResult;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
|
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
|
||||||
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
||||||
import com.foxinmy.weixin4j.type.IdQuery;
|
import com.foxinmy.weixin4j.type.IdQuery;
|
||||||
import com.foxinmy.weixin4j.type.IdType;
|
import com.foxinmy.weixin4j.type.IdType;
|
||||||
import com.foxinmy.weixin4j.type.TradeType;
|
import com.foxinmy.weixin4j.type.TradeType;
|
||||||
|
import com.foxinmy.weixin4j.type.mch.BillType;
|
||||||
import com.foxinmy.weixin4j.util.Consts;
|
import com.foxinmy.weixin4j.util.Consts;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -43,17 +43,15 @@ public class PayTest {
|
|||||||
protected final static WeixinPayProxy PAY;
|
protected final static WeixinPayProxy PAY;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ACCOUNT = new WeixinPayAccount("wx0d1d598c0c03c999",
|
ACCOUNT = new WeixinPayAccount(
|
||||||
"GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ", "10020674");
|
"appid",
|
||||||
|
"paysignKey",
|
||||||
|
"mchId",
|
||||||
|
"证书密码,为空取mchid",
|
||||||
|
"证书路径,绝对路径&classpath路径:/path/to/certificate.p12,或者填写classpath:path/to/certificate.p12");
|
||||||
SIGNATURE = new WeixinPaymentSignature(ACCOUNT.getPaySignKey());
|
SIGNATURE = new WeixinPaymentSignature(ACCOUNT.getPaySignKey());
|
||||||
PAY = new WeixinPayProxy(
|
PAY = new WeixinPayProxy(ACCOUNT);
|
||||||
new Weixin4jSettings<WeixinPayAccount>(ACCOUNT));
|
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* 商户证书文件
|
|
||||||
*/
|
|
||||||
protected File caFile = new File(
|
|
||||||
"/Users/jy/workspace/feican/canyi-weixin-parent/canyi-weixin-service/src/main/resources/10020674.p12");
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void queryOrder() throws WeixinException {
|
public void queryOrder() throws WeixinException {
|
||||||
@ -86,22 +84,22 @@ public class PayTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void downbill() throws WeixinException {
|
public void downbill() throws WeixinException, IOException {
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
c.set(Calendar.YEAR, 2016);
|
c.set(Calendar.YEAR, 2016);
|
||||||
c.set(Calendar.MONTH, 3);
|
c.set(Calendar.MONTH, 3);
|
||||||
c.set(Calendar.DAY_OF_MONTH, 4);
|
c.set(Calendar.DAY_OF_MONTH, 4);
|
||||||
System.err.println(c.getTime());
|
System.err.println(c.getTime());
|
||||||
File file = PAY.downloadBill(c.getTime(), null);
|
OutputStream os = new FileOutputStream("/tmp/bill20160813.txt");
|
||||||
System.err.println(file);
|
PAY.downloadBill(c.getTime(), BillType.ALL, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void refund() throws WeixinException, IOException {
|
public void refund() throws WeixinException, IOException {
|
||||||
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
|
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
|
||||||
RefundResult result = PAY.applyRefund(new FileInputStream(caFile),
|
RefundResult result = PAY.applyRefund(idQuery,
|
||||||
idQuery, "TT_R" + System.currentTimeMillis(), 0.01d, 0.01d,
|
"TT_R" + System.currentTimeMillis(), 0.01d, 0.01d, null,
|
||||||
null, "10020674");
|
"10020674");
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getReturnCode());
|
||||||
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
Assert.assertEquals(Consts.SUCCESS, result.getResultCode());
|
||||||
System.err.println(result);
|
System.err.println(result);
|
||||||
|
|||||||
@ -8,37 +8,31 @@
|
|||||||
|
|
||||||
<!-- 微信接口代理~start -->
|
<!-- 微信接口代理~start -->
|
||||||
<bean id="weixinProxy" class="com.foxinmy.weixin4j.mp.WeixinProxy">
|
<bean id="weixinProxy" class="com.foxinmy.weixin4j.mp.WeixinProxy">
|
||||||
|
<!-- 公众号信息:不声明则默认使用weixin4j.properties配置的weixin4j.account字段 -->
|
||||||
<constructor-arg>
|
<constructor-arg>
|
||||||
<bean class="com.foxinmy.weixin4j.setting.Weixin4jSettings">
|
<bean class="com.foxinmy.weixin4j.model.WeixinAccount">
|
||||||
<!-- 公众号信息:不声明则默认使用weixin4j.properties配置的weixin4j.account字段 -->
|
<constructor-arg index="0" value="公众账号的appid" />
|
||||||
<constructor-arg>
|
<constructor-arg index="1" value="公众账号的appsecret" />
|
||||||
<bean class="com.foxinmy.weixin4j.model.WeixinAccount">
|
</bean>
|
||||||
<constructor-arg index="0" value="公众账号的appid" />
|
</constructor-arg>
|
||||||
<constructor-arg index="1" value="公众账号的appsecret" />
|
<!-- token存储:不声明则默认使用文件方式(FileCacheStorager)保存,请自行引入redis配置文件 -->
|
||||||
</bean>
|
<constructor-arg>
|
||||||
</constructor-arg>
|
<bean class="com.foxinmy.weixin4j.cache.RedisCacheStorager">
|
||||||
<!-- token存储:不声明则默认使用文件方式(FileTokenStorager)保存 -->
|
<constructor-arg type="redis.clients.jedis.JedisPool">
|
||||||
<!-- property name="tokenStorager">
|
<bean class="redis.clients.jedis.JedisPool">
|
||||||
<bean class="com.foxinmy.weixin4j.token.RedisTokenStorager">
|
<constructor-arg index="0">
|
||||||
<constructor-arg type="redis.clients.jedis.JedisPool">
|
<bean class="redis.clients.jedis.JedisPoolConfig">
|
||||||
<bean class="redis.clients.jedis.JedisPool">
|
<property name="maxTotal" value="${redis.maxTotal}" />
|
||||||
<constructor-arg index="0">
|
<property name="maxIdle" value="${redis.maxIdle}" />
|
||||||
<bean class="redis.clients.jedis.JedisPoolConfig">
|
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
|
||||||
<property name="maxTotal" value="${redis.maxTotal}" />
|
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
|
||||||
<property name="maxIdle" value="${redis.maxIdle}" />
|
|
||||||
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
|
|
||||||
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
|
|
||||||
</bean>
|
|
||||||
</constructor-arg>
|
|
||||||
<constructor-arg index="1" value="${redis.host}" />
|
|
||||||
<constructor-arg index="2" value="${redis.port}" />
|
|
||||||
<constructor-arg index="3" value="${redis.timeout}" />
|
|
||||||
</bean>
|
</bean>
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
|
<constructor-arg index="1" value="${redis.host}" />
|
||||||
|
<constructor-arg index="2" value="${redis.port}" />
|
||||||
|
<constructor-arg index="3" value="${redis.timeout}" />
|
||||||
</bean>
|
</bean>
|
||||||
</property -->
|
</constructor-arg>
|
||||||
<!-- 临时目录:weixin4j调用某些接口时需要用到的临时目录,不声明则获取顺序为:weixin4j.properties#weixin4j.tmpdir->`java.io.tmp` -->
|
|
||||||
<property name="tmpdir" value="/tmp/weixin4j" />
|
|
||||||
</bean>
|
</bean>
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
@ -47,19 +41,15 @@
|
|||||||
<!-- 微信支付接口代理~start -->
|
<!-- 微信支付接口代理~start -->
|
||||||
<bean id="weixinPayProxy" class="com.foxinmy.weixin4j.payment.WeixinPayProxy">
|
<bean id="weixinPayProxy" class="com.foxinmy.weixin4j.payment.WeixinPayProxy">
|
||||||
<constructor-arg>
|
<constructor-arg>
|
||||||
<bean class="com.foxinmy.weixin4j.setting.Weixin4jSettings">
|
<!-- 商户信息:不声明则默认使用weixin4j.properties配置的weixin4j.account字段 -->
|
||||||
<!-- 商户信息:不声明则默认使用weixin4j.properties配置的weixin4j.account字段 -->
|
<bean class="com.foxinmy.weixin4j.model.WeixinPayAccount">
|
||||||
<constructor-arg>
|
<constructor-arg index="0" value="公众账号的appid" />
|
||||||
<bean class="com.foxinmy.weixin4j.model.WeixinPayAccount">
|
<constructor-arg index="1" value="商户平台的支付密钥:paySignkey" />
|
||||||
<constructor-arg index="0" value="公众账号的appid" />
|
<constructor-arg index="2" value="商户平台的商户ID:mchId" />
|
||||||
<constructor-arg index="1" value="商户平台的支付密钥:paySignkey" />
|
<!-- 以下是证书配置,如用到请配置 -->
|
||||||
<constructor-arg index="2" value="商户平台的商户ID:mchId" />
|
<constructor-arg index="3" value="加载支付证书文件的密码(默认为商户号)" />
|
||||||
</bean>
|
|
||||||
</constructor-arg>
|
|
||||||
<!-- ca证书:调用某些支付接口(如退款、红包)需要用到的证书文件,不声明则获取顺序为:weixin4j.properties#weixin4j.certificate.file->`classpath:ca.p12` -->
|
<!-- ca证书:调用某些支付接口(如退款、红包)需要用到的证书文件,不声明则获取顺序为:weixin4j.properties#weixin4j.certificate.file->`classpath:ca.p12` -->
|
||||||
<property name="certificateFile" value="/path/to/certificate/file" />
|
<constructor-arg index="4" value="/path/to/certificate/file" />
|
||||||
<!-- 临时目录:weixin4j调用某些接口时需要用到的临时目录,不声明则获取顺序为:weixin4j.properties#weixin4j.tmpdir->`java.io.tmp` -->
|
|
||||||
<property name="tmpdir" value="/tmp/weixin4j" />
|
|
||||||
</bean>
|
</bean>
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
</bean>
|
</bean>
|
||||||
@ -67,18 +57,19 @@
|
|||||||
|
|
||||||
<!-- 微信消息服务~start -->
|
<!-- 微信消息服务~start -->
|
||||||
<bean
|
<bean
|
||||||
class="com.foxinmy.weixin4j.example.server.Weixin4jServerStartupWithThread" init-method="start" destroy-method="stop">
|
class="com.foxinmy.weixin4j.example.server.Weixin4jServerStartupWithThread"
|
||||||
|
init-method="start" destroy-method="stop">
|
||||||
<!-- 端口号 微信暂时只支持80端口 所以需要自己把微信被动消息请求转发(nginx等)到这个端口上来 -->
|
<!-- 端口号 微信暂时只支持80端口 所以需要自己把微信被动消息请求转发(nginx等)到这个端口上来 -->
|
||||||
<constructor-arg index="0" value="30000" />
|
<constructor-arg index="0" value="30000" />
|
||||||
<!-- token信息 -->
|
<!-- token信息 -->
|
||||||
<constructor-arg index="1">
|
<constructor-arg index="1">
|
||||||
<!-- 明文模式 -->
|
<!-- 明文模式 -->
|
||||||
<bean class="com.foxinmy.weixin4j.util.AesToken">
|
<bean class="com.foxinmy.weixin4j.util.AesToken">
|
||||||
<constructor-arg index="0" value="weixin4j" />
|
<constructor-arg index="0" value="开发者Token" />
|
||||||
</bean>
|
</bean>
|
||||||
<!-- 加密模式 -->
|
<!-- 加密模式 -->
|
||||||
<!-- bean class="com.foxinmy.weixin4j.util.AesToken"> <constructor-arg
|
<!-- bean class="com.foxinmy.weixin4j.util.AesToken"> <constructor-arg
|
||||||
index="0" value="公众号的应用ID(appid/corpid)" /> <constructor-arg index="1" value="开发者Token"
|
index="0" value="公众号的应用ID(appid/corpid)" /> <constructor-arg index="1" value="开发者Token"
|
||||||
/> <constructor-arg index="2" value="解密的EncodingAESKey" /> </bean -->
|
/> <constructor-arg index="2" value="解密的EncodingAESKey" /> </bean -->
|
||||||
</constructor-arg>
|
</constructor-arg>
|
||||||
<!-- 处理微信消息的全限包名 -->
|
<!-- 处理微信消息的全限包名 -->
|
||||||
|
|||||||
@ -1,18 +1,25 @@
|
|||||||
|
# weixin4j\u7684\u914d\u7f6e\u6587\u4ef6:\u5982\u679c\u6ca1\u6709\u8bf7\u6784\u9020\u76f8\u5e94\u53c2\u6570\u4f20\u5165 \u5982\u679c\u6709\u8bf7\u4fdd\u8bc1\u5728classpath\u7684\u6839\u76ee\u5f55\u4e0b
|
||||||
|
|
||||||
# \u516c\u4f17\u53f7\u4fe1\u606f \u8bf7\u6309\u9700\u586b\u5199
|
# \u516c\u4f17\u53f7\u4fe1\u606f \u8bf7\u6309\u9700\u586b\u5199
|
||||||
weixin4j.account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
weixin4j.account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
|
||||||
|
"components":[{"id":"\u5e94\u7528\u7ec4\u4ef6\u7684id","secret":"\u5e94\u7528\u7ec4\u4ef6\u7684secret"}],\
|
||||||
"mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
"mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
||||||
"certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\
|
"certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\
|
||||||
|
"certificateFile":"\u5fae\u4fe1\u652f\u4ed8\u67d0\u4e9b\u63a5\u53e3(\u9000\u6b3e\u7b49)\u9700\u8981\u7684ca\u8bc1\u4e66\u5b58\u653e\u7684\u8def\u5f84,classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199classpath:xxxxx.p12,\u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6classpath\u6839\u76ee\u5f55\u4e0b\u7684ca.p12\u6587\u4ef6",\
|
||||||
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
||||||
|
|
||||||
# weixin4j\u7684\u4e34\u65f6\u76ee\u5f55
|
# \u516c\u4f17\u53f7\u5fae\u4fe1\u7f51\u9875oauth\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
# \u53ef\u80fd\u5b58\u653etoken\u6587\u4ef6\u3001\u4e8c\u7ef4\u7801\u6587\u4ef6\u3001\u5a92\u4f53\u6587\u4ef6\u3001\u5bf9\u8d26\u5355\u6587\u4ef6\u7b49
|
# \u8be6\u89c1\uff1ahttps://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN
|
||||||
# \u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6java.io.tmpdir\u4e34\u65f6\u76ee\u5f55
|
weixin4j.user.oauth.redirect.uri=
|
||||||
weixin4j.tmpdir=
|
|
||||||
# \u5fae\u4fe1\u652f\u4ed8\u67d0\u4e9b\u63a5\u53e3\u9700\u8981\u7684ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
|
|
||||||
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199
|
|
||||||
# weixin4j.certificate.file=classpath:xxxxx.p12
|
|
||||||
# \u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6classpath\u6839\u76ee\u5f55\u4e0b\u7684ca.p12\u6587\u4ef6
|
|
||||||
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
|
|
||||||
|
|
||||||
# \u7528\u6237oauth\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
|
# \u7f51\u7ad9\u626b\u63cf\u767b\u9646oauth\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
weixin4j.user.oauth.redirect.uri=
|
# \u8be6\u89c1\uff1ahttps://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
|
||||||
|
weixin4j.open.user.oauth.redirect.uri=
|
||||||
|
|
||||||
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528ComponentApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
|
# \u8be6\u89c1\uff1ahttps://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1453779503&token=&lang=zh_CN
|
||||||
|
weixin4j.component.oauth.redirect.uri=
|
||||||
|
|
||||||
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u66ff\u6388\u6743\u516c\u4f17\u53f7\u53d1\u8d77\u7f51\u9875\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528ComponentApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
|
# \u8be6\u89c1\uff1ahttps://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318590&token=&lang=zh_CN
|
||||||
|
weixin4j.component.user.oauth.redirect.uri=
|
||||||
@ -3,17 +3,17 @@ package com.foxinmy.weixin4j.mp;
|
|||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.foxinmy.weixin4j.cache.CacheStorager;
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.model.Token;
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
import com.foxinmy.weixin4j.mp.api.ComponentApi;
|
import com.foxinmy.weixin4j.mp.api.ComponentApi;
|
||||||
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
|
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
|
||||||
import com.foxinmy.weixin4j.mp.type.URLConsts;
|
import com.foxinmy.weixin4j.mp.type.URLConsts;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.token.TicketManager;
|
import com.foxinmy.weixin4j.token.TicketManager;
|
||||||
import com.foxinmy.weixin4j.util.Consts;
|
import com.foxinmy.weixin4j.util.Consts;
|
||||||
import com.foxinmy.weixin4j.util.StringUtil;
|
import com.foxinmy.weixin4j.util.StringUtil;
|
||||||
@ -38,41 +38,66 @@ public class WeixinComponentProxy {
|
|||||||
*/
|
*/
|
||||||
private Map<String, ComponentApi> componentMap;
|
private Map<String, ComponentApi> componentMap;
|
||||||
/**
|
/**
|
||||||
* 配置相关
|
* 微信账号信息
|
||||||
*/
|
*/
|
||||||
private final Weixin4jSettings<WeixinMpAccount> settings;
|
private final WeixinMpAccount weixinMpAccount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认使用文件方式保存token、使用weixin4j.properties配置的账号信息
|
* 微信第三方组件接口实现(使用weixin4j.properties配置的account#components账号信息,
|
||||||
|
* 使用FileCacheStorager文件方式缓存TOKEN)
|
||||||
*/
|
*/
|
||||||
public WeixinComponentProxy() {
|
public WeixinComponentProxy() {
|
||||||
this(new Weixin4jSettings<WeixinMpAccount>(
|
this(new FileCacheStorager<Token>());
|
||||||
JSON.parseObject(Weixin4jConfigUtil.getValue("account"), WeixinMpAccount.class)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 微信第三方组件接口实现(使用weixin4j.properties配置的account#components账号信息)
|
||||||
* @param settings
|
*
|
||||||
* 配置信息
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
*/
|
*/
|
||||||
public WeixinComponentProxy(Weixin4jSettings<WeixinMpAccount> settings) {
|
public WeixinComponentProxy(CacheStorager<Token> cacheStorager) {
|
||||||
this.settings = settings;
|
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
|
||||||
List<WeixinAccount> components = settings.getAccount().getComponents();
|
WeixinMpAccount.class), cacheStorager);
|
||||||
this.componentMap = new HashMap<String, ComponentApi>(components.size());
|
|
||||||
for (WeixinAccount component : components) {
|
|
||||||
this.componentMap.put(component.getId(), new ComponentApi(
|
|
||||||
new TicketManager(component.getId(), component.getSecret(), settings.getCacheStorager0())));
|
|
||||||
}
|
|
||||||
this.componentMap.put(null, componentMap.get(components.get(0).getId()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公众号信息
|
* 微信第三方组件接口实现
|
||||||
|
*
|
||||||
|
* @param weixinMpAccount
|
||||||
|
* 账号信息
|
||||||
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
|
*/
|
||||||
|
public WeixinComponentProxy(WeixinMpAccount weixinMpAccount,
|
||||||
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
if (weixinMpAccount == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"weixinPayAccount must not be empty");
|
||||||
|
}
|
||||||
|
if (cacheStorager == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"cacheStorager must not be empty");
|
||||||
|
}
|
||||||
|
this.weixinMpAccount = weixinMpAccount;
|
||||||
|
this.componentMap = new HashMap<String, ComponentApi>(weixinMpAccount
|
||||||
|
.getComponents().size());
|
||||||
|
for (WeixinAccount component : weixinMpAccount.getComponents()) {
|
||||||
|
this.componentMap.put(component.getId(), new ComponentApi(
|
||||||
|
new TicketManager(component.getId(), component.getSecret(),
|
||||||
|
cacheStorager)));
|
||||||
|
}
|
||||||
|
this.componentMap.put(null, componentMap.get(weixinMpAccount
|
||||||
|
.getComponents().get(0).getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取微信账号信息
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinMpAccount getWeixinAccount() {
|
public WeixinMpAccount getWeixinMpAccount() {
|
||||||
return this.settings.getAccount();
|
return this.weixinMpAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -103,17 +128,20 @@ public class WeixinComponentProxy {
|
|||||||
* @param componentId
|
* @param componentId
|
||||||
* 组件ID
|
* 组件ID
|
||||||
* @return 预授权码
|
* @return 预授权码
|
||||||
|
* @see #cacheComponentTicket(String, String)
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTicketManager()
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTicketManager()
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPreCodeManager()
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPreCodeManager()
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getPreComponentTicket(String componentId) throws WeixinException {
|
public String getPreComponentTicket(String componentId)
|
||||||
Token token = component(componentId).getTicketManager().getTicket();
|
throws WeixinException {
|
||||||
|
ComponentApi component = component(componentId);
|
||||||
|
Token token = component.getTicketManager().getTicket();
|
||||||
if (token == null || StringUtil.isBlank(token.getAccessToken())) {
|
if (token == null || StringUtil.isBlank(token.getAccessToken())) {
|
||||||
throw new WeixinException("maybe oauth first?");
|
throw new WeixinException("maybe oauth first?");
|
||||||
}
|
}
|
||||||
return token.getAccessToken();
|
return component.getPreCodeManager().getAccessToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,27 +153,34 @@ public class WeixinComponentProxy {
|
|||||||
* 组件ticket内容
|
* 组件ticket内容
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public void cacheComponentTicket(String componentId, String componentTicket) throws WeixinException {
|
public void cacheComponentTicket(String componentId, String componentTicket)
|
||||||
component(componentId).getTicketManager().cachingTicket(componentTicket);
|
throws WeixinException {
|
||||||
|
component(componentId).getTicketManager()
|
||||||
|
.cachingTicket(componentTicket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用组件授权 <font color="red">需先缓存ticket</font>
|
* 应用组件授权 <font color="red">需先缓存ticket</font> <li>
|
||||||
*
|
* redirectUri默认填写weixin4j.properties#component.oauth.redirect.uri <li>
|
||||||
* @see {@link #getComponentAuthorizeURL(String, String,String)}
|
* state默认填写state
|
||||||
|
*
|
||||||
* @param componentId
|
* @param componentId
|
||||||
* 组件ID
|
* 组件ID
|
||||||
* @see {@link #cacheComponentTicket(String, String)}
|
* @see {@link #getComponentAuthorizationURL(String, String,String)}
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getComponentAuthorizeURL(String componentId) throws WeixinException {
|
public String getComponentAuthorizationURL(String componentId)
|
||||||
String redirectUri = Weixin4jConfigUtil.getValue("component.oauth.redirect.uri");
|
throws WeixinException {
|
||||||
return getComponentAuthorizeURL(componentId, redirectUri, "state");
|
String redirectUri = Weixin4jConfigUtil
|
||||||
|
.getValue("component.oauth.redirect.uri");
|
||||||
|
return getComponentAuthorizationURL(componentId, redirectUri, "state");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用组件授权 <font color="red">需先缓存ticket</font>
|
* 应用组件授权 <font
|
||||||
|
* color="red">需先缓存ticket,在授权完成之后需要调用ComponentApi#exchangeAuthInfo方法
|
||||||
|
* ,否则无法缓存token相关导致后续的组件接口调用失败</font>
|
||||||
*
|
*
|
||||||
* @param componentId
|
* @param componentId
|
||||||
* 组件ID
|
* 组件ID
|
||||||
@ -153,16 +188,21 @@ public class WeixinComponentProxy {
|
|||||||
* 授权后重定向url
|
* 授权后重定向url
|
||||||
* @param state
|
* @param state
|
||||||
* 回调后原样返回
|
* 回调后原样返回
|
||||||
|
* @see #cacheComponentTicket(String, String)
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTicketManager()
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTicketManager()
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPreCodeManager()
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPreCodeManager()
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#exchangeAuthInfo(String)
|
||||||
|
* @see <a
|
||||||
|
* href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1453779503&token=&lang=zh_CN">应用组件授权</a>
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getComponentAuthorizeURL(String componentId, String redirectUri, String state)
|
public String getComponentAuthorizationURL(String componentId,
|
||||||
throws WeixinException {
|
String redirectUri, String state) throws WeixinException {
|
||||||
try {
|
try {
|
||||||
return String.format(URLConsts.COMPONENT_OAUTH_URL, componentId, getPreComponentTicket(componentId),
|
return String.format(URLConsts.COMPONENT_OAUTH_URL, componentId,
|
||||||
|
getPreComponentTicket(componentId),
|
||||||
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state);
|
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
;
|
;
|
||||||
@ -181,8 +221,8 @@ public class WeixinComponentProxy {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinProxy getWeixinProxy(String componentId, String authAppId) {
|
public WeixinProxy getWeixinProxy(String componentId, String authAppId) {
|
||||||
return new WeixinProxy(component(componentId).getRefreshTokenManager(authAppId),
|
return new WeixinProxy(component(componentId).getRefreshTokenManager(
|
||||||
component(componentId).getTokenManager());
|
authAppId), component(componentId).getTokenManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static String VERSION = "1.7.1";
|
public final static String VERSION = "1.7.1";
|
||||||
|
|||||||
@ -4,9 +4,12 @@ import java.io.InputStream;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.cache.CacheStorager;
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
||||||
import com.foxinmy.weixin4j.model.Button;
|
import com.foxinmy.weixin4j.model.Button;
|
||||||
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
import com.foxinmy.weixin4j.model.card.CardCoupon;
|
import com.foxinmy.weixin4j.model.card.CardCoupon;
|
||||||
import com.foxinmy.weixin4j.model.card.CardCoupons;
|
import com.foxinmy.weixin4j.model.card.CardCoupons;
|
||||||
@ -28,6 +31,7 @@ import com.foxinmy.weixin4j.mp.api.MassApi;
|
|||||||
import com.foxinmy.weixin4j.mp.api.MediaApi;
|
import com.foxinmy.weixin4j.mp.api.MediaApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.MenuApi;
|
import com.foxinmy.weixin4j.mp.api.MenuApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.NotifyApi;
|
import com.foxinmy.weixin4j.mp.api.NotifyApi;
|
||||||
|
import com.foxinmy.weixin4j.mp.api.OauthApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.QrApi;
|
import com.foxinmy.weixin4j.mp.api.QrApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.TagApi;
|
import com.foxinmy.weixin4j.mp.api.TagApi;
|
||||||
import com.foxinmy.weixin4j.mp.api.TmplApi;
|
import com.foxinmy.weixin4j.mp.api.TmplApi;
|
||||||
@ -56,8 +60,8 @@ import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
|
|||||||
import com.foxinmy.weixin4j.mp.type.DatacubeType;
|
import com.foxinmy.weixin4j.mp.type.DatacubeType;
|
||||||
import com.foxinmy.weixin4j.mp.type.IndustryType;
|
import com.foxinmy.weixin4j.mp.type.IndustryType;
|
||||||
import com.foxinmy.weixin4j.mp.type.Lang;
|
import com.foxinmy.weixin4j.mp.type.Lang;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.token.PerTicketManager;
|
import com.foxinmy.weixin4j.token.PerTicketManager;
|
||||||
|
import com.foxinmy.weixin4j.token.TokenCreator;
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
import com.foxinmy.weixin4j.tuple.MassTuple;
|
import com.foxinmy.weixin4j.tuple.MassTuple;
|
||||||
import com.foxinmy.weixin4j.tuple.MpArticle;
|
import com.foxinmy.weixin4j.tuple.MpArticle;
|
||||||
@ -77,7 +81,10 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
|||||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php">api文档</a>
|
* @see <a href="http://mp.weixin.qq.com/wiki/index.php">api文档</a>
|
||||||
*/
|
*/
|
||||||
public class WeixinProxy {
|
public class WeixinProxy {
|
||||||
|
/**
|
||||||
|
* 授权API
|
||||||
|
*/
|
||||||
|
private final OauthApi oauthApi;
|
||||||
/**
|
/**
|
||||||
* 媒体素材API
|
* 媒体素材API
|
||||||
*/
|
*/
|
||||||
@ -131,64 +138,94 @@ public class WeixinProxy {
|
|||||||
*/
|
*/
|
||||||
private final CardApi cardApi;
|
private final CardApi cardApi;
|
||||||
/**
|
/**
|
||||||
* token实现
|
* token管理
|
||||||
*/
|
*/
|
||||||
private final TokenManager tokenManager;
|
private final TokenManager tokenManager;
|
||||||
/**
|
/**
|
||||||
* 配置信息
|
* 账号信息
|
||||||
*/
|
*/
|
||||||
private Weixin4jSettings<WeixinAccount> settings;
|
private final WeixinAccount weixinAccount;
|
||||||
|
/**
|
||||||
|
* token存储
|
||||||
|
*/
|
||||||
|
private final CacheStorager<Token> cacheStorager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认使用文件方式保存token、使用weixin4j.properties配置的账号信息
|
* 微信接口实现(使用weixin4j.properties配置的account账号信息,
|
||||||
|
* 使用FileCacheStorager文件方式缓存TOKEN)
|
||||||
*/
|
*/
|
||||||
public WeixinProxy() {
|
public WeixinProxy() {
|
||||||
this(new Weixin4jSettings<WeixinAccount>(
|
this(new FileCacheStorager<Token>());
|
||||||
Weixin4jConfigUtil.getWeixinAccount()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 微信接口实现(使用weixin4j.properties配置的account账号信息)
|
||||||
* @param settings
|
*
|
||||||
* 微信配置信息
|
* @param cacheStorager
|
||||||
* @see com.foxinmy.weixin4j.setting.Weixin4jSettings
|
* token管理
|
||||||
*/
|
*/
|
||||||
public WeixinProxy(Weixin4jSettings<WeixinAccount> settings) {
|
public WeixinProxy(CacheStorager<Token> cacheStorager) {
|
||||||
this(new TokenManager(new WeixinTokenCreator(settings.getAccount()
|
this(Weixin4jConfigUtil.getWeixinAccount(), cacheStorager);
|
||||||
.getId(), settings.getAccount().getSecret()),
|
|
||||||
settings.getCacheStorager0()));
|
|
||||||
this.settings = settings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 第三方组件(永久刷新令牌机制)
|
* 微信接口实现
|
||||||
|
*
|
||||||
|
* @param weixinAccount
|
||||||
|
* 账号信息
|
||||||
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
|
*/
|
||||||
|
public WeixinProxy(WeixinAccount weixinAccount,
|
||||||
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
this(weixinAccount, new WeixinTokenCreator(weixinAccount.getId(),
|
||||||
|
weixinAccount.getSecret()), cacheStorager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方组件方式创建微信接口实现(永久刷新令牌机制)
|
||||||
*
|
*
|
||||||
* @param perTicketManager
|
* @param perTicketManager
|
||||||
* 第三方组件永久刷新token
|
* 第三方组件永久刷新token
|
||||||
* {@link com.foxinmy.weixin4j.mp.api.ComponentApi#getPerCodeManager(String)}
|
|
||||||
* @param componentTokenManager
|
* @param componentTokenManager
|
||||||
* 第三方组件凭证token
|
* 第三方组件凭证token
|
||||||
* {@link com.foxinmy.weixin4j.mp.api.ComponentApi#getTokenManager}
|
|
||||||
* @see com.foxinmy.weixin4j.mp.api.ComponentApi
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getPerCodeManager(String)
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.ComponentApi#getTokenManager
|
||||||
*/
|
*/
|
||||||
public WeixinProxy(PerTicketManager perTicketManager,
|
public WeixinProxy(PerTicketManager perTicketManager,
|
||||||
TokenManager componentTokenManager) {
|
TokenManager componentTokenManager) {
|
||||||
this(new TokenManager(new WeixinTokenComponentCreator(perTicketManager,
|
this(new WeixinAccount(perTicketManager.getThirdId(),
|
||||||
componentTokenManager), perTicketManager.getCacheStorager()));
|
perTicketManager.getThirdSecret()),
|
||||||
this.settings = new Weixin4jSettings<WeixinAccount>(new WeixinAccount(
|
new WeixinTokenComponentCreator(perTicketManager,
|
||||||
perTicketManager.getAuthAppId(), null));
|
componentTokenManager), perTicketManager
|
||||||
this.settings.setCacheStorager(perTicketManager.getCacheStorager());
|
.getCacheStorager());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意:TokenCreator 需为 <font color="red">WeixinTokenCreator</font>
|
* 微信接口实现
|
||||||
*
|
*
|
||||||
* @see com.foxinmy.weixin4j.mp.token.WeixinTokenCreator
|
* @param settings
|
||||||
|
* 配置信息
|
||||||
* @param tokenManager
|
* @param tokenManager
|
||||||
* token管理
|
* token管理
|
||||||
*/
|
*/
|
||||||
private WeixinProxy(TokenManager tokenManager) {
|
private WeixinProxy(WeixinAccount weixinAccount, TokenCreator tokenCreator,
|
||||||
this.tokenManager = tokenManager;
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
if (weixinAccount == null) {
|
||||||
|
throw new IllegalArgumentException("settings must not be empty");
|
||||||
|
}
|
||||||
|
if (tokenCreator == null) {
|
||||||
|
throw new IllegalArgumentException("tokenCreator must not be empty");
|
||||||
|
}
|
||||||
|
if (cacheStorager == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"cacheStorager must not be empty");
|
||||||
|
}
|
||||||
|
this.tokenManager = new TokenManager(tokenCreator, cacheStorager);
|
||||||
|
this.weixinAccount = weixinAccount;
|
||||||
|
this.cacheStorager = cacheStorager;
|
||||||
|
this.oauthApi = new OauthApi(weixinAccount);
|
||||||
this.mediaApi = new MediaApi(tokenManager);
|
this.mediaApi = new MediaApi(tokenManager);
|
||||||
this.notifyApi = new NotifyApi(tokenManager);
|
this.notifyApi = new NotifyApi(tokenManager);
|
||||||
this.customApi = new CustomApi(tokenManager);
|
this.customApi = new CustomApi(tokenManager);
|
||||||
@ -210,7 +247,7 @@ public class WeixinProxy {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinAccount getWeixinAccount() {
|
public WeixinAccount getWeixinAccount() {
|
||||||
return this.settings.getAccount();
|
return weixinAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -222,6 +259,16 @@ public class WeixinProxy {
|
|||||||
return this.tokenManager;
|
return this.tokenManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取oauth授权API
|
||||||
|
*
|
||||||
|
* @see com.foxinmy.weixin4j.mp.api.OauthApi
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public OauthApi getOauthApi() {
|
||||||
|
return oauthApi;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取JSSDK Ticket的tokenManager
|
* 获取JSSDK Ticket的tokenManager
|
||||||
*
|
*
|
||||||
@ -230,9 +277,8 @@ public class WeixinProxy {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public TokenManager getTicketManager(TicketType ticketType) {
|
public TokenManager getTicketManager(TicketType ticketType) {
|
||||||
return new TokenManager(new WeixinTicketCreator(getWeixinAccount()
|
return new TokenManager(new WeixinTicketCreator(weixinAccount.getId(),
|
||||||
.getId(), ticketType, this.tokenManager),
|
ticketType, this.tokenManager), this.cacheStorager);
|
||||||
this.settings.getCacheStorager0());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1537,7 +1583,7 @@ public class WeixinProxy {
|
|||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public ApiResult clearQuota() throws WeixinException {
|
public ApiResult clearQuota() throws WeixinException {
|
||||||
return helperApi.clearQuota(getWeixinAccount().getId());
|
return helperApi.clearQuota(weixinAccount.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.foxinmy.weixin4j.mp.api;
|
package com.foxinmy.weixin4j.mp.api;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -14,12 +16,15 @@ import com.foxinmy.weixin4j.mp.component.WeixinComponentPreCodeCreator;
|
|||||||
import com.foxinmy.weixin4j.mp.component.WeixinComponentTokenCreator;
|
import com.foxinmy.weixin4j.mp.component.WeixinComponentTokenCreator;
|
||||||
import com.foxinmy.weixin4j.mp.component.WeixinTokenComponentCreator;
|
import com.foxinmy.weixin4j.mp.component.WeixinTokenComponentCreator;
|
||||||
import com.foxinmy.weixin4j.mp.model.AuthorizerOption;
|
import com.foxinmy.weixin4j.mp.model.AuthorizerOption;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.OauthToken;
|
||||||
import com.foxinmy.weixin4j.mp.model.AuthorizerOption.AuthorizerOptionName;
|
import com.foxinmy.weixin4j.mp.model.AuthorizerOption.AuthorizerOptionName;
|
||||||
import com.foxinmy.weixin4j.mp.model.ComponentAuthInfo;
|
import com.foxinmy.weixin4j.mp.model.ComponentAuthInfo;
|
||||||
import com.foxinmy.weixin4j.token.PerTicketManager;
|
import com.foxinmy.weixin4j.token.PerTicketManager;
|
||||||
import com.foxinmy.weixin4j.token.TicketManager;
|
import com.foxinmy.weixin4j.token.TicketManager;
|
||||||
import com.foxinmy.weixin4j.token.TokenCreator;
|
import com.foxinmy.weixin4j.token.TokenCreator;
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
|
import com.foxinmy.weixin4j.util.Consts;
|
||||||
|
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 第三方应用组件
|
* 第三方应用组件
|
||||||
@ -101,6 +106,110 @@ public class ComponentApi extends MpApi {
|
|||||||
ticketManager.getCacheStorager());
|
ticketManager.getCacheStorager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方组件代替授权公众号发起网页授权:获取code <li>
|
||||||
|
* redirectUri默认填写weixin4j.properties#component.user.oauth.redirect.uri <li>
|
||||||
|
* scope默认填写snsapi_base <li>
|
||||||
|
* state默认填写state
|
||||||
|
*
|
||||||
|
* @param authAppId
|
||||||
|
* 公众号的appid
|
||||||
|
* @see #getAuthorizationURL(String, String, String, String)
|
||||||
|
* @see <a
|
||||||
|
* href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318590&token=&lang=zh_CN">第三方组件代替授权公众号发起网页授权</a>
|
||||||
|
*/
|
||||||
|
public String getUserAuthorizationURL(String authAppId) {
|
||||||
|
String redirectUri = Weixin4jConfigUtil
|
||||||
|
.getValue("component.user.oauth.redirect.uri");
|
||||||
|
return getUserAuthorizationURL(authAppId, redirectUri, "snsapi_base",
|
||||||
|
"state");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方组件代替授权公众号发起网页授权:获取code
|
||||||
|
*
|
||||||
|
* @param authAppId
|
||||||
|
* 公众号的appid
|
||||||
|
* @param redirectUri
|
||||||
|
* 重定向地址,这里填写的应是服务开发方的回调地址
|
||||||
|
* @param scope
|
||||||
|
* 应用授权作用域,snsapi_base/snsapi_userinfo
|
||||||
|
* @param state
|
||||||
|
* 重定向后会带上state参数,开发者可以填写任意参数值,最多128字节
|
||||||
|
* @return oauth授权URL
|
||||||
|
* @see <a
|
||||||
|
* href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318590&token=&lang=zh_CN">第三方组件代替授权公众号发起网页授权</a>
|
||||||
|
*/
|
||||||
|
public String getUserAuthorizationURL(String authAppId, String redirectUri,
|
||||||
|
String scope, String state) {
|
||||||
|
String sns_component_user_auth_uri = getRequestUri("sns_component_user_auth_uri");
|
||||||
|
try {
|
||||||
|
return String.format(sns_component_user_auth_uri, authAppId,
|
||||||
|
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), scope,
|
||||||
|
state, this.ticketManager.getThirdId());
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方组件代替授权公众号发起网页授权:换取token
|
||||||
|
*
|
||||||
|
* @param authAppId
|
||||||
|
* 公众号的appid
|
||||||
|
* @param code
|
||||||
|
* 用户同意授权获取的code
|
||||||
|
* @return token信息
|
||||||
|
* @see #getUserAuthorizationURL(String, String, String, String)
|
||||||
|
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
||||||
|
* @throws WeixinException
|
||||||
|
*/
|
||||||
|
public OauthToken getAuthorizationToken(String authAppId, String code)
|
||||||
|
throws WeixinException {
|
||||||
|
String sns_component_user_token_uri = getRequestUri("sns_component_user_token_uri");
|
||||||
|
String accessToken = tokenManager.getAccessToken();
|
||||||
|
WeixinResponse response = weixinExecutor.get(String.format(
|
||||||
|
sns_component_user_token_uri, authAppId, code,
|
||||||
|
ticketManager.getThirdId(), accessToken));
|
||||||
|
JSONObject result = response.getAsJson();
|
||||||
|
OauthToken token = new OauthToken(result.getString("access_token"),
|
||||||
|
result.getLongValue("expires_in") * 1000l);
|
||||||
|
token.setOpenId(result.getString("openid"));
|
||||||
|
token.setScope(result.getString("scope"));
|
||||||
|
token.setRefreshToken(result.getString("refresh_token"));
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 第三方组件代替授权公众号发起网页授权:刷新token
|
||||||
|
*
|
||||||
|
* @param authAppId
|
||||||
|
* 公众号的appid
|
||||||
|
* @param refreshToken
|
||||||
|
* 填写通过access_token获取到的refresh_token参数
|
||||||
|
* @return token信息
|
||||||
|
* @see #getAuthorizationToken(String, String)
|
||||||
|
* @see OauthApi#getAuthorizationUser(OauthToken)
|
||||||
|
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
||||||
|
* @throws WeixinException
|
||||||
|
*/
|
||||||
|
public OauthToken refreshAuthorizationToken(String authAppId,
|
||||||
|
String refreshToken) throws WeixinException {
|
||||||
|
String sns_component_token_refresh_uri = getRequestUri("sns_component_token_refresh_uri");
|
||||||
|
String accessToken = tokenManager.getAccessToken();
|
||||||
|
WeixinResponse response = weixinExecutor.get(String.format(
|
||||||
|
sns_component_token_refresh_uri, authAppId,
|
||||||
|
ticketManager.getThirdId(), accessToken, refreshToken));
|
||||||
|
JSONObject result = response.getAsJson();
|
||||||
|
OauthToken token = new OauthToken(result.getString("access_token"),
|
||||||
|
result.getLongValue("expires_in") * 1000l);
|
||||||
|
token.setOpenId(result.getString("openid"));
|
||||||
|
token.setScope(result.getString("scope"));
|
||||||
|
token.setRefreshToken(result.getString("refresh_token"));
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 使用授权码换取公众号的接口调用凭据和授权信息:用于使用授权码换取授权公众号的授权信息,
|
* 使用授权码换取公众号的接口调用凭据和授权信息:用于使用授权码换取授权公众号的授权信息,
|
||||||
* 并换取authorizer_access_token和authorizer_refresh_token。
|
* 并换取authorizer_access_token和authorizer_refresh_token。
|
||||||
@ -111,6 +220,7 @@ public class ComponentApi extends MpApi {
|
|||||||
* @param authCode
|
* @param authCode
|
||||||
* 授权code
|
* 授权code
|
||||||
* @return 第三方组件授权信息
|
* @return 第三方组件授权信息
|
||||||
|
* @see {@link com.foxinmy.weixin4j.mp.WeixinComponentProxy#getComponentAuthorizeURL(String, String, String)}
|
||||||
* @see com.foxinmy.weixin4j.mp.model.ComponentAuthInfo
|
* @see com.foxinmy.weixin4j.mp.model.ComponentAuthInfo
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
@ -169,22 +279,23 @@ public class ComponentApi extends MpApi {
|
|||||||
WeixinResponse response = weixinExecutor.post(
|
WeixinResponse response = weixinExecutor.post(
|
||||||
String.format(component_get_authorizer_uri,
|
String.format(component_get_authorizer_uri,
|
||||||
tokenManager.getAccessToken()), obj.toJSONString());
|
tokenManager.getAccessToken()), obj.toJSONString());
|
||||||
obj = response.getAsJson().getJSONObject("authorizer_info");
|
obj = response.getAsJson();
|
||||||
ComponentAuthInfo info = JSON
|
JSONObject auth = obj.getJSONObject("authorizer_info");
|
||||||
.toJavaObject(obj, ComponentAuthInfo.class);
|
ComponentAuthInfo info = JSON.toJavaObject(auth,
|
||||||
info.setServiceType(obj.getJSONObject("service_type_info").getIntValue(
|
ComponentAuthInfo.class);
|
||||||
|
info.setServiceType(auth.getJSONObject("service_type_info")
|
||||||
|
.getIntValue("id"));
|
||||||
|
info.setVerifyType(auth.getJSONObject("verify_type_info").getIntValue(
|
||||||
"id"));
|
"id"));
|
||||||
info.setVerifyType(obj.getJSONObject("verify_type_info").getIntValue(
|
auth = obj.getJSONObject("authorization_info");
|
||||||
"id"));
|
JSONArray privilegesObj = auth.getJSONArray("func_info");
|
||||||
JSONArray privilegesObj = obj.getJSONObject("authorization_info")
|
|
||||||
.getJSONArray("func_info");
|
|
||||||
List<Integer> privileges = new ArrayList<Integer>(privilegesObj.size());
|
List<Integer> privileges = new ArrayList<Integer>(privilegesObj.size());
|
||||||
for (int i = 0; i < privilegesObj.size(); i++) {
|
for (int i = 0; i < privilegesObj.size(); i++) {
|
||||||
privileges.add(privilegesObj.getJSONObject(i)
|
privileges.add(privilegesObj.getJSONObject(i)
|
||||||
.getJSONObject("funcscope_category").getInteger("id"));
|
.getJSONObject("funcscope_category").getInteger("id"));
|
||||||
}
|
}
|
||||||
info.setPrivileges(privileges);
|
info.setPrivileges(privileges);
|
||||||
info.setAppId(authAppId);
|
info.setAppId(auth.getString("appid"));
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -21,8 +21,6 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
|||||||
* @author jinyu(foxinmy@gmail.com)
|
* @author jinyu(foxinmy@gmail.com)
|
||||||
* @date 2015年3月6日
|
* @date 2015年3月6日
|
||||||
* @since JDK 1.6
|
* @since JDK 1.6
|
||||||
* @see <a
|
|
||||||
* href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&lang=zh_CN">微信登陆</a>
|
|
||||||
*/
|
*/
|
||||||
public class OauthApi extends MpApi {
|
public class OauthApi extends MpApi {
|
||||||
|
|
||||||
@ -45,20 +43,23 @@ public class OauthApi extends MpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 公众号base静默oauth授权:重定向URL使用weixin4j.properties#user.oauth.redirect.uri
|
* 公众号网页获取用户资料oauth授权:请求code<li>
|
||||||
|
* redirectUri默认填写weixin4j.properties#user.oauth.redirect.uri <li>
|
||||||
|
* scope默认填写snsapi_base <li>
|
||||||
|
* state默认填写state
|
||||||
*
|
*
|
||||||
* @see {@link #getAuthorizeURL(String, String,String)}
|
* @see {@link #getUserAuthorizationURL(String, String,String)}
|
||||||
*
|
*
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
*/
|
*/
|
||||||
public String getAuthorizeURL() {
|
public String getUserAuthorizationURL() {
|
||||||
String redirectUri = Weixin4jConfigUtil
|
String redirectUri = Weixin4jConfigUtil
|
||||||
.getValue("user.oauth.redirect.uri");
|
.getValue("user.oauth.redirect.uri");
|
||||||
return getAuthorizeURL(redirectUri, "state", "snsapi_base");
|
return getUserAuthorizationURL(redirectUri, "state", "snsapi_base");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 请求CODE
|
* 公众号网页获取用户资料oauth授权:请求code
|
||||||
*
|
*
|
||||||
* @param redirectUri
|
* @param redirectUri
|
||||||
* 重定向地址<br>
|
* 重定向地址<br>
|
||||||
@ -86,7 +87,8 @@ public class OauthApi extends MpApi {
|
|||||||
* ,这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。<br>
|
* ,这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。<br>
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
*/
|
*/
|
||||||
public String getAuthorizeURL(String redirectUri, String state, String scope) {
|
public String getUserAuthorizationURL(String redirectUri, String state,
|
||||||
|
String scope) {
|
||||||
String sns_user_auth_uri = getRequestUri("sns_user_auth_uri");
|
String sns_user_auth_uri = getRequestUri("sns_user_auth_uri");
|
||||||
try {
|
try {
|
||||||
return String.format(sns_user_auth_uri, account.getId(),
|
return String.format(sns_user_auth_uri, account.getId(),
|
||||||
@ -99,15 +101,17 @@ public class OauthApi extends MpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* code换取token
|
* 公众号网页获取用户资料oauth授权:code换取token
|
||||||
*
|
*
|
||||||
* @param code
|
* @param code
|
||||||
* 用户同意授权获取的code,
|
* 用户同意授权获取的code,
|
||||||
* code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次
|
* code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次
|
||||||
* ,5分钟未被使用自动过期。
|
* ,5分钟未被使用自动过期。
|
||||||
* @return oauthtoken信息
|
* @return oauthtoken信息
|
||||||
|
* @see #getUserAuthorizationURL(String, String,String)
|
||||||
|
* @see #getAuthorizationUser(OauthToken)
|
||||||
*/
|
*/
|
||||||
public OauthToken getOauthToken(String code) throws WeixinException {
|
public OauthToken getAuthorizationToken(String code) throws WeixinException {
|
||||||
String user_token_uri = getRequestUri("sns_user_token_uri");
|
String user_token_uri = getRequestUri("sns_user_token_uri");
|
||||||
WeixinResponse response = weixinExecutor.get(String.format(
|
WeixinResponse response = weixinExecutor.get(String.format(
|
||||||
user_token_uri, account.getId(), account.getSecret(), code));
|
user_token_uri, account.getId(), account.getSecret(), code));
|
||||||
@ -122,23 +126,29 @@ public class OauthApi extends MpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新token:由于access_token拥有较短的有效期,当access_token超时后,可以使用refresh_token进行刷新,
|
* 公众号网页获取用户资料oauth授权:刷新token,由于access_token拥有较短的有效期,当access_token超时后,
|
||||||
* refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。
|
* 可以使用refresh_token进行刷新, refresh_token有效期为30天,当refresh_token失效之后,需要用户重新授权。
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* @param refreshToken
|
* @param refreshToken
|
||||||
* 填写通过access_token获取到的refresh_token参数
|
* 填写通过access_token获取到的refresh_token参数
|
||||||
* {@link #getOauthToken(String)}
|
* @see {@link #getAuthorizationToken(String)}
|
||||||
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
||||||
* @return oauthtoken信息
|
* @return oauthtoken信息
|
||||||
*/
|
*/
|
||||||
public OauthToken refreshToken(String refreshToken) throws WeixinException {
|
public OauthToken refreshAuthorizationToken(String refreshToken)
|
||||||
|
throws WeixinException {
|
||||||
String sns_token_refresh_uri = getRequestUri("sns_token_refresh_uri");
|
String sns_token_refresh_uri = getRequestUri("sns_token_refresh_uri");
|
||||||
WeixinResponse response = weixinExecutor.get(String.format(
|
WeixinResponse response = weixinExecutor.get(String.format(
|
||||||
sns_token_refresh_uri, account.getId(), refreshToken));
|
sns_token_refresh_uri, account.getId(), refreshToken));
|
||||||
|
JSONObject result = response.getAsJson();
|
||||||
return response.getAsObject(new TypeReference<OauthToken>() {
|
OauthToken token = new OauthToken(result.getString("access_token"),
|
||||||
});
|
result.getLongValue("expires_in") * 1000l);
|
||||||
|
token.setUnionId(result.getString("unionid"));
|
||||||
|
token.setOpenId(result.getString("openid"));
|
||||||
|
token.setScope(result.getString("scope"));
|
||||||
|
token.setRefreshToken(result.getString("refresh_token"));
|
||||||
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -150,7 +160,7 @@ public class OauthApi extends MpApi {
|
|||||||
* 用户标识
|
* 用户标识
|
||||||
* @return 验证结果
|
* @return 验证结果
|
||||||
*/
|
*/
|
||||||
public boolean authAccessToken(String oauthToken, String openId) {
|
public boolean verifyAuthorizationToken(String oauthToken, String openId) {
|
||||||
String sns_auth_token_uri = getRequestUri("sns_auth_token_uri");
|
String sns_auth_token_uri = getRequestUri("sns_auth_token_uri");
|
||||||
try {
|
try {
|
||||||
weixinExecutor.get(String.format(sns_auth_token_uri, oauthToken,
|
weixinExecutor.get(String.format(sns_auth_token_uri, oauthToken,
|
||||||
@ -163,7 +173,7 @@ public class OauthApi extends MpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* oauth获取用户信息(需scope为 snsapi_userinfo)
|
* oauth授权获取用户信息(需scope为 snsapi_userinfo)
|
||||||
*
|
*
|
||||||
* @param token
|
* @param token
|
||||||
* 授权信息(token&openid)
|
* 授权信息(token&openid)
|
||||||
@ -173,11 +183,11 @@ public class OauthApi extends MpApi {
|
|||||||
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN">授权获取用户信息</a>
|
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN">授权获取用户信息</a>
|
||||||
* @see com.foxinmy.weixin4j.mp.model.User
|
* @see com.foxinmy.weixin4j.mp.model.User
|
||||||
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
||||||
* @see {@link #getOauthToken(String)}
|
* @see {@link #getAuthorizationUser(String,Sring,Lang)}
|
||||||
* @see {@link #getUser(String,Sring,Lang)}
|
|
||||||
*/
|
*/
|
||||||
public User getUser(OauthToken token) throws WeixinException {
|
public User getAuthorizationUser(OauthToken token) throws WeixinException {
|
||||||
return getUser(token.getAccessToken(), token.getOpenId(), Lang.zh_CN);
|
return getAuthorizationUser(token.getAccessToken(), token.getOpenId(),
|
||||||
|
Lang.zh_CN);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -193,10 +203,11 @@ public class OauthApi extends MpApi {
|
|||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
* @see <a
|
* @see <a
|
||||||
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN">授权获取用户信息</a>
|
* href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN">授权获取用户信息</a>
|
||||||
|
* @see {@link #getAuthorizationToken(String)}
|
||||||
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
* @see com.foxinmy.weixin4j.mp.model.OauthToken
|
||||||
* @see com.foxinmy.weixin4j.mp.model.User
|
* @see com.foxinmy.weixin4j.mp.model.User
|
||||||
*/
|
*/
|
||||||
public User getUser(String oauthToken, String openid, Lang lang)
|
public User getAuthorizationUser(String oauthToken, String openid, Lang lang)
|
||||||
throws WeixinException {
|
throws WeixinException {
|
||||||
String user_info_uri = getRequestUri("sns_user_info_uri");
|
String user_info_uri = getRequestUri("sns_user_info_uri");
|
||||||
WeixinResponse response = weixinExecutor.get(String.format(
|
WeixinResponse response = weixinExecutor.get(String.format(
|
||||||
@ -207,28 +218,32 @@ public class OauthApi extends MpApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信开放平台oauth授权:重定向URL使用weixin4j.properties#user.oauth.redirect.uri
|
* 微信开放平台oauth授权(扫码登陆)<li>
|
||||||
*
|
* redirectUri默认填写weixin4j.properties#open.user.oauth.redirect.uri <li>
|
||||||
* @see {@link #getOpenAuthorizeURL(String, String)}
|
* state默认填写state
|
||||||
*
|
*
|
||||||
|
* @see {@link #getOpenAuthorizationURL(String, String)}
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
*/
|
*/
|
||||||
public String getOpenAuthorizeURL() {
|
public String getOpenAuthorizationURL() {
|
||||||
String redirectUri = Weixin4jConfigUtil
|
String redirectUri = Weixin4jConfigUtil
|
||||||
.getValue("user.oauth.redirect.uri");
|
.getValue("open.user.oauth.redirect.uri");
|
||||||
return getOpenAuthorizeURL(redirectUri, "state");
|
return getOpenAuthorizationURL(redirectUri, "state");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 微信开放平台oauth授权:请求CODE
|
* 微信开放平台oauth授权(扫码登陆):请求CODE
|
||||||
*
|
*
|
||||||
* @param redirectUri
|
* @param redirectUri
|
||||||
* 重定向地址 域名与审核时填写的授权域名一致
|
* 重定向地址 域名与审核时填写的授权域名一致
|
||||||
* @param state
|
* @param state
|
||||||
* 用于保持请求和回调的状态,授权请求后原样带回给第三方
|
* 用于保持请求和回调的状态,授权请求后原样带回给第三方
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
|
* @see <a
|
||||||
|
* href="https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN">网站扫描登陆oauth授权</a>
|
||||||
|
* @see #getAuthorizationToken(String)
|
||||||
*/
|
*/
|
||||||
public String getOpenAuthorizeURL(String redirectUri, String state) {
|
public String getOpenAuthorizationURL(String redirectUri, String state) {
|
||||||
String open_user_auth_uri = getRequestUri("open_user_auth_uri");
|
String open_user_auth_uri = getRequestUri("open_user_auth_uri");
|
||||||
try {
|
try {
|
||||||
return String.format(open_user_auth_uri, account.getId(),
|
return String.format(open_user_auth_uri, account.getId(),
|
||||||
|
|||||||
@ -25,6 +25,8 @@ import com.alibaba.fastjson.JSON;
|
|||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import com.alibaba.fastjson.TypeReference;
|
import com.alibaba.fastjson.TypeReference;
|
||||||
import com.alibaba.fastjson.parser.Feature;
|
import com.alibaba.fastjson.parser.Feature;
|
||||||
|
import com.foxinmy.weixin4j.cache.CacheStorager;
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.http.entity.FormUrlEntity;
|
import com.foxinmy.weixin4j.http.entity.FormUrlEntity;
|
||||||
import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
||||||
@ -38,7 +40,6 @@ import com.foxinmy.weixin4j.mp.oldpayment.WeixinOldPayAccount;
|
|||||||
import com.foxinmy.weixin4j.mp.oldpayment.WeixinOldPaymentSignature;
|
import com.foxinmy.weixin4j.mp.oldpayment.WeixinOldPaymentSignature;
|
||||||
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
|
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
|
||||||
import com.foxinmy.weixin4j.payment.PayRequest;
|
import com.foxinmy.weixin4j.payment.PayRequest;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
|
import com.foxinmy.weixin4j.sign.WeixinPaymentSignature;
|
||||||
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
import com.foxinmy.weixin4j.sign.WeixinSignature;
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
@ -66,44 +67,80 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
|
|||||||
*/
|
*/
|
||||||
public class PayOldApi extends MpApi {
|
public class PayOldApi extends MpApi {
|
||||||
|
|
||||||
private final Weixin4jSettings<WeixinOldPayAccount> settings;
|
private final WeixinOldPayAccount weixinPayAccount;
|
||||||
private final WeixinOldPayAccount weixinAccount;
|
|
||||||
private final TokenManager tokenManager;
|
private final TokenManager tokenManager;
|
||||||
private final WeixinSignature weixinMD5Signature;
|
private final WeixinSignature weixinMD5Signature;
|
||||||
private final WeixinOldPaymentSignature weixinOldSignature;
|
private final WeixinOldPaymentSignature weixinSignature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认使用weixin4j.properties配置信息
|
* 支付对象(使用weixin4j.properties配置的account商户信息,使用FileCacheStorager文件方式缓存TOKEN)
|
||||||
*/
|
*/
|
||||||
public PayOldApi() {
|
public PayOldApi() {
|
||||||
this(new Weixin4jSettings<WeixinOldPayAccount>(JSON.parseObject(
|
this(new FileCacheStorager<Token>());
|
||||||
Weixin4jConfigUtil.getValue("account"),
|
|
||||||
WeixinOldPayAccount.class)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 支付对象(使用weixin4j.properties配置的account商户信息)
|
||||||
* @param settings
|
|
||||||
* 微信配置信息
|
|
||||||
*/
|
*/
|
||||||
public PayOldApi(Weixin4jSettings<WeixinOldPayAccount> settings) {
|
public PayOldApi(CacheStorager<Token> cacheStorager) {
|
||||||
this.settings = settings;
|
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
|
||||||
this.weixinAccount = settings.getAccount();
|
WeixinOldPayAccount.class), cacheStorager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 支付对象
|
||||||
|
*
|
||||||
|
* @param weixinPayAccount
|
||||||
|
* 商户信息
|
||||||
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
|
*/
|
||||||
|
public PayOldApi(WeixinOldPayAccount weixinPayAccount,
|
||||||
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
if (weixinPayAccount == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"weixinPayAccount must not be empty");
|
||||||
|
}
|
||||||
|
if (cacheStorager == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"cacheStorager must not be empty");
|
||||||
|
}
|
||||||
|
this.weixinPayAccount = weixinPayAccount;
|
||||||
this.tokenManager = new TokenManager(new WeixinTokenCreator(
|
this.tokenManager = new TokenManager(new WeixinTokenCreator(
|
||||||
weixinAccount.getId(), weixinAccount.getSecret()),
|
weixinPayAccount.getId(), weixinPayAccount.getSecret()),
|
||||||
settings.getCacheStorager0());
|
cacheStorager);
|
||||||
this.weixinMD5Signature = new WeixinPaymentSignature(
|
this.weixinMD5Signature = new WeixinPaymentSignature(
|
||||||
weixinAccount.getPartnerKey());
|
weixinPayAccount.getPartnerKey());
|
||||||
this.weixinOldSignature = new WeixinOldPaymentSignature(
|
this.weixinSignature = new WeixinOldPaymentSignature(
|
||||||
weixinAccount.getPaySignKey(), weixinAccount.getPartnerKey());
|
weixinPayAccount.getPaySignKey(),
|
||||||
|
weixinPayAccount.getPartnerKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回商户信息
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public WeixinOldPayAccount getWeixinPayAccount() {
|
public WeixinOldPayAccount getWeixinPayAccount() {
|
||||||
return this.weixinAccount;
|
return weixinPayAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* token管理
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public TokenManager getTokenManager() {
|
||||||
|
return this.tokenManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回签名对象
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
public WeixinOldPaymentSignature getWeixinPaymentSignature() {
|
public WeixinOldPaymentSignature getWeixinPaymentSignature() {
|
||||||
return this.weixinOldSignature;
|
return this.weixinSignature;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +161,7 @@ public class PayOldApi extends MpApi {
|
|||||||
public String createPayJsRequestJson(String body, String outTradeNo,
|
public String createPayJsRequestJson(String body, String outTradeNo,
|
||||||
double totalFee, String notifyUrl, String createIp) {
|
double totalFee, String notifyUrl, String createIp) {
|
||||||
PayPackageV2 payPackage = new PayPackageV2(
|
PayPackageV2 payPackage = new PayPackageV2(
|
||||||
weixinAccount.getPartnerId(), body, outTradeNo, totalFee,
|
weixinPayAccount.getPartnerId(), body, outTradeNo, totalFee,
|
||||||
notifyUrl, createIp);
|
notifyUrl, createIp);
|
||||||
return createPayJsRequestJson(payPackage);
|
return createPayJsRequestJson(payPackage);
|
||||||
}
|
}
|
||||||
@ -137,9 +174,9 @@ public class PayOldApi extends MpApi {
|
|||||||
* @return 支付json串
|
* @return 支付json串
|
||||||
*/
|
*/
|
||||||
public String createPayJsRequestJson(PayPackageV2 payPackage) {
|
public String createPayJsRequestJson(PayPackageV2 payPackage) {
|
||||||
PayRequest payRequest = new PayRequest(weixinAccount.getId(),
|
PayRequest payRequest = new PayRequest(weixinPayAccount.getId(),
|
||||||
weixinOldSignature.sign(payPackage));
|
weixinSignature.sign(payPackage));
|
||||||
payRequest.setPaySign(weixinOldSignature.sign(payRequest));
|
payRequest.setPaySign(weixinSignature.sign(payRequest));
|
||||||
payRequest.setSignType(SignType.SHA1);
|
payRequest.setSignType(SignType.SHA1);
|
||||||
return JSON.toJSONString(payRequest);
|
return JSON.toJSONString(payRequest);
|
||||||
}
|
}
|
||||||
@ -155,14 +192,14 @@ public class PayOldApi extends MpApi {
|
|||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
String timestamp = DateUtil.timestamp2string();
|
String timestamp = DateUtil.timestamp2string();
|
||||||
String noncestr = RandomUtil.generateString(16);
|
String noncestr = RandomUtil.generateString(16);
|
||||||
map.put("appid", weixinAccount.getId());
|
map.put("appid", weixinPayAccount.getId());
|
||||||
map.put("timestamp", timestamp);
|
map.put("timestamp", timestamp);
|
||||||
map.put("noncestr", noncestr);
|
map.put("noncestr", noncestr);
|
||||||
map.put("productid", productId);
|
map.put("productid", productId);
|
||||||
map.put("appkey", weixinAccount.getPaySignKey());
|
map.put("appkey", weixinPayAccount.getPaySignKey());
|
||||||
String sign = weixinOldSignature.sign(map);
|
String sign = weixinSignature.sign(map);
|
||||||
String nativepay_uri = getRequestUri("nativepay_old_uri");
|
String nativepay_uri = getRequestUri("nativepay_old_uri");
|
||||||
return String.format(nativepay_uri, sign, weixinAccount.getId(),
|
return String.format(nativepay_uri, sign, weixinPayAccount.getId(),
|
||||||
productId, timestamp, noncestr);
|
productId, timestamp, noncestr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,23 +219,23 @@ public class PayOldApi extends MpApi {
|
|||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
sb.append(idQuery.getType().getName()).append("=")
|
sb.append(idQuery.getType().getName()).append("=")
|
||||||
.append(idQuery.getId());
|
.append(idQuery.getId());
|
||||||
sb.append("&partner=").append(weixinAccount.getPartnerId());
|
sb.append("&partner=").append(weixinPayAccount.getPartnerId());
|
||||||
String part = sb.toString();
|
String part = sb.toString();
|
||||||
sb.append("&key=").append(weixinAccount.getPartnerKey());
|
sb.append("&key=").append(weixinPayAccount.getPartnerKey());
|
||||||
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
|
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
|
||||||
sb.delete(0, sb.length());
|
sb.delete(0, sb.length());
|
||||||
sb.append(part).append("&sign=").append(sign);
|
sb.append(part).append("&sign=").append(sign);
|
||||||
|
|
||||||
String timestamp = DateUtil.timestamp2string();
|
String timestamp = DateUtil.timestamp2string();
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
obj.put("appid", weixinAccount.getId());
|
obj.put("appid", weixinPayAccount.getId());
|
||||||
obj.put("appkey", weixinAccount.getPaySignKey());
|
obj.put("appkey", weixinPayAccount.getPaySignKey());
|
||||||
obj.put("package", sb.toString());
|
obj.put("package", sb.toString());
|
||||||
obj.put("timestamp", timestamp);
|
obj.put("timestamp", timestamp);
|
||||||
String signature = weixinOldSignature.sign(obj);
|
String signature = weixinSignature.sign(obj);
|
||||||
|
|
||||||
obj.clear();
|
obj.clear();
|
||||||
obj.put("appid", weixinAccount.getId());
|
obj.put("appid", weixinPayAccount.getId());
|
||||||
obj.put("package", sb.toString());
|
obj.put("package", sb.toString());
|
||||||
obj.put("timestamp", timestamp);
|
obj.put("timestamp", timestamp);
|
||||||
obj.put("app_signature", signature);
|
obj.put("app_signature", signature);
|
||||||
@ -259,7 +296,7 @@ public class PayOldApi extends MpApi {
|
|||||||
// 填写为 1.0 时,操作员密码为明文
|
// 填写为 1.0 时,操作员密码为明文
|
||||||
// 填写为 1.1 时,操作员密码为 MD5(密码)值
|
// 填写为 1.1 时,操作员密码为 MD5(密码)值
|
||||||
map.put("service_version", "1.1");
|
map.put("service_version", "1.1");
|
||||||
map.put("partner", weixinAccount.getPartnerId());
|
map.put("partner", weixinPayAccount.getPartnerId());
|
||||||
map.put("out_refund_no", outRefundNo);
|
map.put("out_refund_no", outRefundNo);
|
||||||
map.put("total_fee",
|
map.put("total_fee",
|
||||||
Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
|
Integer.toString(DateUtil.formatYuan2Fen(totalFee)));
|
||||||
@ -267,7 +304,7 @@ public class PayOldApi extends MpApi {
|
|||||||
Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
|
Integer.toString(DateUtil.formatYuan2Fen(refundFee)));
|
||||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||||
if (StringUtil.isBlank(opUserId)) {
|
if (StringUtil.isBlank(opUserId)) {
|
||||||
opUserId = weixinAccount.getPartnerId();
|
opUserId = weixinPayAccount.getPartnerId();
|
||||||
}
|
}
|
||||||
map.put("op_user_id", opUserId);
|
map.put("op_user_id", opUserId);
|
||||||
if (mopara != null && !mopara.isEmpty()) {
|
if (mopara != null && !mopara.isEmpty()) {
|
||||||
@ -280,7 +317,7 @@ public class PayOldApi extends MpApi {
|
|||||||
KeyStore ks = null;
|
KeyStore ks = null;
|
||||||
String jksPwd = "";
|
String jksPwd = "";
|
||||||
File jksFile = new File(String.format("%s%stenpay_cacert.jks",
|
File jksFile = new File(String.format("%s%stenpay_cacert.jks",
|
||||||
settings.getTmpdir0(), File.separator));
|
System.getProperty("java.io.tmpdir"), File.separator));
|
||||||
// create jks ca
|
// create jks ca
|
||||||
if (!jksFile.exists()) {
|
if (!jksFile.exists()) {
|
||||||
CertificateFactory cf = CertificateFactory
|
CertificateFactory cf = CertificateFactory
|
||||||
@ -307,8 +344,8 @@ public class PayOldApi extends MpApi {
|
|||||||
KeyManagerFactory kmf = KeyManagerFactory
|
KeyManagerFactory kmf = KeyManagerFactory
|
||||||
.getInstance(Consts.SunX509);
|
.getInstance(Consts.SunX509);
|
||||||
ks = KeyStore.getInstance(Consts.PKCS12);
|
ks = KeyStore.getInstance(Consts.PKCS12);
|
||||||
ks.load(certificate, weixinAccount.getPartnerId().toCharArray());
|
ks.load(certificate, weixinPayAccount.getPartnerId().toCharArray());
|
||||||
kmf.init(ks, weixinAccount.getPartnerId().toCharArray());
|
kmf.init(ks, weixinPayAccount.getPartnerId().toCharArray());
|
||||||
|
|
||||||
ctx = SSLContext.getInstance(Consts.TLS);
|
ctx = SSLContext.getInstance(Consts.TLS);
|
||||||
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
|
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
|
||||||
@ -442,7 +479,7 @@ public class PayOldApi extends MpApi {
|
|||||||
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
|
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
|
||||||
String fileName = String.format("weixin4j_bill_%s_%s_%s.txt",
|
String fileName = String.format("weixin4j_bill_%s_%s_%s.txt",
|
||||||
formatBillDate, billType.name().toLowerCase(),
|
formatBillDate, billType.name().toLowerCase(),
|
||||||
weixinAccount.getId());
|
weixinPayAccount.getId());
|
||||||
File file = new File(String.format("%s%s%s", billPath, File.separator,
|
File file = new File(String.format("%s%s%s", billPath, File.separator,
|
||||||
fileName));
|
fileName));
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
@ -451,12 +488,12 @@ public class PayOldApi extends MpApi {
|
|||||||
String downloadbill_uri = getRequestUri("downloadbill_old_uri");
|
String downloadbill_uri = getRequestUri("downloadbill_old_uri");
|
||||||
|
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
map.put("spid", weixinAccount.getPartnerId());
|
map.put("spid", weixinPayAccount.getPartnerId());
|
||||||
map.put("trans_time", DateUtil.fortmat2yyyy_MM_dd(billDate));
|
map.put("trans_time", DateUtil.fortmat2yyyy_MM_dd(billDate));
|
||||||
map.put("stamp", DateUtil.timestamp2string());
|
map.put("stamp", DateUtil.timestamp2string());
|
||||||
map.put("cft_signtype", "0");
|
map.put("cft_signtype", "0");
|
||||||
map.put("mchtype", Integer.toString(billType.getVal()));
|
map.put("mchtype", Integer.toString(billType.getVal()));
|
||||||
map.put("key", weixinAccount.getPartnerKey());
|
map.put("key", weixinPayAccount.getPartnerKey());
|
||||||
String sign = DigestUtil.MD5(MapUtil.toJoinString(map, false, false));
|
String sign = DigestUtil.MD5(MapUtil.toJoinString(map, false, false));
|
||||||
map.put("sign", sign.toLowerCase());
|
map.put("sign", sign.toLowerCase());
|
||||||
WeixinResponse response = weixinExecutor.get(String.format("%s?%s",
|
WeixinResponse response = weixinExecutor.get(String.format("%s?%s",
|
||||||
@ -507,7 +544,7 @@ public class PayOldApi extends MpApi {
|
|||||||
String refundquery_uri = getRequestUri("refundquery_old_uri");
|
String refundquery_uri = getRequestUri("refundquery_old_uri");
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
map.put("input_charset", Consts.UTF_8.name());
|
map.put("input_charset", Consts.UTF_8.name());
|
||||||
map.put("partner", weixinAccount.getPartnerId());
|
map.put("partner", weixinPayAccount.getPartnerId());
|
||||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||||
String sign = weixinMD5Signature.sign(map);
|
String sign = weixinMD5Signature.sign(map);
|
||||||
map.put("sign", sign.toLowerCase());
|
map.put("sign", sign.toLowerCase());
|
||||||
@ -540,15 +577,15 @@ public class PayOldApi extends MpApi {
|
|||||||
Token token = tokenManager.getCache();
|
Token token = tokenManager.getCache();
|
||||||
|
|
||||||
Map<String, String> map = new HashMap<String, String>();
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
map.put("appid", weixinAccount.getId());
|
map.put("appid", weixinPayAccount.getId());
|
||||||
map.put("appkey", weixinAccount.getPaySignKey());
|
map.put("appkey", weixinPayAccount.getPaySignKey());
|
||||||
map.put("openid", openId);
|
map.put("openid", openId);
|
||||||
map.put("transid", transid);
|
map.put("transid", transid);
|
||||||
map.put("out_trade_no", outTradeNo);
|
map.put("out_trade_no", outTradeNo);
|
||||||
map.put("deliver_timestamp", DateUtil.timestamp2string());
|
map.put("deliver_timestamp", DateUtil.timestamp2string());
|
||||||
map.put("deliver_status", status ? "1" : "0");
|
map.put("deliver_status", status ? "1" : "0");
|
||||||
map.put("deliver_msg", statusMsg);
|
map.put("deliver_msg", statusMsg);
|
||||||
map.put("app_signature", weixinOldSignature.sign(map));
|
map.put("app_signature", weixinSignature.sign(map));
|
||||||
map.put("sign_method", SignType.SHA1.name().toLowerCase());
|
map.put("sign_method", SignType.SHA1.name().toLowerCase());
|
||||||
|
|
||||||
WeixinResponse response = weixinExecutor.post(
|
WeixinResponse response = weixinExecutor.post(
|
||||||
|
|||||||
@ -9,12 +9,23 @@ tenpay_base_url=http://mch.tenpay.com
|
|||||||
tenpay_ssl_base_url=https://mch.tenpay.com
|
tenpay_ssl_base_url=https://mch.tenpay.com
|
||||||
tenpay_gw_base_url=https://gw.tenpay.com
|
tenpay_gw_base_url=https://gw.tenpay.com
|
||||||
|
|
||||||
# \u7f51\u9875\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
# \u7f51\u9875oauth\u6388\u6743URL
|
||||||
sns_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
|
sns_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
|
||||||
sns_user_token_uri=https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u516c\u4f17\u53f7\u7f51\u9875oauth\u6388\u6743URL
|
||||||
sns_token_refresh_uri=https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s
|
sns_component_user_auth_uri=https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s&component_appid=%s#wechat_redirect
|
||||||
sns_auth_token_uri=https://api.weixin.qq.com/sns/auth?access_token=%s&openid=%s
|
# \u7f51\u9875oauth\u6388\u6743\u83b7\u53d6token
|
||||||
sns_user_info_uri=https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s
|
sns_user_token_uri={api_base_url}/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code
|
||||||
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u516c\u4f17\u53f7\u7f51\u9875oauth\u6388\u6743\u83b7\u53d6token
|
||||||
|
sns_component_user_token_uri={api_base_url}/sns/oauth2/component/access_token?appid=%s&code=%s&grant_type=authorization_code&component_appid=%s&component_access_token=%s
|
||||||
|
# \u7f51\u9875oauth\u6388\u6743\u5237\u65b0token
|
||||||
|
sns_token_refresh_uri={api_base_url}/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s
|
||||||
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u516c\u4f17\u53f7\u7f51\u9875oauth\u6388\u6743\u5237\u65b0token
|
||||||
|
sns_component_token_refresh_uri={api_base_url}/sns/oauth2/component/refresh_token?appid=%s&grant_type=refresh_token&component_appid=%s&component_access_token=%s&refresh_token=%s
|
||||||
|
# \u7f51\u9875oauthoauth\u6388\u6743\u9a8c\u8bc1token
|
||||||
|
sns_auth_token_uri={api_base_url}/sns/auth?access_token=%s&openid=%s
|
||||||
|
# \u7f51\u9875oauth\u6388\u6743\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
||||||
|
sns_user_info_uri={api_base_url}/sns/userinfo?access_token=%s&openid=%s&lang=%s
|
||||||
|
# \u5f00\u653e\u5e73\u53f0\u626b\u7801\u767b\u9646\u6388\u6743
|
||||||
open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
|
open_user_auth_uri=https://open.weixin.qq.com/connect/qrconnect?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect
|
||||||
|
|
||||||
# \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
# \u76f4\u63a5\u83b7\u53d6\u7528\u6237\u4fe1\u606f
|
||||||
|
|||||||
@ -18,7 +18,7 @@ public class OauthToken extends Token {
|
|||||||
/**
|
/**
|
||||||
* 用户的openid
|
* 用户的openid
|
||||||
*/
|
*/
|
||||||
@JSONField(name = "openId")
|
@JSONField(name = "openid")
|
||||||
private String openId;
|
private String openId;
|
||||||
/**
|
/**
|
||||||
* 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
|
* 只有在用户将公众号绑定到微信开放平台帐号后,才会出现该字段
|
||||||
|
|||||||
@ -12,8 +12,7 @@ import com.foxinmy.weixin4j.model.WeixinAccount;
|
|||||||
* @className WeixinMpAccount
|
* @className WeixinMpAccount
|
||||||
* @author jinyu
|
* @author jinyu
|
||||||
* @date Jul 6, 2016
|
* @date Jul 6, 2016
|
||||||
* @since JDK 1.8
|
* @since JDK 1.6
|
||||||
* @see
|
|
||||||
*/
|
*/
|
||||||
public class WeixinMpAccount extends WeixinAccount {
|
public class WeixinMpAccount extends WeixinAccount {
|
||||||
|
|
||||||
|
|||||||
@ -14,15 +14,18 @@ public final class URLConsts {
|
|||||||
/**
|
/**
|
||||||
* 公众平台获取token的url
|
* 公众平台获取token的url
|
||||||
*/
|
*/
|
||||||
public static final String ASSESS_TOKEN_URL = BASE_URL + "/token?grant_type=client_credential&appid=%s&secret=%s";
|
public static final String ASSESS_TOKEN_URL = BASE_URL
|
||||||
|
+ "/token?grant_type=client_credential&appid=%s&secret=%s";
|
||||||
/**
|
/**
|
||||||
* 公众平台jssdk获取token的url
|
* 公众平台jssdk获取token的url
|
||||||
*/
|
*/
|
||||||
public static final String JS_TICKET_URL = BASE_URL + "/ticket/getticket?access_token=%s&type=%s";
|
public static final String JS_TICKET_URL = BASE_URL
|
||||||
|
+ "/ticket/getticket?access_token=%s&type=%s";
|
||||||
/**
|
/**
|
||||||
* 开放平台获取token的url
|
* 开放平台获取token的url
|
||||||
*/
|
*/
|
||||||
public static final String COMPONENT_TOKEN_URL = BASE_URL + "/component/api_component_token";
|
public static final String COMPONENT_TOKEN_URL = BASE_URL
|
||||||
|
+ "/component/api_component_token";
|
||||||
/**
|
/**
|
||||||
* 开放平台获取预授权码的url
|
* 开放平台获取预授权码的url
|
||||||
*/
|
*/
|
||||||
@ -36,6 +39,5 @@ public final class URLConsts {
|
|||||||
/**
|
/**
|
||||||
* 开放平台oauth授权的url
|
* 开放平台oauth授权的url
|
||||||
*/
|
*/
|
||||||
public static final String COMPONENT_OAUTH_URL = BASE_URL
|
public static final String COMPONENT_OAUTH_URL = "https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s";
|
||||||
+ "/componentloginpage?component_appid=%s&pre_auth_code=%s&redirect_uri=%s";
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,20 +5,21 @@ weixin4j.account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed0
|
|||||||
"components":[{"id":"\u5e94\u7528\u7ec4\u4ef6\u7684id","secret":"\u5e94\u7528\u7ec4\u4ef6\u7684secret"}],\
|
"components":[{"id":"\u5e94\u7528\u7ec4\u4ef6\u7684id","secret":"\u5e94\u7528\u7ec4\u4ef6\u7684secret"}],\
|
||||||
"mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
"mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
||||||
"certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\
|
"certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\
|
||||||
|
"certificateFile":"\u5fae\u4fe1\u652f\u4ed8\u67d0\u4e9b\u63a5\u53e3(\u9000\u6b3e\u7b49)\u9700\u8981\u7684ca\u8bc1\u4e66\u5b58\u653e\u7684\u8def\u5f84,classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199classpath:xxxxx.p12,\u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6classpath\u6839\u76ee\u5f55\u4e0b\u7684ca.p12\u6587\u4ef6",\
|
||||||
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
||||||
|
|
||||||
# weixin4j\u7684\u4e34\u65f6\u76ee\u5f55
|
# \u516c\u4f17\u53f7\u5fae\u4fe1\u7f51\u9875oauth\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
# \u53ef\u80fd\u5b58\u653etoken\u6587\u4ef6\u3001\u4e8c\u7ef4\u7801\u6587\u4ef6\u3001\u5a92\u4f53\u6587\u4ef6\u3001\u5bf9\u8d26\u5355\u6587\u4ef6\u7b49
|
# \u8be6\u89c1\uff1ahttps://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842&token=&lang=zh_CN
|
||||||
# \u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6java.io.tmpdir\u4e34\u65f6\u76ee\u5f55
|
|
||||||
weixin4j.tmpdir=
|
|
||||||
# \u5fae\u4fe1\u652f\u4ed8\u67d0\u4e9b\u63a5\u53e3\u9700\u8981\u7684ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
|
|
||||||
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199
|
|
||||||
# weixin4j.certificate.file=classpath:xxxxx.p12
|
|
||||||
# \u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6classpath\u6839\u76ee\u5f55\u4e0b\u7684ca.p12\u6587\u4ef6
|
|
||||||
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
|
|
||||||
|
|
||||||
# \u7528\u6237oauth\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
|
|
||||||
weixin4j.user.oauth.redirect.uri=
|
weixin4j.user.oauth.redirect.uri=
|
||||||
|
|
||||||
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528ComponentApi\u65f6\u586b\u5199)
|
# \u7f51\u7ad9\u626b\u63cf\u767b\u9646oauth\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
weixin4j.component.oauth.redirect.uri=
|
# \u8be6\u89c1\uff1ahttps://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419316505&token=&lang=zh_CN
|
||||||
|
weixin4j.open.user.oauth.redirect.uri=
|
||||||
|
|
||||||
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528ComponentApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
|
# \u8be6\u89c1\uff1ahttps://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1453779503&token=&lang=zh_CN
|
||||||
|
weixin4j.component.oauth.redirect.uri=
|
||||||
|
|
||||||
|
# \u7b2c\u4e09\u65b9\u7ec4\u4ef6\u4ee3\u66ff\u6388\u6743\u516c\u4f17\u53f7\u53d1\u8d77\u7f51\u9875\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528ComponentApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
|
# \u8be6\u89c1\uff1ahttps://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419318590&token=&lang=zh_CN
|
||||||
|
weixin4j.component.user.oauth.redirect.uri=
|
||||||
@ -44,6 +44,6 @@ public class HelperTest extends TokenTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void clearQuota() throws WeixinException {
|
public void clearQuota() throws WeixinException {
|
||||||
System.err.println(helperApi.clearQuota(settings.getAccount().getId()));
|
System.err.println(helperApi.clearQuota(weixinAccount.getId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,10 +7,11 @@ import java.util.Calendar;
|
|||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.mp.api.PayOldApi;
|
import com.foxinmy.weixin4j.mp.api.PayOldApi;
|
||||||
import com.foxinmy.weixin4j.mp.oldpayment.WeixinOldPayAccount;
|
import com.foxinmy.weixin4j.mp.oldpayment.WeixinOldPayAccount;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.type.IdQuery;
|
import com.foxinmy.weixin4j.type.IdQuery;
|
||||||
import com.foxinmy.weixin4j.type.IdType;
|
import com.foxinmy.weixin4j.type.IdType;
|
||||||
|
|
||||||
@ -24,14 +25,14 @@ import com.foxinmy.weixin4j.type.IdType;
|
|||||||
* @see
|
* @see
|
||||||
*/
|
*/
|
||||||
public class PayTest {
|
public class PayTest {
|
||||||
protected final static PayOldApi PAY2;
|
private final static PayOldApi PAY2;
|
||||||
protected final static Weixin4jSettings<WeixinOldPayAccount> settings;
|
private final static WeixinOldPayAccount WEIXIN_OLD_PAY_ACCOUNT;
|
||||||
static {
|
static {
|
||||||
settings = new Weixin4jSettings<WeixinOldPayAccount>(
|
WEIXIN_OLD_PAY_ACCOUNT = new WeixinOldPayAccount("请填入v2版本的appid",
|
||||||
new WeixinOldPayAccount("请填入v2版本的appid", "请填入v2版本的appSecret",
|
"请填入v2版本的appSecret", "请填入v2版本的paysignkey", "请填入v2版本的partnerId",
|
||||||
"请填入v2版本的paysignkey", "请填入v2版本的partnerId",
|
"请填入v2版本的partnerKey");
|
||||||
"请填入v2版本的partnerKey"));
|
PAY2 = new PayOldApi(WEIXIN_OLD_PAY_ACCOUNT,
|
||||||
PAY2 = new PayOldApi(settings);
|
new FileCacheStorager<Token>());
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 商户证书文件
|
* 商户证书文件
|
||||||
|
|||||||
@ -4,10 +4,11 @@ import org.junit.Assert;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
|
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||||
|
|
||||||
@ -22,15 +23,14 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
|||||||
public class TokenTest {
|
public class TokenTest {
|
||||||
|
|
||||||
protected TokenManager tokenManager;
|
protected TokenManager tokenManager;
|
||||||
protected Weixin4jSettings<WeixinAccount> settings;
|
protected WeixinAccount weixinAccount;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.settings = new Weixin4jSettings<WeixinAccount>(
|
this.weixinAccount = Weixin4jConfigUtil.getWeixinAccount();
|
||||||
Weixin4jConfigUtil.getWeixinAccount());
|
tokenManager = new TokenManager(new WeixinTokenCreator(
|
||||||
tokenManager = new TokenManager(new WeixinTokenCreator(settings
|
weixinAccount.getId(), weixinAccount.getSecret()),
|
||||||
.getAccount().getId(), settings.getAccount().getSecret()),
|
new FileCacheStorager<Token>());
|
||||||
settings.getCacheStorager0());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.foxinmy.weixin4j.mp.test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
|
import com.foxinmy.weixin4j.mp.WeixinProxy;
|
||||||
|
import com.foxinmy.weixin4j.mp.model.Menu;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信接口测试
|
||||||
|
*
|
||||||
|
* @className WeixinProxyTest
|
||||||
|
* @author jinyu(foxinmy@gmail.com)
|
||||||
|
* @date 2016年8月18日
|
||||||
|
* @since JDK 1.6
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public class WeixinProxyTest {
|
||||||
|
private WeixinProxy weixinProxy;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
this.weixinProxy = new WeixinProxy();
|
||||||
|
// Weixin4jSettings<WeixinAccount> settings = new
|
||||||
|
// Weixin4jSettings<WeixinAccount>(RediscacheStorager);
|
||||||
|
// this.weixinProxy= new WeixinProxy(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() throws WeixinException{
|
||||||
|
List<Menu> buttons = weixinProxy.getAllMenu();
|
||||||
|
System.err.println(buttons);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,9 +3,12 @@ package com.foxinmy.weixin4j.qy;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.cache.CacheStorager;
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
||||||
import com.foxinmy.weixin4j.model.Button;
|
import com.foxinmy.weixin4j.model.Button;
|
||||||
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
import com.foxinmy.weixin4j.model.media.MediaCounter;
|
import com.foxinmy.weixin4j.model.media.MediaCounter;
|
||||||
import com.foxinmy.weixin4j.model.media.MediaDownloadResult;
|
import com.foxinmy.weixin4j.model.media.MediaDownloadResult;
|
||||||
@ -20,6 +23,7 @@ import com.foxinmy.weixin4j.qy.api.HelperApi;
|
|||||||
import com.foxinmy.weixin4j.qy.api.MediaApi;
|
import com.foxinmy.weixin4j.qy.api.MediaApi;
|
||||||
import com.foxinmy.weixin4j.qy.api.MenuApi;
|
import com.foxinmy.weixin4j.qy.api.MenuApi;
|
||||||
import com.foxinmy.weixin4j.qy.api.NotifyApi;
|
import com.foxinmy.weixin4j.qy.api.NotifyApi;
|
||||||
|
import com.foxinmy.weixin4j.qy.api.OauthApi;
|
||||||
import com.foxinmy.weixin4j.qy.api.PartyApi;
|
import com.foxinmy.weixin4j.qy.api.PartyApi;
|
||||||
import com.foxinmy.weixin4j.qy.api.TagApi;
|
import com.foxinmy.weixin4j.qy.api.TagApi;
|
||||||
import com.foxinmy.weixin4j.qy.api.UserApi;
|
import com.foxinmy.weixin4j.qy.api.UserApi;
|
||||||
@ -45,8 +49,8 @@ import com.foxinmy.weixin4j.qy.type.ChatType;
|
|||||||
import com.foxinmy.weixin4j.qy.type.InviteType;
|
import com.foxinmy.weixin4j.qy.type.InviteType;
|
||||||
import com.foxinmy.weixin4j.qy.type.KfType;
|
import com.foxinmy.weixin4j.qy.type.KfType;
|
||||||
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.token.PerTicketManager;
|
import com.foxinmy.weixin4j.token.PerTicketManager;
|
||||||
|
import com.foxinmy.weixin4j.token.TokenCreator;
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
import com.foxinmy.weixin4j.tuple.MpArticle;
|
import com.foxinmy.weixin4j.tuple.MpArticle;
|
||||||
import com.foxinmy.weixin4j.type.MediaType;
|
import com.foxinmy.weixin4j.type.MediaType;
|
||||||
@ -63,7 +67,10 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
|||||||
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php">api文档</a>
|
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php">api文档</a>
|
||||||
*/
|
*/
|
||||||
public class WeixinProxy {
|
public class WeixinProxy {
|
||||||
|
/**
|
||||||
|
* 授权API
|
||||||
|
*/
|
||||||
|
private final OauthApi oauthApi;
|
||||||
/**
|
/**
|
||||||
* 媒体素材API
|
* 媒体素材API
|
||||||
*/
|
*/
|
||||||
@ -105,33 +112,48 @@ public class WeixinProxy {
|
|||||||
*/
|
*/
|
||||||
private final ChatApi chatApi;
|
private final ChatApi chatApi;
|
||||||
/**
|
/**
|
||||||
* token实现
|
* token管理
|
||||||
*/
|
*/
|
||||||
private final TokenManager tokenManager;
|
private final TokenManager tokenManager;
|
||||||
/**
|
/**
|
||||||
* 配置信息
|
* 账号信息
|
||||||
*/
|
*/
|
||||||
private Weixin4jSettings<WeixinAccount> settings;
|
private final WeixinAccount weixinAccount;
|
||||||
|
/**
|
||||||
|
* token存储
|
||||||
|
*/
|
||||||
|
private final CacheStorager<Token> cacheStorager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认使用文件方式保存token、使用weixin4j.properties配置的账号信息
|
* 微信接口实现(使用weixin4j.properties配置的account账号信息,
|
||||||
|
* 使用FileCacheStorager文件方式缓存TOKEN)
|
||||||
*/
|
*/
|
||||||
public WeixinProxy() {
|
public WeixinProxy() {
|
||||||
this(new Weixin4jSettings<WeixinAccount>(
|
this(new FileCacheStorager<Token>());
|
||||||
Weixin4jConfigUtil.getWeixinAccount()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 微信接口实现(使用weixin4j.properties配置的account账号信息)
|
||||||
* @param settings
|
*
|
||||||
* 微信配置信息
|
* @param cacheStorager
|
||||||
* @see com.foxinmy.weixin4j.setting.Weixin4jSettings
|
* token管理
|
||||||
*/
|
*/
|
||||||
public WeixinProxy(Weixin4jSettings<WeixinAccount> settings) {
|
public WeixinProxy(CacheStorager<Token> cacheStorager) {
|
||||||
this(new TokenManager(new WeixinTokenCreator(settings.getAccount()
|
this(Weixin4jConfigUtil.getWeixinAccount(), cacheStorager);
|
||||||
.getId(), settings.getAccount().getSecret()),
|
}
|
||||||
settings.getCacheStorager0()));
|
|
||||||
this.settings = settings;
|
/**
|
||||||
|
* 微信接口实现
|
||||||
|
*
|
||||||
|
* @param weixinAccount
|
||||||
|
* 账号信息
|
||||||
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
|
*/
|
||||||
|
public WeixinProxy(WeixinAccount weixinAccount,
|
||||||
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
this(weixinAccount, new WeixinTokenCreator(weixinAccount.getId(),
|
||||||
|
weixinAccount.getSecret()), cacheStorager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -148,21 +170,37 @@ public class WeixinProxy {
|
|||||||
*/
|
*/
|
||||||
public WeixinProxy(PerTicketManager perTicketManager,
|
public WeixinProxy(PerTicketManager perTicketManager,
|
||||||
TokenManager suiteTokenManager) {
|
TokenManager suiteTokenManager) {
|
||||||
this(new TokenManager(new WeixinTokenSuiteCreator(perTicketManager,
|
this(
|
||||||
suiteTokenManager), perTicketManager.getCacheStorager()));
|
new WeixinAccount(perTicketManager.getThirdId(),
|
||||||
this.settings = new Weixin4jSettings<WeixinAccount>(new WeixinAccount(
|
perTicketManager.getThirdSecret()),
|
||||||
perTicketManager.getAuthAppId(), null));
|
new WeixinTokenSuiteCreator(perTicketManager, suiteTokenManager),
|
||||||
|
perTicketManager.getCacheStorager());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注意:TokenCreator 需为 <font
|
* 微信接口实现
|
||||||
* color="red">WeixinTokenCreator或WeixinTokenSuiteCreator</font>
|
*
|
||||||
*
|
* @param settings
|
||||||
* @see com.foxinmy.weixin4j.qy.token.WeixinTokenCreator
|
* 配置信息
|
||||||
* @param tokenManager
|
* @param tokenManager
|
||||||
|
* token管理
|
||||||
*/
|
*/
|
||||||
private WeixinProxy(TokenManager tokenManager) {
|
private WeixinProxy(WeixinAccount weixinAccount, TokenCreator tokenCreator,
|
||||||
this.tokenManager = tokenManager;
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
if (weixinAccount == null) {
|
||||||
|
throw new IllegalArgumentException("settings must not be empty");
|
||||||
|
}
|
||||||
|
if (tokenCreator == null) {
|
||||||
|
throw new IllegalArgumentException("tokenCreator must not be empty");
|
||||||
|
}
|
||||||
|
if (cacheStorager == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"cacheStorager must not be empty");
|
||||||
|
}
|
||||||
|
this.tokenManager = new TokenManager(tokenCreator, cacheStorager);
|
||||||
|
this.weixinAccount = weixinAccount;
|
||||||
|
this.cacheStorager = cacheStorager;
|
||||||
|
this.oauthApi = new OauthApi(weixinAccount);
|
||||||
this.partyApi = new PartyApi(tokenManager);
|
this.partyApi = new PartyApi(tokenManager);
|
||||||
this.userApi = new UserApi(tokenManager);
|
this.userApi = new UserApi(tokenManager);
|
||||||
this.tagApi = new TagApi(tokenManager);
|
this.tagApi = new TagApi(tokenManager);
|
||||||
@ -184,13 +222,23 @@ public class WeixinProxy {
|
|||||||
return this.tokenManager;
|
return this.tokenManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取oauth授权API
|
||||||
|
*
|
||||||
|
* @see com.foxinmy.weixin4j.qy.api.OauthApi
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public OauthApi getOauthApi() {
|
||||||
|
return oauthApi;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取微信账号信息
|
* 获取微信账号信息
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinAccount getWeixinAccount() {
|
public WeixinAccount getWeixinAccount() {
|
||||||
return this.settings.getAccount();
|
return weixinAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -201,9 +249,8 @@ public class WeixinProxy {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public TokenManager getTicketManager(TicketType ticketType) {
|
public TokenManager getTicketManager(TicketType ticketType) {
|
||||||
return new TokenManager(new WeixinTicketCreator(getWeixinAccount()
|
return new TokenManager(new WeixinTicketCreator(weixinAccount.getId(),
|
||||||
.getId(), ticketType, this.tokenManager),
|
ticketType, this.tokenManager), cacheStorager);
|
||||||
this.settings.getCacheStorager0());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -769,11 +816,11 @@ public class WeixinProxy {
|
|||||||
* 获取部门成员
|
* 获取部门成员
|
||||||
*
|
*
|
||||||
* @param partyId
|
* @param partyId
|
||||||
* 部门ID 必须
|
* 部门ID
|
||||||
* @param fetchChild
|
* @param fetchChild
|
||||||
* 是否递归获取子部门下面的成员 非必须
|
* 是否递归获取子部门下面的成员
|
||||||
* @param userStatus
|
* @param userStatus
|
||||||
* 成员状态 status可叠加 非必须 未填写则默认为未关注(4)
|
* 成员状态 status可叠加 未填写则默认为未关注(4)
|
||||||
* @param findDetail
|
* @param findDetail
|
||||||
* 是否获取详细信息
|
* 是否获取详细信息
|
||||||
* @see com.foxinmy.weixin4j.qy.model.User
|
* @see com.foxinmy.weixin4j.qy.model.User
|
||||||
@ -789,6 +836,21 @@ public class WeixinProxy {
|
|||||||
return userApi.listUser(partyId, fetchChild, userStatus, findDetail);
|
return userApi.listUser(partyId, fetchChild, userStatus, findDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取权限范围内的所有成员列表
|
||||||
|
*
|
||||||
|
* @param userStatus
|
||||||
|
* 成员状态 未填写则默认为全部状态下的成员
|
||||||
|
* @return 成员列表
|
||||||
|
* @see com.foxinmy.weixin4j.qy.api.UserApi
|
||||||
|
* @see {@link #listUser(int, boolean, UserStatus,boolean)}
|
||||||
|
* @see {@link PartyApi#listParty(int)}
|
||||||
|
* @throws WeixinException
|
||||||
|
*/
|
||||||
|
public List<User> listAllUser(UserStatus userStatus) throws WeixinException {
|
||||||
|
return userApi.listAllUser(userStatus);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取部门下所有状态成员(不进行递归)
|
* 获取部门下所有状态成员(不进行递归)
|
||||||
*
|
*
|
||||||
|
|||||||
@ -7,6 +7,8 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.foxinmy.weixin4j.cache.CacheStorager;
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
import com.foxinmy.weixin4j.model.Token;
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
@ -17,7 +19,6 @@ import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
|
|||||||
import com.foxinmy.weixin4j.qy.token.WeixinProviderTokenCreator;
|
import com.foxinmy.weixin4j.qy.token.WeixinProviderTokenCreator;
|
||||||
import com.foxinmy.weixin4j.qy.type.LoginTargetType;
|
import com.foxinmy.weixin4j.qy.type.LoginTargetType;
|
||||||
import com.foxinmy.weixin4j.qy.type.URLConsts;
|
import com.foxinmy.weixin4j.qy.type.URLConsts;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.token.TicketManager;
|
import com.foxinmy.weixin4j.token.TicketManager;
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
import com.foxinmy.weixin4j.util.Consts;
|
import com.foxinmy.weixin4j.util.Consts;
|
||||||
@ -47,40 +48,65 @@ public class WeixinSuiteProxy {
|
|||||||
*/
|
*/
|
||||||
private ProviderApi providerApi;
|
private ProviderApi providerApi;
|
||||||
/**
|
/**
|
||||||
* 配置相关
|
* 企业号账号信息
|
||||||
*/
|
*/
|
||||||
private final Weixin4jSettings<WeixinQyAccount> settings;
|
private final WeixinQyAccount weixinQyAccount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 默认使用文件方式保存token、使用weixin4j.properties配置的账号信息
|
* 微信第三方套件接口实现(使用weixin4j.properties配置的account账号信息,
|
||||||
|
* 使用FileCacheStorager文件方式缓存TOKEN)
|
||||||
*/
|
*/
|
||||||
public WeixinSuiteProxy() {
|
public WeixinSuiteProxy() {
|
||||||
this(new Weixin4jSettings<WeixinQyAccount>(
|
this(new FileCacheStorager<Token>());
|
||||||
JSON.parseObject(Weixin4jConfigUtil.getValue("account"), WeixinQyAccount.class)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* 微信第三方套件接口实现(使用weixin4j.properties配置的account账号信息)
|
||||||
* @param settings
|
*
|
||||||
* 配置信息
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
*/
|
*/
|
||||||
public WeixinSuiteProxy(Weixin4jSettings<WeixinQyAccount> settings) {
|
public WeixinSuiteProxy(CacheStorager<Token> cacheStorager) {
|
||||||
this.settings = settings;
|
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
|
||||||
List<WeixinAccount> suites = settings.getAccount().getSuites();
|
WeixinQyAccount.class), cacheStorager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信第三方套件接口实现
|
||||||
|
*
|
||||||
|
* @param weixinQyAccount
|
||||||
|
* 账号信息
|
||||||
|
* @param cacheStorager
|
||||||
|
* token管理
|
||||||
|
*/
|
||||||
|
public WeixinSuiteProxy(WeixinQyAccount weixinQyAccount,
|
||||||
|
CacheStorager<Token> cacheStorager) {
|
||||||
|
if (weixinQyAccount == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"weixinQyAccount must not be empty");
|
||||||
|
}
|
||||||
|
if (cacheStorager == null) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"cacheStorager must not be empty");
|
||||||
|
}
|
||||||
|
this.weixinQyAccount = weixinQyAccount;
|
||||||
|
List<WeixinAccount> suites = weixinQyAccount.getSuites();
|
||||||
if (suites != null && !suites.isEmpty()) {
|
if (suites != null && !suites.isEmpty()) {
|
||||||
this.suiteMap = new HashMap<String, SuiteApi>(suites.size());
|
this.suiteMap = new HashMap<String, SuiteApi>(suites.size());
|
||||||
for (WeixinAccount suite : suites) {
|
for (WeixinAccount suite : suites) {
|
||||||
this.suiteMap.put(suite.getId(), new SuiteApi(
|
this.suiteMap.put(suite.getId(), new SuiteApi(
|
||||||
new TicketManager(suite.getId(), suite.getSecret(), settings.getCacheStorager0())));
|
new TicketManager(suite.getId(), suite.getSecret(),
|
||||||
|
cacheStorager)));
|
||||||
}
|
}
|
||||||
this.suiteMap.put(null, suiteMap.get(suites.get(0).getId()));
|
this.suiteMap.put(null, suiteMap.get(suites.get(0).getId()));
|
||||||
}
|
}
|
||||||
if (StringUtil.isNotBlank(settings.getAccount().getId())
|
if (StringUtil.isNotBlank(weixinQyAccount.getId())
|
||||||
&& StringUtil.isNotBlank(settings.getAccount().getProviderSecret())) {
|
&& StringUtil.isNotBlank(weixinQyAccount.getProviderSecret())) {
|
||||||
this.providerApi = new ProviderApi(
|
this.providerApi = new ProviderApi(
|
||||||
new TokenManager(new WeixinProviderTokenCreator(settings.getAccount().getId(),
|
new TokenManager(new WeixinProviderTokenCreator(
|
||||||
settings.getAccount().getProviderSecret()), settings.getCacheStorager0()),
|
weixinQyAccount.getId(), weixinQyAccount
|
||||||
settings.getCacheStorager0());
|
.getProviderSecret()), cacheStorager),
|
||||||
|
cacheStorager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,8 +115,8 @@ public class WeixinSuiteProxy {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinQyAccount getWeixinAccount() {
|
public WeixinQyAccount getWeixinQyAccount() {
|
||||||
return this.settings.getAccount();
|
return weixinQyAccount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -121,17 +147,19 @@ public class WeixinSuiteProxy {
|
|||||||
* @param suiteId
|
* @param suiteId
|
||||||
* 套件ID
|
* 套件ID
|
||||||
* @return 预授权码
|
* @return 预授权码
|
||||||
|
* @see #cacheSuiteTicket(String, String)
|
||||||
* @see com.foxinmy.weixin4j.qy.api.SuiteApi
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi
|
||||||
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#getTicketManager()
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#getTicketManager()
|
||||||
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#getPreCodeManager()
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#getPreCodeManager()
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getPreSuiteTicket(String suiteId) throws WeixinException {
|
public String getPreSuiteTicket(String suiteId) throws WeixinException {
|
||||||
Token token = suite(suiteId).getTicketManager().getTicket();
|
SuiteApi suite = suite(suiteId);
|
||||||
|
Token token = suite.getTicketManager().getTicket();
|
||||||
if (token == null || StringUtil.isBlank(token.getAccessToken())) {
|
if (token == null || StringUtil.isBlank(token.getAccessToken())) {
|
||||||
throw new WeixinException("maybe oauth first?");
|
throw new WeixinException("maybe oauth first?");
|
||||||
}
|
}
|
||||||
return token.getAccessToken();
|
return suite.getPreCodeManager().getAccessToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,27 +174,33 @@ public class WeixinSuiteProxy {
|
|||||||
* 推送suite_ticket协议</a>
|
* 推送suite_ticket协议</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public void cacheSuiteTicket(String suiteId, String suiteTicket) throws WeixinException {
|
public void cacheSuiteTicket(String suiteId, String suiteTicket)
|
||||||
|
throws WeixinException {
|
||||||
suite(suiteId).getTicketManager().cachingTicket(suiteTicket);
|
suite(suiteId).getTicketManager().cachingTicket(suiteTicket);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用套件授权 <font color="red">需先缓存ticket</font>
|
* 应用套件授权 <font color="red">需先缓存ticket</font> <li>
|
||||||
*
|
* redirectUri默认填写weixin4j.properties#suite.oauth.redirect.uri <li>
|
||||||
* @see {@link #getSuiteAuthorizeURL(String, String,String)}
|
* state默认填写state
|
||||||
|
*
|
||||||
* @param suiteId
|
* @param suiteId
|
||||||
* 套件ID
|
* 套件ID
|
||||||
* @see {@link #cacheSuiteTicket(String, String)}
|
* @see {@link #getSuiteAuthorizationURL(String, String,String)}
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getSuiteAuthorizeURL(String suiteId) throws WeixinException {
|
public String getSuiteAuthorizationURL(String suiteId)
|
||||||
String redirectUri = Weixin4jConfigUtil.getValue("suite.oauth.redirect.uri");
|
throws WeixinException {
|
||||||
return getSuiteAuthorizeURL(suiteId, redirectUri, "state");
|
String redirectUri = Weixin4jConfigUtil
|
||||||
|
.getValue("suite.oauth.redirect.uri");
|
||||||
|
return getSuiteAuthorizationURL(suiteId, redirectUri, "state");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 应用套件授权 <font color="red">需先缓存ticket</font>
|
* 应用套件授权 <font
|
||||||
|
* color="red">需先缓存ticket,在授权完成之后需要调用SuiteApi#exchangeAuthInfo方法
|
||||||
|
* ,否则无法缓存token相关导致后续的组件接口调用失败</font>
|
||||||
*
|
*
|
||||||
* @param suiteId
|
* @param suiteId
|
||||||
* 套件ID
|
* 套件ID
|
||||||
@ -174,16 +208,22 @@ public class WeixinSuiteProxy {
|
|||||||
* 授权后重定向url
|
* 授权后重定向url
|
||||||
* @param state
|
* @param state
|
||||||
* 回调后原样返回
|
* 回调后原样返回
|
||||||
|
* @see #cacheSuiteTicket(String, String)
|
||||||
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi
|
||||||
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#getTicketManager()
|
||||||
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#getPreCodeManager()
|
||||||
|
* @see com.foxinmy.weixin4j.qy.api.SuiteApi#exchangeAuthInfo(String)
|
||||||
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php?title
|
* @see <a href="http://qydev.weixin.qq.com/wiki/index.php?title
|
||||||
* =%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%AE%A1%E7%90%86%E5%91%98%E6%
|
* =%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%AE%A1%E7%90%86%E5%91%98%E6%
|
||||||
* 8E%88%E6%9D%83%E5%BA%94%E7%94%A8">企业号第三方应用套件授权</a>
|
* 8E%88%E6%9D%83%E5%BA%94%E7%94%A8">企业号第三方应用套件授权</a>
|
||||||
* @see {@link SuiteApi#getPreCodeManager}
|
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getSuiteAuthorizeURL(String suiteId, String redirectUri, String state) throws WeixinException {
|
public String getSuiteAuthorizationURL(String suiteId, String redirectUri,
|
||||||
|
String state) throws WeixinException {
|
||||||
try {
|
try {
|
||||||
return String.format(URLConsts.SUITE_OAUTH_URL, suiteId, getPreSuiteTicket(suiteId),
|
return String.format(URLConsts.SUITE_OAUTH_URL, suiteId,
|
||||||
|
getPreSuiteTicket(suiteId),
|
||||||
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state);
|
URLEncoder.encode(redirectUri, Consts.UTF_8.name()), state);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
;
|
;
|
||||||
@ -225,7 +265,8 @@ public class WeixinSuiteProxy {
|
|||||||
* 获取登录企业号官网的url</a>
|
* 获取登录企业号官网的url</a>
|
||||||
* @throws WeixinException
|
* @throws WeixinException
|
||||||
*/
|
*/
|
||||||
public String getLoginUrl(String corpId, LoginTargetType targetType, int agentId) throws WeixinException {
|
public String getLoginUrl(String corpId, LoginTargetType targetType,
|
||||||
|
int agentId) throws WeixinException {
|
||||||
return providerApi.getLoginUrl(corpId, targetType, agentId);
|
return providerApi.getLoginUrl(corpId, targetType, agentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -240,7 +281,8 @@ public class WeixinSuiteProxy {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public WeixinProxy getWeixinProxy(String suiteId, String authCorpId) {
|
public WeixinProxy getWeixinProxy(String suiteId, String authCorpId) {
|
||||||
return new WeixinProxy(suite(suiteId).getPerTicketManager(authCorpId), suite(suiteId).getTokenManager());
|
return new WeixinProxy(suite(suiteId).getPerTicketManager(authCorpId),
|
||||||
|
suite(suiteId).getTokenManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static String VERSION = "1.7.1";
|
public final static String VERSION = "1.7.1";
|
||||||
|
|||||||
@ -44,33 +44,34 @@ public class OauthApi extends QyApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业号用户身份授权:重定向URL使用weixin4j.properties#user.oauth.redirect.uri
|
* 企业号成员身份授权<li>
|
||||||
*
|
* redirectUri默认填写weixin4j.properties#user.oauth.redirect.uri <li>
|
||||||
* @see {@link #getUserAuthorizeURL(String,String)}
|
* state默认填写state
|
||||||
|
*
|
||||||
|
* @see {@link #getUserAuthorizationURL(String,String)}
|
||||||
*
|
*
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
*/
|
*/
|
||||||
public String getUserAuthorizeURL() {
|
public String getUserAuthorizationURL() {
|
||||||
String redirectUri = Weixin4jConfigUtil
|
String redirectUri = Weixin4jConfigUtil
|
||||||
.getValue("user.oauth.redirect.uri");
|
.getValue("user.oauth.redirect.uri");
|
||||||
return getUserAuthorizeURL(redirectUri, "state");
|
return getUserAuthorizationURL(redirectUri, "state");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业号用户身份授权
|
* 企业号成员身份授权
|
||||||
*
|
*
|
||||||
* @param redirectUri
|
* @param redirectUri
|
||||||
* 重定向地址
|
* 重定向地址
|
||||||
* @param state
|
* @param state
|
||||||
* 用于保持请求和回调的状态
|
* 用于保持请求和回调的状态
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
* @see UserApi
|
* @see UserApi#getOUserInfoByCode(String, String)
|
||||||
* @see {@link com.foxinmy.weixin4j.qy.WeixinProxy#getUserByCode(String)}
|
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81">
|
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81">
|
||||||
* 企业号用户身份授权</a>
|
* 企业号用户身份授权</a>
|
||||||
*/
|
*/
|
||||||
public String getUserAuthorizeURL(String redirectUri, String state) {
|
public String getUserAuthorizationURL(String redirectUri, String state) {
|
||||||
String oauth_uri = getRequestUri("user_oauth_uri");
|
String oauth_uri = getRequestUri("user_oauth_uri");
|
||||||
try {
|
try {
|
||||||
return String.format(oauth_uri, account.getId(),
|
return String.format(oauth_uri, account.getId(),
|
||||||
@ -82,20 +83,22 @@ public class OauthApi extends QyApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业号第三方提供商授权:重定向URL使用weixin4j.properties#third.oauth.redirect.uri
|
* 企业号第三方提供商登陆授权<li>
|
||||||
|
* redirectUri默认填写weixin4j.properties#third.oauth.redirect.uri <li>
|
||||||
|
* state默认填写state
|
||||||
*
|
*
|
||||||
* @see {@link #getThirdAuthorizeURL(String,String)}
|
* @see {@link #getThirdAuthorizationURL(String,String)}
|
||||||
*
|
*
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
*/
|
*/
|
||||||
public String getThirdAuthorizeURL() {
|
public String getThirdAuthorizationURL() {
|
||||||
String redirectUri = Weixin4jConfigUtil
|
String redirectUri = Weixin4jConfigUtil
|
||||||
.getValue("third.oauth.redirect.uri");
|
.getValue("third.oauth.redirect.uri");
|
||||||
return getThirdAuthorizeURL(redirectUri, "state");
|
return getThirdAuthorizationURL(redirectUri, "state");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 企业号登陆授权
|
* 企业号第三方提供商登陆授权
|
||||||
*
|
*
|
||||||
* @param corpId
|
* @param corpId
|
||||||
* 企业号(提供商)的corpid
|
* 企业号(提供商)的corpid
|
||||||
@ -104,13 +107,12 @@ public class OauthApi extends QyApi {
|
|||||||
* @param state
|
* @param state
|
||||||
* 用于保持请求和回调的状态,授权请求后原样带回给第三方
|
* 用于保持请求和回调的状态,授权请求后原样带回给第三方
|
||||||
* @return 请求授权的URL
|
* @return 请求授权的URL
|
||||||
* @see ProviderApi
|
* @see ProviderApi#getOUserInfoByCode(String)
|
||||||
* @see {@link com.foxinmy.weixin4j.qy.WeixinSuiteProxy#getOUserInfoByCode(String)}
|
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E6%88%90%E5%91%98%E7%99%BB%E5%BD%95%E6%8E%88%E6%9D%83">
|
* "http://qydev.weixin.qq.com/wiki/index.php?title=%E6%88%90%E5%91%98%E7%99%BB%E5%BD%95%E6%8E%88%E6%9D%83">
|
||||||
* 企业号第三方提供商授权</a>
|
* 企业号第三方提供商授权</a>
|
||||||
*/
|
*/
|
||||||
public String getThirdAuthorizeURL(String redirectUri, String state) {
|
public String getThirdAuthorizationURL(String redirectUri, String state) {
|
||||||
String oauth_uri = getRequestUri("provider_oauth_uri");
|
String oauth_uri = getRequestUri("provider_oauth_uri");
|
||||||
try {
|
try {
|
||||||
return String.format(oauth_uri, account.getId(),
|
return String.format(oauth_uri, account.getId(),
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import com.foxinmy.weixin4j.http.weixin.ApiResult;
|
|||||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||||
import com.foxinmy.weixin4j.model.Token;
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.qy.model.OUserInfo;
|
import com.foxinmy.weixin4j.qy.model.OUserInfo;
|
||||||
|
import com.foxinmy.weixin4j.qy.model.Party;
|
||||||
import com.foxinmy.weixin4j.qy.model.User;
|
import com.foxinmy.weixin4j.qy.model.User;
|
||||||
import com.foxinmy.weixin4j.qy.type.InviteType;
|
import com.foxinmy.weixin4j.qy.type.InviteType;
|
||||||
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
import com.foxinmy.weixin4j.qy.type.UserStatus;
|
||||||
@ -33,11 +34,13 @@ import com.foxinmy.weixin4j.util.StringUtil;
|
|||||||
*/
|
*/
|
||||||
public class UserApi extends QyApi {
|
public class UserApi extends QyApi {
|
||||||
private final MediaApi mediaApi;
|
private final MediaApi mediaApi;
|
||||||
|
private final PartyApi partyApi;
|
||||||
private final TokenManager tokenManager;
|
private final TokenManager tokenManager;
|
||||||
|
|
||||||
public UserApi(TokenManager tokenManager) {
|
public UserApi(TokenManager tokenManager) {
|
||||||
this.tokenManager = tokenManager;
|
this.tokenManager = tokenManager;
|
||||||
this.mediaApi = new MediaApi(tokenManager);
|
this.mediaApi = new MediaApi(tokenManager);
|
||||||
|
this.partyApi = new PartyApi(tokenManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -243,11 +246,11 @@ public class UserApi extends QyApi {
|
|||||||
* 获取部门成员
|
* 获取部门成员
|
||||||
*
|
*
|
||||||
* @param partyId
|
* @param partyId
|
||||||
* 部门ID 必须
|
* 部门ID
|
||||||
* @param fetchChild
|
* @param fetchChild
|
||||||
* 是否递归获取子部门下面的成员 非必须
|
* 是否递归获取子部门下面的成员
|
||||||
* @param userStatus
|
* @param userStatus
|
||||||
* 成员状态 status可叠加 非必须 未填写则默认为未关注(4)
|
* 成员状态 status可叠加 未填写则默认为未关注(4)
|
||||||
* @param findDetail
|
* @param findDetail
|
||||||
* 是否获取详细信息
|
* 是否获取详细信息
|
||||||
* @see com.foxinmy.weixin4j.qy.model.User
|
* @see com.foxinmy.weixin4j.qy.model.User
|
||||||
@ -303,6 +306,31 @@ public class UserApi extends QyApi {
|
|||||||
return listUser(partyId, false, UserStatus.BOTH, false);
|
return listUser(partyId, false, UserStatus.BOTH, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取权限范围内的所有成员列表
|
||||||
|
*
|
||||||
|
* @param userStatus
|
||||||
|
* 成员状态 未填写则默认为全部状态下的成员
|
||||||
|
* @return 成员列表
|
||||||
|
* @see {@link #listUser(int, boolean, UserStatus,boolean)}
|
||||||
|
* @see {@link PartyApi#listParty(int)}
|
||||||
|
* @throws WeixinException
|
||||||
|
*/
|
||||||
|
public List<User> listAllUser(UserStatus userStatus) throws WeixinException {
|
||||||
|
List<User> users = null;
|
||||||
|
List<Party> parties = partyApi.listParty(0);
|
||||||
|
if (!parties.isEmpty()) {
|
||||||
|
if (userStatus == null) {
|
||||||
|
userStatus = UserStatus.BOTH;
|
||||||
|
}
|
||||||
|
users = new ArrayList<User>();
|
||||||
|
for (Party party : parties) {
|
||||||
|
users.addAll(listUser(party.getId(), true, userStatus, true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除成员
|
* 删除成员
|
||||||
*
|
*
|
||||||
|
|||||||
@ -230,6 +230,31 @@ public class User implements Serializable {
|
|||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = 1;
|
||||||
|
result = prime * result + ((userId == null) ? 0 : userId.hashCode());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (obj == null)
|
||||||
|
return false;
|
||||||
|
if (getClass() != obj.getClass())
|
||||||
|
return false;
|
||||||
|
User other = (User) obj;
|
||||||
|
if (userId == null) {
|
||||||
|
if (other.userId != null)
|
||||||
|
return false;
|
||||||
|
} else if (!userId.equals(other.userId))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "User [userId=" + userId + ", name=" + name + ", partyIds="
|
return "User [userId=" + userId + ", name=" + name + ", partyIds="
|
||||||
|
|||||||
@ -60,6 +60,7 @@ public class WeixinTicketCreator extends TokenCreator {
|
|||||||
}
|
}
|
||||||
JSONObject result = response.getAsJson();
|
JSONObject result = response.getAsJson();
|
||||||
return new Token(result.getString("ticket"),
|
return new Token(result.getString("ticket"),
|
||||||
result.getLong("expires_in") * 1000l);
|
result.getLong("expires_in") * 1000l).pushExtra("group_id",
|
||||||
|
result.getString("group_id"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,29 +1,23 @@
|
|||||||
# weixin4j\u7684\u914d\u7f6e\u6587\u4ef6:\u5982\u679c\u6ca1\u6709\u8bf7\u6784\u9020\u76f8\u5e94\u53c2\u6570\u4f20\u5165 \u5982\u679c\u6709\u8bf7\u4fdd\u8bc1\u5728classpath\u7684\u6839\u76ee\u5f55\u4e0b
|
# weixin4j\u7684\u914d\u7f6e\u6587\u4ef6:\u5982\u679c\u6ca1\u6709\u8bf7\u6784\u9020\u76f8\u5e94\u53c2\u6570\u4f20\u5165 \u5982\u679c\u6709\u8bf7\u4fdd\u8bc1\u5728classpath\u7684\u6839\u76ee\u5f55\u4e0b
|
||||||
|
|
||||||
# \u4f01\u4e1a\u53f7\u4fe1\u606f \u8bf7\u6309\u9700\u586b\u5199
|
# \u4f01\u4e1a\u53f7\u4fe1\u606f \u8bf7\u6309\u9700\u586b\u5199
|
||||||
weixin4j.account={"id":"wx5132afc5da26d661","secret":"GsnKLVDI1pWArdB60Ze4iP2cwFvcW5KCAs2vLJldipilmSYxtbkcAiBcGSHHvu_I",\
|
weixin4j.account={"id":"wxb4a36f8a248475e9","secret":"iZ4Bk1gQN5S9lNoECH57krBwXgcN0fQk6wuPN2cE1talXQmjRT5UcKBpz-YHPRnI",\
|
||||||
"suites":[{"id":"\u5e94\u7528\u5957\u4ef6\u7684id","secret":"\u5e94\u7528\u5957\u4ef6\u7684secret"}],\
|
"suites":[{"id":"\u5e94\u7528\u5957\u4ef6\u7684id","secret":"\u5e94\u7528\u5957\u4ef6\u7684secret"}],\
|
||||||
"providerSecret":"\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546secret(\u4f01\u4e1a\u53f7\u767b\u9646)",\
|
"providerSecret":"\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546secret(\u4f01\u4e1a\u53f7\u767b\u9646)",\
|
||||||
"chatSecret":"\u6d88\u606f\u670d\u52a1secret(\u4f01\u4e1a\u53f7\u6d88\u606f\u670d\u52a1,\u6682\u65f6\u6ca1\u7528\u5230)",\
|
"chatSecret":"\u6d88\u606f\u670d\u52a1secret(\u4f01\u4e1a\u53f7\u6d88\u606f\u670d\u52a1,\u6682\u65f6\u6ca1\u7528\u5230)",\
|
||||||
"mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
"mchId":"\u5fae\u4fe1\u5546\u6237\u53f7 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
|
||||||
"certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\
|
"certificateKey":"\u52a0\u8f7d\u652f\u4ed8\u8bc1\u4e66\u6587\u4ef6\u7684\u5bc6\u7801 \u5982\u679c\u4e0d\u586b\u5199\u5219\u9ed8\u8ba4\u83b7\u53d6mchId\u4f5c\u4e3a\u5bc6\u7801",\
|
||||||
|
"certificateFile":"\u5fae\u4fe1\u652f\u4ed8\u67d0\u4e9b\u63a5\u53e3(\u9000\u6b3e\u7b49)\u9700\u8981\u7684ca\u8bc1\u4e66\u5b58\u653e\u7684\u8def\u5f84,classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199classpath:xxxxx.p12,\u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6classpath\u6839\u76ee\u5f55\u4e0b\u7684ca.p12\u6587\u4ef6",\
|
||||||
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
|
||||||
|
|
||||||
# weixin4j\u7684\u4e34\u65f6\u76ee\u5f55
|
# \u4f01\u4e1a\u53f7\u6210\u5458\u8eab\u4efd\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
# \u53ef\u80fd\u5b58\u653etoken\u6587\u4ef6\u3001\u4e8c\u7ef4\u7801\u6587\u4ef6\u3001\u5a92\u4f53\u6587\u4ef6\u3001\u5bf9\u8d26\u5355\u6587\u4ef6\u7b49
|
# \u8be6\u89c1\uff1ahttp://qydev.weixin.qq.com/wiki/index.php?title=%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81
|
||||||
# \u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6java.io.tmpdir\u4e34\u65f6\u76ee\u5f55
|
|
||||||
weixin4j.tmpdir=
|
|
||||||
# \u5fae\u4fe1\u652f\u4ed8\u67d0\u4e9b\u63a5\u53e3\u9700\u8981\u7684ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84
|
|
||||||
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199
|
|
||||||
# weixin4j.certificate.file=classpath:xxxxx.p12
|
|
||||||
# \u4e3a\u7a7a\u65f6\u5219\u83b7\u53d6classpath\u6839\u76ee\u5f55\u4e0b\u7684ca.p12\u6587\u4ef6
|
|
||||||
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
|
|
||||||
|
|
||||||
# \u4f01\u4e1a\u53f7\u7528\u6237\u8eab\u4efd\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
|
|
||||||
weixin4j.user.oauth.redirect.uri=
|
weixin4j.user.oauth.redirect.uri=
|
||||||
|
|
||||||
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
|
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
|
# \u8be6\u89c1\uff1ahttp://qydev.weixin.qq.com/wiki/index.php?title=%E6%88%90%E5%91%98%E7%99%BB%E5%BD%95%E6%8E%88%E6%9D%83
|
||||||
weixin4j.third.oauth.redirect.uri=
|
weixin4j.third.oauth.redirect.uri=
|
||||||
|
|
||||||
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u5e94\u7528\u5957\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528SuiteApi\u65f6\u586b\u5199)
|
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u5e94\u7528\u5957\u4ef6\u6388\u6743\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528SuiteApi\u65f6\u586b\u5199,\u4e5f\u53ef\u81ea\u5b9a\u4e49\u4f20\u5165)
|
||||||
|
# \u8be6\u89c1\uff1ahttp://qydev.weixin.qq.com/wiki/index.php?title=%E4%BC%81%E4%B8%9A%E5%8F%B7%E7%AE%A1%E7%90%86%E5%91%98%E6%8E%88%E6%9D%83%E5%BA%94%E7%94%A8
|
||||||
weixin4j.suite.oauth.redirect.uri=
|
weixin4j.suite.oauth.redirect.uri=
|
||||||
@ -4,10 +4,11 @@ import org.junit.Assert;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.foxinmy.weixin4j.cache.FileCacheStorager;
|
||||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||||
|
import com.foxinmy.weixin4j.model.Token;
|
||||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||||
import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator;
|
import com.foxinmy.weixin4j.qy.token.WeixinTokenCreator;
|
||||||
import com.foxinmy.weixin4j.setting.Weixin4jSettings;
|
|
||||||
import com.foxinmy.weixin4j.token.TokenManager;
|
import com.foxinmy.weixin4j.token.TokenManager;
|
||||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||||
|
|
||||||
@ -22,15 +23,14 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
|||||||
public class TokenTest {
|
public class TokenTest {
|
||||||
|
|
||||||
protected TokenManager tokenManager;
|
protected TokenManager tokenManager;
|
||||||
protected Weixin4jSettings<WeixinAccount> settings;
|
protected WeixinAccount weixinAccount;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
this.settings = new Weixin4jSettings<WeixinAccount>(
|
weixinAccount = Weixin4jConfigUtil.getWeixinAccount();
|
||||||
Weixin4jConfigUtil.getWeixinAccount());
|
tokenManager = new TokenManager(new WeixinTokenCreator(
|
||||||
tokenManager = new TokenManager(new WeixinTokenCreator(settings
|
weixinAccount.getId(), weixinAccount.getSecret()),
|
||||||
.getAccount().getId(), settings.getAccount().getSecret()),
|
new FileCacheStorager<Token>());
|
||||||
settings.getCacheStorager0());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user