准备开发和钱有关的功能,还有哪些地方要注意 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
5bb864e1fc775087
V2EX    程序员

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

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

已知钱精确到分

准备这样处理:

  • 数据库字段类型用 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
看到 [t/569119?p=1#r_7407244]( 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)
metamask
    5
metamask  
   2020-02-24 13:01:37 +08:00   2
- 用 decimal 避免精度问题;
- 用 ROUND_HALF_EVEN 来做处理,可搜下 银行家舍入法;
- 涉及汇率要谨慎,设置好警报,如果哪天接口异常,可及早处理(或者设置好默认范围,正常的波对不会很大);
- 涉及提现要注意舍入问题,避免造成金额损失;
viiii div class="fr">     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     Solana     5542 人在线   最高记录 6679       Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 39ms UTC 08:54 PVG 16:54 LAX 01:54 JFK 04:54
Do have faith in what you're doing.
ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86