V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
5bb864e1fc775087
V2EX  ›  程序员

准备开发和钱有关的功能,还有哪些地方要注意

  •  1
     
  •   5bb864e1fc775087 · 2020-02-24 12:30:47 +08:00 · 7299 次点击
    这是一个创建于 1736 天前的主题,其中的信息可能已经有所发展或是发生改变。

    已知钱精确到分

    准备这样处理:

    • 数据库字段类型用 int,金额单位存成“分”
    • 前端肯定有些地方要计算金额,所以用 decimal.js 进行计算
    • 后端 PHP 用 bc math 库 进行计算

    还有什么要注意的吗?

    35 条回复    2020-03-04 17:11:27 +08:00
    5bb864e1fc775087
        1
    5bb864e1fc775087  
    OP
       2020-02-24 12:31:10 +08:00
    如果预期后面金额会很大的话,字段类型是不是要用 long 型?而不是 int
    5bb864e1fc775087
        2
    5bb864e1fc775087  
    OP
       2020-02-24 12:31:20 +08:00
    看到 [https://www.v2ex.com/t/569119?p=1#r_7407244]( https://www.v2ex.com/t/569119?p=1#r_7407244) 有人说存成分,遇到利率汇率会有问题?
    opengps
        3
    opengps  
       2020-02-24 12:49:19 +08:00 via Android   ❤️ 2
    用 int 不可取,有些时候要用小数的,比如 10 元 9 个需要求单价。
    我接触过的话几次金额相关的都用了 4 小数位或者 6 小数位 decimal
    lvsshuttao
        4
    lvsshuttao  
       2020-02-24 13:01:23 +08:00   ❤️ 2
    楼上说得对,之前做银行项目,要保留 6 位小数,所以一般都用 decimal,我是用 decimal(20,6) ,decimal(16,2)
    freakxx
        5
    freakxx  
       2020-02-24 13:01:37 +08:00   ❤️ 2
    - 用 decimal 避免精度问题;
    - 用 ROUND_HALF_EVEN 来做处理,可搜下 银行家舍入法;
    - 涉及汇率要谨慎,设置好警报,如果哪天接口异常,可及早处理(或者设置好默认范围,正常的波对不会很大);
    - 涉及提现要注意舍入问题,避免造成金额损失;
    viiii
        6
    viiii  
       2020-02-24 13:01:44 +08:00
    最该注意的难道不是安全么?
    dilu
        7
    dilu  
       2020-02-24 13:14:21 +08:00
    四舍六入五成双了解一下
    5bb864e1fc775087
        8
    5bb864e1fc775087  
    OP
       2020-02-24 13:17:50 +08:00
    @opengps #3
    @lvsshuttao #4
    @freakxx #5
    可以,那就改用 decimal
    gavindexu
        9
    gavindexu  
       2020-02-24 14:18:07 +08:00 via iPhone
    int,存储的时候数字先乘 1000
    ihacku
        10
    ihacku  
       2020-02-24 15:04:22 +08:00   ❤️ 1
    后端要校验,我见过好多次前端改包修改订单参数,比如其中一个参数修改为负数,最终一元支付订单的漏洞。
    hantsy
        11
    hantsy  
       2020-02-24 15:45:54 +08:00
    Java 用 Money API,https://javamoney.github.io/
    asmoker
        12
    asmoker  
       2020-02-24 15:46:33 +08:00
    使用 BigDecimal,设置好 MathContext 和 RoundingMode。
    wlfeng
        13
    wlfeng  
       2020-02-24 16:23:23 +08:00   ❤️ 1
    所有跟钱相关的操作一定要留底,所有数据一定要能够溯源
    siganushka
        14
    siganushka  
       2020-02-24 16:24:10 +08:00
    后端用 BC math 就可以不用 int 了,用了 int 后端也就可以不用 BC 了,纯 int 技术不会出错。
    Aresxue
        15
    Aresxue  
       2020-02-24 16:33:22 +08:00
    严格意义上数据库的 decimal 能够满足需求但是数据处理上比较蛋疼,有条件的话用 bigint 存储分,然后整个后端操作里全都使用分单位,尽量避免小数的出现,唯一的缺陷就是 bigint 比较耗费空间 decimal 在 8 位小数时才用 8 个字节,考虑到分单位可能实际中只需要用 5 个字节,相当于每一条记录多浪费 3 个字节的空间,再加上金额这个字段有很多种,结合下来整体的开销还是不小的。所以这就是个用存储换舒适度的问题。
    hteen
        16
    hteen  
       2020-02-24 16:40:09 +08:00
    bc 函数传入参数用 string, 不然要报错
    ```shell
    php > echo bcdiv(0,0.000001,8);
    PHP Warning: bcdiv(): Division by zero in php shell code on line 1

    Warning: bcdiv(): Division by zero in php shell code on line 1
    ```
    royzheng
        17
    royzheng  
       2020-02-24 16:41:10 +08:00
    你的系统不知道怎么样 ,两个方案你选吧
    1. 使用 bigint,固定小数点位置,比如后三位是小数点
    2. 使用 decimal
    你在这里问,说明你这系统也没多大,所以哪种都行
    jakychen
        18
    jakychen  
       2020-02-24 16:54:30 +08:00   ❤️ 1
    宁愿少给 也不要多给
    kylinC
        19
    kylinC  
       2020-02-24 19:07:19 +08:00 via iPhone
    实际舍入模式要根据实际业务来,不能一味地用银行家模式,这样对账时才能理得清。不知道你是做终端用户的还是只是通道转接或者其他,不管哪方面注意筛选风险交易,也就是做好风控,类似的方面还有很多,有些重要地方特别要注意,一不小心就进去了。
    luozic
        20
    luozic  
       2020-02-24 19:09:43 +08:00 via iPhone
    找个专门做这个的律师咨询一下,这种进去了一版不是轻罪
    CStarter
        21
    CStarter  
       2020-02-24 22:01:13 +08:00
    1.涉及汇率,可能出现小数,例如中东项目一般要保留到 7 位小数。
    2.事务回滚,一定要严测事务一致性。
    3.操作日志,任何一步都要有日志(写入数据表里的日志)
    learnshare
        22
    learnshare  
       2020-02-24 22:12:47 +08:00
    操作全部记录,记录多处备份
    自动计算审核,必要时人工审核
    NoString
        23
    NoString  
       2020-02-24 23:27:55 +08:00
    汇率汇率汇率 重要的事说三遍 一定要注意汇率(如果涉及外币)
    sleepm
        24
    sleepm  
       2020-02-24 23:55:45 +08:00 via Android
    幂等...
    还有存时间戳
    lc7029
        25
    lc7029  
       2020-02-25 00:12:33 +08:00
    银行的套路,出现问题就崩溃,不会带着 bug 运行
    rainysia
        26
    rainysia  
       2020-02-25 00:36:50 +08:00
    跨国电商. 汇率小数点后 10 位了解一下..主要要支持很多币种, 比如 1 USD :13000 INR 的 INR. 1 USD: 23000 的 VND.
    稍微金额一大, 肉眼可见的误差.
    summic
        27
    summic  
       2020-02-25 00:54:59 +08:00
    一定要做好防护,例如熔断,将损失控制在一定范围内。
    人是不可靠的,bug 也避免不了,得能够保障整个体系做到允许损失几万、几十万,但绝不能损失上千万
    Mohanson
        28
    Mohanson  
       2020-02-25 01:38:12 +08:00 via Android
    存成分在算汇率的时候要特别注意,"一分钱能换到 0 美分"这种奇葩,反正做分母的时候一定要设置最小值…
    ericgui
        29
    ericgui  
       2020-02-25 03:31:46 +08:00
    @rainysia。。。。。。真没想到啊,,。。。。
    eamon666
        30
    eamon666  
       2020-02-25 11:07:46 +08:00
    注意 事务和锁 select * from id for update 可以参考参考。
    qyvlik
        31
    qyvlik  
       2020-02-25 14:26:19 +08:00
    数据库的金额字段:用 decimal,控制好小数位数,例如 decimal(20,6),或者 decimal (20, 8),按实际需要定制小数位数。
    数据库表设计和业务逻辑:账务系统是金融电子系统的核心,账务系统记录了用户、商户、客户等包括平台相关账户(运营账户、营收账户)的当前资产和资产流向。可以先了解复式记账,资产类型,热点账户等。
    数据库事务隔离:MySQL 的话,优先 READ-COMMITTED,性能好一些 ,REPEATABLE-READ 对实时对账逻辑设计友好一些。
    锁:在性能和安全上做平衡。
    对账:如果没有分布式事务的问题,通过账务系统可以进行实时对账。如果涉及到分布式事务、TCC 柔性事务、使用消息队列做事务补偿时,以上情况需要对对账系统做额外设计。
    编程语言:使用类似 bigdecimal 库,注意进位方式。
    前端展示:建议不要做过多的计算(前后台计算的进位选择不一致,导致展示上不一致),直接让后台返回计算好的结果(字符串)。
    技术之外的建议,政策、法律法规、权限等多多做功课。
    biguokang
        32
    biguokang  
       2020-02-25 16:28:23 +08:00
    价格计算千万要放在后台,前端只能传货物 id 和货物数量上来,然后你后端就根据货物 id 从数据库查出货物单价,然后让货物单价*货物数量,得出来的价格(先不考虑折扣之类的附加项)丢给各种支付 api 处理。。。。。。。


    还有如果你要和支付宝或者微信支付做对接,你要清楚微信支付和支付宝是以分为单位的,记得区分好元和分,例如你要转 1 块钱给别人,那么你传给支付宝或者微信支付的数据就是 100,我上家公司试过,数据库里面把价格单位定为元,然后一小哥没做转换,看到微信支付支付成功回调返回来的价格字段是 10000 ( 10000 分就是 100 块的意思),自然而然没有做转换所以把价格也存为 10000,导致了一些客户存 100 块能体现 10000 块的 bug。。。。
    q447643445
        33
    q447643445  
       2020-02-25 21:40:56 +08:00
    数据库 decimal . java bigdecimal .
    我觉得这个不好的点就是. 写计算公式的时候 代码又臭又长
    chenhui7373
        34
    chenhui7373  
       2020-02-25 23:26:18 +08:00
    php 记得只要把单位调低 数字变大就避免了很多问题,

    100 分 = 1 元
    LDa
        35
    LDa  
       2020-03-04 17:11:27 +08:00
    技术实现问题都不大,准备点钱赔差额就行
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3374 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 117ms · UTC 12:37 · PVG 20:37 · LAX 04:37 · JFK 07:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.