微信支付服务端自动对账
支付及对账流程链接
自动对账说明
微信支付后每天的商户系统的自动对账还是比较繁琐的,所谓自动对账实际上就是将商户某天交易成功的订单信息与微信某天的账单进行逐一匹配的过程。其涉及到三个专业名词短款、长款和金额不一致,以下对其进行解释:
**短款:**平台资金流有,而支付公司没有的差异,可能是因为支付公司日切早于平台的账务,一旦出现,会出现短款的现象,银行日切导致段差异,会在下一天与银行的勾对中,将此笔差异勾对上,如果是非日切导致的原因,就需要深入追查或让支付公司补款了
**长款:**平台资金流没有,而第三方支付有的差异。可能原因如下:
1)第三方支付日切晚于平台订单账务;
2)平台处理订单时的掉单。一旦出现,则会出现长款(即银行不应该结算而实际结算)的现象,对于因日切导致的差异,在第二天的对账中系统会自动解决,其他原因的,需要技术排查。
**金额不一致:**本地已支付,支付渠道已支付,但是金额不同,这个需要人工来逐一核查。
注意:微信后台是每天九点会生成前一天的账单,故商户后台处理对账下载账单逻辑时建议定时任务定在每天十天再去处理
本人所写自动对账JAVA代码
public void downloadWechatBill() throws Exception {
cachedThreadPool.execute(() -> {
try{
Calendar ca = Calendar.getInstance();
ca.setTime(new Date());
ca.add(Calendar.DATE, -1);
SimpleDateFormat dateFormat= new SimpleDateFormat("yyyyMMdd");
SimpleDateFormat dateFormatStr= new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat dateFormatTime= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Map<Object, Object> map = new HashMap<>();
map.put("appid", APPID);
map.put("mch_id", MCHID);
map.put("nonce_str", RandomUtil.getRandomStringByLength(32));
map.put("bill_date", dateFormat.format(ca.getTime()));
map.put("bill_type", "ALL");
map.put("tar_type", "GZIP");
//根据算法生成签名
String sign = Md5EncryptUtil.getWechatSign(map, KEY_APPSECRET);
map.put("sign", sign);
//将参数转换成xml
String paramXML = XMLParser.converterPayPalm(map);
// 下载文件
LOG.info("【微信对账业务】-开始下载账单");
Boolean downloadSuccess = downloadFile(DOWNLOADB_BILL_URL, FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType()+dateFormat.format(ca.getTime())+".gzip",paramXML);
if(downloadSuccess){
LOG.info("【微信对账业务】-下载账单成功");
//如所传日期有账单并下载成功,刚将其上传至ftp服务器做备份
FileInputStream in=new FileInputStream(new File(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType()+dateFormat.format(ca.getTime())+".gzip"));
uploadFile(FILE_FTP_HOST, Integer.valueOf(FILE_FTP_PORT), FILE_FTP_USERNAME, FILE_FTP_PASSWORD, FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType(), dateFormat.format(ca.getTime())+".gzip", in);
//从服务器所存储账单的路径下读取账单信息并开始对账服务
List<String[]> billInfoArr = this.readGzipBillInfo(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType()+dateFormat.format(ca.getTime())+".gzip");
List<Map<String, Object>> saveDiffShortList = new ArrayList<>();
List<Map<String, Object>> saveDiffLongList = new ArrayList<>();
if(billInfoArr == null){
LOG.info("【微信对账业务】-总金额相等无须逐一对账");
//无须对账将服务器中的文件删除
this.deleteServerFile(FileCatalogEnum.WECHAT_DOWNLOAD_BILL_FILE.getType()+dateFormat.format(ca.getTime())+".gzip");
return;
}
if(billInfoArr.size()>0){
//此处为对账业务逻辑处理
//获取下载账单日期的商户后台的当日订单
List<PaymentTradePO> paymentTradePOList = iWechatPayDao.getOrderByBillDate(dateFormatStr.format(ca.getTime()));
LOG.info("【微信对账业务】-开始对账");
//首先以商户后台的订单为主去比对微信的订单,如商户有订单而微信没有则标记为短款,如两者都有但金额不一致则标记为金额不一致
for(PaymentTradePO tradePO : paymentTradePOList){
int count = 1;
String tradeId = tradePO.getTradeId();
String account = tradePO.getPrice().setScale(2, BigDecimal.ROUND_HALF_UP).toString();
for(String[] strArr : billInfoArr){
Date tradeTime = dateFormatTime.parse(strArr[0]);
String appid = s