- 集成指南
- 支持的功能(付款方式)
- <<ach>> 支付
<<ach>>
<<ach>> 是一个电子网络,处理美国金融机构之间的批量借贷交易。 其由全国自动化票据交换协会 (NACHA) 管理。
此网络可用于账户之间资金的电子转账。 其通过 <<ach>> 用于直接付款(例如,重复按揭付款或网络客户购物),并通过 <<ach>> 用于直接存款(例如,发薪、对网络购物执行的退款或 B2B 付款)。
此网关允许您通过 <<ach>> 处理直接付款(付款)和直接存款(退款)。
此页介绍通过 QNB ALAHLI 处理 <<ach>> 付款的要求,并提供付款流概述以及有关支持的 <<ach>> 支付的 <<webServicesIntegration>> 操作的详细信息。
先决条件
您必须通过 <<ach>> 收单行配置 <<ach>> 账户。
- 您必须先获得明确的客户授权才能够进行 <<ach>> 结算。
- 虽然 <<ach>> 不是实时网络,但在付款请求提交到 QNB ALAHLI 后仍可以执行退货。
- 您必须遵守 NACHA 规则。 如果违规则可能承担实质性的惩罚。 若要掌握最新的规则,请访问 https://www.nacha.org/
- 您必须制定、实施和更新与开始、处理和输入存储相关的策略、规程和制度,目的是:
- 确保信息的机密性。
- 防范信息安全威胁。
- 防范未授权的信息使用。
<<ach>> 数据流
- 付款人为付款或存款授权。
NACHA 许可标准输入代码 (SEC) 为:
TEL
. 电话发起输入。WEB
. 网络发起输入。PPD
. 预定付款和存款。
- 商家将交易请求发送至 QNB ALAHLI。
请求可以是
PAY
、REFUND
或VOID
。 - QNB ALAHLI 发出包含状态信息的响应(例如,
APPROVED_PENDING_SETTLEMENT
)。交易被添加到当前结算批次。
交易批处理以两种方式之一关闭:
- 于配置时间,每天一次。
- 截止到您通过提交 <<webServicesIntegration>>
CLOSE_BATCH
请求关闭目前打开的批处理。 任何后续交易都会被添加到新的批处理中。
一天结束时,尚未提交的所有关闭的批处理将被收集到结算文件中并传送到 <<ach>> 收单行。
- <<ach>> 收单行发出立即响应,包含传送数据的验证结果(例如,
APPROVED
或DECLINED
),并将付款请求提交到 <<ach>> 网络进行处理。注意:
- <<ach>> 收单行发出的
APPROVED
状态仅表明传送接受状态已通过验证可以进行进一步处理;不是对财务交易的实际审批。 - 若要收到 <<ach>> 收单行响应通知,请订阅 Webhook 通知。
- <<ach>> 收单行发出的
- <<ach>> 网络管理适用金融机构之间的付款交易。
- 最多延迟 3 天后,<<ach>> 网络将未审批付款请求的异常报告发送到 <<ach>> 收单行,后者将为您提供此报告。
集成 <<ach>> 支付
将 <<ach>> 支付集成到付款页有三个选项:
如果您有现有的 <<checkout>> 集成,您可以使用 <<checkout>> 来验证 <<ach>> 付款详细信息。
您可以通过在 Create Checkout Session 请求中设置 interaction.operation=VERIFY
来执行此操作。<<checkout>> 将 <<ach>> 支付作为付款选项向付款人显示。 付款人输入的数据使用配置收单行支持的验证方法进行验证。
您可以通过比较 resultIndicator
和 successIndicator
来确定验证操作是否成功。 如果交互未成功,<<checkout>> 将显示指示验证失败的消息,并提示付款人重试。
如果您有自己的付款页,那么您可以选择 Hosted Session 集成选项来让 QNB ALAHLI 安全捕获 <<ach>> 付款详细信息,并将这些信息存储到付款会话中。
<html> <head> <!-- INCLUDE SESSION.JS JAVASCRIPT LIBRARY --> <script src="https://qnbalahli.test.gateway.mastercard.com/form/version/72/merchant/<MERCHANTID>/session.js"></script> <!-- APPLY CLICK-JACKING STYLING AND HIDE CONTENTS OF THE PAGE --> <style id="antiClickjack">body{display:none !important;}</style> </head> <body> <!-- CREATE THE HTML FOR THE PAYMENT PAGE --> <div>Please enter your Automated Clearing House details:</div> <div> <label class="control-label" id="ach-account-type-label">Account Type:</label> <select class="form-control col-sm-6" name="ach-account-type" id="ach-account-type"> <option value="CONSUMER_SAVINGS">Consumer Savings Account</option> <option value="CONSUMER_CHECKING" selected>Consumer Checking Account</option> <option value="CORPORATE_CHECKING">Business Checking Account</option> </select> </div> <div>Bank Account Holder: <input type="text" id="ach-account-holder" class="input-field" value="" readonly></div> <div>Bank Account Number:<input type="text" id="ach-account-number" class="input-field" value="" readonly></div> <div>Routing Number:<input type="text" id="ach-routing-number" class="input-field" value="" readonly></div> <div><button id="payButton" onclick="pay();">Pay Now</button></div> <!-- JAVASCRIPT FRAME-BREAKER CODE TO PROVIDE PROTECTION AGAINST IFRAME CLICK-JACKING --> <script type="text/javascript"> if (self === top) { var antiClickjack = document.getElementById("antiClickjack"); antiClickjack.parentNode.removeChild(antiClickjack); } else { top.location = self.location; } PaymentSession.configure({ fields: { // ATTACH HOSTED FIELDS TO YOUR PAYMENT PAGE FOR ACH ach: { accountType: "#ach-account-type", bankAccountHolder: "#ach-account-holder", bankAccountNumber: "#ach-account-number", routingNumber: "#ach-routing-number" } }, //SPECIFY YOUR MITIGATION OPTION HERE frameEmbeddingMitigation: ["javascript"], callbacks: { initialized: function(response) { // HANDLE INITIALIZATION RESPONSE }, formSessionUpdate: function(response) { // HANDLE RESPONSE FOR UPDATE SESSION if (response.status) { if ("ok" == response.status) { console.log("Session updated with data: " + response.session.id); } else if ("fields_in_error" == response.status) { console.log("Session update failed with field errors."); if (response.errors.bankAccountHolder) { console.log("Bank account holder invalid."); } if (response.errors.bankAccountNummber) { console.log("Bank account number invalid."); } if (response.errors.routingNumber) { console.log("Routing number invalid."); } } else if ("request_timeout" == response.status) { console.log("Session update failed with request timeout: " + response.errors.message); } else if ("system_error" == response.status) { console.log("Session update failed with system error: " + response.errors.message); } } else { console.log("Session update failed: " + response); } } } }); function pay() { // UPDATE THE SESSION WITH THE INPUT FROM HOSTED FIELDS PaymentSession.updateSessionFromForm('ach'); } </script> </body> </html>
- 在付款页包括网关托管的
session.js
客户端 JavaScript 库。 此文件的路径包括 api 版本和会话的商家识别码。 - 为包含 <<ach>> 付款详细信息的付款页创建 HTML。
为阻止向服务器提交敏感数据,请确保敏感数据字段为readonly
且不具有name
属性。 - 调用
PaymentSession.configure(configuration)
函数。
configuration
对象允许您将托管字段附加到付款页。 您需要提供以下项:
- 会话(可选),如果未提供,客户端库将创建付款会话。
- <<ach>> 支付字段的字段选择器,提供后由嵌入在 QNB ALAHLI 托管的内嵌框架中的相应代理字段替换。 代理字段具有与替换字段相同的外观。
-
阻止点阅绑架的缓解选项
点阅绑架又称“UI 纠正攻击”:用户打算点击最上层页面时,攻击者使用多个透明或不透明层欺骗用户点击另一页面上的按钮或链接。 若要使用 Hosted Session,您必须实施以下针对点阅绑架攻击的一项或多项防范。
框架缓解选项 实施 javascript
在付款页中包括“框架式截断符”JavaScript。 x-frame-options
您的服务器应返回 X 框架选项 HTTP 响应标头。 csp
您的服务器应返回包含框架继承指令的 Content-Security-Policy HTTP 响应标头。 您必须指定通过
PaymentSession.configure(configuration)
调用中的frameEmbeddingMitigation
参数实施哪些防范。 有关防范点阅绑架攻击的信息,请参阅 OWASP 外部网站的点阅绑架防范备忘单。 -
Hosted Session 交互期间处理各个事件的回调
initialized( )
: 当托管字段附加到付款页时调用。formSessionUpdate( )
: 在PaymentSession.updateSessionFromForm('ach')
函数的响应中调用(参见下一步)
- 调用
PaymentSession.updateSessionFromForm('ach')
将收集的 <<ach>> 付款详细信息存储到付款会话中。 操作完成后,将调用formSessionUpdate( )
回调,其中包含结果参数。 您必须检查result.status
值以确定操作是否成功。 请参见处理回调响应。 - 您可以使用返回的付款会话 (session.id) 来执行令牌化或付款交易(如果需要)。 有关详细信息,请参见使用会话执行操作。
session.js 参考[JavaScript]
您可以使用以下操作将 <<ach>> 付款详细信息直接提交到 QNB ALAHLI。
通过提交 <<webServicesIntegration>>PAY
请求发起 <<ach>> 付款,通过提交 <<webServicesIntegration>>REFUND
请求发起退款。
请确保在您的请求中包含以下信息:
sourceOfFunds.type = ACH.
sourceOfFunds.provided.ach.routingNumber
: 付款人银行的路由号码。sourceOfFunds.provided.ach.bankAccountNumber
: 付款人的银行账号。sourceOfFunds.provided.ach.bankAccountHolder
: 付款人的开户人姓名。sourceOfFunds.provided.ach.accountType
: 付款人的银行账户类型。sourceOfFunds.provided.ach.secCode
: 适用于此交易的 <<ach>> 支付的 SEC 代码。SEC 代码必须是以下代码中的一个:
TEL
: 客户通过电话授权的 B2C 付款的 <<ach>> 借方输入。 如果您与付款人之间的关系已存在,只能使用 TEL,如果关系不存在,付款人将开始与您联系。WEB
: 通过互联网或无线网络授权的 B2C 付款的 <<ach>> 借方输入。PPD
: 基于付款人提供的已验证授权的 <<ach>> 贷方或贷方输入。 PPD 用于 B2C 付款(例如,员工薪金、按揭付款或费用报销)。
您可以通过为目标交易 ID 参数引用 PAY
或 REFUND
请求的订单提交 <<webServicesIntegration>>VOID
请求来避开订单上的前一项交易。
对于成功的 <<webServicesIntegration>>VOID
请求,参考的目标交易将从批处理中删除,因而不会提交到 <<ach>> 收单行。
包含参考的目标交易的批处理已关闭进行结算(即正在进行结算)或已经结算后,交易无法再被取消。
批处理管理和结算
您可以通过提交包含您 <<ach>> 收单行的收单行 ID 的 <<webServicesIntegration>>CLOSE_BATCH
请求来控制批处理结账。 收单行 ID 在交易响应的 transaction.acquirer.id
中提供。
因此,QNB ALAHLI 中当前的 <<ach>> 收单行批处理将被关闭。 后续 <<ach>> 交易将被添加到新的 QNB ALAHLI 内部批处理。
对账
成功 <<ach>> 交易的 Retrieve Transaction 响应包含收单行在 transaction.receipt
中使用的交易的识别码。
此识别码将用于 Paymentech Salem <<ach>> 收单行提供的异常详细信息报告。 这包含所有未成功的 <<ach>> 交易,可用于付款对账。
网关 (response.gatewayCode
) 提供的交易状态不更新为 <<ach>> 网络的实际响应。
测试 <<ach>> 交易
您可以使用测试商家配置文件来测试您的集成。
QNB ALAHLI 提供模拟器,此模拟器将使用 response.gatewayCode=APPROVED
返回 <<ach>> 支付所有有效请求的响应。