作者:Xie, James
摘要
支付结果通知看似一个很简单的需求,但是做到一个安全高效可靠的架构和设计也是值得研究和探讨的一个问题。本人通过总结实战中不同的通知机制的研究分析,希望从中找到需求的本质,从而启发我们如何更好的在今后的工作中设计通知机制。
本人分析了四种通知机制,ReviseCheckoutStatus,Instant Payment Notification,Payment Data Transfer和WebHooks方式。然后从安全性,高效性和可靠性三个方面分析了各个通知机制。最后由现行的通知方案中得到一些启发。比如如何权衡安全性高效性和可靠性,如何设计UID使得交易处理匹配更顺畅。
因此,本文即讲了我们在通知机制设计中怎么做的,也讲了为什么采取这种通知机制的设计,希望给自己和读者的今后的工作一定的启发。
1. 问题提出
在电子商务交易过程中,第三方支付的出现解决了各种银行接口和消息格式不统一的问题,清结算更加灵活方便,手续费更加优惠。
但是与此同时,由于电子商务平台和第三方支付平台分属于不同的网络,一方面支付平台需要知道订单信息作为支付的上下文,以便更好的实现金融风险控制。另一方面电子商务平台也需要知道任何支付结果或者原支付交易的变动,才能在自己的订单系统反应订单状态,避免误解和减少纠纷。
关于订单信息如何安全简单高效的流转到第三方支付公司,本人的另外一篇《基于OAUTH的电子商务支付集成研究与实现》有详细的研究。这里我想讨论的是关于支付结果和变动如何通知回电子商务平台的问题。
对于支付系统的通知需求来说,主要有以下几个方面,
1. 安全是保障
在互联网的环境下,如何验证发送通知是首要考虑的问题,如果不能很好的验证身份,那么伪造支付结果将成为可能。欺诈性销售等一系列问题随之而来。所以安全性是任何支付系统互联首要考虑的问题。
2. 高效是手段
支付交易在大型的电子商务平台上流量会非常大,并发的通知需要我们很好的设计我们的处理机制,否则很可能造成服务器拒绝服务。
3. 可靠是目的
如何保证通知准确可靠的送达电子商务平台,然后更新相应的订单状态是支付结果通知的意义和目的所在,任何的通知都需要尽可能的准确无遗漏的正确处理。否则不仅可能造成电子商务平台本身的财务对账系统账不平,而且会使得用户的购物体验造成影响。
2. 方案分析
下面举eBay平台为例,分析各种通知机制,以启发我们对于如何建立更好的支付结果通知机制的思考。
2.1 第1代通知机制
对于支付结果来说,最终的目的是更新订单的状态,因此,eBay开放平台中设计了一个接口--- ReviseCheckoutStatus。
我们来看看大致是怎么工作的,见下图2-1,
主要处理流程如下,
1. 每当有一笔支付结果产生或者原交易支付状态变化,PayPal都会调用eBay的ReviseChecoutStatus发送订单的支付状态变化
2. eBay的ReviseCheckoutStatus接口接收到支付结果以后,首先根据orderId匹配原始order,并做相应的明细调整
3. eBay的ReviseCheckoutStatus接口接收到支付结果以后,还会把支付信息发送给Payment系统,更新相应的财务账目。
4. eBay的ReviseCheckoutStatus接口在完成上述操作后把更新结果返回给PayPal
5. PayPal在接收到失败响应后会放到retry队列,安排下次再次发送。
接下来我们来看看ReviseCheckoutStatus接口明细,
<?xml version="1.0" encoding="utf-8"?> <ReviseCheckoutStatusRequest xmlns="urn:ebay:apis:eBLBaseComponents"> <RequesterCredentials><eBayAuthToken>ABC...123</eBayAuthToken><RequestUserId>paypal</RequestUserId> <RequestPassword>******</RequestPassword> </RequesterCredentials> <AdjustmentAmount currencyID="CurrencyCodeType">AmountType (double) </AdjustmentAmount> <AmountPaid currencyID="CurrencyCodeType">AmountType (double) </AmountPaid> <CheckoutStatus>CompleteStatusCodeType </CheckoutStatus> <CODCost currencyID="CurrencyCodeType">AmountType (double) </CODCost> <EncryptedID>string </EncryptedID> <ExternalTransaction>ExternalTransactionType <ExternalTransactionID>string </ExternalTransactionID> <ExternalTransactionTime>dateTime </ExternalTransactionTime> </ |