电商账户系统设计

01 背景

设立账户系统的目的是为了完善公司作为电商平台的清结算体系, 将内部账户和外部账户关联起来,通过渠道接口实现资金划拨(各类资金托管外部渠道避免二清), 满足财务记账需求。注:为了这里说的外部账户是在外部渠道侧开立的账户。

1、账户领域需要什么功能,与哪些其他系统交互?
2、账户记账方式(单式/复式),记账符号(增减/借贷)?
3、需要创建哪些数据库表结构

收到需求,然后开始一顿:mag:,于是账户、财务、会计、清分、结算这些词语都跳出来了,更恶心的还有人把财务/账务/账户/帐户这几个字放一起。然而并没有一个很清晰的解释,即:为什么要划分这些领域,各领域的边界在哪?

大家都很容易陷入一个怪圈,习惯于强行向网上流传的大厂的”业务架构设计“靠拢,为了领域设计而设计,为了标准化而标准化。而脱离了初衷:业务方是否有需求?考虑业务架构的拓展性无可厚非,但臆想业务需求其实就没必要了。

(当然网上前辈总结出的方案是很有启发的,系统职责更细分,在此分享几篇个人觉得比较有价值的


  

1、《支付系统中,账户体系的设计与记账处理》

http://www.woshipm.com/pd/681205.html

2、《支付系统设计:支付系统的账户模型》

http://www.woshipm.com/pd/459443.html

3、《全面解构支付系统设计——你不可不知的会计核心》

http://www.woshipm.com/pd/1586244.html

02 账户的作用 

电商账户领域功能:

1、支付、退款、充值、提现、转账

2、记账、对账

3、内外账户映射(如有外部账户场景)

很多公司会按照交易、财务两个领域划分出两个账户系统。交易领域账户更常见的是 给用户提供一个零钱账户用以支付或者支付时抵扣。财务领域的偏向于异步记账结算。 个人感觉也是OK的,毕竟交易领域对实效性处理要求更高。

03 账户系统如何交互 

和账户相关的,这里简单划分为上面几个。

简单提下财务系统职责, 财务系统订阅订单消息后,生成账单。如针对每个订单生成营销款账单,运费账单,售后退款账单。生成账单的过程其实完成了【清分】的动作,即按照一定规则(比如货款结算规则,平台抽成比例,营销费用补贴方式)计算出各方的应收应付。 财务系统向账户系统发指令进行不同账户间不同类型的转款。这个动作,就叫会计分录。(可以了解下简单分录和复合分录)

04 账户模型

4.1 记账方法

      这里选用收付记账法(简单理解为收付记账和增减记账法是一回事)。记账符号为收/支。

账户类型就是我们说的科目。

采用借贷记账时需要关心账户的所属科目以确定记账方向,参考以下记账口诀

借增贷减是资产,权益和它正相反。

成本资产总相同,细细记牢莫弄乱。
损益账户要分辨,费用收入不一般。
收入增加贷方看,减少借方来结转。

在收付记账法中,记账方向和科目无关。相信这一点可以将很多人从上面让人混淆的记账公式中解脱出来。

总结:   如果不是面向会计人员和会计工作流(会计账会计凭证会计核算)设计账户系统,建议采用这种。记账逻辑简单而且足以描述经济业务行为,需要的时候流水也可以转换为借贷记账形式导给财务。

4.2 账户属性    

账户主体表
账户号 account_no
客户号 customer_no
客户类型 customer_type
有效余额 balance
冻结金额 frozen_amount
账户类型 account_type
账户名称 account_name
账户状态 status
是否可提现 withdraw_flag
是否关联外部户 extern_account_flag
是否为虚户 dummy_flag
是否可提现 withdraw_flag
是否关联外部户 extern_account_flag
是否为虚户 dummy_flag
外部账户主体
内部账户号 account_no
外部渠道代码 customer_no
外部账户号 customer_type
外部账户名 balance
外部账户类型 frozen_amount
备注 account_type
是否可提现 withdraw_flag

1、客户号和账号是一对多的关系。譬如同一个商家会存在待结算户(不可提现)和余额户(可提现)两种账户。

2、客户类型包括:用户(买家)、平台、商家(卖家)

3、如果关联外部户,内部的账户动作需要关联外部账户调用外部接口保持一致。这里采用TCC柔性事务保持最终一致。比如转账、提现、结算。

4、虚户作为一种特殊账户。特点是无余额。只记录流水不更新余额。比如平台中间户就是一个频繁使用的虚户。既有资产性质(比如在途资金)又有负债性质(应付资金),应该对应会计科目中的共同类。

4.3 同步入账和异步入账

首先明确一点:一切经济业务行为最终都会分解为两个或者多个账户之间的 转账

业务账单最终分解为账户流水可以参考上图。大多数在财务系统进行定义分录方案,然后调用账户接口进行会计分录记账。但针对某些业务行为需要账户系统自身处理的,比如提现。这时候业务账单记录在账户系统内。

资产变动请求表中记录会计分录的方案,为每次的转账生成一个处理流水。当然请求不一定成功,失败的话,进行回滚操作(释放冻结账户余额等)。所以请求表中数据状态包括:初始、已完成、已回滚。

同步入账: 所以对于外部系统而言,转账是最原子化的操作。如果是纯粹的内部转账,可直接将资金变动请求表中数据状态置为已完成,更新双方余额并在双方账户下分别生成收款、付款的流水。

异步入账: 先提交请求(Try),业务处理成功后确认入账(Confirm),业务处理失败后回滚(Cancel),像余额组合支付、余额提现时(标准的TCC流程) 。另外在关联外部户时,异步调用外部渠道的接口成功后再进行内部入账确认。

突然感觉画面索然无味。先写到这吧~~~

附录:

业务表(这里以提现表为例)


 

CREATE TABLE `account_withdraw_log` (

`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键字段',

`withdraw_no` varchar(32) NOT NULL COMMENT '提现流水号',

`customer_no` varchar(32) NOT NULL COMMENT '客户号',

`account_no` varchar(32) NOT NULL COMMENT '账户号',

`amount` decimal(15,2) NOT NULL COMMENT '提现金额',

`channel` varchar(32) NOT NULL COMMENT '提现渠道',

`payee_name` varchar(128) NOT NULL COMMENT '收款人姓名',

`bankcard_no` varchar(32) NOT NULL COMMENT '收款账号',

`bank_name` varchar(64) NOT NULL COMMENT '银行简称',

`memo` varchar(64) DEFAULT NULL COMMENT '提现备注',

`status` varchar(32) DEFAULT NULL COMMENT '提现状态(初始:INIT,完成:COMPLETED 处理中:PROCESSING 失败:FAIL)',

`error_msg` varchar(128) DEFAULT NULL COMMENT '错误信息',

`extern_trade_no` varchar(64) DEFAULT NULL COMMENT '外部渠道流水号',

`mobile_phone` varchar(16) DEFAULT NULL COMMENT '手机号',

`finish_time` datetime DEFAULT NULL COMMENT '完成时间',

`fee` decimal(15,2) DEFAULT 0.00 COMMENT '渠道手续费',

PRIMARY KEY (`id`) COMMENT '主键',

UNIQUE KEY `uk_withdraw_no` (`withdraw_no`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账户提现流水';

资金变动流水表


 

CREATE TABLE account_transaction_log(

id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键字段',

transaction_no VARCHAR(32) NOT NULL COMMENT '流水号',

account_no VARCHAR(32) NOT NULL COMMENT '账户号',

other_account_no VARCHAR(32) COMMENT '交易对方账户',

amount DECIMAL(15,2) NOT NULL COMMENT '交易金额',

biz_type VARCHAR(32) NOT NULL COMMENT '业务类型',

out_biz_no VARCHAR(64) NOT NULL COMMENT '业务单号',

memo VARCHAR(128) COMMENT '交易备注',

extern_flag TINYINT NOT NULL COMMENT '是否关联外部资金变动',

extern_account_no VARCHAR(64) COMMENT '关联的外部账号',

extern_trade_no VARCHAR(64) COMMENT '外部渠道流水号',

ending_balance DECIMAL(15,2) COMMENT '变动后余额',

fund_direction VARCHAR(16) NOT NULL COMMENT '资金流向(入账:IN 出账:OUT)',

PRIMARY KEY (id),

CONSTRAINT uk_transaction_no UNIQUE (transaction_no)

)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='账户资金变动流水';

资金变动请求表


 

CREATE TABLE account_transaction_proposal(

id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键字段',

create_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '记录创建时间',

update_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL COMMENT '记录最近修改时间',

proposal_no VARCHAR(32) NOT NULL COMMENT '序列号',

payer_account_no VARCHAR(32) NOT NULL COMMENT '付款方账号',

payee_account_no VARCHAR(32) NOT NULL COMMENT '收款方账号',

amount DECIMAL(15,2) NOT NULL COMMENT '金额',

biz_type VARCHAR(32) NOT NULL COMMENT '业务类型',

out_biz_no VARCHAR(64) NOT NULL COMMENT '业务单号',

memo VARCHAR(128) COMMENT '备注',

status VARCHAR(32) NOT NULL COMMENT '提交状态(初始:INIT 确认:COMMIT 回滚:ROLLBACK)',

PRIMARY KEY (id),

CONSTRAINT uk_proposal_no UNIQUE (proposal_no),

CONSTRAINT uk_acctno_biztype_outbizno UNIQUE (biz_type, out_biz_no, payer_account_no,

payee_account_no)

)ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='资金变动请求表';

猜你还想看这些文章

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章