银企直联转账和企业通过网银转账一样,都会有手续费和退票问题,所以在实际对接中,这两个问题是不可避免,必须要处理的业务问题。
2019-05-14补充 转账时手续费受多种因素影响,实际生产环境中,出现了仅仅因为判断时,因为系统中收款方银行开户地未填写城市名,导致判断时,错误的判断为跨行异地,即LOCAL=N,导致手续费由1元直接提升为5元
!
对于手续费,企业通过银企直联进行转账操作时,正常来说每笔操作都会产生一笔手续费,这和企业通过网银操作时并无区别,不过一般情况下,为了吸引企业将资金留在本行,可能银行会对本行内转账进行免费,但跨行转账涉及人行及其它银行,这部分费用是不可避免的。而既然产生手续费,那对于企业来说就是一笔额外的开支,企业财务上肯定需要有这些手续费的对账信息,所以我们需要知道如何查询手续费。
你可以通过银企直联SDK下的BEDA.CIB
来获取兴业银行对应的银企直联SDK,在兴业银行银企直联的API中,你只能通过通过3.3.6 账户余额和交易流水分页查询
这个接口来查询手续费,请求代码示例如下,你可以通过此处来查看完整的代码,注意此处采用了查询接口2.0版本:
string tid = string.Format("{0:yyyyMMddHHmmss}_3.3.6", DateTime.Now);
var rq = GetRequest<FOXRQ<V1_SCUSTSTMTTRNRQ, V1_SCUSTSTMTTRNRS>>();
rq.SECURITIES_MSGSRQV1 = new V1_SCUSTSTMTTRNRQ
{
SCUSTSTMTTRNRQ = new SCUSTSTMTTRNRQ
{
TRNUID = tid,
SCUSTSTMTRQ = new SCUSTSTMTTRN_SCUSTSTMTRQ
{
VERSION = "2.0",
ACCTFROM = new ACCTFROM
{
ACCTID = mainAccountId
},
INCTRAN = new INCTRAN
{
DTEND = DateTime.Now.AddDays(-2),
DTSTART = DateTime.Now.AddDays(-3),
TRNTYPE = 2,
},
SELTYPE = 1
}
}
};
var rs = client.Execute(rq);
Console.WriteLine(rs.ResponseContent);
接口返回Xml报文如下(虽说是测试环境,但可能存在真实的银行卡信息,所以对应部分信息已脱敏,且删除了大部分记录,只保留少量交易和手续费记录):
<FOX>
<SIGNONMSGSRSV1>
<SONRS>
<STATUS>
<CODE>0</CODE>
<SEVERITY>INFO</SEVERITY>
</STATUS>
<DTSERVER>2019-03-18 10:38:44</DTSERVER>
</SONRS>
</SIGNONMSGSRSV1>
<SECURITIES_MSGSRSV1>
<SCUSTSTMTTRNRS>
<TRNUID>20190318093928_3.3.6</TRNUID>
<STATUS>
<CODE>0</CODE>
<SEVERITY>INFO</SEVERITY>
</STATUS>
<CLTCOOKIE>123</CLTCOOKIE>
<SCUSTSTMTRS>
<CURDEF>RMB</CURDEF>
<ACCTFROM>
<ACCTID>117010100100000177</ACCTID>
</ACCTFROM>
<TRANLIST MORE="N">
<DTSTART>2019-03-15</DTSTART>
<DTEND>2019-03-16</DTEND>
<STMTTRN>
<SRVRTID>99990076</SRVRTID>
<TRNTYPE>DEBIT</TRNTYPE>
<TRNCODE>227</TRNCODE>
<DTACCT>2019-03-16T14:48:59</DTACCT>
<TRNAMT>0.60</TRNAMT>
<BALAMT>111538864425.34</BALAMT>
<CURRENCY>RMB</CURRENCY>
<MEMO></MEMO>
<CORRELATE_ACCTID></CORRELATE_ACCTID>
<CORRELATE_NAME></CORRELATE_NAME>
<CHEQUENUM></CHEQUENUM>
<BILLTYPE></BILLTYPE>
<BILLNUMBER></BILLNUMBER>
<CORRELATE_BANKNAME></CORRELATE_BANKNAME>
<CORRELATE_BANKCODE></CORRELATE_BANKCODE>
<BUSINESSTYPE>银行扣款</BUSINESSTYPE>
<ATTACHINFO>2019031600025392082000001</ATTACHINFO>
<HXJYLSBH>H00100201903160004624317620000</HXJYLSBH>
<SUMMNAME>收费</SUMMNAME>
<SUMMDESC>收费</SUMMDESC>
<PURPOSE>企业网银转账手续费;</PURPOSE>
<BRANCHNO>11701</BRANCHNO>
<CHANNELCODE>204</CHANNELCODE>
<CASHFLAG>1</CASHFLAG>
<CBBZ>0</CBBZ>
<BCZBZ>0</BCZBZ>
<ROUTECHOICE></ROUTECHOICE>
<BIZREF></BIZREF>
<TEXT1></TEXT1>
<TEXT2></TEXT2>
<TEXT3></TEXT3>
</STMTTRN>
<STMTTRN>
<SRVRTID>99990076</SRVRTID>
<TRNTYPE>DEBIT</TRNTYPE>
<TRNCODE>231</TRNCODE>
<DTACCT>2019-03-16T14:48:59</DTACCT>
<TRNAMT>3000.00</TRNAMT>
<BALAMT>111538861425.34</BALAMT>
<CURRENCY>RMB</CURRENCY>
<MEMO></MEMO>
<CORRELATE_ACCTID></CORRELATE_ACCTID>
<CORRELATE_NAME>薛</CORRELATE_NAME>
<CHEQUENUM>110334936</CHEQUENUM>
<BILLTYPE></BILLTYPE>
<BILLNUMBER></BILLNUMBER>
<CORRELATE_BANKNAME>招商银行</CORRELATE_BANKNAME>
<CORRELATE_BANKCODE></CORRELATE_BANKCODE>
<BUSINESSTYPE>网上汇款</BUSINESSTYPE>
<ATTACHINFO>2019031600025392083000001</ATTACHINFO>
<HXJYLSBH>H00100201903160004624317620000</HXJYLSBH>
<SUMMNAME>汇款</SUMMNAME>
<SUMMDESC>网上汇款</SUMMDESC>
<PURPOSE>P201903040000016--报销-TMS系统-物流预支(EBP-20190304-0004)</PURPOSE>
<BRANCHNO>11701</BRANCHNO>
<CHANNELCODE>204</CHANNELCODE>
<CASHFLAG>1</CASHFLAG>
<CBBZ>0</CBBZ>
<BCZBZ>0</BCZBZ>
<ROUTECHOICE>4</ROUTECHOICE>
<BIZREF></BIZREF>
<TEXT1></TEXT1>
<TEXT2></TEXT2>
<TEXT3></TEXT3>
</STMTTRN>
<STMTTRN>
<SRVRTID>99990078</SRVRTID>
<TRNTYPE>DEBIT</TRNTYPE>
<TRNCODE>227</TRNCODE>
<DTACCT>2019-03-16T14:50:33</DTACCT>
<TRNAMT>4.00</TRNAMT>
<BALAMT>111538861120.73</BALAMT>
<CURRENCY>RMB</CURRENCY>
<MEMO></MEMO>
<CORRELATE_ACCTID></CORRELATE_ACCTID>
<CORRELATE_NAME></CORRELATE_NAME>
<CHEQUENUM></CHEQUENUM>
<BILLTYPE></BILLTYPE>
<BILLNUMBER></BILLNUMBER>
<CORRELATE_BANKNAME></CORRELATE_BANKNAME>
<CORRELATE_BANKCODE></CORRELATE_BANKCODE>
<BUSINESSTYPE>银行扣款</BUSINESSTYPE>
<ATTACHINFO>2019031600025392086000001</ATTACHINFO>
<HXJYLSBH>H00100201903160004624189420000</HXJYLSBH>
<SUMMNAME>收费</SUMMNAME>
<SUMMDESC>收费</SUMMDESC>
<PURPOSE>企业网银转账手续费;</PURPOSE>
<BRANCHNO>11701</BRANCHNO>
<CHANNELCODE>204</CHANNELCODE>
<CASHFLAG>1</CASHFLAG>
<CBBZ>0</CBBZ>
<BCZBZ>0</BCZBZ>
<ROUTECHOICE></ROUTECHOICE>
<BIZREF></BIZREF>
<TEXT1></TEXT1>
<TEXT2></TEXT2>
<TEXT3></TEXT3>
</STMTTRN>
<STMTTRN>
<SRVRTID>99990078</SRVRTID>
<TRNTYPE>DEBIT</TRNTYPE>
<TRNCODE>231</TRNCODE>
<DTACCT>2019-03-16T14:50:33</DTACCT>
<TRNAMT>0.01</TRNAMT>
<BALAMT>111538861120.72</BALAMT>
<CURRENCY>RMB</CURRENCY>
<MEMO></MEMO>
<CORRELATE_ACCTID></CORRELATE_ACCTID>
<CORRELATE_NAME>马</CORRELATE_NAME>
<CHEQUENUM>110334938</CHEQUENUM>
<BILLTYPE></BILLTYPE>
<BILLNUMBER></BILLNUMBER>
<CORRELATE_BANKNAME>建设银行</CORRELATE_BANKNAME>
<CORRELATE_BANKCODE></CORRELATE_BANKCODE>
<BUSINESSTYPE>网上汇款</BUSINESSTYPE>
<ATTACHINFO>2019031600025392087000001</ATTACHINFO>
<HXJYLSBH>H00100201903160004624189420000</HXJYLSBH>
<SUMMNAME>汇款</SUMMNAME>
<SUMMDESC>网上汇款</SUMMDESC>
<PURPOSE>P201903040000009--报销</PURPOSE>
<BRANCHNO>11701</BRANCHNO>
<CHANNELCODE>204</CHANNELCODE>
<CASHFLAG>1</CASHFLAG>
<CBBZ>0</CBBZ>
<BCZBZ>0</BCZBZ>
<ROUTECHOICE>4</ROUTECHOICE>
<BIZREF></BIZREF>
<TEXT1></TEXT1>
<TEXT2></TEXT2>
<TEXT3></TEXT3>
</STMTTRN>
</TRANLIST>
<LEDGERBAL>
<BALAMT>111540544183.22</BALAMT>
<DTASOF>2019-03-18</DTASOF>
</LEDGERBAL>
<AVAILBAL>
<BALAMT>111536518538.20</BALAMT>
<DTASOF>2019-03-18</DTASOF>
</AVAILBAL>
</SCUSTSTMTRS>
</SCUSTSTMTTRNRS>
</SECURITIES_MSGSRSV1>
</FOX>
在报文中,我们可以发现转账对应的流水记录中BUSINESSTYPE
为网上汇款,而其流水是紧邻转账记录,其BUSINESSTYPE
为银行扣款,当然仅凭此还不能判断哪条记录为对应手续费,但我们可以发现转账流水和手续费对应的SRVRTID
是完全一样的,再细看包括其DTACCT
交易时间也是完全一样,所以我们可以通过这两个字段来将结果进行分组。
rs.SECURITIES_MSGSRSV1.SCUSTSTMTTRNRS.SCUSTSTMTRS.TRANLIST
.List.GroupBy(t=>new {t.SRVRTID,t.DTACCT })
2019-03-19补充
测试时发现其实交易流水的HXJYLSBH
和手续费的HXJYLSBH
是完全一样的,所以也可以通过HXJYLSBH
来进行分组
rs.SECURITIES_MSGSRSV1.SCUSTSTMTTRNRS.SCUSTSTMTRS.TRANLIST
.List.GroupBy(x => x.HXJYLSBH)
转账和其对应的手续费如何查询我们是已经知道了,但如何知道该笔汇款对应企业内部系统的哪条记录呢?兴业银行的API没提供专门的字段用于记录外部系统id,而是通过TRNUID
来区分不同的交易记录,在兴业银行交易中标志一笔交易的唯一性字段为HXJYLSBH
(核心交易流水编号),该字段只能通过3.3.6 账户余额和交易流水分页查询
查询才能得到,而3.4.1 转账汇款指令提交
或3.4.2 查询转账交易状态
只能获取交易是否成功,并不能获取HXJYLSBH
,所以我们需要通过其它方式来间接的记录该笔交易在企业内部系统中的唯一性id,如上面报文所示,我们可以通过PURPOSE
字段来间接的记录企业内部系统id,然后我们可以按照特定的规则来判断PURPOSE
,以便达到两个系统内交易流水的映射关系。
当然,如果只是手续费,HXJYLSBH
并不重要,该字段的用处是辅助判断退票如何关联转账交易。所谓退票,就是指跨行交易时,当银行将转账信息提交至人行,人行响应成功时,银行这边就会记录该笔交易状态为已成功PAYOUT
,但实际此时人行只是接收信息成功,真正是否能交易成功,需要待人行将转账信息提交给目标银行,目标银行在处理之后,才会给出是否交易成功,如果账号信息之类有误,那么目标银行就会反馈交易失败,此时人行会再通知发起银行该笔交易失败,在兴业银行中,它不会去更新之前那笔状态为PAYOUT
的交易记录,而是会产生一笔退票流水,所以我们的问题就是如何查询这笔退票流水。
在兴业银行某文档中有以下截图的一段内容,当然很可惜我没能拿到这份文档。
图中内容详细的描述了应当如何查询退票流水,因为同样是调用的是3.3.6 账户余额和交易流水分页查询
接口,所以此处就不再罗列示例代码,请自行替换SELTYPE
值为3进行查询。当然图中只是阐述了如何查询退票流水,以及如何去查询其对应的转账交易记录,并没有描述如何得知转账失败原因,因为测试环境中未能查询到退票记录,所以此处只能以另外一张截图示例:
通过截图,可以发现PURPOSE
记录了退票原因,所以我们可以将该字段的内容持久化到企业内部系统中,用于展示转账失败原因。
最后,按兴业银行相关人员回馈,银行内部转账(即收款账户为兴业银行账户)时,都是实时返回,是不可能会出现退票现象的,但个人建议还是与跨行交易一视同仁,按都可能存在退票这种业务情况进行处理。