06 支付模块

作者: 阳光的小mi | 来源:发表于2019-08-04 17:17 被阅读10次

    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 优惠券模块

    相关文章

      网友评论

        本文标题:06 支付模块

        本文链接:https://www.haomeiwen.com/subject/kwiqrctx.html