diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java index a6dd6654..004cd5bc 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/WxMpPayService.java @@ -240,9 +240,10 @@ public interface WxMpPayService { * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。 * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 * - * @param productId 产品Id + * + * @param productId 产品Id * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 - * @param logoFile 商户logo图片的文件对象,可以为空 + * @param logoFile 商户logo图片的文件对象,可以为空 * @return 生成的二维码的字节数组 */ byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength); @@ -254,8 +255,9 @@ public interface WxMpPayService { * 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。 * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 * - * @param codeUrl 微信返回的交易会话的二维码链接 - * @param logoFile 商户logo图片的文件对象,可以为空 + * + * @param codeUrl 微信返回的交易会话的二维码链接 + * @param logoFile 商户logo图片的文件对象,可以为空 * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 * @return 生成的二维码的字节数组 */ @@ -273,4 +275,25 @@ public interface WxMpPayService { * */ void report(WxPayReportRequest request) throws WxErrorException; + + /** + *
+ * 下载对账单 + * 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。 + * 注意: + * 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED; + * 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取; + * 3、对账单中涉及金额的字段单位为“元”。 + * 4、对账单接口只能下载三个月以内的账单。 + * 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill + * 详情请见: 下载对账单 + *+ * + * @param billDate 对账单日期 bill_date 下载对账单的日期,格式:20140603 + * @param billType 账单类型 bill_type ALL,返回当日所有订单信息,默认值,SUCCESS,返回当日成功支付的订单,REFUND,返回当日退款订单 + * @param tarType 压缩账单 tar_type 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 + * @param deviceInfo 设备号 device_info 非必传参数,终端设备号 + * @return 保存到本地的临时文件 + */ + File downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxErrorException; } diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java index b4813a33..b0ccacd9 100644 --- a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImpl.java @@ -41,6 +41,7 @@ public class WxMpPayServiceImpl implements WxMpPayService { private static final String PAY_BASE_URL = "https://api.mch.weixin.qq.com"; private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"}; private static final String[] REFUND_ACCOUNT = new String[]{"REFUND_SOURCE_RECHARGE_FUNDS", "REFUND_SOURCE_UNSETTLED_FUNDS"}; + private static final String[] BILL_TYPE = new String[]{"ALL","REFUND","SUCCESS"};; private final Logger log = LoggerFactory.getLogger(this.getClass()); private WxMpService wxMpService; @@ -121,6 +122,19 @@ public class WxMpPayServiceImpl implements WxMpPayService { } } + private void checkParameters(WxPayDownloadBillRequest request) throws WxErrorException { + BeanUtils.checkRequiredFields(request); + + if (StringUtils.isNotBlank(request.getTarType()) && !"GZIP".equals(request.getTarType())) { + throw new IllegalArgumentException("tar_type值如果存在,只能为GZIP"); + } + + if ( !ArrayUtils.contains(BILL_TYPE, request.getBillType())) { + throw new IllegalArgumentException("bill_tpye目前必须为" + Arrays.toString(BILL_TYPE) + "其中之一,实际值:" + request.getBillType()); + } + + } + private void checkParameters(WxPayRefundRequest request) throws WxErrorException { BeanUtils.checkRequiredFields(request); @@ -373,6 +387,26 @@ public class WxMpPayServiceImpl implements WxMpPayService { this.checkResult(result); } + @Override + public File downloadBill(String billDate, String billType, String tarType, String deviceInfo) throws WxErrorException { + WxPayDownloadBillRequest request = new WxPayDownloadBillRequest(); + this.initRequest(request); + request.setBillType(billType); + request.setBillDate(billDate); + request.setTarType(tarType); + request.setDeviceInfo(deviceInfo); + this.checkParameters(request); + request.setSign(this.createSign(request)); + + String url = this.getPayBaseUrl() + "/pay/downloadbill"; + //TODO 返回的内容可能是文件流,也有可能是xml,需要区分对待 + String responseContent = this.wxMpService.post(url, request.toXML()); + + WxPayCommonResult result = WxPayBaseResult.fromXML(responseContent, WxPayCommonResult.class); + this.checkResult(result); + return null; + } + private String executeRequest(String url, String requestStr) throws WxErrorException { HttpPost httpPost = new HttpPost(url); if (this.wxMpService.getHttpProxy() != null) { diff --git a/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayDownloadBillRequest.java b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayDownloadBillRequest.java new file mode 100644 index 00000000..9e1ab4dc --- /dev/null +++ b/weixin-java-mp/src/main/java/me/chanjar/weixin/mp/bean/pay/request/WxPayDownloadBillRequest.java @@ -0,0 +1,123 @@ +package me.chanjar.weixin.mp.bean.pay.request; + +import com.thoughtworks.xstream.annotations.XStreamAlias; +import me.chanjar.weixin.common.annotation.Required; + +/** + *
+ * 微信支付下载对账单请求参数类 + * Created by Binary Wang on 2017-01-11. + * @author binarywang(Binary Wang) + *+ */ +@XStreamAlias("xml") +public class WxPayDownloadBillRequest extends WxPayBaseRequest { + /** + *
+ * 设备号 + * device_info + * 否 + * String(32) + * 13467007045764 + * 终端设备号 + *+ */ + @XStreamAlias("device_info") + private String deviceInfo; + + /** + *
+ * 签名类型 + * sign_type + * 否 + * String(32) + * HMAC-SHA256 + * 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5 + *+ */ + @XStreamAlias("sign_type") + private String signType; + + /** + *
+ * 账单类型 + * bill_type + * 是 + * ALL + * String(8) + * --ALL,返回当日所有订单信息,默认值 + * --SUCCESS,返回当日成功支付的订单 + * --REFUND,返回当日退款订单 + *+ */ + @Required + @XStreamAlias("bill_type") + private String billType; + + /** + *
+ * 对账单日期 + * bill_date + * 是 + * String(8) + * 20140603 + * 下载对账单的日期,格式:20140603 + *+ */ + @Required + @XStreamAlias("bill_date") + private String billDate; + + /** + *
+ * 压缩账单 + * tar_type + * 否 + * String(8) + * GZIP + * 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 + *+ */ + @XStreamAlias("tar_type") + private String tarType; + + public String getDeviceInfo() { + return deviceInfo; + } + + public void setDeviceInfo(String deviceInfo) { + this.deviceInfo = deviceInfo; + } + + public String getSignType() { + return signType; + } + + public void setSignType(String signType) { + this.signType = signType; + } + + public String getBillType() { + return billType; + } + + public void setBillType(String billType) { + this.billType = billType; + } + + public String getBillDate() { + return billDate; + } + + public void setBillDate(String billDate) { + this.billDate = billDate; + } + + public String getTarType() { + return tarType; + } + + public void setTarType(String tarType) { + this.tarType = tarType; + } +} diff --git a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java index 783bdb86..f46765c7 100644 --- a/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java +++ b/weixin-java-mp/src/test/java/me/chanjar/weixin/mp/api/impl/WxMpPayServiceImplTest.java @@ -8,9 +8,9 @@ import me.chanjar.weixin.mp.api.WxMpService; import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage; import me.chanjar.weixin.mp.bean.pay.request.*; import me.chanjar.weixin.mp.bean.pay.result.*; -import org.testng.annotations.Guice; -import org.testng.annotations.Test; +import org.testng.annotations.*; +import java.io.File; import java.nio.file.Files; import java.nio.file.Path; @@ -25,6 +25,7 @@ import static org.testng.Assert.*; @Test @Guice(modules = ApiTestModule.class) public class WxMpPayServiceImplTest { + @Inject protected WxMpService wxService; @@ -33,6 +34,14 @@ public class WxMpPayServiceImplTest { } + @Test + public void testDownloadBill() throws Exception { + File file = this.wxService.getPayService().downloadBill("20170101","ALL","GZIP","1111111"); + assertNotNull(file); + //必填字段为空时,抛出异常 + this.wxService.getPayService().downloadBill("","","",null); + } + @Test public void testReport() throws Exception { WxPayReportRequest request = new WxPayReportRequest();