laravel电商学习系列-06 支付模块

1. 前言

支付模块不管在哪个系统都是重要的(跟钱有关系的能不重要嘛)。课程中使用的是yansongda/pay的支付库,集成了支付宝、微信支付,使用方便。支付模块主要是按照支付通道的支付规则编码实现,其实质就是接口请求。课程中侧重开发实现,介绍了支付拓展包的使用。因此,支付集成的部分,本章节暂且跳过,只记录学习点。
课程传送门-支付集成

此外,课程中还实现了电商行业大热分期付款。本章节主要梳理课程中对分期付款的实现方案。
课程传送门-分期付款

2. 功能分析

2.1 支付集成

2.1.1 编码学习

支付模块单拎出来就很抗打,涉及到加解密、字符编码的处理,代码封装。

  • 实现过程
    支付模块比较有意思的是代码实现部分,不同支付通道支持的支付方式不同,传递的参数、验证方式不同。怎么样把不同支付通道的代码封装起来,方便统一处理调用值得去研究。
  • 容器的使用

2.2 分期付款

分期付款可以看作是新的一种支付网关,对于一个订单来说,它跟银行卡支付、支付宝支付一样,都可以作为支付方式,只是它每一期分期付款还是依赖于真实的支付方式支付。


分期付款的逻辑分析

2.2.1 需求分析

分期付款的业务逻辑如下:

  • 只有当商品订单总金额高于某个数值时才可以使用分期付款;
  • 用户使用分期付款时,需要选择还款期限,通常为 3 个月的倍数;
  • 使用分期付款需要支付手续费,不同的还款期限手续费费率不同,还款期限越久费率越高;
  • 分期付款的手续费与银行贷款的利息不同,银行贷款的利息会随着还款而逐渐降低,而分期付款的手续费则是固定的;
  • 使用分期付款后,用户需要立即支付第一期的费用,当第一期费用支付成功后,对应的商品订单状态即变为已支付;
  • 用户需每 30 天还款一次,如果在还款截止日期之后仍未还款,需支付逾期费,逾期费按天计算;
  • 逾期之后产生的逾期费用最多不超过当期的本金 + 手续费;
  • 每一期还款金额计算公式:(本金 + 手续费) / 还款期数 + 当期逾期费;
  • 使用了分期付款的商品订单如果发生退款,则退回所有已支付的本金,手续费与逾期费不退回。

2.2.2 实现逻辑

  1. 选择分期付款下单:
  • 在用户选择分期付款时,按照分期期数和金额计算出每一期需要还款的本金、手续费、还款时间等还款信息;
  • 再用一个定时脚本去计算当期的逾期费;
  1. 分期还款支付:(请求支付和支付回调与普通商品的不一样,需要单独实现)
  • 请求支付,使用当期的流水号、当期支付金额、分期的回调地址和返回地址去请求第三方支付;
  • 按照分期逻辑实现支付回调,更新当期支付信息,若是第一期需更新订单的状态和支付信息,以及分期状态;
  1. 分期退款:
    分期的每一期批量退款,修改订单退款状态;


    分期付款流程图

2.2.3 表设计

分期分款可以选择还款期数,需要计算每一期还款的本金、手续费、还款时间,以及需要保存每一期还款的具体支付方式和支付单号。因此,我们需要用两张表来分别保存分期信息和每期分期的详细信息。
具体表结构如下:

# 分期表
CREATE TABLE `installments` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, # 自增ID
  `no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, # 分期单号
  `user_id` int(10) unsigned NOT NULL, # 所属用户ID
  `order_id` int(10) unsigned NOT NULL, # 对应订单ID
  `total_amount` decimal(8,2) NOT NULL, # 总本金
  `count` int(10) unsigned NOT NULL, # 还款期数
  `fee_rate` double(8,2) NOT NULL, # 手续费率
  `fine_rate` double(8,2) NOT NULL, # 逾期费率
  `status` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending', # 还款状态,默认未执行
  `created_at` timestamp NULL DEFAULT NULL, # 创建时间
  `updated_at` timestamp NULL DEFAULT NULL, # 更新时间
  PRIMARY KEY (`id`),
  UNIQUE KEY `installments_no_unique` (`no`),
  KEY `installments_user_id_foreign` (`user_id`),
  KEY `installments_order_id_foreign` (`order_id`),
  CONSTRAINT `installments_order_id_foreign` FOREIGN KEY (`order_id`) REFERENCES `orders` (`id`) ON DELETE CASCADE,
  CONSTRAINT `installments_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

# 分期项表
CREATE TABLE `installment_items` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, # 自增ID
  `installment_id` int(10) unsigned NOT NULL, # 分期ID
  `sequence` int(10) unsigned NOT NULL, # 期数
  `base` decimal(8,2) NOT NULL, # 当期本金
  `fee` decimal(8,2) NOT NULL, # 当期手续费
  `fine` decimal(8,2) DEFAULT NULL, # 当期逾期费
  `due_date` datetime NOT NULL, # 还款截止日期
  `paid_at` datetime DEFAULT NULL, # 还款日期
  `payment_method` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, # 还款支付方式
  `payment_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL, # 换的支付单号
  `refund_status` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'pending', # 退款状态 默认未退款
  `created_at` timestamp NULL DEFAULT NULL, # 创建时间
  `updated_at` timestamp NULL DEFAULT NULL, # 更新时间
  PRIMARY KEY (`id`),
  KEY `installment_items_installment_id_foreign` (`installment_id`),
  CONSTRAINT `installment_items_installment_id_foreign` FOREIGN KEY (`installment_id`) REFERENCES `installments` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

2.3.4 代码借鉴

本章节业务逻辑有点复杂,实现方案不算复杂,学习到了以下几点:

  • 浮点数的计算方式(使用 bcmath)
  • 在处理大数据量的数据库操作时,使用chunkById减少内存占用;

上一节:05 购物车&订单模块
下一节:07 优惠券模块

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • 随着布拉格第一场雪的到来,这里即将进入圣诞季的节奏,尽管冬季的布拉格气候寒冷,但还是阻挡不了游客们的脚步! 布拉格...
    华007阅读 527评论 0 1
  • 今日体验 今天开数据分析会,有很多项目的是空的,检查一定要仔细,逢车必检不能落下,保证质量把车修好
    王松奇阅读 146评论 0 0
  • 文/陈康慧 刚上班的那几天每天如履薄冰步步惊心,生怕自己哪里做错了不够好这份工作就没了。 因为人,都有个天性,就想...
    陈康慧阅读 847评论 0 13