新增Weixin4jSettings配置类

This commit is contained in:
jinyu 2016-01-29 09:38:47 +08:00
parent c4bf06d372
commit 2e2d207e76
46 changed files with 717 additions and 464 deletions

View File

@ -629,4 +629,8 @@
* 2016-01-26
+ weixin4j-qy:新增上传图文消息内的图片接口
+ weixin4j-qy:新增上传图文消息内的图片接口
* 2016-01-29
+ 新增Weixin4jSettings配置类

View File

@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.6.6</version>
<version>1.6.7</version>
<packaging>pom</packaging>
<name>weixin4j</name>
<url>https://github.com/foxinmy/weixin4j</url>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.6.6</version>
<version>1.6.7</version>
</parent>
<artifactId>weixin4j-base</artifactId>
<name>weixin4j-base</name>

View File

@ -5,11 +5,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
/**
* API基础
@ -45,21 +40,4 @@ public abstract class BaseApi {
m.appendTail(sb);
return sb.toString();
}
/**
* 默认使用weixin4j.properties文件中的公众号信息
*/
public final static WeixinAccount DEFAULT_WEIXIN_ACCOUNT;
/**
* 默认token使用File的方式存储
*/
public final static TokenStorager DEFAULT_TOKEN_STORAGER;
static {
DEFAULT_WEIXIN_ACCOUNT = Weixin4jConfigUtil.getWeixinAccount();
DEFAULT_TOKEN_STORAGER = new FileTokenStorager(
Weixin4jConfigUtil.getValue("token.path",
Weixin4jConst.DEFAULT_TOKEN_PATH));
}
}

View File

@ -48,7 +48,7 @@ public class CashApi {
* 发放红包 企业向微信用户个人发现金红包
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param redpacket
* 红包信息
* @return 发放结果
@ -71,7 +71,7 @@ public class CashApi {
WeixinResponse response = null;
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor
.post(redpacket.getTotalNum() > 1 ? PayURLConsts.MCH_REDPACK_GROUPSEND_URL
: PayURLConsts.MCH_REDPACKSEND_URL, param);
@ -92,7 +92,7 @@ public class CashApi {
* 查询红包记录
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param outTradeNo
* 商户发放红包的商户订单号
* @return 红包记录
@ -116,7 +116,7 @@ public class CashApi {
WeixinResponse response = null;
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_REDPACKQUERY_URL,
param);
} finally {
@ -136,7 +136,7 @@ public class CashApi {
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param mpPayment
* 付款信息
* @return 付款结果
@ -160,7 +160,7 @@ public class CashApi {
WeixinResponse response = null;
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_ENPAYMENT_URL,
param);
} finally {
@ -184,7 +184,7 @@ public class CashApi {
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param outTradeNo
* 商户调用企业付款API时使用的商户订单号
* @return 付款记录
@ -206,7 +206,7 @@ public class CashApi {
WeixinResponse response = null;
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_ENPAYQUERY_URL,
param);
} finally {

View File

@ -44,7 +44,7 @@ public class CouponApi {
* 发放代金券(需要证书)
*
* @param ca
* 证书文件(后缀为*.p12)
* 后缀为*.p12的证书文件
* @param couponStockId
* 代金券批次id
* @param partnerTradeNo
@ -81,7 +81,7 @@ public class CouponApi {
WeixinResponse response = null;
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_COUPONSEND_URL,
param);
} finally {

View File

@ -29,12 +29,12 @@ import com.foxinmy.weixin4j.payment.MicroPayPackage;
import com.foxinmy.weixin4j.payment.PayURLConsts;
import com.foxinmy.weixin4j.payment.mch.APPPayRequest;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.AuthCodeOpenIdResult;
import com.foxinmy.weixin4j.payment.mch.JSAPIPayRequest;
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
import com.foxinmy.weixin4j.payment.mch.NATIVEPayRequest;
import com.foxinmy.weixin4j.payment.mch.NativePayResponse;
import com.foxinmy.weixin4j.payment.mch.OpenIdResult;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
@ -51,8 +51,6 @@ import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.xml.XmlStream;
@ -496,7 +494,7 @@ public class Pay3Api {
* </p>
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
@ -539,7 +537,7 @@ public class Pay3Api {
map.put("sign", sign);
String param = XmlStream.map2xml(map);
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
response = weixinExecutor.post(PayURLConsts.MCH_REFUNDAPPLY_URL,
param);
} finally {
@ -559,7 +557,7 @@ public class Pay3Api {
* 退款申请(全额退款)
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
@ -582,7 +580,7 @@ public class Pay3Api {
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
@ -594,7 +592,7 @@ public class Pay3Api {
throws WeixinException {
try {
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
weixinAccount.getMchId(), ca);
weixinAccount.getCertificateKey(), ca);
Map<String, String> map = baseMap(idQuery);
String sign = DigestUtil.paysignMd5(map,
weixinAccount.getPaySignKey());
@ -681,13 +679,15 @@ public class Pay3Api {
* @param billType
* 下载对账单的类型 ALL,返回当日所有订单信息, 默认值 SUCCESS,返回当日成功支付的订单
* REFUND,返回当日退款订单
* @param billPath
* 对账单保存路径
* @return excel表格
* @since V3
* @see <a
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单API</a>
* @throws WeixinException
*/
public File downloadBill(Date billDate, BillType billType)
public File downloadBill(Date billDate, BillType billType, String billPath)
throws WeixinException {
if (billDate == null) {
Calendar now = Calendar.getInstance();
@ -698,11 +698,9 @@ public class Pay3Api {
billType = BillType.ALL;
}
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
String bill_path = Weixin4jConfigUtil.getValue("bill.path",
Weixin4jConst.DEFAULT_BILL_PATH);
String fileName = String.format("%s_%s_%s.txt", formatBillDate,
billType.name().toLowerCase(), weixinAccount.getId());
File file = new File(String.format("%s/%s", bill_path, fileName));
File file = new File(String.format("%s/%s", billPath, fileName));
if (file.exists()) {
return file;
}
@ -820,13 +818,12 @@ public class Pay3Api {
* @param authCode
* 扫码支付授权码设备读取用户微信中的条码或者二维码信息
* @return 查询结果
* @see com.foxinmy.weixin4j.payment.mch.AuthCodeOpenIdResult
* @see com.foxinmy.weixin4j.payment.mch.OpenIdResult
* @see <a
* href="https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9">授权码查询OPENID</a>
* @throws WeixinException
*/
public AuthCodeOpenIdResult authCode2openId(String authCode)
throws WeixinException {
public OpenIdResult authCode2openId(String authCode) throws WeixinException {
Map<String, String> map = baseMap(null);
map.put("auth_code", authCode);
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
@ -834,7 +831,7 @@ public class Pay3Api {
String param = XmlStream.map2xml(map);
WeixinResponse response = weixinExecutor.post(
PayURLConsts.MCH_AUTHCODE_OPENID_URL, param);
return response.getAsObject(new TypeReference<AuthCodeOpenIdResult>() {
return response.getAsObject(new TypeReference<OpenIdResult>() {
});
}

View File

@ -32,6 +32,10 @@ public class WeixinPayAccount extends WeixinAccount {
* 微信支付分配的商户号(商户平台版)
*/
private String mchId;
/**
* 加载支付证书文件的密码(商户平台版)
*/
private String certificateKey;
/**
* 微信支付分配的子商户号受理模式下必填(商户平台版)
*/
@ -40,10 +44,6 @@ public class WeixinPayAccount extends WeixinAccount {
* 微信支付分配的设备号(商户平台版)
*/
private String deviceInfo;
/**
* 微信支付版本号(如果无则按照mchId来做判断)
*/
private int version;
/**
* 商户平台版本(V3)字段
@ -57,8 +57,9 @@ public class WeixinPayAccount extends WeixinAccount {
* @param mchId
* 微信支付分配的商户号(必填)
*/
public WeixinPayAccount(String appId, String appSecret, String paySignKey, String mchId) {
this(appId, appSecret, paySignKey, mchId, null, null, null, null);
public WeixinPayAccount(String appId, String appSecret, String paySignKey,
String mchId) {
this(appId, appSecret, paySignKey, mchId, null, null, null, null, null);
}
/**
@ -72,6 +73,8 @@ public class WeixinPayAccount extends WeixinAccount {
* 支付密钥字符串(必填)
* @param mchId
* 微信支付分配的商户号(V3商户平台版必填)
* @param certificateKey
* 加载支付证书文件的密码(商户平台版)
* @param subMchId
* 微信支付分配的子商户号受理模式下必填(V3商户平台版 非必须)
* @param deviceInfo
@ -82,13 +85,19 @@ public class WeixinPayAccount extends WeixinAccount {
* 财付通商户权限密钥Key(V2版本必填)
*/
@JSONCreator
public WeixinPayAccount(@JSONField(name = "id") String appId, @JSONField(name = "secret") String appSecret,
@JSONField(name = "paySignKey") String paySignKey, @JSONField(name = "mchId") String mchId,
@JSONField(name = "subMchId") String subMchId, @JSONField(name = "deviceInfo") String deviceInfo,
@JSONField(name = "partnerId") String partnerId, @JSONField(name = "partnerKey") String partnerKey) {
public WeixinPayAccount(@JSONField(name = "id") String appId,
@JSONField(name = "secret") String appSecret,
@JSONField(name = "paySignKey") String paySignKey,
@JSONField(name = "mchId") String mchId,
@JSONField(name = "certificateKey") String certificateKey,
@JSONField(name = "subMchId") String subMchId,
@JSONField(name = "deviceInfo") String deviceInfo,
@JSONField(name = "partnerId") String partnerId,
@JSONField(name = "partnerKey") String partnerKey) {
super(appId, appSecret);
this.paySignKey = paySignKey;
this.mchId = mchId;
this.certificateKey = certificateKey;
this.subMchId = subMchId;
this.deviceInfo = deviceInfo;
this.partnerId = partnerId;
@ -119,17 +128,16 @@ public class WeixinPayAccount extends WeixinAccount {
return deviceInfo;
}
public int getVersion() {
if (version == 0) {
return StringUtil.isNotBlank(mchId) ? 3 : 2;
}
return version;
public String getCertificateKey() {
return StringUtil.isBlank(certificateKey) ? mchId : certificateKey;
}
@Override
public String toString() {
return "WeixinPayAccount [" + super.toString() + ", paySignKey=" + paySignKey + ", partnerId=" + partnerId
+ ", partnerKey=" + partnerKey + ", mchId=" + mchId + ", subMchId=" + subMchId + ", deviceInfo="
+ deviceInfo + ", version=" + getVersion() + "]";
return "WeixinPayAccount [" + super.toString() + ", paySignKey="
+ paySignKey + ", partnerId=" + partnerId + ", partnerKey="
+ partnerKey + ", mchId=" + mchId + ", certificateKey="
+ getCertificateKey() + ", subMchId=" + subMchId
+ ", deviceInfo=" + deviceInfo + "]";
}
}

View File

@ -6,7 +6,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.api.CashApi;
import com.foxinmy.weixin4j.api.CouponApi;
import com.foxinmy.weixin4j.api.Pay3Api;
@ -18,25 +17,24 @@ import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
import com.foxinmy.weixin4j.payment.coupon.CouponResult;
import com.foxinmy.weixin4j.payment.coupon.CouponStock;
import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.AuthCodeOpenIdResult;
import com.foxinmy.weixin4j.payment.mch.MPPayment;
import com.foxinmy.weixin4j.payment.mch.MPPaymentRecord;
import com.foxinmy.weixin4j.payment.mch.MPPaymentResult;
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
import com.foxinmy.weixin4j.payment.mch.NativePayResponse;
import com.foxinmy.weixin4j.payment.mch.OpenIdResult;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.payment.mch.Redpacket;
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
import com.foxinmy.weixin4j.settings.Weixin4jPaySettings;
import com.foxinmy.weixin4j.type.BillType;
import com.foxinmy.weixin4j.type.CurrencyType;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
/**
* 微信支付接口实现
@ -54,26 +52,26 @@ public class WeixinPayProxy {
private final CouponApi couponApi;
private final CashApi cashApi;
private final WeixinPayAccount payAccount;
private final Weixin4jPaySettings settings;
/**
* 使用weixin4j.properties配置的账号信息
* 使用weixin4j.properties配置的支付账号信息
*/
public WeixinPayProxy() {
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
WeixinPayAccount.class));
this(new Weixin4jPaySettings());
}
/**
*
* @param weixinAccount
* 支付相关的公众号账号信息
* @param settings
* 支付相关配置信息
* @see com.foxinmy.weixin4j.settings.Weixin4jPaySettings
*/
public WeixinPayProxy(WeixinPayAccount payAccount) {
this.payAccount = payAccount;
this.pay3Api = new Pay3Api(payAccount);
this.couponApi = new CouponApi(payAccount);
this.cashApi = new CashApi(payAccount);
public WeixinPayProxy(Weixin4jPaySettings settings) {
this.settings = settings;
this.pay3Api = new Pay3Api(settings.getPayAccount());
this.couponApi = new CouponApi(settings.getPayAccount());
this.cashApi = new CashApi(settings.getPayAccount());
}
/**
@ -82,9 +80,7 @@ public class WeixinPayProxy {
* @return
*/
public WeixinPayAccount getPayAccount() {
// clone ...
String text = JSON.toJSONString(payAccount);
return JSON.parseObject(text, WeixinPayAccount.class);
return this.settings.getPayAccount();
}
/**
@ -429,7 +425,7 @@ public class WeixinPayProxy {
* </p>
*
* @param ca
* 证书文件(后缀为*.p12)
* 后缀为*.p12的证书文件
* @param idQuery
* 商户系统内部的订单号, transaction_id out_trade_no 二选一,如果同时存在优先级:
* transaction_id> out_trade_no
@ -461,7 +457,7 @@ public class WeixinPayProxy {
}
/**
* 退款申请(全额退款)采用properties中配置的ca文件
* 退款申请(全额退款)
*
* @throws IOException
*
@ -470,12 +466,9 @@ public class WeixinPayProxy {
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply(
IdQuery idQuery, String outRefundNo, double totalFee)
throws WeixinException, IOException {
return pay3Api
.refundApply(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
idQuery, outRefundNo, totalFee);
return pay3Api.refundApply(
new FileInputStream(settings.getCertificatePath()), idQuery,
outRefundNo, totalFee);
}
/**
@ -521,7 +514,7 @@ public class WeixinPayProxy {
*/
public File downloadBill(Date billDate, BillType billType)
throws WeixinException {
return pay3Api.downloadBill(billDate, billType);
return pay3Api.downloadBill(billDate, billType, settings.getBillPath());
}
/**
@ -546,7 +539,7 @@ public class WeixinPayProxy {
}
/**
* 冲正撤销:默认采用properties中配置的ca文件
* 冲正撤销
*
* @param idQuery
* transaction_idout_trade_no 二选一
@ -557,12 +550,8 @@ public class WeixinPayProxy {
*/
public ApiResult reverseOrder(IdQuery idQuery) throws WeixinException,
IOException {
return pay3Api
.reverseOrder(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
idQuery);
return pay3Api.reverseOrder(
new FileInputStream(settings.getCertificatePath()), idQuery);
}
/**
@ -635,7 +624,7 @@ public class WeixinPayProxy {
* 发放代金券(需要证书)
*
* @param ca
* 证书文件(后缀为*.p12)
* 后缀为*.p12的证书文件
* @param couponStockId
* 代金券批次id
* @param partnerTradeNo
@ -659,18 +648,15 @@ public class WeixinPayProxy {
}
/**
* 发放代金券采用properties中配置的ca文件
* 发放代金券
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#sendCoupon(InputStream, String, String, String, String)}
*/
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
String openId) throws WeixinException, IOException {
return couponApi
.sendCoupon(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
couponStockId, partnerTradeNo, openId, null);
return couponApi.sendCoupon(
new FileInputStream(settings.getCertificatePath()),
couponStockId, partnerTradeNo, openId, null);
}
/**
@ -711,7 +697,7 @@ public class WeixinPayProxy {
* 发放红包 企业向微信用户个人发现金红包
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param redpacket
* 红包信息
* @return 发放结果
@ -728,25 +714,21 @@ public class WeixinPayProxy {
}
/**
* 发放红包采用properties中配置的ca文件
* 发放红包
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#sendRedpack(InputStream, Redpacket)}
*/
public RedpacketSendResult sendRedpack(Redpacket redpacket)
throws WeixinException, IOException {
return cashApi
.sendRedpack(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
redpacket);
return cashApi.sendRedpack(
new FileInputStream(settings.getCertificatePath()), redpacket);
}
/**
* 查询红包记录
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param outTradeNo
* 商户发放红包的商户订单号
* @return 红包记录
@ -762,25 +744,21 @@ public class WeixinPayProxy {
}
/**
* 查询红包采用properties中配置的ca文件
* 查询红包
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#queryRedpack(InputStream,String)}
*/
public RedpacketRecord queryRedpack(String outTradeNo)
throws WeixinException, IOException {
return cashApi
.queryRedpack(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
outTradeNo);
return cashApi.queryRedpack(
new FileInputStream(settings.getCertificatePath()), outTradeNo);
}
/**
* 企业付款 实现企业向个人付款针对部分有开发能力的商户 提供通过API完成企业付款的功能 比如目前的保险行业向客户退保给付理赔
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param mpPayment
* 付款信息
* @return 付款结果
@ -797,25 +775,21 @@ public class WeixinPayProxy {
}
/**
* 企业付款采用properties中配置的ca文件
* 企业付款
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#mpPayment(InputStream, MPPayment)}
*/
public MPPaymentResult mpPayment(MPPayment mpPayment)
throws WeixinException, IOException {
return cashApi
.mchPayment(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
mpPayment);
return cashApi.mchPayment(
new FileInputStream(settings.getCertificatePath()), mpPayment);
}
/**
* 企业付款查询 用于商户的企业付款操作进行结果查询返回付款操作详细结果
*
* @param ca
* 证书文件(V3版本后缀为*.p12)
* 后缀为*.p12的证书文件
* @param outTradeNo
* 商户调用企业付款API时使用的商户订单号
* @return 付款记录
@ -831,18 +805,14 @@ public class WeixinPayProxy {
}
/**
* 企业付款查询采用properties中配置的ca文件
* 企业付款查询
*
* @see {@link com.foxinmy.weixin4j.payment.WeixinPayProxy#mpPaymentQuery(InputStream, String)}
*/
public MPPaymentRecord mpPaymentQuery(String outTradeNo)
throws WeixinException, IOException {
return cashApi
.mchPaymentQuery(
new FileInputStream(Weixin4jConfigUtil
.getClassPathValue("certificate.file",
Weixin4jConst.DEFAULT_CAFILE_PATH)),
outTradeNo);
return cashApi.mchPaymentQuery(
new FileInputStream(settings.getCertificatePath()), outTradeNo);
}
/**
@ -852,15 +822,14 @@ public class WeixinPayProxy {
* 扫码支付授权码设备读取用户微信中的条码或者二维码信息
* @return 查询结果
* @see com.foxinmy.weixin4j.api.CashApi
* @see com.foxinmy.weixin4j.payment.mch.AuthCodeOpenIdResult
* @see com.foxinmy.weixin4j.payment.mch.OpenIdResult
* @see <a
* href="https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_13&index=9">授权码查询OPENID</a>
* @throws WeixinException
*/
public AuthCodeOpenIdResult authCode2openId(String authCode)
throws WeixinException {
public OpenIdResult authCode2openId(String authCode) throws WeixinException {
return pay3Api.authCode2openId(authCode);
}
public final static String VERSION = "1.6.6";
public final static String VERSION = "1.6.7";
}

View File

@ -80,7 +80,6 @@ public class CouponDetail extends ApiResult {
@XmlElement(name = "coupon_type")
@JSONField(name = "coupon_type")
private int couponType;
/**
* 代金券描述
*/

View File

@ -5,8 +5,10 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import com.alibaba.fastjson.annotation.JSONField;
/**
* Native支付回调时POST的信息
* Native支付回调时POST的信息
*
* @className PayNativeNotify
* @author jy
@ -16,27 +18,37 @@ import javax.xml.bind.annotation.XmlRootElement;
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class NativePayNotify extends ApiResult {
public class NativePayNotify extends OpenIdResult {
private static final long serialVersionUID = 4515471400239795492L;
/**
* 用户是否关注公众账号,Y- 关注,N-未关注,仅在公众 账号类型支付有效
*/
@XmlElement(name = "is_subscribe")
@JSONField(name = "is_subscribe")
private String isSubscribe;
/**
* 产品ID 可视为订单ID
*/
@XmlElement(name = "product_id")
@JSONField(name = "product_id")
private String productId;
protected NativePayNotify() {
// jaxb required
}
public String getProductId() {
return productId;
}
public String getIsSubscribe() {
return isSubscribe;
}
@Override
public String toString() {
return "NativePayNotify [productId=" + productId + ", "
+ super.toString() + "]";
return "NativePayNotify [productId=" + productId + ", isSubscribe="
+ isSubscribe + ", " + super.toString() + "]";
}
}

View File

@ -10,7 +10,7 @@ import com.alibaba.fastjson.annotation.JSONField;
/**
* authcode2openid
*
* @className AuthCodeOpenIdResult
* @className OpenIdResult
* @author jy
* @date 2015年7月23日
* @since JDK 1.6
@ -18,7 +18,7 @@ import com.alibaba.fastjson.annotation.JSONField;
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class AuthCodeOpenIdResult extends ApiResult {
public class OpenIdResult extends ApiResult {
private static final long serialVersionUID = 902743989722741814L;
@ -35,7 +35,7 @@ public class AuthCodeOpenIdResult extends ApiResult {
@Override
public String toString() {
return "AuthCodeOpenIdResult [openId=" + openId + ", "
return "OpenIdResult [openId=" + openId + ", "
+ super.toString() + "]";
}
}

View File

@ -144,10 +144,6 @@ public class Redpacket implements Serializable {
return amtType;
}
public void setAmtType(String amtType) {
this.amtType = amtType;
}
public String getClientIp() {
return clientIp;
}

View File

@ -0,0 +1,14 @@
package com.foxinmy.weixin4j.settings;
/**
* 微信请求配置相关(待实现
*
* @className Weixin4jHttpSettings
* @author jy
* @date 2016年1月28日
* @since JDK 1.6
* @see
*/
public class Weixin4jHttpSettings {
}

View File

@ -0,0 +1,108 @@
package com.foxinmy.weixin4j.settings;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.model.WeixinPayAccount;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
/**
* 微信支付配置相关
*
* @className Weixin4jPaySettings
* @author jy
* @date 2016年1月28日
* @since JDK 1.6
* @see
*/
public class Weixin4jPaySettings {
private final WeixinPayAccount payAccount;
public Weixin4jPaySettings() {
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
WeixinPayAccount.class));
}
public Weixin4jPaySettings(WeixinPayAccount payAccount) {
this.payAccount = payAccount;
}
/**
* 支付账号信息
*
* @return
*/
public WeixinPayAccount getPayAccount() {
return this.payAccount;
}
private String billPath;
/**
* 对账单保存路径
*
* @param billPath
* 硬盘目录
*/
public Weixin4jPaySettings billPath(String billPath) {
this.billPath = billPath;
return this;
}
/**
* 默认对账单保存路径
*/
public static final String DEFAULT_BILL_PATH = "/tmp/weixin4j/bill";
/**
* 对账单保存路径,默认值为{@link #DEFAULT_BILL_PATH}
*
* @return
*/
public String getBillPath() {
if (StringUtil.isBlank(billPath)) {
this.billPath = Weixin4jConfigUtil.getClassPathValue("bill.path",
DEFAULT_BILL_PATH);
}
return this.billPath;
}
private String certificatePath;
/**
* ca证书存放路径
*
* @param certificatePath
* 硬盘目录
* @return
*/
public Weixin4jPaySettings certificatePath(String certificatePath) {
this.certificatePath = certificatePath;
return this;
}
/**
* 默认ca证书存放路径
*/
public static final String DEFAULT_CAFILE_PATH = "classpath:ca.p12";
/**
* ca证书存放路径,默认值为{@link #DEFAULT_CAFILE_PATH}
*
* @return
*/
public String getCertificatePath() {
if (StringUtil.isBlank(certificatePath)) {
this.certificatePath = Weixin4jConfigUtil.getClassPathValue(
"certificate.path", DEFAULT_CAFILE_PATH);
}
return this.certificatePath;
}
@Override
public String toString() {
return "Weixin4jPaySettings [payAccount=" + payAccount + ", billPath="
+ getBillPath() + ", certificatePath=" + getCertificatePath()
+ "]";
}
}

View File

@ -0,0 +1,168 @@
package com.foxinmy.weixin4j.settings;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
/**
* 微信基础配置相关
*
* @className Weixin4jSettings
* @author jy
* @date 2016年1月28日
* @since JDK 1.6
* @see
*/
public class Weixin4jSettings {
private final WeixinAccount account;
public Weixin4jSettings() {
this(Weixin4jConfigUtil.getWeixinAccount());
}
/**
*
* @param id
* 应用唯一标识 appid/corpid
* @param secret
* 应用接口密钥
*/
public Weixin4jSettings(String id, String secret) {
this(new WeixinAccount(id, secret));
}
public Weixin4jSettings(WeixinAccount account) {
this.account = account;
}
/**
* 微信账号信息
*/
public WeixinAccount getAccount() {
return this.account;
}
private String tokenPath;
/**
* 使用FileTokenStorager时token的存放路径
*
* @param tokenPath
* 硬盘目录
* @return
*/
public Weixin4jSettings setTokenPath(String tokenPath) {
this.tokenPath = tokenPath;
return this;
}
/**
* 默认token的存放路径
*/
public static final String DEFAULT_TOKEN_PATH = "/tmp/weixin4j/token";
/**
* 使用FileTokenStorager时token的存放路径,默认值为{@link #DEFAULT_TOKEN_PATH}
*/
public String getTokenPath() {
if (StringUtil.isBlank(tokenPath)) {
tokenPath = Weixin4jConfigUtil.getClassPathValue("token.path",
DEFAULT_TOKEN_PATH);
}
return tokenPath;
}
private String qrcodePath;
/**
* 二维码保存路径
*
* @param qrcodePath
* 硬盘目录
*/
public Weixin4jSettings setQrcodePath(String qrcodePath) {
this.qrcodePath = qrcodePath;
return this;
}
/**
* 默认二维码保存路径
*/
public static final String DEFAULT_QRCODE_PATH = "/tmp/weixin4j/qrcode";
/**
* 二维码保存路径,默认值为{@link #DEFAULT_QRCODE_PATH}
*/
public String getQrcodePath() {
if (StringUtil.isBlank(qrcodePath)) {
this.qrcodePath = Weixin4jConfigUtil.getClassPathValue(
"qrcode.path", DEFAULT_QRCODE_PATH);
}
return this.qrcodePath;
}
private String mediaPath;
/**
* 媒体文件保存路径
*
* @param mediaPath
* 硬盘目录
*/
public Weixin4jSettings setMediaPath(String mediaPath) {
this.mediaPath = mediaPath;
return this;
}
/**
* 默认媒体文件保存路径
*/
public static final String DEFAULT_MEDIA_PATH = "/tmp/weixin4j/media";
/**
* 媒体文件保存路径,默认值为{@link #DEFAULT_MEDIA_PATH}
*/
public String getMediaPath() {
if (StringUtil.isBlank(mediaPath)) {
this.mediaPath = Weixin4jConfigUtil.getClassPathValue("media.path",
DEFAULT_MEDIA_PATH);
}
return this.mediaPath;
}
private TokenStorager tokenStorager;
/**
* token存储
*
* @param tokenStorager
* @return
*/
public Weixin4jSettings setTokenStorager(TokenStorager tokenStorager) {
this.tokenStorager = tokenStorager;
return this;
}
/**
* 获取token存储方式 默认为FileTokenStorager
*
* @return
*/
public TokenStorager getTokenStorager() {
if (tokenStorager == null) {
this.tokenStorager = new FileTokenStorager(getTokenPath());
}
return this.tokenStorager;
}
@Override
public String toString() {
return "Weixin4jSettings [account=" + account + ", tokenPath="
+ getTokenPath() + ", qrcodePath=" + getQrcodePath()
+ ", mediaPath=" + getMediaPath() + ", tokenStorager="
+ getTokenStorager() + "]";
}
}

View File

@ -44,7 +44,7 @@ public interface CacheStorager<T> {
T evict(String cacheKey);
/**
* 清除所有缓存对象(<font color="red">请慎重</a>)
* 清除所有缓存对象(<font color="red">请慎重</font>)
*/
void clear();
}

View File

@ -1,11 +1,16 @@
package com.foxinmy.weixin4j.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.payment.mch.NativePayNotify;
import com.foxinmy.weixin4j.xml.XmlStream;
/**
* 签名工具类
@ -130,4 +135,12 @@ public final class DigestUtil {
return sb.toString();
}
public static void main(String[] args) throws FileNotFoundException {
NativePayNotify notify = XmlStream.fromXML(new FileInputStream(
new File("/Users/jy/Downloads/weixin4j.xml")),
NativePayNotify.class);
notify.setSign(null);
System.err.println(paysignMd5(notify, "GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ"));
}
}

View File

@ -75,7 +75,7 @@ public class Weixin4jConfigUtil {
value = getValue(key);
} catch (MissingResourceException e) {
;
}catch (NullPointerException e){
} catch (NullPointerException e) {
;
}
return value;
@ -88,8 +88,7 @@ public class Weixin4jConfigUtil {
* @return
*/
public static String getClassPathValue(String key) {
return new File(getValue(key).replaceFirst(CLASSPATH_PREFIX,
CLASSPATH_VALUE)).getPath();
return getValue(key).replaceFirst(CLASSPATH_PREFIX, CLASSPATH_VALUE);
}
/**
@ -99,18 +98,18 @@ public class Weixin4jConfigUtil {
* @return
*/
public static String getClassPathValue(String key, String defaultValue) {
return new File(getValue(key, defaultValue).replaceFirst(
CLASSPATH_PREFIX, CLASSPATH_VALUE)).getPath();
return getValue(key, defaultValue).replaceFirst(CLASSPATH_PREFIX,
CLASSPATH_VALUE);
}
public static WeixinAccount getWeixinAccount() {
if (weixinBundle == null) {
return null;
}
WeixinAccount account = null;
try {
account = JSON
.parseObject(getValue("account"), WeixinAccount.class);
} catch (NullPointerException e) {
System.err
.println("'weixin4j.account' key not found in weixin4j.properties.");
} catch (MissingResourceException e) {
System.err
.println("'weixin4j.account' key not found in weixin4j.properties.");

View File

@ -1,33 +0,0 @@
package com.foxinmy.weixin4j.util;
/**
* 常量配置
*
* @className Weixin4jConst
* @author jy
* @date 2015年7月1日
* @since JDK 1.6
* @see
*/
public final class Weixin4jConst {
/**
* 使用FileTokenStorager时token的存放路径
*/
public static final String DEFAULT_TOKEN_PATH = "/tmp/weixin4j/token";
/**
* 二维码保存路径
*/
public static final String DEFAULT_QRCODE_PATH = "/tmp/weixin4j/qrcode";
/**
* 媒体文件保存路径
*/
public static final String DEFAULT_MEDIA_PATH = "/tmp/weixin4j/media";
/**
* 对账单保存路径
*/
public static final String DEFAULT_BILL_PATH = "/tmp/weixin4j/bill";
/**
* ca证书存放的完整路径 (V2版本后缀为*.pfx,V3版本后缀为*.p12)
*/
public static final String DEFAULT_CAFILE_PATH = "classpath:ca.p12";
}

View File

@ -67,7 +67,9 @@ public class HttpClientTest {
}
public static void main(String[] args) throws Exception {
for(int i=0;i<100000;i++){
test1();
}
System.out.println("---------------------");
test2();
System.out.println("---------------------");

View File

@ -58,21 +58,27 @@ weixin4j.properties说明
完整填写示例(properties中换行用右斜杆\\)
weixin4j.account={"id":"appId","secret":"appSecret",\
"mchId":"V3.x版本下的微信商户号",\
"partnerId":"V2版本下的财付通的商户号",\
"partnerKey":"V2版本下的财付通商户权限密钥Key",\
"paySignKey":"微信支付中调用API的密钥"}
weixin4j.account={"id":"appid","secret":"appsecret",\
"mchId":"V3.x版本下的微信商户号 微信支付时需要填入",\
"certificateKey":"加载支付证书文件的密码 如果不填写则默认获取mchId作为密码",\
"partnerId":"V2版本下的财付通的商户号 微信支付时需要填入",\
"partnerKey":"V2版本下的财付通商户权限密钥Key 微信支付时需要填入",\
"paySignKey":"微信支付中调用API的密钥 微信支付时需要填入"}
# 使用FileTokenStorager时token的存放路径(如果不填则默认为Weixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.token.path=/tmp/weixin4j/token
# 二维码保存路径(如果不填则默认为Weixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.qrcode.path=/tmp/weixin4j/qrcode
# 媒体文件保存路径(如果不填则默认为Weixin4jConst#DEFAULT_MEDIA_PATH)
weixin4j.media.path=/tmp/weixin4j/media
# 对账单保存路径(如果不填则默认为Weixin4jConst#DEFAULT_BILL_PATH)
weixin4j.bill.path=/tmp/weixin4j/bill
# ca证书存放的完整路径 (V2版本后缀为*.pfx,V3版本后缀为*.p12)
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
#classpath路径下:weixin4j.certificate.file=classpath:xxxxx.p12
# classpath路径下可以这么写(如果不填则默认为Weixin4jConst#DEFAULT_CAFILE_PATH)
# weixin4j.certificate.file=classpath:xxxxx.pfx
#公众号登陆授权的重定向路径(使用OauthApi时需要填写)
# 用户oauth授权后重定向的url(在使用OauthApi时填写)
weixin4j.user.oauth.redirect.uri=http://xxx
2.实例化微信公众号接口代理对象,调用具体的API方法

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.6.6</version>
<version>1.6.7</version>
</parent>
<artifactId>weixin4j-mp</artifactId>
<name>weixin4j-mp</name>

View File

@ -14,6 +14,7 @@ import com.foxinmy.weixin4j.model.MediaItem;
import com.foxinmy.weixin4j.model.MediaRecord;
import com.foxinmy.weixin4j.model.MediaUploadResult;
import com.foxinmy.weixin4j.model.Pageable;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.mp.api.CustomApi;
import com.foxinmy.weixin4j.mp.api.DataApi;
import com.foxinmy.weixin4j.mp.api.GroupApi;
@ -21,7 +22,6 @@ import com.foxinmy.weixin4j.mp.api.HelperApi;
import com.foxinmy.weixin4j.mp.api.MassApi;
import com.foxinmy.weixin4j.mp.api.MediaApi;
import com.foxinmy.weixin4j.mp.api.MenuApi;
import com.foxinmy.weixin4j.mp.api.MpApi;
import com.foxinmy.weixin4j.mp.api.NotifyApi;
import com.foxinmy.weixin4j.mp.api.QrApi;
import com.foxinmy.weixin4j.mp.api.TmplApi;
@ -47,8 +47,8 @@ import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.mp.type.DatacubeType;
import com.foxinmy.weixin4j.mp.type.IndustryType;
import com.foxinmy.weixin4j.mp.type.Lang;
import com.foxinmy.weixin4j.settings.Weixin4jSettings;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.tuple.MassTuple;
import com.foxinmy.weixin4j.tuple.MpArticle;
import com.foxinmy.weixin4j.tuple.MpVideo;
@ -80,45 +80,26 @@ public class WeixinProxy {
private final DataApi dataApi;
private final TokenHolder tokenHolder;
private String appId;
private Weixin4jSettings settings;
/**
* 默认使用文件方式保存token使用weixin4j.properties配置的账号信息
*/
public WeixinProxy() {
this(MpApi.DEFAULT_TOKEN_STORAGER);
}
/**
* 默认使用weixin4j.properties配置的账号信息
*
* @param tokenStorager
*/
public WeixinProxy(TokenStorager tokenStorager) {
this(MpApi.DEFAULT_WEIXIN_ACCOUNT.getId(), MpApi.DEFAULT_WEIXIN_ACCOUNT
.getSecret(), tokenStorager);
this(new Weixin4jSettings());
}
/**
*
* @param appid
* @param appsecret
* @param settings
* 配置信息
* @see com.foxinmy.weixin4j.settings.Weixin4jSettings
*/
public WeixinProxy(String appid, String appsecret) {
this(appid, appsecret, MpApi.DEFAULT_TOKEN_STORAGER);
}
/**
*
* @param appid
* @param appsecret
* @param tokenStorager
*/
public WeixinProxy(String appid, String appsecret,
TokenStorager tokenStorager) {
this(new TokenHolder(new WeixinTokenCreator(appid, appsecret),
tokenStorager));
this.appId = appid;
public WeixinProxy(Weixin4jSettings settings) {
this(new TokenHolder(new WeixinTokenCreator(settings.getAccount()
.getId(), settings.getAccount().getSecret()),
settings.getTokenStorager()));
this.settings = settings;
}
/**
@ -143,12 +124,12 @@ public class WeixinProxy {
}
/**
* 获取appid
* 获取微信账号信息
*
* @return
*/
public String getAppId() {
return this.appId;
public WeixinAccount getWeixinAccount() {
return this.settings.getAccount();
}
/**
@ -168,8 +149,9 @@ public class WeixinProxy {
* @return
*/
public TokenHolder getTicketHolder(TicketType ticketType) {
return new TokenHolder(new WeixinTicketCreator(this.appId, ticketType,
this.tokenHolder), this.tokenHolder.getTokenStorager());
return new TokenHolder(new WeixinTicketCreator(getWeixinAccount()
.getId(), ticketType, this.tokenHolder),
this.tokenHolder.getTokenStorager());
}
/**
@ -248,10 +230,8 @@ public class WeixinProxy {
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @param mediaType
* 媒体类型
* @param isMaterial
* 是否永久素材
* 是否下载永久素材
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see <a
@ -261,7 +241,8 @@ public class WeixinProxy {
*/
public File downloadMediaFile(String mediaId, boolean isMaterial)
throws WeixinException {
return mediaApi.downloadMediaFile(mediaId, isMaterial);
return mediaApi.downloadMediaFile(mediaId, isMaterial,
settings.getMediaPath());
}
/**
@ -1215,11 +1196,13 @@ public class WeixinProxy {
* 生成带参数的二维码
*
* @return 硬盘存储的文件对象
* @param parameter
* 二维码参数
* @throws WeixinException
* @see {@link #createQR(QRParameter)}
*/
public File createQRFile(QRParameter parameter) throws WeixinException {
return qrApi.createQRFile(parameter);
return qrApi.createQRFile(parameter, settings.getQrcodePath());
}
/**
@ -1463,5 +1446,5 @@ public class WeixinProxy {
return dataApi.datacube(datacubeType, date);
}
public final static String VERSION = "1.6.6";
public final static String VERSION = "1.6.7";
}

View File

@ -48,8 +48,6 @@ import com.foxinmy.weixin4j.util.IOUtil;
import com.foxinmy.weixin4j.util.ObjectId;
import com.foxinmy.weixin4j.util.RegexUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
import com.foxinmy.weixin4j.util.WeixinErrorUtil;
/**
@ -238,7 +236,11 @@ public class MediaApi extends MpApi {
*
* @param mediaId
* 存储在微信服务器上的媒体标识
* @return 写入硬盘后的文件对象,存储路径见weixin4j.properties配置
* @param isMaterial
* 是否下载永久素材
* @param mediaPath
* 媒体素材保存路径
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see <a
* href="http://mp.weixin.qq.com/wiki/11/07b6b76a6b6e8848e855a435d5e34a5f.html">下载临时媒体文件</a>
@ -246,12 +248,10 @@ public class MediaApi extends MpApi {
* href="http://mp.weixin.qq.com/wiki/4/b3546879f07623cb30df9ca0e420a5d0.html">下载永久媒体素材</a>
* @see {@link #downloadMedia(String,boolean)}
*/
public File downloadMediaFile(String mediaId, boolean isMaterial)
throws WeixinException {
String media_path = Weixin4jConfigUtil.getValue("media.path",
Weixin4jConst.DEFAULT_MEDIA_PATH);
public File downloadMediaFile(String mediaId, boolean isMaterial,
String mediaPath) throws WeixinException {
final String prefixName = String.format("%s.", mediaId);
File[] files = new File(media_path).listFiles(new FilenameFilter() {
File[] files = new File(mediaPath).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith(prefixName);
@ -261,7 +261,7 @@ public class MediaApi extends MpApi {
return files[0];
}
MediaDownloadResult result = downloadMedia(mediaId, isMaterial);
File file = new File(media_path + File.separator + result.getFileName());
File file = new File(mediaPath + File.separator + result.getFileName());
OutputStream os = null;
try {
if (file.createNewFile()) {

View File

@ -7,11 +7,12 @@ import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.mp.model.OauthToken;
import com.foxinmy.weixin4j.mp.model.User;
import com.foxinmy.weixin4j.mp.type.Lang;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
/**
* oauth授权
@ -25,13 +26,23 @@ import com.foxinmy.weixin4j.util.StringUtil;
*/
public class OauthApi extends MpApi {
private final WeixinAccount account;
public OauthApi() {
this(Weixin4jConfigUtil.getWeixinAccount());
}
public OauthApi(WeixinAccount account) {
this.account = account;
}
/**
* @see {@link #getAuthorizeURL(String, String,String)}
*
* @return 请求授权的URL
*/
public String getAuthorizeURL() {
String appId = DEFAULT_WEIXIN_ACCOUNT.getId();
String appId = account.getId();
String redirectUri = Weixin4jConfigUtil
.getValue("user.oauth.redirect.uri");
return getAuthorizeURL(appId, redirectUri, "state", "snsapi_base");
@ -67,8 +78,7 @@ public class OauthApi extends MpApi {
* @return
*/
public OauthToken getOauthToken(String code) throws WeixinException {
return getOauthToken(code, DEFAULT_WEIXIN_ACCOUNT.getId(),
DEFAULT_WEIXIN_ACCOUNT.getSecret());
return getOauthToken(code, account.getId(), account.getSecret());
}
/**
@ -100,7 +110,7 @@ public class OauthApi extends MpApi {
* @return
*/
public OauthToken refreshToken(String refreshToken) throws WeixinException {
return refreshToken(DEFAULT_WEIXIN_ACCOUNT.getId(), refreshToken);
return refreshToken(account.getId(), refreshToken);
}
/**

View File

@ -40,6 +40,9 @@ import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2;
import com.foxinmy.weixin4j.mp.payment.v2.RefundResultV2;
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
import com.foxinmy.weixin4j.payment.PayRequest;
import com.foxinmy.weixin4j.settings.Weixin4jSettings;
import com.foxinmy.weixin4j.settings.Weixin4jPaySettings;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.type.BillType;
@ -51,8 +54,6 @@ import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.MapUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
/**
@ -66,23 +67,27 @@ import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
*/
public class Pay2Api extends MpApi {
private final WeixinPayAccount weixinAccount;
private final Weixin4jPaySettings settings;
private final TokenHolder tokenHolder;
public Pay2Api() {
this(JSON.parseObject(Weixin4jConfigUtil.getValue("account"),
WeixinPayAccount.class));
this(new Weixin4jPaySettings());
}
public Pay2Api(WeixinPayAccount weixinAccount) {
this(weixinAccount, DEFAULT_TOKEN_STORAGER);
public Pay2Api(Weixin4jPaySettings settings) {
this(settings, new FileTokenStorager(
Weixin4jSettings.DEFAULT_TOKEN_PATH));
}
public Pay2Api(WeixinPayAccount weixinAccount, TokenStorager tokenStorager) {
this.weixinAccount = weixinAccount;
this.tokenHolder = new TokenHolder(new WeixinTokenCreator(
weixinAccount.getId(), weixinAccount.getSecret()),
tokenStorager);
public Pay2Api(Weixin4jPaySettings settings, TokenStorager tokenStorager) {
this.settings = settings;
this.tokenHolder = new TokenHolder(
new WeixinTokenCreator(settings.getPayAccount().getId(),
settings.getPayAccount().getSecret()), tokenStorager);
}
public WeixinPayAccount getPayAccount() {
return this.settings.getPayAccount();
}
/**
@ -137,20 +142,20 @@ public class Pay2Api extends MpApi {
double totalFee, String notifyUrl, String createIp, String attach,
Date timeStart, Date timeExpire, double transportFee,
double productFee, String goodsTag) {
PayPackageV2 payPackage = new PayPackageV2(
weixinAccount.getPartnerId(), body, outTradeNo, totalFee,
notifyUrl, createIp);
PayPackageV2 payPackage = new PayPackageV2(settings.getPayAccount()
.getPartnerId(), body, outTradeNo, totalFee, notifyUrl,
createIp);
payPackage.setAttach(attach);
payPackage.setTimeStart(timeStart);
payPackage.setTimeExpire(timeExpire);
payPackage.setTransportFee(transportFee);
payPackage.setProductFee(productFee);
payPackage.setGoodsTag(goodsTag);
PayRequest payRequest = new PayRequest(weixinAccount.getId(),
DigestUtil.packageSign(payPackage,
weixinAccount.getPartnerKey()));
payRequest.setPaySign(DigestUtil.paysignSha(payRequest,
weixinAccount.getPaySignKey()));
PayRequest payRequest = new PayRequest(getPayAccount().getId(),
DigestUtil.packageSign(payPackage, getPayAccount()
.getPartnerKey()));
payRequest.setPaySign(DigestUtil.paysignSha(payRequest, getPayAccount()
.getPaySignKey()));
payRequest.setSignType(SignType.SHA1);
return JSON.toJSONString(payRequest);
}
@ -166,14 +171,14 @@ public class Pay2Api extends MpApi {
Map<String, String> map = new HashMap<String, String>();
String timestamp = DateUtil.timestamp2string();
String noncestr = RandomUtil.generateString(16);
map.put("appid", weixinAccount.getId());
map.put("appid", getPayAccount().getId());
map.put("timestamp", timestamp);
map.put("noncestr", noncestr);
map.put("productid", productId);
map.put("appkey", weixinAccount.getPaySignKey());
map.put("appkey", getPayAccount().getPaySignKey());
String sign = DigestUtil.paysignSha(map, null);
String ordernative_v2_uri = getRequestUri("ordernative_v2_uri");
return String.format(ordernative_v2_uri, sign, weixinAccount.getId(),
return String.format(ordernative_v2_uri, sign, getPayAccount().getId(),
productId, timestamp, noncestr);
}
@ -193,23 +198,23 @@ public class Pay2Api extends MpApi {
StringBuilder sb = new StringBuilder();
sb.append(idQuery.getType().getName()).append("=")
.append(idQuery.getId());
sb.append("&partner=").append(weixinAccount.getPartnerId());
sb.append("&partner=").append(getPayAccount().getPartnerId());
String part = sb.toString();
sb.append("&key=").append(weixinAccount.getPartnerKey());
sb.append("&key=").append(getPayAccount().getPartnerKey());
String sign = DigestUtil.MD5(sb.toString()).toUpperCase();
sb.delete(0, sb.length());
sb.append(part).append("&sign=").append(sign);
String timestamp = DateUtil.timestamp2string();
JSONObject obj = new JSONObject();
obj.put("appid", weixinAccount.getId());
obj.put("appkey", weixinAccount.getPaySignKey());
obj.put("appid", getPayAccount().getId());
obj.put("appkey", getPayAccount().getPaySignKey());
obj.put("package", sb.toString());
obj.put("timestamp", timestamp);
String signature = DigestUtil.paysignSha(obj, null);
obj.clear();
obj.put("appid", weixinAccount.getId());
obj.put("appid", getPayAccount().getId());
obj.put("package", sb.toString());
obj.put("timestamp", timestamp);
obj.put("app_signature", signature);
@ -271,20 +276,20 @@ public class Pay2Api extends MpApi {
// 填写为 1.0 ,操作员密码为明文
// 填写为 1.1 ,操作员密码为 MD5(密码)
map.put("service_version", "1.1");
map.put("partner", weixinAccount.getPartnerId());
map.put("partner", getPayAccount().getPartnerId());
map.put("out_refund_no", outRefundNo);
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
map.put(idQuery.getType().getName(), idQuery.getId());
if (StringUtil.isBlank(opUserId)) {
opUserId = weixinAccount.getPartnerId();
opUserId = getPayAccount().getPartnerId();
}
map.put("op_user_id", opUserId);
if (mopara != null && !mopara.isEmpty()) {
map.putAll(mopara);
}
String sign = DigestUtil.paysignMd5(map,
weixinAccount.getPartnerKey());
String sign = DigestUtil.paysignMd5(map, getPayAccount()
.getPartnerKey());
map.put("sign", sign.toUpperCase());
SSLContext ctx = null;
@ -319,8 +324,8 @@ public class Pay2Api extends MpApi {
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(com.foxinmy.weixin4j.model.Consts.SunX509);
ks = KeyStore.getInstance(com.foxinmy.weixin4j.model.Consts.PKCS12);
ks.load(ca, weixinAccount.getPartnerId().toCharArray());
kmf.init(ks, weixinAccount.getPartnerId().toCharArray());
ks.load(ca, getPayAccount().getPartnerId().toCharArray());
kmf.init(ks, getPayAccount().getPartnerId().toCharArray());
ctx = SSLContext.getInstance(com.foxinmy.weixin4j.model.Consts.TLS);
ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(),
@ -451,23 +456,22 @@ public class Pay2Api extends MpApi {
billType = BillType.ALL;
}
String formatBillDate = DateUtil.fortmat2yyyyMMdd(billDate);
String bill_path = Weixin4jConfigUtil.getValue("bill.path",
Weixin4jConst.DEFAULT_BILL_PATH);
String fileName = String.format("%s_%s_%s.txt", formatBillDate,
billType.name().toLowerCase(), weixinAccount.getId());
File file = new File(String.format("%s/%s", bill_path, fileName));
billType.name().toLowerCase(), getPayAccount().getId());
File file = new File(String.format("%s/%s", settings.getBillPath(),
fileName));
if (file.exists()) {
return file;
}
String downloadbill_uri = getRequestUri("downloadbill_v2_uri");
Map<String, String> map = new LinkedHashMap<String, String>();
map.put("spid", weixinAccount.getPartnerId());
map.put("spid", getPayAccount().getPartnerId());
map.put("trans_time", DateUtil.fortmat2yyyy_MM_dd(billDate));
map.put("stamp", DateUtil.timestamp2string());
map.put("cft_signtype", "0");
map.put("mchtype", Integer.toString(billType.getVal()));
map.put("key", weixinAccount.getPartnerKey());
map.put("key", getPayAccount().getPartnerKey());
String sign = DigestUtil.MD5(MapUtil.toJoinString(map, false, false));
map.put("sign", sign.toLowerCase());
WeixinResponse response = weixinExecutor.get(downloadbill_uri, map);
@ -517,9 +521,10 @@ public class Pay2Api extends MpApi {
String refundquery_uri = getRequestUri("refundquery_v2_uri");
Map<String, String> map = new HashMap<String, String>();
map.put("input_charset", Consts.UTF_8.name());
map.put("partner", weixinAccount.getPartnerId());
map.put("partner", getPayAccount().getPartnerId());
map.put(idQuery.getType().getName(), idQuery.getId());
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPartnerKey());
String sign = DigestUtil.paysignMd5(map, getPayAccount()
.getPartnerKey());
map.put("sign", sign.toLowerCase());
WeixinResponse response = weixinExecutor.get(refundquery_uri, map);
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
@ -549,8 +554,8 @@ public class Pay2Api extends MpApi {
Token token = tokenHolder.getToken();
Map<String, String> map = new HashMap<String, String>();
map.put("appid", weixinAccount.getId());
map.put("appkey", weixinAccount.getPaySignKey());
map.put("appid", getPayAccount().getId());
map.put("appkey", getPayAccount().getPaySignKey());
map.put("openid", openId);
map.put("transid", transid);
map.put("out_trade_no", outTradeNo);

View File

@ -13,8 +13,6 @@ import com.foxinmy.weixin4j.mp.model.QRParameter;
import com.foxinmy.weixin4j.mp.model.QRResult;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.util.IOUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
/**
* 二维码相关API
@ -55,7 +53,8 @@ public class QrApi extends MpApi {
QRResult result = response.getAsObject(new TypeReference<QRResult>() {
});
qr_uri = getRequestUri("qr_image_uri");
response = weixinExecutor.get(String.format(qr_uri, result.getTicket()));
response = weixinExecutor
.get(String.format(qr_uri, result.getTicket()));
try {
result.setContent(IOUtil.toByteArray(response.getBody()));
} catch (IOException e) {
@ -72,6 +71,8 @@ public class QrApi extends MpApi {
*
* @param parameter
* 二维码参数
* @param qrcodePath
* 二维码保存路径
* @return 硬盘存储的文件对象
* @throws WeixinException
* @see <a
@ -79,13 +80,12 @@ public class QrApi extends MpApi {
* @see #createQR(QRParameter)
* @see com.foxinmy.weixin4j.mp.model.QRParameter
*/
public File createQRFile(QRParameter parameter) throws WeixinException {
String qr_path = Weixin4jConfigUtil.getValue("qrcode.path",
Weixin4jConst.DEFAULT_QRCODE_PATH);
public File createQRFile(QRParameter parameter, String qrcodePath)
throws WeixinException {
String filename = String.format("%s_%s_%d.jpg", parameter.getQrType()
.name(), parameter.getSceneValue(), parameter
.getExpireSeconds());
File file = new File(qr_path + File.separator + filename);
File file = new File(qrcodePath + File.separator + filename);
if (parameter.getQrType().ordinal() > 0 && file.exists()) {
return file;
}

View File

@ -1,23 +1,24 @@
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
# \u516c\u4f17\u53f7\u4fe1\u606f
weixin4j.account={"id":"wx4ab8f8de58159a57","secret":"1d4eb0f4bf556aaed539f30ed05ca795",\
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\u5fae\u4fe1\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"partnerId":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"partnerKey":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u670d\u52a1\u53f7\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
"mchId":"V3.x\u7248\u672c\u4e0b\u7684\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",\
"partnerId":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u7684\u5546\u6237\u53f7 \u8001\u7248\u672c\u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165",\
"partnerKey":"V2\u7248\u672c\u4e0b\u7684\u8d22\u4ed8\u901a\u5546\u6237\u6743\u9650\u5bc6\u94a5Key \u8001\u7248\u672c\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"}
# \u4f7f\u7528FileTokenStorager\u65f6token\u7684\u5b58\u653e\u8def\u5f84
# \u4f7f\u7528FileTokenStorager\u65f6token\u7684\u5b58\u653e\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.token.path=/tmp/weixin4j/token
# \u4e8c\u7ef4\u7801\u4fdd\u5b58\u8def\u5f84
# \u4e8c\u7ef4\u7801\u4fdd\u5b58\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.qrcode.path=/tmp/weixin4j/qrcode
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_MEDIA_PATH)
weixin4j.media.path=/tmp/weixin4j/media
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_BILL_PATH)
weixin4j.bill.path=/tmp/weixin4j/bill
# ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84 (V2\u7248\u672c\u540e\u7f00\u4e3a*.pfx,V3\u7248\u672c\u540e\u7f00\u4e3a*.p12)
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_CAFILE_PATH)
# weixin4j.certificate.file=classpath:xxxxx.pfx
# \u7528\u6237oauth\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url
# \u7528\u6237oauth\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
weixin4j.user.oauth.redirect.uri=

View File

@ -94,7 +94,8 @@ public class MediaTest extends TokenTest {
@Test
public void download2() throws WeixinException, IOException {
File file = mediaApi.downloadMediaFile("8790403529", true);
File file = mediaApi.downloadMediaFile("8790403529", true,
"/tmp/weixin4j/media");
Assert.assertTrue(file.exists());
}

View File

@ -19,12 +19,11 @@ import com.foxinmy.weixin4j.payment.mch.ApiResult;
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.payment.mch.PrePay;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.settings.Weixin4jPaySettings;
import com.foxinmy.weixin4j.type.IdQuery;
import com.foxinmy.weixin4j.type.IdType;
import com.foxinmy.weixin4j.type.TradeType;
import com.foxinmy.weixin4j.util.DigestUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
public class PayTest {
protected final static Pay2Api PAY2;
@ -33,14 +32,13 @@ public class PayTest {
protected final static WeixinPayAccount ACCOUNT3;
static {
ACCOUNT2 = new WeixinPayAccount("请填入v2版本的appid", "请填入v2版本的appSecret",
"请填入v2版本的paysignkey", null, null, null, "请填入v2版本的partnerId",
"请填入v2版本的partnerKey");
PAY2 = new Pay2Api(ACCOUNT2, new FileTokenStorager(
Weixin4jConfigUtil
.getValue("token.path", "/tmp/weixin4j/token")));
"请填入v2版本的paysignkey", null, null, null, null,
"请填入v2版本的partnerId", "请填入v2版本的partnerKey");
PAY2 = new Pay2Api(new Weixin4jPaySettings(ACCOUNT2));
ACCOUNT3 = new WeixinPayAccount("请填入v3版本的appid", "请填入v3版本的appSecret",
"请填入v3版本的paysignkey", "请填入v3版本的mchid", null, null, null, null);
PAY3 = new WeixinPayProxy(ACCOUNT3);
"请填入v3版本的paysignkey", "请填入v3版本的mchid", null, null, null, null,
null);
PAY3 = new WeixinPayProxy(new Weixin4jPaySettings(ACCOUNT3));
}
/**
* 商户证书文件
@ -55,7 +53,6 @@ public class PayTest {
@Test
public void refundV2() throws WeixinException {
File caFile = new File("证书文件如12333.pfx");
IdQuery idQuery = new IdQuery("D15020300005", IdType.TRADENO);
System.err.println(PAY2.refundApply(caFile, idQuery, "1422925555037",
16d, 16d, "1221928801", "111111", null, null, null));
@ -84,7 +81,8 @@ public class PayTest {
System.err.println(order);
String sign = order.getSign();
order.setSign(null);
String valiSign = DigestUtil.paysignMd5(order, ACCOUNT3.getPaySignKey());
String valiSign = DigestUtil
.paysignMd5(order, ACCOUNT3.getPaySignKey());
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);
@ -98,7 +96,8 @@ public class PayTest {
// 这里的验证签名需要把details循环拼接
String sign = record.getSign();
record.setSign(null);
String valiSign = DigestUtil.paysignMd5(record, ACCOUNT3.getPaySignKey());
String valiSign = DigestUtil.paysignMd5(record,
ACCOUNT3.getPaySignKey());
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);
@ -118,7 +117,6 @@ public class PayTest {
@Test
public void refundV3() throws WeixinException, IOException {
File caFile = new File("签名文件如123.p12");
IdQuery idQuery = new IdQuery("TT_1427183696238", IdType.TRADENO);
com.foxinmy.weixin4j.payment.mch.RefundResult result = PAY3
.refundApply(new FileInputStream(caFile), idQuery, "TT_R"
@ -127,7 +125,8 @@ public class PayTest {
System.err.println(result);
String sign = result.getSign();
result.setSign(null);
String valiSign = DigestUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
String valiSign = DigestUtil.paysignMd5(result,
ACCOUNT3.getPaySignKey());
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);
@ -154,7 +153,8 @@ public class PayTest {
System.err.println(result);
String sign = result.getSign();
result.setSign(null);
String valiSign = DigestUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
String valiSign = DigestUtil.paysignMd5(result,
ACCOUNT3.getPaySignKey());
System.err
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
Assert.assertEquals(valiSign, sign);

View File

@ -29,19 +29,23 @@ public class QRTest extends TokenTest {
@Test
public void temp_qr() throws WeixinException, IOException {
File file = qrApi.createQRFile(QRParameter.createTemporary(1200, 1200));
File file = qrApi.createQRFile(QRParameter.createTemporary(1200, 1200),
"/tmp/weixin4j/qrcode");
Assert.assertTrue(file.exists());
}
@Test
public void forever_qr_int() throws WeixinException, IOException {
File file = qrApi.createQRFile(QRParameter.createPermanenceInt(2));
File file = qrApi.createQRFile(QRParameter.createPermanenceInt(2),
"/tmp/weixin4j/qrcode");
Assert.assertTrue(file.exists());
}
@Test
public void forever_qr_str() throws WeixinException, IOException {
File file = qrApi.createQRFile(QRParameter.createPermanenceStr("1200中文"));
File file = qrApi.createQRFile(
QRParameter.createPermanenceStr("1200中文"),
"/tmp/weixin4j/qrcode");
Assert.assertTrue(file.exists());
}
}

View File

@ -168,3 +168,7 @@
* 2016-01-23
+ 新增获取客服列表接口
* 2016-01-26
+ 新增上传图文消息内的图片接口

View File

@ -25,13 +25,13 @@ weixin4j-qy
* PartyApi `部门管理API`
* ProviderApi `服务商API`
* ProviderApi `服务商API`
* SuiteApi `第三方应用API`
* SuiteApi `第三方应用API`
* TagApi `标签管理API`
* TagApi `标签管理API`
* UserApi `成员管理API`
* UserApi `成员管理API`
如何使用
@ -61,25 +61,32 @@ weixin4j.properties说明
示例(properties中换行用右斜杆\\)
weixin4j.account={"id":"corpid","secret":"corpsecret",\
"suites":[{"id":"应用套件的id","secret":"应用套件的secret"}],\
"providerSecret:"第三方提供商secret(企业号登陆)",\
"chatSecret":"消息服务secret(企业号消息服务,暂时没用到)"}
"suites":[{"id":"应用套件的id","secret":"应用套件的secret"}],\
"providerSecret":"第三方提供商secret(企业号登陆)",\
"chatSecret":"消息服务secret(企业号消息服务,暂时没用到)",\
"mchId":"微信商户号 微信支付时需要填入",\
"certificateKey":"加载支付证书文件的密码 如果不填写则默认获取mchId作为密码",\
"paySignKey":"微信支付中调用API的密钥 微信支付时需要填入"}
# 使用FileTokenStorager时token的存放路径(如果不填则默认为Weixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.token.path=/tmp/weixin4j/token
# 二维码保存路径(如果不填则默认为Weixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.qrcode.path=/tmp/weixin4j/qrcode
# 媒体文件保存路径(如果不填则默认为Weixin4jConst#DEFAULT_MEDIA_PATH)
weixin4j.media.path=/tmp/weixin4j/media
# 对账单保存路径(如果不填则默认为Weixin4jConst#DEFAULT_BILL_PATH)
weixin4j.bill.path=/tmp/weixin4j/bill
# ca证书存放的完整路径 (证书文件后缀为*.p12)
# ca证书存放的完整路径
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
#classpath路径下:weixin4j.certificate.file=classpath:xxxxx.p12
# classpath路径下可以这么写(如果不填则默认为Weixin4jConst#DEFAULT_CAFILE_PATH)
# weixin4j.certificate.file=classpath:xxxxx.pfx
#企业号用户身份授权后重定向的url(使用OauthApi时需要填写)
weixin4j.user.oauth.redirect.uri=http://xxx
#企业号第三方管理员授权后重定向的url(使用OauthApi时需要填写)
weixin4j.third.oauth.redirect.uri=http://xxx
#企业号第三方应用套件授权后重定向的url(使用OauthApi时需要填写)
weixin4j.suite.oauth.redirect.uri=http://xxx
# 企业号用户身份授权后重定向的url(在使用OauthApi时填写)
weixin4j.user.oauth.redirect.uri=
# 企业号第三方提供商授权后重定向的url(在使用OauthApi时填写)
weixin4j.third.oauth.redirect.uri=
# 企业号第三方应用套件授权后重定向的url(在使用OauthApi时填写)
weixin4j.suite.oauth.redirect.uri=
2.实例化微信企业号接口代理对象,调用具体的API方法

View File

@ -5,7 +5,7 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.6.6</version>
<version>1.6.7</version>
</parent>
<artifactId>weixin4j-qy</artifactId>
<name>weixin4j-qy</name>

View File

@ -14,6 +14,7 @@ import com.foxinmy.weixin4j.model.MediaItem;
import com.foxinmy.weixin4j.model.MediaRecord;
import com.foxinmy.weixin4j.model.MediaUploadResult;
import com.foxinmy.weixin4j.model.Pageable;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.qy.api.AgentApi;
import com.foxinmy.weixin4j.qy.api.BatchApi;
import com.foxinmy.weixin4j.qy.api.ChatApi;
@ -22,7 +23,6 @@ import com.foxinmy.weixin4j.qy.api.MediaApi;
import com.foxinmy.weixin4j.qy.api.MenuApi;
import com.foxinmy.weixin4j.qy.api.NotifyApi;
import com.foxinmy.weixin4j.qy.api.PartyApi;
import com.foxinmy.weixin4j.qy.api.QyApi;
import com.foxinmy.weixin4j.qy.api.TagApi;
import com.foxinmy.weixin4j.qy.api.UserApi;
import com.foxinmy.weixin4j.qy.message.ChatMessage;
@ -47,6 +47,7 @@ import com.foxinmy.weixin4j.qy.type.ChatType;
import com.foxinmy.weixin4j.qy.type.InviteType;
import com.foxinmy.weixin4j.qy.type.KfType;
import com.foxinmy.weixin4j.qy.type.UserStatus;
import com.foxinmy.weixin4j.settings.Weixin4jSettings;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.tuple.MpArticle;
@ -76,50 +77,27 @@ public class WeixinProxy {
private final ChatApi chatApi;
private final TokenHolder tokenHolder;
private String corpId;
private Weixin4jSettings settings;
/**
* 默认使用文件方式保存token使用weixin4j.properties配置的账号信息
*/
public WeixinProxy() {
this(QyApi.DEFAULT_TOKEN_STORAGER);
}
/**
* 默认使用weixin4j.properties配置的账号信息
*
* @param tokenStorager
* token存储策略
*/
public WeixinProxy(TokenStorager tokenStorager) {
this(QyApi.DEFAULT_WEIXIN_ACCOUNT.getId(), QyApi.DEFAULT_WEIXIN_ACCOUNT
.getSecret(), tokenStorager);
}
/**
* corpid,corpsecret
*
* @param corpid
* @param corpsecret
*/
public WeixinProxy(String corpid, String corpsecret) {
this(corpid, corpsecret, QyApi.DEFAULT_TOKEN_STORAGER);
this(new Weixin4jSettings());
}
/**
*
* @param corpid
* 企业号ID
* @param corpsecret
* 企业号secret
* @param tokenStorager
* 企业号token存储器
* @param settings
* 配置信息
* @see com.foxinmy.weixin4j.settings.Weixin4jSettings
*/
public WeixinProxy(String corpid, String corpsecret,
TokenStorager tokenStorager) {
this(new TokenHolder(new WeixinTokenCreator(corpid, corpsecret),
tokenStorager));
this.corpId = corpid;
public WeixinProxy(Weixin4jSettings settings) {
this(new TokenHolder(new WeixinTokenCreator(settings.getAccount()
.getId(), settings.getAccount().getSecret()),
settings.getTokenStorager()));
this.settings = settings;
}
/**
@ -133,7 +111,7 @@ public class WeixinProxy {
public WeixinProxy(WeixinTokenSuiteCreator tokenCreator,
TokenStorager tokenStorager) {
this(new TokenHolder(tokenCreator, tokenStorager));
this.corpId = tokenCreator.getAuthCorpId();
this.settings = new Weixin4jSettings(tokenCreator.getAuthCorpId(), null);
}
/**
@ -167,12 +145,12 @@ public class WeixinProxy {
}
/**
* 企业号ID
* 获取微信账号信息
*
* @return
*/
public String getCorpId() {
return this.corpId;
public WeixinAccount getWeixinAccount() {
return this.settings.getAccount();
}
/**
@ -183,8 +161,9 @@ public class WeixinProxy {
* @return
*/
public TokenHolder getTicketHolder(TicketType ticketType) {
return new TokenHolder(new WeixinTicketCreator(this.corpId, ticketType,
this.tokenHolder), this.tokenHolder.getTokenStorager());
return new TokenHolder(new WeixinTicketCreator(getWeixinAccount()
.getId(), ticketType, this.tokenHolder),
this.tokenHolder.getTokenStorager());
}
/**
@ -312,6 +291,25 @@ public class WeixinProxy {
return menuApi.deleteMenu(agentid);
}
/**
* 上传图文消息内的图片:用于上传图片到企业号服务端接口返回图片url请注意该url仅可用于图文消息的发送
* 且每个企业每天最多只能上传100张图片
*
* @param is
* 图片数据
* @param fileName
* 文件名
* @see <a
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E4%B8%8A%E4%BC%A0%E5%9B%BE%E6%96%87%E6%B6%88%E6%81%AF%E5%86%85%E7%9A%84%E5%9B%BE%E7%89%87">上传图文消息内的图片</a>
* @return 图片url
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @throws WeixinException
*/
public String uploadImage(InputStream is, String fileName)
throws WeixinException {
return mediaApi.uploadImage(is, fileName);
}
/**
* 上传媒体文件
* <p>
@ -348,7 +346,7 @@ public class WeixinProxy {
* 企业应用Id(<font color="red">大于0时视为获取永久媒体文件</font>)
* @param mediaId
* 存储在微信服务器上的媒体标识
* @return 写入硬盘后的文件对象,存储路径见weixin4j.properties配置
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see com.foxinmy.weixin4j.qy.api.MediaApi
* @see com.foxinmy.weixin4j.type.MediaType
@ -356,7 +354,8 @@ public class WeixinProxy {
*/
public File downloadMediaFile(int agentid, String mediaId)
throws WeixinException {
return mediaApi.downloadMediaFile(agentid, mediaId);
return mediaApi.downloadMediaFile(agentid, mediaId,
settings.getMediaPath());
}
/**
@ -1334,5 +1333,5 @@ public class WeixinProxy {
return chatApi.sendChatMessage(message);
}
public final static String VERSION = "1.6.6";
public final static String VERSION = "1.6.7";
}

View File

@ -3,19 +3,22 @@ package com.foxinmy.weixin4j.qy;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.qy.api.ProviderApi;
import com.foxinmy.weixin4j.qy.api.QyApi;
import com.foxinmy.weixin4j.qy.api.SuiteApi;
import com.foxinmy.weixin4j.qy.model.OUserInfo;
import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
import com.foxinmy.weixin4j.qy.suite.SuiteTicketHolder;
import com.foxinmy.weixin4j.qy.token.WeixinProviderTokenCreator;
import com.foxinmy.weixin4j.qy.type.LoginTargetType;
import com.foxinmy.weixin4j.settings.Weixin4jSettings;
import com.foxinmy.weixin4j.token.FileTokenStorager;
import com.foxinmy.weixin4j.token.TokenHolder;
import com.foxinmy.weixin4j.token.TokenStorager;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
/**
* 微信第三方应用接口实现
@ -34,20 +37,16 @@ public class WeixinSuiteProxy {
private ProviderApi providerApi;
public WeixinSuiteProxy() {
this(QyApi.DEFAULT_TOKEN_STORAGER);
this(Weixin4jSettings.DEFAULT_TOKEN_PATH);
}
/**
*
* @param suiteId
* 应用ID
* @param suiteSecret
* 应用secret
* @throws WeixinException
* @param tokenPath
* 使用文件存储token的保存路径
*/
public WeixinSuiteProxy(String suiteId, String suiteSecret) {
this(QyApi.DEFAULT_TOKEN_STORAGER, null, null, new WeixinAccount(
suiteId, suiteSecret));
public WeixinSuiteProxy(String tokenPath) {
this(new FileTokenStorager(tokenPath));
}
/**
@ -56,7 +55,8 @@ public class WeixinSuiteProxy {
* token存储
*/
public WeixinSuiteProxy(TokenStorager tokenStorager) {
this(tokenStorager, QyApi.DEFAULT_WEIXIN_ACCOUNT);
this(tokenStorager, JSON.parseObject(
Weixin4jConfigUtil.getValue("account"), WeixinQyAccount.class));
}
/**
@ -76,14 +76,14 @@ public class WeixinSuiteProxy {
*
* @param tokenStorager
* token存储
* @param corpId
* @param providerCorpId
* 服务商的企业号ID <font color="red">使用服务商API时必填项</font>
* @param providerSecret
* 服务商secret <font color="red">使用服务商API时必填项</font>
* @param suites
* 套件信息 <font color="red">使用套件API时必填项</font>
*/
public WeixinSuiteProxy(TokenStorager tokenStorager, String corpId,
public WeixinSuiteProxy(TokenStorager tokenStorager, String providerCorpId,
String providerSecret, WeixinAccount... suites) {
if (suites != null) {
this.suiteMap = new HashMap<String, SuiteApi>();
@ -94,11 +94,11 @@ public class WeixinSuiteProxy {
this.suiteMap.put(null, suiteMap.get(suites[0].getId()));
}
}
if (StringUtil.isNotBlank(corpId)
if (StringUtil.isNotBlank(providerCorpId)
&& StringUtil.isNotBlank(providerSecret)) {
this.providerApi = new ProviderApi(new TokenHolder(
new WeixinProviderTokenCreator(corpId, providerSecret),
tokenStorager));
new WeixinProviderTokenCreator(providerCorpId,
providerSecret), tokenStorager));
}
}
@ -160,5 +160,5 @@ public class WeixinSuiteProxy {
return providerApi.getLoginUrl(corpId, targetType, agentId);
}
public final static String VERSION = "1.6.6";
public final static String VERSION = "1.6.7";
}

View File

@ -51,8 +51,6 @@ import com.foxinmy.weixin4j.util.IOUtil;
import com.foxinmy.weixin4j.util.ObjectId;
import com.foxinmy.weixin4j.util.RegexUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
import com.foxinmy.weixin4j.util.Weixin4jConst;
import com.foxinmy.weixin4j.util.WeixinErrorUtil;
/**
@ -199,17 +197,17 @@ public class MediaApi extends QyApi {
* 企业应用Id(<font color="red">大于0时视为获取永久媒体文件</font>)
* @param mediaId
* 存储在微信服务器上的媒体标识
* @return 写入硬盘后的文件对象,存储路径见weixin4j.properties配置
* @param mediaPath
* 媒体素材保存路径
* @return 写入硬盘后的文件对象
* @throws WeixinException
* @see com.foxinmy.weixin4j.type.MediaType
* @see {@link #downloadMedia(int,String)}
*/
public File downloadMediaFile(int agentid, String mediaId)
public File downloadMediaFile(int agentid, String mediaId, String mediaPath)
throws WeixinException {
String media_path = Weixin4jConfigUtil.getValue("media.path",
Weixin4jConst.DEFAULT_MEDIA_PATH);
final String prefixName = String.format("%d_%s.", agentid, mediaId);
File[] files = new File(media_path).listFiles(new FilenameFilter() {
File[] files = new File(mediaPath).listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.startsWith(prefixName);
@ -219,7 +217,7 @@ public class MediaApi extends QyApi {
return files[0];
}
MediaDownloadResult result = downloadMedia(agentid, mediaId);
File file = new File(media_path + File.separator + result.getFileName());
File file = new File(mediaPath + File.separator + result.getFileName());
OutputStream os = null;
try {
if (file.createNewFile()) {

View File

@ -4,6 +4,7 @@ import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinAccount;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
/**
@ -21,6 +22,15 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
* href="http://qydev.weixin.qq.com/wiki/index.php?title=%E7%AC%AC%E4%B8%89%E6%96%B9%E5%BA%94%E7%94%A8%E6%8E%88%E6%9D%83">企业号第三方套件应用授权说明</a>
*/
public class OauthApi extends QyApi {
private final WeixinAccount account;
public OauthApi() {
this(Weixin4jConfigUtil.getWeixinAccount());
}
public OauthApi(WeixinAccount account) {
this.account = account;
}
/**
* 企业号用户身份授权
@ -30,7 +40,7 @@ public class OauthApi extends QyApi {
* @return 请求授权的URL
*/
public String getUserAuthorizeURL() {
String corpId = DEFAULT_WEIXIN_ACCOUNT.getId();
String corpId = account.getId();
String redirectUri = Weixin4jConfigUtil
.getValue("user.oauth.redirect.uri");
return getUserAuthorizeURL(corpId, redirectUri, "state");
@ -69,7 +79,7 @@ public class OauthApi extends QyApi {
* @return 请求授权的URL
*/
public String getThirdAuthorizeURL() {
String corpId = DEFAULT_WEIXIN_ACCOUNT.getId();
String corpId = account.getId();
String redirectUri = Weixin4jConfigUtil
.getValue("third.oauth.redirect.uri");
return getThirdAuthorizeURL(corpId, redirectUri, "state");

View File

@ -2,10 +2,7 @@ package com.foxinmy.weixin4j.qy.api;
import java.util.ResourceBundle;
import com.alibaba.fastjson.JSON;
import com.foxinmy.weixin4j.api.BaseApi;
import com.foxinmy.weixin4j.qy.model.WeixinQyAccount;
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
/**
* 微信企业号API
@ -20,16 +17,9 @@ import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
public class QyApi extends BaseApi {
private final static ResourceBundle WEIXIN_BUNDLE;
/**
* 默认使用weixin4j.properties文件中的企业号信息
*/
public final static WeixinQyAccount DEFAULT_WEIXIN_ACCOUNT;
static {
WEIXIN_BUNDLE = ResourceBundle
.getBundle("com/foxinmy/weixin4j/qy/api/weixin");
DEFAULT_WEIXIN_ACCOUNT = JSON.parseObject(
Weixin4jConfigUtil.getValue("account"), WeixinQyAccount.class);
}
@Override

View File

@ -47,9 +47,6 @@ public class SuiteApi extends QyApi {
*
* @param suiteTicketHolder
* 套件ticket存取
* @param tokenStorager
* 应用token存储器
* @throws WeixinException
*/
public SuiteApi(SuiteTicketHolder suiteTicketHolder) {
this.suiteTicketHolder = suiteTicketHolder;

View File

@ -1,26 +1,29 @@
# \u6d4b\u8bd5\u4e4b\u7528 \u6b63\u5f0f\u73af\u5883\u4e0bcopy\u4e00\u4efd\u5230classpath
# \u4f01\u4e1a\u53f7\u4fe1\u606f
weixin4j.account={"id":"id","secret":"secret",\
weixin4j.account={"id":"wx5132afc5da26d661","secret":"GsnKLVDI1pWArdB60Ze4iP2cwFvcW5KCAs2vLJldipilmSYxtbkcAiBcGSHHvu_I",\
"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)",\
"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",\
"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",\
"paySignKey":"\u5fae\u4fe1\u652f\u4ed8\u4e2d\u8c03\u7528API\u7684\u5bc6\u94a5 \u5fae\u4fe1\u652f\u4ed8\u65f6\u9700\u8981\u586b\u5165"}
# \u4f7f\u7528FileTokenStorager\u65f6token\u7684\u5b58\u653e\u8def\u5f84
# \u4f7f\u7528FileTokenStorager\u65f6token\u7684\u5b58\u653e\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_TOKEN_PATH)
weixin4j.token.path=/tmp/weixin4j/token
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84
# \u5a92\u4f53\u6587\u4ef6\u4fdd\u5b58\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_MEDIA_PATH)
weixin4j.media.path=/tmp/weixin4j/media
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84
# \u5bf9\u8d26\u5355\u4fdd\u5b58\u8def\u5f84(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_BILL_PATH)
weixin4j.bill.path=/tmp/weixin4j/bill
# ca\u8bc1\u4e66\u5b58\u653e\u7684\u5b8c\u6574\u8def\u5f84 (V2\u7248\u672c\u540e\u7f00\u4e3a*.pfx,V3\u7248\u672c\u540e\u7f00\u4e3a*.p12)
weixin4j.certificate.file=/tmp/weixin4j/xxxxx.p12
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199
# classpath\u8def\u5f84\u4e0b\u53ef\u4ee5\u8fd9\u4e48\u5199(\u5982\u679c\u4e0d\u586b\u5219\u9ed8\u8ba4\u4e3aWeixin4jConst#DEFAULT_CAFILE_PATH)
# weixin4j.certificate.file=classpath:xxxxx.pfx
# \u4f01\u4e1a\u53f7\u7528\u6237\u8eab\u4efd\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url
# \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=
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u63d0\u4f9b\u5546\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
weixin4j.third.oauth.redirect.uri=
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u5e94\u7528\u5957\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url
# \u4f01\u4e1a\u53f7\u7b2c\u4e09\u65b9\u5e94\u7528\u5957\u4ef6\u6388\u6743\u540e\u91cd\u5b9a\u5411\u7684url(\u5728\u4f7f\u7528OauthApi\u65f6\u586b\u5199)
weixin4j.suite.oauth.redirect.uri=

View File

@ -47,7 +47,8 @@ public class MediaTest extends TokenTest {
File file = mediaApi
.downloadMediaFile(
0,
"1y0NWE5ochkfOoiyJsPwQ3Wg7gsyRHNp8SveqhGXY_1rOH7OcOMwfHDg8KH6s88osq59AfS3BX-MBBKvERB7Bvw");
"1y0NWE5ochkfOoiyJsPwQ3Wg7gsyRHNp8SveqhGXY_1rOH7OcOMwfHDg8KH6s88osq59AfS3BX-MBBKvERB7Bvw",
"/tmp/weixin4j/media");
Assert.assertTrue(file.exists());
}

View File

@ -28,8 +28,8 @@ public class TokenTest {
WeixinAccount weixinAccount = Weixin4jConfigUtil.getWeixinAccount();
tokenHolder = new TokenHolder(new WeixinTokenCreator(
weixinAccount.getId(), weixinAccount.getSecret()),
new FileTokenStorager(Weixin4jConfigUtil.getValue(
"token.path", "/tmp/weixin4j/token")));
new FileTokenStorager(Weixin4jConfigUtil.getValue("token.path",
"/tmp/weixin4j/token")));
}
@Test

View File

@ -5,10 +5,10 @@
<parent>
<groupId>com.foxinmy</groupId>
<artifactId>weixin4j</artifactId>
<version>1.6.6</version>
<version>1.6.7</version>
</parent>
<artifactId>weixin4j-server</artifactId>
<version>1.1.5</version>
<version>1.1.6</version>
<name>weixin4j-server</name>
<url>https://github.com/foxinmy/weixin4j/tree/master/weixin4j-server</url>
<description>微信消息netty服务器</description>

View File

@ -315,5 +315,5 @@ public final class WeixinServerBootstrap {
return this;
}
public final static String VERSION = "1.1.5";
public final static String VERSION = "1.1.6";
}