账户体系是支付系统的基础,它的设计直接影响整个系统的特性。这里探讨如何针对电子商务系统的支付账户体系设计。我们从一些基本概念开始入手,了解怎么建模。
在支付系统中,账户的设置,主要是从如下几个方面来考虑:
这五个需求,按照其设计的优先级,也是从支付、记账、对账、风控来进行。支付系统根据其发展所处的阶段,逐步将新增需求纳入设计中。
账户设置,一般是从交易开始的。交易的实现必须有账户的支持,账户是交易的基本构成元素。从支付系统的角度,交易中涉及到的资金流是资金从一个账户流向另一个账户。发起交易的一方,被称之为交易主体,他可以是个人,也可以是一个机构。
资金从该主体所拥有的账户中流出。而接收交易的一方,被称为交易对手,他也可以是个人,或者机构。和第三方支付或者金融机构的交易不同,电商系统中,交易还会涉及到渠道。
由于电商系统本身并无清结算的资质,所有资金从交易主体到交易对手的账户的流动,在大部分情况下,并没有经过电商系统,而是由电商系统调用支付渠道提供的接口,由它来完成真正的支付过程。当然,渠道也不是活雷锋,在这过程中,渠道要收取费用。
所以,在电商系统中,一次交易会涉及到三个账户:交易主体账户、交易对手账户以及支付渠道账户。如何在这三个账户中完成一次交易,我们将在后续的《交易和记账》一文中详细分析。
公司的会计需要对每一笔交易都要做详细的记录,即记账。公司每天都产生大量的交易行为,为了便于管理和统计,一个简单的方法是对交易进行分类,比如食品、带宽、办公用品等等。这个分类,按照公司的规模和业务复杂度,可以有一级,二级,三级或者更多级的结构,这被称之为会计科目。记账时,除了交易明细,还需要在每个级别上对交易额进行汇总。
一般来说,一级科目上汇总称为总帐科目,而详细记录称为明细科目。在电商系统中,由于涉及到的参与方较多,记账也相对复杂,但基本方法也是类似的。电商的参与者可以分为商户、买家和渠道,对这三类参与者,都需要分别建立总帐账户和明细账户。
当用户使用银行卡来支付时,电商支付系统需要和银行对接,从用户银行卡所代表的账户上扣除资金。对接了银行,第三方支付等机构的电商支付系统,它需要连接到用户在这些机构的账户来执行扣款或者充值操作,这些账户或称为外部账户。对外部账户,支付系统只能记录账户在本系统的明细以及累计消费额,无法得知账户真正余额。不少电商在玩零钱的概念,也就是让用户充值到零钱,使用的时候就直接从零钱中扣除。这就需要零钱账号。这是电商系统中自己设立的账号,所以也叫内部账号,可以知道账号的全部消费明细和余额。当然,除了零钱账号,也可以有储值卡账号,信用账号等。
那问题来了,什么时候需要建立账户,比如优惠券,需要账户吗?一次消费的储值卡和可以充值的储值卡,需要建立账户吗?这里先埋个雷,后续介绍支付和记账时,给出答案。
当电商要对接银行时,往往都会被要求开设一个收款账户。用户通过这个银行来支付时,钱就被转到这个账户上。对第三方支付也是一样。收款账户是开设在银行或者第三方支付这边的,即渠道侧。一般来说,渠道每天都可以提供这个账户的交易流水供电商对账用。这样在电商这边,渠道就成为一个收单机构。所以在电商这边,建立这个收款账户对应的对账用的收单账号,用来记录通过这个渠道进行的各项交易流水。
根据业务需要,可以设置多种账户,如支付账户、预付卡账户、代扣账户、零钱账户、结算账户等。从类别上来说,这里的账户,一般指总账账户。一般来说电商系统中涉及的账户类型有:
对这些账户,需要设置如下属性:基本属性,包括:
银行卡、第三方支付信息:
注意,有些第三方信息是不能保存的,如用户的账号密码、信用卡的CV号等。为了避免账户信息被爬库或者数据库信息意外泄露,一般还需要对敏感字段,如密码等,进行加密保存,甚至保存到另外的表中。更进一步,为了避免账户信息被意外修改,还可以增加一个校验字段,在写入数据时设置该字段,在读取数据时做校验,一旦发现数据有问题,则关闭该账号。
交易记录,交易流水,账户流水,交易台账,这三个容易混淆的概念,从数据上来说,却并不复杂,它们的核心是交易流水,账户流水是从账户视角的交易流水。那对一笔交易,涉及到的方方面面内容很多,有哪些需要记录的呢?考虑到交易记录将被用于风控和信用分析,能收集到的信息是越全面越好。
可以说,对账是支付系统最头疼的事情。每一笔交易,都要做到各参与者的记录能够吻合,没有偏差。对账系统的工作,是发现有差异的记录,即轧帐;然后通过人工或者自动的方式,解决这些差异,即平帐。
那有哪些记录需要对账?目前主要是两个:一个是交易记录;一个是退款记录。
一般来说,对账流程涉及到如下步骤:渠道对账单下载、本地交易记录准备、轧账、平账。
银行,第三方支付,银联等,基本都会提供对账单下载的功能。不过也有少数工作做不到位或者太到位的银行,只提供账单查询后台,不提供对账单下载功能。
对开发人员来说,这里有几个坑:
看一下第三方支付的对账单情况:
银行直连的对账情况:
由于每个渠道的账单格式都不尽相同,在得到账单后,下一步是对账单做标准化处理,这样轧帐以及后续工作就可以统一处理了。标准化后的账单数据可以放在文件系统或者数据库中。这取决于交易数据量。每天百万以上的量,还是使用文件系统,比较合适。数据库操作相对比较慢,也浪费资源。
基于文件系统的标准化涉及如下内容:
为了加快处理速度,我们使用hdfs作为文件系统,有利于后续的对账的处理。
本地交易记录的准备,总的来说有如下方法:–啥都不做,直接用原始数据。鉴于大部分系统使用的是mysql,这也意味着在MySQL上做对账。对账时需要大量的数据查找工作,必然会影响线上业务。在数据规模较大,比如超过100万时,就不太合适了。
轧帐是按照客户订单号来比较本地交易记录和渠道交易记录是否一致。从算法角度,是计算两个数组的差异。在单机运行时,可以采用的算法不少,这里不详细介绍。我们推荐采用mapreduce来轧帐,这有个优势,可以按照订单号将渠道提供的记录和本地记录shuffle到同一个reduce处理上,这样就可以很容易进行数据比对。轧帐中最大的坑,莫过于切分点的问题。
发现两边不一致的数据,那应该如何处理?数据量不大时,记录起来,人工甄别就行。但如果数据量很大,每天上千条,人工处理就成本太高了。这个没有统一的处理方法,需要根据有问题的数据,做个分析,然后做自动处理。针对交易记录的对账的处理,主要有如下情况:
针对退款的对账处理,主要有如下情况:
总之,对账工作,即复杂也不复杂。需要细心,对业务要有深入的了解,并选择合适的架构。
这一期,回到支付系统的核心业务,即支付。每个电商公司的支付系统都已经或多或少的实现了交易核心功能,可也都是一直在改进,总是不断的有新的需求冒出来。所以这一期开始,我们梳理一下:到底有哪些支付方式?每种支付方式都是怎么运作的?
说到支付就不得不提交易。这两个概念在不同公司中是不一样的。我们的定义是,交易是生成订单;支付是对订单进行付款。订单生成过程我们以后另开话题来说。这一次重点介绍支付。而就支付行为来说,我们碰到的大部分都是单次支付,其次还有转账和退款。在苹果推出订阅支付后,国内支付宝等也在陆续跟进。单次支付是我们用的最多的支付方式了,即一次结清所有款项。把单次支付走通了,其他支付方式也容易处理。本期重点介绍单次支付。
先说大家比较熟悉的银行卡支付,它分为线上支付和线下支付两种形式。线下支付就是通常说的POS收单,这里不介绍这个内容。对线上支付,按照卡的类别,分为贷记卡支付,也叫motopay、ePOS,即信用卡支付;和借记卡支付。按照支付形态,又分为认证支付、网银支付、快捷支付几种形态。银行卡网银支付要求银行卡必须开通在线支付功能,而快捷支付并不需要开通在线支付功能。主要利用支付验证要素(卡号、密码、手机号、CVN2、CVV2等),结合安全认证(例如短信验证码),让持卡人完成互联网支付。
指用户在绑卡时,将卡信息提供给电商。这样在支付时,用户无需再输入这些信息,由电商在服务器侧保留用户的账户信息,比如身份证号,卡号,手机号。在用户支付时,无需再输入这些内容,最多就提供个密码或者校验码,就可以完成支付。这基本不会打断用户的使用体验,所以也是电商喜欢的支付方式。但认证支付最让人诟病的就是安全性。一方面需要向电商暴露个人信息,一旦被窃取,资金就容易被盗走。还有在手机上执行支付,一旦手机丢失,窃取者就可以轻而易举的使用或者转移资金。
快捷支付和认证支付类似,不同点在于绑卡之后,有些银行接口会返回token,后续使用token来作为支付凭证,无需提供卡号信息,这样电商也不需要本地保留卡号了。目前主要是银联有提供token接口。
相对来说,网银支付要安全很多。网银支付是由银联或者银行提供支付界面,用户必须在页面上输入卡号,密码等验证信息才可以执行支付。大部分银行还要求用户使用U盾或者其它安全硬件。但安全和易用永远是个矛盾。网银使用会打断用户体验,增加用户使用难度。对使用硬件加密的支付,不可能天天带着U盘跑。另外网银主要用在web端,在手机端,嵌入网银页面,还是比较难看的
走一个具体的例子看看吧。比如用户在电商系统中买了200块钱的东西,然后通过浦发银行卡做结算,用的是快捷支付。这个过程是:
用户在交易界面上,提交订单到交易系统中;交易系统确认订单无误后,请求支付系统进行结算。这是在交易系统做的,后面工作就进入支付系统。
用户被引导到收银台页面,让用户确认交易金额,选择支付方式,调用支付系统接口。
支付系统接收到支付请求,验证请求的各个字段是否有问题,确认无误后,调用支付网关执行支付。
支付网关请求浦发银行的快捷支付接口执行支付。
支付网关接收到支付结果报文后,对结果报文做解析,获取结果,并将结果告知交易系统。这可以通过URL或者RPC调用来实现。
商城系统收到支付结果后,开始执行后续操作。如果是支付成功,则开始准备出库。这一步在交易系统中处理,这里不做介绍。
网银支付,和快捷相比,就在第4步,插入一个步骤,将用户导航到网银页面输入支付信息,后续步骤是一样的。在资金流上也是相同的。而在第五步获取返回结果上,一般银行就直接同步返回,银联是分为同步和异步返回。同步告知操作成功或者失败,异步告知扣款成功或者失败。同步操作和异步操作都需要调用方提供一个回调的URL地址,银联会将参数附加在这个地址上。通过解析这些参数可以得到执行结果。异步操作一般有2-3秒的延迟,取决于网络,以及该交易处理的复杂度。
上一节说的是支付的信息流,那资金流应该是怎么走的?在第三步,会触发资金流。资金从用户个人账户上转移到电商公司的账户。当然,银行也不是活雷锋,这一笔交易是要收手续费的。资金是实时到账的,手续费一般是按月结算。有按交易笔数计费的,但大部分还是按照交易金额来收费。
同行快捷支付是比较简单的场景,让我们来逐步增加难度。如果支付系统没有对接浦发银行,那对浦发卡,就得走其它支付方式:银联或者第三方支付。
先说银联快捷。银联提供的多种接入方式,常说的快捷支付,在银联文档中叫商户侧开通token接口。通过这个接口,可以实现同行和跨行资金结算。不管收款行是浦发还是其它行,都可以完成结算。对本地和用户来说,体验是一样的。而在银联侧,后台资金流处理却不一样。了解这个资金流,有助于在异常情况下,了解资金到底跑到哪里了。
如果收款行也是浦发银行,银联发报文给浦发,浦发使用内部系统完成两个账户间的转帐,即时完成。
如果使用的是第三方支付,对用户来说,处理的流程和银联一样。但资金流会不一样。第三方支付在浦发和工行一般都会有落地的托管资金。发生交易后,一般来说不会产生跨行资金流动。用户在浦发行的钱会被结算到第三方支付在浦发行的托管账户,而在工行的钱,会由第三方支付在工行的账户打到客户账户上。这就降低了跨行资金流动成本。
目前国内主要银行都提供快捷和直联的接口。对电商来说,要对接哪些银行是个需要考虑的问题。怎么对接银行,渠道和第三方支付。
一般来说,大部分银行都提供直联和网银接口,但不需要直接对接所有银行。银联和第三方支付也提供直联接口,可以直接对接国内主要银行。也不是所有银行都被银联支持,这和银联签约的接口有关,需要在对接时咨询银联。从我们使用情况看,浦发借记卡、邮储银行卡是不支持的。另外交行、平安(含原深发)、上海银行、浦发、北京银行,上述银行卡需通过这个地址开通银联在线支付业务。
大部分银行提供的银行卡支付接口,借记卡支付和贷记卡支付是不一样的。但也有几个好心的银行,可以用一套接口同时开通借记卡和贷记卡。点名赞一下这些银行:宇宙第一大行工商银行和建设银行。其他同学对接中如果也发现借记卡和贷记卡用一个接口的,也请及时告知。作为国内最保守的软件团队,和银行对接时务必做好足够的准备。在商务谈判完成、拿到银行的接口文档后,需要考虑两个问题:专线问题、加密问题。
专线问题
首先是专线问题。大部分银行对接是需要专线的。与银行沟通的时候,注意收集如下信息:
前置机IP,这个需要在银行侧和电商侧进行配置。专线其实是在银行和电商之间建立一个局域网,需要双方分配通讯IP。其实这两组IP都是NAT后的IP,银行分配给我们的是电商真实的前置机IP经过最外端的网络防火墙转换后的IP段,后者也是对方的真实前置机IP经过转换后的IP段。出于安全考虑,双方都不会将真实IP暴露出去,所以要NAT。
接入地址:即电商这边机房的地址。
加密问题
其次是加密问题。部分银行,如中行,前置要求使用加密机。此处加密机的常用功能有三方面:
对接银联比对接银行简单,不需要专线,不需要加密机。不过需要获取ADSS认证。银联最近在推Token接口,有两套接口,一套是银联侧开通,一套是商户侧开通。前者类似网银支付,后者类似快捷支付。务必要求接入后者接口啊。基本上读完接口文档就知道怎么写代码了。
在上一篇支付系统之银行卡支付中,挖了个坑,就是关于绑卡的坑。在用户使用银行卡做支付之前,首先需要完成绑卡的操作。怎么实现绑卡,怎么验证用户绑的是自己的而不是隔壁老王的卡,这就是本期的重点。
如果说用户绑卡是图省事,那商户为什么要做这个事?首先当然是提升用户体验了,让用户花钱更容易。其次,提升支付成功率。使用网银支付成功率在20%左右,银联直联成功率一般在50%左右,银行卡直联可以提升到70%左右。这是相当可观的数据。所以,当你看到绑卡送洗衣粉之类做法时,不需要担心商家会不会赔本。
怎么绑卡?我们知道对接银行有两种途径,直接对接银行接口和通过银联来间接对接。这两种情况下绑卡处理也不同。
直观的,电商网站会在用户后台提供一个绑卡的入口,让用户直接绑卡。以支付宝绑卡流程为例,我们可以体验下:
这里有如下要点:
对这个入口不要指望太多,更多的用户是在支付中绑卡。也就是提交订单后,发现没有银行卡了,就开始绑卡。和纯绑卡流程不同的是,最后一步,绑卡成功后,一般都同时完成支付。有些渠道会提供绑卡并支付的接口,减少交互次数。
先介绍比较简单的银联直联绑卡。为了保证卡的安全,绑卡有这些前置需求:
这里有个问题,如何根据卡号判断发卡行?这就需要卡bin。BIN号即银行标识代码的英文缩写。BIN由6位数字表示,出现在卡号的前6位,由国际标准化组织(ISO)分配给各从事跨行转接交换的银行卡组织。银行卡的卡号是标识发卡机构和持卡人信息的号码,由以下三部分组成:发卡行标识代码(BIN号)、发卡行自定义位、校验码。
目前,国内的银行卡按照数字打头的不同分别归属于不同的银行卡组织,其中以BIN号“4”字打头的银行卡属于VISA卡组织,以“5”字打头的属于MASTERCARD卡组织,以“9”字和“62”、“60”打头的属于中国银联,而“62”、“60”打头的银联卡是符合国际标准的银联标准卡,可以在国外使用,这也是中国银联近几年来主要发行的银行卡片。大部分银行卡号前6位即可确定发卡行和卡类型,但也有非标卡需要6-10位才可以判断出来。需要维护一个卡bin库。附件是一个比较完整的卡bin库,csv格式的。
一般绑卡操作第五步需要银行下发短信验证码。短信验证的接口,不同银行还不一样。有些银行是短信和身份验证一起做了;有些银行是可以配置身份验证是否同时发短信。还有些比较奇葩的机构,比如某联,接口中让你传身份信息,但实际上没传也是可以的,也不验证身份信息到底对不对。这在对接渠道时需要特别注意。
此类接口一般包含如下内容:
系统会返回上述数据的验证结果。如果验证通过,则会发短信。但这不是所有的渠道都是这样。哪些字段会参与验证、需不需要发短信,需要注意看接口文档。
绑卡接口和发短信接口类似,还需要将用户的卡号,身份证等信息传递过去。在绑卡成功后,会返回一个签约号。这个签约号是后续调用支付,解约等接口所必须的。这里有个问题,已经绑卡的用户,调用绑卡签约接口再绑一次,会出现什么情况?这个和银行实现有关。大部分银行,如农业、浦发、建行等,对绑卡签约接口调用,会首先验证身份信息,如果验证不通过,则不执行后续操作。验证通过后,再检查这个卡在该商户下是否已经绑过了,如果没有绑过,则执行绑卡,否则会提示卡已经绑定过了,不能重复签约。但工行的实现不一样,他是首先验证这个卡是不是已经绑过了,如果已经绑卡,则不继续验证身份信息。总之,银行都不支持重复绑卡。
银联直联绑卡和银行绑卡类似,但是得注意验证接口,仅验证卡号和姓名,不验证身份证号和手机号。这导致第5步无法正常进行。银联只有到第六步执行绑卡时才做身份验证。所以在处理上,还需要做一些调整,来确保和银行的流程的一致。一种处理方法是,对银联,在第五步就开始调用银联接口执行绑卡操作,但是在本地标记为预绑卡状态;商户侧发送短信验证码,验证通过后,才将状态设置为绑卡成功。
银联网银绑卡处理起来比较麻烦。用户在电商页面上输入卡号,然后被导航到银联页面上去完成绑卡操作,成功后,银联返回一个token作为签约号,用于支持后续操作。这问题就来了,用户可以在银联页面上绑定一个别人的卡,而电商侧是无法知道这个卡的情况的。所以这种方式尽量不要用。
绑卡操作有个不错的副产品,就是实名认证。常说的二要素,三要素,四要素认证,可以通过这个操作完成。二要素指姓名和身份证号,三要素加上银行卡号,四要素则加上手机号。看起来,似乎银行都应该支持四要素验证,但大部分银行接口仅支持三要素,毕竟手机号还是非常容易变。当然,实名认证,也就是二要素认证,是应用最多的认证了。国内唯一的库是在公安部这,由NCIIC负责对外提供接口。可以提供如下功能:
官方接口收费是5元/条。市面上主要的第三方服务提供商有国政通(简项、返照)、诺证通(简项)、IDface(三接口)等,收费简项核查:0.5~2.0元、返照核查为0.8~2.1元、人像核查2.0~8.0元不等。一般都和访问量有关,量大从优。
应用内支付指使用手机操作系统自带的支付功能来支持支付。目前国内主要的应用内支付有GooglePay、ApplePay、小米支付、华为支付等。其中ApplePay是典型的一个应用内支付,Android平台的各种支付也一般是沿用ApplePay的设计。
1.2AppsutilizingasystemotherthantheIn-AppPurchaseAPI(IAP)topurchasecontent,functionality,orservicesinanAppwillberejected.
在App内使用非IAP的系统来购买内容、功能或服务将被拒绝。
11.3AppsusingIAPtopurchasephysicalgoodsorgoodsandservicesusedoutsideoftheAppwillberejected.
IAP购买实物或者应用外的商品或服务将会被拒绝;
11.4AppsthatuseIAPtopurchasecreditsorothercurrenciesmustconsumethosecreditswithintheApp
通过IAP购买的积分或者其他货币必须只在App内使用。
这问题就来了,如果要购买的服务,即在IOS内使用,也在Android等IOS系统外使用,那应该是使用规则11.2或者规则11.3来执行?比如说视频网站,视频既可以在IOS上看,也可以在Android上看,那是否是需要通过IAP来购买?苹果公司在这一点上采取模糊的策略。爱奇艺、腾讯视频,在IOS上购买会员,只能用IAP支付。这就和苹果公司的审核有关。
一般IAP支付的开发流程,首先需要一些准备工作,包括:
完成这些准备工作后,既可以进入正式的开发,开发代码我们这里就不说了,流程如下:
老司机都能看出来,这里有好多好多的坑。
IAPSubscription又是一个大坑。官方的文档在这里。内容不多,没有说明的东西却很多。
IAP主要提供给周期性订阅的音乐、电子书等内容使用。一般就按月来计算周期。苹果是以自然月来算权益周期。比如在1月3号买了权益,到2月3号,这个权益就过期啦,需要在此之前完成续费。那问题来了,1月31号买的权益,到几号过期?以自然月算,这个权益会在3月1日前到期,如果2月份,3月份都续费了,到4月份,也是享受到4月30日了。
免费试用不是强制需求,但这有利于用户判断是否值得购买这个物品。免费试用期是在itunesconnect中设置。当用户第一次购买这个东西的时候,客户端接收到的Receipt中包含免费试用信息。在免费期快到的时候,苹果发起第一次扣款。整个过程和自动续费类似,唯一区别是第一个月是免费的。
客户端接收到Receipt之后,需要提交到服务器端进行处理,开通权益。这就来了个问题:Receipt应该在客户端还是服务器端解析?当然需要在服务器端处理,这样可以防止越狱后的一些插件,如IAPCracker、IAPFree等伪造交易凭证,欺骗苹果服务器,开通权益。此外,还需注意,客户端和服务器端之间需通过HTTPS以及参数签名等方式来确保通讯安全。服务器端接收到Receipt之后,首先验证请求的有效性,然后将Receipt发送到苹果服务器上进行验证和解析。接收到苹果处理结果后,将Receipt中的user_id,product_id、purchase_date、transaction_id等做验证和处理。
既然Iap的验证主要是在苹果服务器端和手机客户端进行,并且是使用域名。这简直是为攻击打开了一扇大门,而不仅仅是漏洞。早期的IAP内购解锁工具IAPcracker对IAP的破解比较简单粗暴。写过IAP程序的人都知道,程序中基本都是用transactionState来判断交易是否成功。
transactionState有四个状态:
SKPaymentTransactionStatePurchased表示购买成功了。只要修改这个变量值,如果客户端应用直接根据交易状态来处理业务流程,那就会收到这个假的交易成功信息,接下来用户就能不花钱得到所买的物品。这个过程,甚至都不需要接入网络。
另一个工具IAPfree功能更强大,安装使用也复杂很多。它是通过修改DNS,让客户端访问黑客提供的服务器来取代访问苹果服务器,实现所谓的MITM中间人攻击。当用户在客户端触发购买流程时,会被引导到伪装的苹果服务器上,不扣款而直接返回扣款成功收据。用户不需要支付任何资金,客户端能够拿到完整的收据。如果是在客户端处理收据验证也没有任何问题。为了避免用户所使用的设备被封,这些软件甚至可以提供伪造UDID的功能。为此,苹果特别说明,一定要在服务器端验证用户购买信息,验证内容包括收据签名,证书,产家信息等,确保收据无误后,才能授予权益。如果发现有诈,则将用户拉黑。
基准价格调整,如果是往高了调整,则在用户下一次续费时,需要用户确认。如果往低了调,那就不需要用户确认,直接扣款了。
苹果对商家的产品价格体系有分组(Group)的概念,同国内说的价格体系,比如白金会员、黄金会员、贵宾等,在同一个Group里面,用户只能选择一个档,比如用户要么是白金要么是黄金会员,不会同时是。
目前用的是IOS10.0版本,这个版本和IAP有关的坑,先记录下: