业务实践系列(六):对账-微信交易账单数据解析

star2017 1年前 ⋅ 110 阅读

支付系统就一定需要对账,需要下载支付平台侧的账单与自己业务系统的交易数据时行对账。

微信账单:商户(支付通道)通过下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。

交易账单

  1. 微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致;
  2. 微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;
  3. 对账单中涉及金额的字段单位为
  4. 对账单接口只能下载三个月以内的账单;
  5. 对账单是以商户号纬度来生成的,如一个商户号与多个appid有绑定关系,则使用其中任何一个appid都可以请求下载对账单。对账单中的appid取自交易时候提交的appid,与请求下载对账单时使用的appid无关。
  6. 自2018年起入驻的商户默认是开通免充值券后的结算对账单。

账单数据

账单数据格式请查阅微信支付官方说明:下载交易账单。原始的账单的文本数据包含了 \r\n 换行符。

  1. 获取微信账单数据,成功时,数据以文本表格的方式返回,第一行为表头,后面各行为对应的字段内容,字段内容跟查询订单或退款结果一致,具体字段说明可查阅相应接口。
  2. 从第二行起,为数据记录,各参数以逗号分隔,参数前增加`符号,为标准键盘1左边键的字符,字段顺序与表头一致。
  3. 倒数第二行为订单统计标题,最后一行为统计数据。

示例数据如下:

备注:原始数据的第一行表头首字母有个特殊的符号,返回到 Postman 时显示乱码,在 IDEA 断点查看响应内容又看不到这个特殊符号,粘贴到这里又有显示。

交易时间,公众账号ID,商户号,特约商户号,设备号,微信订单号,商户订单号,用户标识,交易类型,交易状态,付款银行,货币种类,应结订单金额,代金券金额,微信退款单号,商户退款单号,退款金额,充值券退款金额,退款类型,退款状态,商品名称,商户数据包,手续费,费率,订单金额,申请退款金额,费率备注
`2020-07-22 09:35:43,`wx9c63650xxxxxxxx,`14988xxxxx,`14876xxxxx,`,`4200000xxxxxxx479,`1200131xxxxx24,`ogdwzxxxxxxxRFSRy4,`NATIVE,`SUCCESS,`OTHERS,`CNY,`0.01,`0.00,`0,`0,`0.00,`0.00,`,`,`挂号费测试,`,`0.00000,`1.00%,`0.01,`0.00,`
`2020-07-22 09:48:22,`wx9c63650xxxxxxxx,`14988xxxxx,`14876xxxxx,`,`4200000xxxxxxx479,`1200131xxxxx24,`ogdwzxxxxxxxRFSRy4,`NATIVE,`REFUND,`OTHERS,`CNY,`0.00,`0.00,`50300704872020072201640769932,`12001318629846188408832,`0.01,`0.00,`ORIGINAL,`SUCCESS,`挂号费测试,`,`0.00000,`1.00%,`0.00,`0.01,`
`2020-07-22 10:05:37,`wx9c63650xxxxxxxx,`14988xxxxx,`14876xxxxx,`,`4200000xxxxxxx708,`1200131xxxxx48,`ogdwzxxxxxxxRFSRy4,`NATIVE,`REFUND,`OTHERS,`CNY,`0.00,`0.00,`50300405062020072201639753977,`12001318634185946677248,`0.01,`0.00,`ORIGINAL,`SUCCESS,`挂号费测试,`,`0.00000,`1.00%,`0.00,`0.01,`
`2020-07-22 10:02:20,`wx9c63650xxxxxxxx,`14988xxxxx,`14876xxxxx,`,`4200000xxxxxxx708,`1200131xxxxx48,`ogdwzxxxxxxxRFSRy4,`NATIVE,`SUCCESS,`OTHERS,`CNY,`0.01,`0.00,`0,`0,`0.00,`0.00,`,`,`挂号费测试,`,`0.00000,`1.00%,`0.01,`0.00,`
总交易单数,应结订单总金额,退款总金额,充值券退款总金额,手续费总金额,订单总金额,申请退款总金额
`4,`0.02,`0.02,`0.00,`0.00000,`0.02,`0.02

账单解析

实体类

账单明细

/**
 * @desc: 微信账单明细
 */
@Data
@SuperBuilder
@Accessors(chain = true)
public class WxPayBillDetail implements Serializable {

    private static final long serialVersionUID = 8406089574169555667L;

    /**
     * 交易时间
     */
    private String tradeTime;
    /**
     * 公众号账号ID
     */
    private String publicId;
    /**
     * 商户号
     */
    private String mchId;
    /**
     * 特约商户号(子商户号)
     */
    private String subMchId;
    /**
     * 设备号
     */
    private String deviceNo;
    /**
     * 微信支付单号
     */
    private String wxTransactionId;
    /**
     * 商户订单号(payId)
     */
    private String outTradeNo;
    /**
     * 用户标识
     */
    private String userTag;
    /**
     * 交易类型
     */
    private String tradeType;
    /**
     * 交易状态
     */
    private String tradeStatus;
    /**
     * 付款银行
     * 银行类型,采用字符串类型的银行标识,银行类型见银行列表
     * 例如:ICBC_DEBIT 表示 工商银行(借记卡)
     */
    private String bankType;
    /**
     * 货币种类
     */
    private String currencyType;
    /**
     * 应结订单金额
     */
    private String settlementTotalFee;
    /**
     * 代金券金额
     */
    private String couponFee;
    /**
     * 微信退款单号
     */
    private String wxRefundId;
    /**
     * 商户退款单号
     */
    private String outRefundNo;
    /**
     * 退款金额(结算)
     */
    private String settlementRefundFee;
    /**
     * 充值券退款金额
     */
    private String couponRefundFee;
    /**
     * 退款类型
     */
    private String refundType;
    /**
     * 退款状态
     */
    private String refundStatus;
    /**
     * 商品名称
     */
    private String goodsName;
    /**
     * 商品数据包
     */
    private String goodsData;
    /**
     * 手续费
     */
    private String serviceFee;
    /**
     * 费率
     */
    private String serviceRate;
    /**
     * 订单金额
     */
    private String payOrderTotalFee;
    /**
     * 申请退款金额
     */
    private String refundFee;
    /**
     * 费率备注
     */
    private String serviceRateRemark;
}

数据解析

/**
 * @desc: 下载微信账单业务
 */
@Service
public class WxPayBillServiceImpl implements WxPayBillService {
    private static final Logger logger = LogManager.getLogger(WxPayBillServiceImpl.class);

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

    //----------省略获取支付账号,发送下载交易账单请求逻辑............

    /**
     * 解析微信账单数据
     *
     * @param billData 文本表格数据
     */
    private List<WxPayBillDetail> parseBillData(String billData) {

        // 拆分行
        String[] lineArray = billData.split("\r\n");
        logger.info("微信账单明细表头:{}", lineArray[0]);
        logger.info("微信账单汇总表头:{},汇总数据:{}", lineArray[lineArray.length - 2], lineArray[lineArray.length - 1]);

        List<WxPayBillDetail> detailList = new ArrayList<>();
        /*第一行是明细表头,最后两行是汇总表头和汇总数据*/
        for (int i = 1; i < lineArray.length - 2; i++) {
            // 明细数据行
            String line = lineArray[i].replace("`", "");
            String[] dataArray = line.split(",");
            WxPayBillDetail billDetail = WxPayBillDetail.builder()
                    .tradeTime(dataArray[0])
                    .publicId(dataArray[1])
                    .mchId(dataArray[2])
                    .subMchId(dataArray[3])
                    .deviceNo(dataArray[4])
                    .wxTransactionId(dataArray[5])
                    .outTradeNo(dataArray[6])
                    .userTag(dataArray[7])
                    .tradeType(dataArray[8])
                    .tradeStatus(dataArray[9])
                    .bankType(dataArray[10])
                    .currencyType(dataArray[11])
                    .settlementTotalFee(dataArray[12])
                    .couponFee(dataArray[13])
                    .wxRefundId(dataArray[14])
                    .outRefundNo(dataArray[15])
                    .settlementRefundFee(dataArray[16])
                    .couponRefundFee(dataArray[17])
                    .refundType(dataArray[18])
                    .refundStatus(dataArray[19])
                    .goodsName(dataArray[20])
                    .goodsData(dataArray[21])
                    .serviceFee(dataArray[22])
                    .serviceRate(dataArray[23])
                    .payOrderTotalFee(dataArray[24])
                    .refundFee(dataArray[25])
                    .build();
            detailList.add(billDetail);
        }
        return detailList;
    }
}
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: