| @@ -240,9 +240,10 @@ public interface WxMpPayService { | |||||
| * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。 | * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。 | ||||
| * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 | * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4 | ||||
| * </pre> | * </pre> | ||||
| * @param productId 产品Id | |||||
| * | |||||
| * @param productId 产品Id | |||||
| * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 | * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 | ||||
| * @param logoFile 商户logo图片的文件对象,可以为空 | |||||
| * @param logoFile 商户logo图片的文件对象,可以为空 | |||||
| * @return 生成的二维码的字节数组 | * @return 生成的二维码的字节数组 | ||||
| */ | */ | ||||
| byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength); | 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 | * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5 | ||||
| * </pre> | * </pre> | ||||
| * @param codeUrl 微信返回的交易会话的二维码链接 | |||||
| * @param logoFile 商户logo图片的文件对象,可以为空 | |||||
| * | |||||
| * @param codeUrl 微信返回的交易会话的二维码链接 | |||||
| * @param logoFile 商户logo图片的文件对象,可以为空 | |||||
| * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 | * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 | ||||
| * @return 生成的二维码的字节数组 | * @return 生成的二维码的字节数组 | ||||
| */ | */ | ||||
| @@ -273,4 +275,25 @@ public interface WxMpPayService { | |||||
| * </pre> | * </pre> | ||||
| */ | */ | ||||
| void report(WxPayReportRequest request) throws WxErrorException; | void report(WxPayReportRequest request) throws WxErrorException; | ||||
| /** | |||||
| * <pre> | |||||
| * 下载对账单 | |||||
| * 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。 | |||||
| * 注意: | |||||
| * 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED; | |||||
| * 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取; | |||||
| * 3、对账单中涉及金额的字段单位为“元”。 | |||||
| * 4、对账单接口只能下载三个月以内的账单。 | |||||
| * 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill | |||||
| * 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单</a> | |||||
| * </pre> | |||||
| * | |||||
| * @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; | |||||
| } | } | ||||
| @@ -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 PAY_BASE_URL = "https://api.mch.weixin.qq.com"; | ||||
| private static final String[] TRADE_TYPES = new String[]{"JSAPI", "NATIVE", "APP"}; | 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[] 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 final Logger log = LoggerFactory.getLogger(this.getClass()); | ||||
| private WxMpService wxMpService; | 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 { | private void checkParameters(WxPayRefundRequest request) throws WxErrorException { | ||||
| BeanUtils.checkRequiredFields(request); | BeanUtils.checkRequiredFields(request); | ||||
| @@ -373,6 +387,26 @@ public class WxMpPayServiceImpl implements WxMpPayService { | |||||
| this.checkResult(result); | 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 { | private String executeRequest(String url, String requestStr) throws WxErrorException { | ||||
| HttpPost httpPost = new HttpPost(url); | HttpPost httpPost = new HttpPost(url); | ||||
| if (this.wxMpService.getHttpProxy() != null) { | if (this.wxMpService.getHttpProxy() != null) { | ||||
| @@ -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; | |||||
| /** | |||||
| * <pre> | |||||
| * 微信支付下载对账单请求参数类 | |||||
| * Created by Binary Wang on 2017-01-11. | |||||
| * @author <a href="https://github.com/binarywang">binarywang(Binary Wang)</a> | |||||
| * </pre> | |||||
| */ | |||||
| @XStreamAlias("xml") | |||||
| public class WxPayDownloadBillRequest extends WxPayBaseRequest { | |||||
| /** | |||||
| * <pre> | |||||
| * 设备号 | |||||
| * device_info | |||||
| * 否 | |||||
| * String(32) | |||||
| * 13467007045764 | |||||
| * 终端设备号 | |||||
| * </pre> | |||||
| */ | |||||
| @XStreamAlias("device_info") | |||||
| private String deviceInfo; | |||||
| /** | |||||
| * <pre> | |||||
| * 签名类型 | |||||
| * sign_type | |||||
| * 否 | |||||
| * String(32) | |||||
| * HMAC-SHA256 | |||||
| * 签名类型,目前支持HMAC-SHA256和MD5,默认为MD5 | |||||
| * </pre> | |||||
| */ | |||||
| @XStreamAlias("sign_type") | |||||
| private String signType; | |||||
| /** | |||||
| * <pre> | |||||
| * 账单类型 | |||||
| * bill_type | |||||
| * 是 | |||||
| * ALL | |||||
| * String(8) | |||||
| * --ALL,返回当日所有订单信息,默认值 | |||||
| * --SUCCESS,返回当日成功支付的订单 | |||||
| * --REFUND,返回当日退款订单 | |||||
| * </pre> | |||||
| */ | |||||
| @Required | |||||
| @XStreamAlias("bill_type") | |||||
| private String billType; | |||||
| /** | |||||
| * <pre> | |||||
| * 对账单日期 | |||||
| * bill_date | |||||
| * 是 | |||||
| * String(8) | |||||
| * 20140603 | |||||
| * 下载对账单的日期,格式:20140603 | |||||
| * </pre> | |||||
| */ | |||||
| @Required | |||||
| @XStreamAlias("bill_date") | |||||
| private String billDate; | |||||
| /** | |||||
| * <pre> | |||||
| * 压缩账单 | |||||
| * tar_type | |||||
| * 否 | |||||
| * String(8) | |||||
| * GZIP | |||||
| * 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 | |||||
| * </pre> | |||||
| */ | |||||
| @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; | |||||
| } | |||||
| } | |||||
| @@ -8,9 +8,9 @@ import me.chanjar.weixin.mp.api.WxMpService; | |||||
| import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage; | import me.chanjar.weixin.mp.api.WxXmlMpInMemoryConfigStorage; | ||||
| import me.chanjar.weixin.mp.bean.pay.request.*; | import me.chanjar.weixin.mp.bean.pay.request.*; | ||||
| import me.chanjar.weixin.mp.bean.pay.result.*; | 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.Files; | ||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||
| @@ -25,6 +25,7 @@ import static org.testng.Assert.*; | |||||
| @Test | @Test | ||||
| @Guice(modules = ApiTestModule.class) | @Guice(modules = ApiTestModule.class) | ||||
| public class WxMpPayServiceImplTest { | public class WxMpPayServiceImplTest { | ||||
| @Inject | @Inject | ||||
| protected WxMpService wxService; | 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 | @Test | ||||
| public void testReport() throws Exception { | public void testReport() throws Exception { | ||||
| WxPayReportRequest request = new WxPayReportRequest(); | WxPayReportRequest request = new WxPayReportRequest(); | ||||