新增企业付款查询接口 & 对多个公众号的接入支持
This commit is contained in:
@@ -112,4 +112,8 @@
|
||||
|
||||
* 2015-06-04
|
||||
|
||||
+ 新增查询红包接口
|
||||
+ 新增查询红包接口
|
||||
|
||||
* 2015-06-23
|
||||
|
||||
+ 新增企业付款查询接口
|
||||
@@ -18,6 +18,7 @@ import com.foxinmy.weixin4j.mp.payment.coupon.CouponResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.coupon.CouponStock;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.MPPayment;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentRecord;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.Redpacket;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketRecord;
|
||||
@@ -30,7 +31,6 @@ import com.foxinmy.weixin4j.mp.type.IdType;
|
||||
import com.foxinmy.weixin4j.mp.type.RefundType;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenStorager;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
|
||||
/**
|
||||
* 微信支付接口实现
|
||||
@@ -239,9 +239,8 @@ public class WeixinPayProxy {
|
||||
IdQuery idQuery, String outRefundNo, double totalFee,
|
||||
double refundFee, String opUserId, String opUserPasswd)
|
||||
throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return refundV2(caFile, idQuery, outRefundNo, totalFee, refundFee,
|
||||
opUserId, opUserPasswd);
|
||||
return refundV2(PayApi.DEFAULT_CA_FILE, idQuery, outRefundNo, totalFee,
|
||||
refundFee, opUserId, opUserPasswd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,9 +357,8 @@ public class WeixinPayProxy {
|
||||
public com.foxinmy.weixin4j.mp.payment.v3.RefundResult refundV3(
|
||||
IdQuery idQuery, String outRefundNo, double totalFee,
|
||||
double refundFee, String opUserId) throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return pay3Api.refund(caFile, idQuery, outRefundNo, totalFee,
|
||||
refundFee, CurrencyType.CNY, opUserId);
|
||||
return pay3Api.refund(PayApi.DEFAULT_CA_FILE, idQuery, outRefundNo,
|
||||
totalFee, refundFee, CurrencyType.CNY, opUserId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -444,8 +442,7 @@ public class WeixinPayProxy {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public ApiResult reverse(IdQuery idQuery) throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return payApi.reverse(caFile, idQuery);
|
||||
return payApi.reverse(PayApi.DEFAULT_CA_FILE, idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -552,9 +549,8 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
|
||||
String openId) throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return couponApi.sendCoupon(caFile, couponStockId, partnerTradeNo,
|
||||
openId, null);
|
||||
return couponApi.sendCoupon(PayApi.DEFAULT_CA_FILE, couponStockId,
|
||||
partnerTradeNo, openId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -618,8 +614,7 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public RedpacketSendResult sendRedpack(Redpacket redpacket)
|
||||
throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return cashApi.sendRedpack(caFile, redpacket);
|
||||
return cashApi.sendRedpack(PayApi.DEFAULT_CA_FILE, redpacket);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -648,8 +643,7 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public RedpacketRecord queryRedpack(String outTradeNo)
|
||||
throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return cashApi.queryRedpack(caFile, outTradeNo);
|
||||
return cashApi.queryRedpack(PayApi.DEFAULT_CA_FILE, outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -679,7 +673,35 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public MPPaymentResult mpPayment(MPPayment mpPayment)
|
||||
throws WeixinException {
|
||||
File caFile = new File(ConfigUtil.getClassPathValue("ca_file"));
|
||||
return cashApi.mpPayment(caFile, mpPayment);
|
||||
return cashApi.mpPayment(PayApi.DEFAULT_CA_FILE, mpPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
||||
*
|
||||
* @param caFile
|
||||
* 证书文件(V3版本后缀为*.p12)
|
||||
* @param outTradeNo
|
||||
* 商户调用企业付款API时使用的商户订单号
|
||||
* @return 付款记录
|
||||
* @see com.foxinmy.weixin4j.mp.api.CashApi
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.MPPaymentRecord
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MPPaymentRecord mpPaymentQuery(File caFile, String outTradeNo)
|
||||
throws WeixinException {
|
||||
return cashApi.mpPaymentQuery(caFile, outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业付款查询采用properties中配置的ca文件
|
||||
*
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinPayProxy#mpPaymentQuery(File, String)}
|
||||
*/
|
||||
public MPPaymentRecord mpPaymentQuery(String outTradeNo)
|
||||
throws WeixinException {
|
||||
return cashApi.mpPaymentQuery(PayApi.DEFAULT_CA_FILE, outTradeNo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.mp.model.WeixinMpAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.MPPayment;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentRecord;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.MPPaymentResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.Redpacket;
|
||||
import com.foxinmy.weixin4j.mp.payment.v3.RedpacketRecord;
|
||||
@@ -194,4 +195,52 @@ public class CashApi extends MpApi {
|
||||
.replaceFirst("</mchid>", "</mch_id>");
|
||||
return XmlStream.fromXML(text, MPPaymentResult.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
|
||||
*
|
||||
* @param caFile
|
||||
* 证书文件(V3版本后缀为*.p12)
|
||||
* @param outTradeNo
|
||||
* 商户调用企业付款API时使用的商户订单号
|
||||
* @return 付款记录
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v3.MPPaymentRecord
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/mch_pay.php?chapter=14_3">企业付款查询</a>
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public MPPaymentRecord mpPaymentQuery(File caFile, String outTradeNo)
|
||||
throws WeixinException {
|
||||
JSONObject obj = new JSONObject();
|
||||
obj.put("nonce_str", RandomUtil.generateString(16));
|
||||
obj.put("mch_id", weixinAccount.getMchId());
|
||||
obj.put("appid", weixinAccount.getId());
|
||||
obj.put("partner_trade_no", outTradeNo);
|
||||
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
obj.put("sign", sign);
|
||||
String param = XmlStream.map2xml(obj);
|
||||
String mp_payquery_uri = getRequestUri("mp_payquery_uri");
|
||||
WeixinResponse response = null;
|
||||
InputStream ca = null;
|
||||
try {
|
||||
ca = new FileInputStream(caFile);
|
||||
SSLHttpClinet request = new SSLHttpClinet(weixinAccount.getMchId(),
|
||||
ca);
|
||||
response = request.post(mp_payquery_uri, param);
|
||||
} catch (WeixinException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
throw new WeixinException(e.getMessage());
|
||||
} finally {
|
||||
if (ca != null) {
|
||||
try {
|
||||
ca.close();
|
||||
} catch (IOException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
return response.getAsObject(new TypeReference<MPPaymentRecord>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,13 @@ import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
* @see <a href="http://mp.weixin.qq.com/wiki/index.php">api文档</a>
|
||||
*/
|
||||
public class MpApi extends BaseApi {
|
||||
|
||||
|
||||
private final static ResourceBundle WEIXIN_BUNDLE;
|
||||
/**
|
||||
* 默认使用weixin4j.properties文件中的公众号信息
|
||||
*/
|
||||
public final static WeixinMpAccount DEFAULT_WEIXIN_ACCOUNT;
|
||||
|
||||
|
||||
static {
|
||||
WEIXIN_BUNDLE = ResourceBundle
|
||||
.getBundle("com/foxinmy/weixin4j/mp/api/weixin");
|
||||
|
||||
@@ -17,6 +17,7 @@ import com.foxinmy.weixin4j.mp.type.BillType;
|
||||
import com.foxinmy.weixin4j.mp.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.mp.type.SignType;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.util.ConfigUtil;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
/**
|
||||
@@ -31,6 +32,12 @@ import com.foxinmy.weixin4j.util.DateUtil;
|
||||
*/
|
||||
public abstract class PayApi extends MpApi {
|
||||
|
||||
/**
|
||||
* 默认的证书文件
|
||||
*/
|
||||
public final static File DEFAULT_CA_FILE = new File(
|
||||
ConfigUtil.getClassPathValue("ca_file"));
|
||||
|
||||
protected final WeixinMpAccount weixinAccount;
|
||||
protected final TokenHolder tokenHolder;
|
||||
|
||||
@@ -93,8 +100,9 @@ public abstract class PayApi extends MpApi {
|
||||
throws WeixinException {
|
||||
String payfeedback_update_uri = getRequestUri("payfeedback_update_uri");
|
||||
Token token = tokenHolder.getToken();
|
||||
WeixinResponse response = weixinClient.get(String.format(payfeedback_update_uri,
|
||||
token.getAccessToken(), openId, feedbackId));
|
||||
WeixinResponse response = weixinClient.get(String.format(
|
||||
payfeedback_update_uri, token.getAccessToken(), openId,
|
||||
feedbackId));
|
||||
return response.getAsJsonResult();
|
||||
}
|
||||
|
||||
|
||||
@@ -180,4 +180,6 @@ redpack_send_uri={mch_base_url}/mmpaymkttransfers/sendredpack
|
||||
# \u67e5\u8be2\u73b0\u91d1\u7ea2\u5305
|
||||
redpack_query_uri={mch_base_url}/mmpaymkttransfers/gethbinfo
|
||||
# \u4f01\u4e1a\u5411\u4e2a\u4eba\u4ed8\u6b3e
|
||||
mp_payment_uri={mch_base_url}/mmpaymkttransfers/promotion/transfers
|
||||
mp_payment_uri={mch_base_url}/mmpaymkttransfers/promotion/transfers
|
||||
# \u4f01\u4e1a\u4ed8\u6b3e\u67e5\u8be2
|
||||
mp_payquery_uri={mch_base_url}/mmpaymkttransfers/gettransferinfo
|
||||
@@ -0,0 +1,193 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v3;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.mp.type.MPPaymentCheckNameType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
|
||||
/**
|
||||
* 企业付款记录
|
||||
*
|
||||
* @className MPPaymentRecord
|
||||
* @author jy
|
||||
* @date 2015年6月23日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
public class MPPaymentRecord extends ApiResult {
|
||||
|
||||
private static final long serialVersionUID = -1926873539419750498L;
|
||||
|
||||
/**
|
||||
* 微信订单订单号
|
||||
*/
|
||||
@JSONField(name = "detail_id")
|
||||
@XmlElement(name = "detail_id")
|
||||
private String transactionId;
|
||||
/**
|
||||
* 商户订单号
|
||||
*/
|
||||
@JSONField(name = "partner_trade_no")
|
||||
@XmlElement(name = "partner_trade_no")
|
||||
private String outTradeNo;
|
||||
/**
|
||||
* 交易状态 SUCCESS:转账成功 FAILED:转账失败
|
||||
*/
|
||||
@JSONField(name = "status")
|
||||
@XmlElement(name = "status")
|
||||
private String transactionStatus;
|
||||
/**
|
||||
* 如果失败则应该有原因
|
||||
*/
|
||||
@JSONField(name = "reason")
|
||||
@XmlElement(name = "reason")
|
||||
private String failureReason;
|
||||
/**
|
||||
* 收款用户openid
|
||||
*/
|
||||
private String openid;
|
||||
/**
|
||||
* 收款用户姓名
|
||||
*/
|
||||
@JSONField(name = "transfer_name")
|
||||
@XmlElement(name = "transfer_name")
|
||||
private String transferName;
|
||||
/**
|
||||
* 付款金额(单位为分)
|
||||
*/
|
||||
@JSONField(name = "payment_amount")
|
||||
@XmlElement(name = "payment_amount")
|
||||
private int paymentAmount;
|
||||
/**
|
||||
* 转账时间
|
||||
*/
|
||||
@JSONField(name = "transfer_time")
|
||||
@XmlElement(name = "transfer_time")
|
||||
private String transferTime;
|
||||
/**
|
||||
* 校验用户姓名选项
|
||||
*
|
||||
* @see com.foxinmy.weixin4j.mp.type.MPPaymentCheckNameType
|
||||
*/
|
||||
@XmlElement(name = "check_name")
|
||||
@JSONField(name = "check_name")
|
||||
private MPPaymentCheckNameType checkNameType;
|
||||
/**
|
||||
* 企业付款描述信息
|
||||
*/
|
||||
private String desc;
|
||||
/**
|
||||
* 实名验证结果 PASS:通过 FAILED:不通过
|
||||
*/
|
||||
@JSONField(name = "check_name_result")
|
||||
@XmlElement(name = "check_name_result")
|
||||
private String checkNameResult;
|
||||
|
||||
protected MPPaymentRecord() {
|
||||
// jaxb required
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public String getOutTradeNo() {
|
||||
return outTradeNo;
|
||||
}
|
||||
|
||||
public String getTransactionStatus() {
|
||||
return transactionStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化交易状态
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public boolean getFormatTransactionStatus() {
|
||||
return "success".equalsIgnoreCase(transactionStatus);
|
||||
}
|
||||
|
||||
public String getFailureReason() {
|
||||
return failureReason;
|
||||
}
|
||||
|
||||
public String getOpenid() {
|
||||
return openid;
|
||||
}
|
||||
|
||||
public String getTransferName() {
|
||||
return transferName;
|
||||
}
|
||||
|
||||
public int getPaymentAmount() {
|
||||
return paymentAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* <font color="red">调用接口获取单位为分,get方法转换为元方便使用</font>
|
||||
*
|
||||
* @return 元单位
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public double getFormatPaymentAmount() {
|
||||
return paymentAmount / 100d;
|
||||
}
|
||||
|
||||
public String getTransferTime() {
|
||||
return transferTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化转账时间
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public Date getFormatTransferTime() {
|
||||
return DateUtil.parse2yyyyMMddHHmmss(transferTime);
|
||||
}
|
||||
|
||||
public MPPaymentCheckNameType getCheckNameType() {
|
||||
return checkNameType;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public String getCheckNameResult() {
|
||||
return checkNameResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化交易状态
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@JSONField(serialize = false)
|
||||
public boolean getFormatCheckNameResult() {
|
||||
return "pass".equalsIgnoreCase(checkNameResult);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MPPaymentRecord [transactionId=" + transactionId
|
||||
+ ", outTradeNo=" + outTradeNo + ", transactionStatus="
|
||||
+ getFormatTransactionStatus() + ", failureReason="
|
||||
+ failureReason + ", openid=" + openid + ", transferName="
|
||||
+ transferName + ", paymentAmount=" + getFormatPaymentAmount()
|
||||
+ ", transferTime=" + transferTime + ", checkNameType="
|
||||
+ checkNameType + ", desc=" + desc + ", checkNameResult="
|
||||
+ getFormatCheckNameResult() + ", " + super.toString() + "]";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user