已知钱精确到分
准备这样处理:
还有什么要注意的吗?
1 5bb864e1fc775087 OP 如果预期后面金额会很大的话,字段类型是不是要用 long 型?而不是 int |
2 5bb864e1fc775087 OP 看到 [t/569119?p=1#r_7407244]( t/569119?p=1#r_7407244) 有人说存成分,遇到利率汇率会有问题? |
![]() | 3 opengps 2020-02-24 12:49:19 +08:00 via Android ![]() 用 int 不可取,有些时候要用小数的,比如 10 元 9 个需要求单价。 我接触过的话几次金额相关的都用了 4 小数位或者 6 小数位 decimal |
4 lvsshuttao 2020-02-24 13:01:23 +08:00 ![]() 楼上说得对,之前做银行项目,要保留 6 位小数,所以一般都用 decimal,我是用 decimal(20,6) ,decimal(16,2) |
![]() | 5 metamask 2020-02-24 13:01:37 +08:00 ![]() - 用 decimal 避免精度问题; - 用 ROUND_HALF_EVEN 来做处理,可搜下 银行家舍入法; - 涉及汇率要谨慎,设置好警报,如果哪天接口异常,可及早处理(或者设置好默认范围,正常的波对不会很大); - 涉及提现要注意舍入问题,避免造成金额损失; |
![]() | div class="fr"> 6 viiii 2020-02-24 13:01:44 +08:00 最该注意的难道不是安全么? |
7 dilu 2020-02-24 13:14:21 +08:00 四舍六入五成双了解一下 |
8 5bb864e1fc775087 OP |
9 gavindexu 2020-02-24 14:18:07 +08:00 via iPhone int,存储的时候数字先乘 1000 |
![]() | 10 ihacku 2020-02-24 15:04:22 +08:00 ![]() 后端要校验,我见过好多次前端改包修改订单参数,比如其中一个参数修改为负数,最终一元支付订单的漏洞。 |
11 hantsy 2020-02-24 15:45:54 +08:00 Java 用 Money API,https://javamoney.github.io/ |
![]() | 12 asmoker 2020-02-24 15:46:33 +08:00 使用 BigDecimal,设置好 MathContext 和 RoundingMode。 |
![]() | 13 wlfeng 2020-02-24 16:23:23 +08:00 ![]() 所有跟钱相关的操作一定要留底,所有数据一定要能够溯源 |
![]() | 14 siganushka 2020-02-24 16:24:10 +08:00 后端用 BC math 就可以不用 int 了,用了 int 后端也就可以不用 BC 了,纯 int 技术不会出错。 |
![]() | 15 Aresxue 2020-02-24 16:33:22 +08:00 严格意义上数据库的 decimal 能够满足需求但是数据处理上比较蛋疼,有条件的话用 bigint 存储分,然后整个后端操作里全都使用分单位,尽量避免小数的出现,唯一的缺陷就是 bigint 比较耗费空间 decimal 在 8 位小数时才用 8 个字节,考虑到分单位可能实际中只需要用 5 个字节,相当于每一条记录多浪费 3 个字节的空间,再加上金额这个字段有很多种,结合下来整体的开销还是不小的。所以这就是个用存储换舒适度的问题。 |
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 ``` |
![]() | 17 royzheng 2020-02-24 16:41:10 +08:00 你的系统不知道怎么样 ,两个方案你选吧 1. 使用 bigint,固定小数点位置,比如后三位是小数点 2. 使用 decimal 你在这里问,说明你这系统也没多大,所以哪种都行 |
18 jakychen 2020-02-24 16:54:30 +08:00 ![]() 宁愿少给 也不要多给 |
19 kylinC 2020-02-24 19:07:19 +08:00 via iPhone 实际舍入模式要根据实际业务来,不能一味地用银行家模式,这样对账时才能理得清。不知道你是做终端用户的还是只是通道转接或者其他,不管哪方面注意筛选风险交易,也就是做好风控,类似的方面还有很多,有些重要地方特别要注意,一不小心就进去了。 |
20 luozic 2020-02-24 19:09:43 +08:00 via iPhone 找个专门做这个的律师咨询一下,这种进去了一版不是轻罪 |
![]() | 21 CStarter 2020-02-24 22:01:13 +08:00 1.涉及汇率,可能出现小数,例如中东项目一般要保留到 7 位小数。 2.事务回滚,一定要严测事务一致性。 3.操作日志,任何一步都要有日志(写入数据表里的日志) |
![]() | 22 learnshare 2020-02-24 22:12:47 +08:00 操作全部记录,记录多处备份 自动计算审核,必要时人工审核 |
![]() | 23 NoString 2020-02-24 23:27:55 +08:00 汇率汇率汇率 重要的事说三遍 一定要注意汇率(如果涉及外币) |
24 sleepm 2020-02-24 23:55:45 +08:00 via Android 幂等... 还有存时间戳 |
25 lc7029 2020-02-25 00:12:33 +08:00 银行的套路,出现问题就崩溃,不会带着 bug 运行 |
![]() | 26 rainysia 2020-02-25 00:36:50 +08:00 跨国电商. 汇率小数点后 10 位了解一下..主要要支持很多币种, 比如 1 USD :13000 INR 的 INR. 1 USD: 23000 的 VND. 稍微金额一大, 肉眼可见的误差. |
![]() | 27 summic 2020-02-25 00:54:59 +08:00 一定要做好防护,例如熔断,将损失控制在一定范围内。 人是不可靠的,bug 也避免不了,得能够保障整个体系做到允许损失几万、几十万,但绝不能损失上千万 |
![]() | 28 Mohanson 2020-02-25 01:38:12 +08:00 via Android 存成分在算汇率的时候要特别注意,"一分钱能换到 0 美分"这种奇葩,反正做分母的时候一定要设置最小值… |
![]() | 30 eamon666 2020-02-25 11:07:46 +08:00 注意 事务和锁 select * from id for update 可以参考参考。 |
31 qyvlik 2020-02-25 14:26:19 +08:00 数据库的金额字段:用 decimal,控制好小数位数,例如 decimal(20,6),或者 decimal (20, 8),按实际需要定制小数位数。 数据库表设计和业务逻辑:账务系统是金融电子系统的核心,账务系统记录了用户、商户、客户等包括平台相关账户(运营账户、营收账户)的当前资产和资产流向。可以先了解复式记账,资产类型,热点账户等。 数据库事务隔离:MySQL 的话,优先 READ-COMMITTED,性能好一些 ,REPEATABLE-READ 对实时对账逻辑设计友好一些。 锁:在性能和安全上做平衡。 对账:如果没有分布式事务的问题,通过账务系统可以进行实时对账。如果涉及到分布式事务、TCC 柔性事务、使用消息队列做事务补偿时,以上情况需要对对账系统做额外设计。 编程语言:使用类似 bigdecimal 库,注意进位方式。 前端展示:建议不要做过多的计算(前后台计算的进位选择不一致,导致展示上不一致),直接让后台返回计算好的结果(字符串)。 技术之外的建议,政策、法律法规、权限等多多做功课。 |
![]() | 32 biguokang 2020-02-25 16:28:23 +08:00 价格计算千万要放在后台,前端只能传货物 id 和货物数量上来,然后你后端就根据货物 id 从数据库查出货物单价,然后让货物单价*货物数量,得出来的价格(先不考虑折扣之类的附加项)丢给各种支付 api 处理。。。。。。。 还有如果你要和支付宝或者微信支付做对接,你要清楚微信支付和支付宝是以分为单位的,记得区分好元和分,例如你要转 1 块钱给别人,那么你传给支付宝或者微信支付的数据就是 100,我上家公司试过,数据库里面把价格单位定为元,然后一小哥没做转换,看到微信支付支付成功回调返回来的价格字段是 10000 ( 10000 分就是 100 块的意思),自然而然没有做转换所以把价格也存为 10000,导致了一些客户存 100 块能体现 10000 块的 bug。。。。 |
![]() | 33 q447643445 2020-02-25 21:40:56 +08:00 数据库 decimal . java bigdecimal . 我觉得这个不好的点就是. 写计算公式的时候 代码又臭又长 |
![]() | 34 chenhui7373 2020-02-25 23:26:18 +08:00 php 记得只要把单位调低 数字变大就避免了很多问题, 100 分 = 1 元 |
![]() | 35 LDa 2020-03-04 17:11:27 +08:00 技术实现问题都不大,准备点钱赔差额就行 |