Braintree PHP 设置数量和避免舍入错误

Posted

技术标签:

【中文标题】Braintree PHP 设置数量和避免舍入错误【英文标题】:Braintree PHP setting amount and avoiding rounding errors 【发布时间】:2017-07-24 21:52:34 【问题描述】:

我正在创建一个使用 php/Laravel 和 Braintree 进行支付的网络应用程序。我正在使用 Braintree dropin。

网络应用的简化流程:

    用户上传文件并从下拉列表中选择服务,提交表单 向用户显示的报价/价格是根据上传文件的字数 * 选择的服务计算得出的 用户通过 Braintree 插件选择付款,提交表单付款 Web 应用程序触发 Braintree_Transaction::sale() 用户显示成功页面

向客户收费

关于上述内容,我想就在步骤 4 中的 Braintree_Transaction::sale() 方法调用中设置金额的最佳做法获得一些建议。

在 Braintree PHP example on github 中,Braintree_Transaction::sale() 方法调用中使用的数量取自表单中的文本输入,这可以由用户编辑,我假设是出于示例目的。

在上述我的网络应用程序流程中,在第 1 步之后,我是否正确设置会话中所选服务的报价/价格,然后在第 2 步中将会话中的该值显示给用户,最后传递该值从amountBraintree_Transaction::sale() 的会话?还是有不同的推荐方法可以采取?我主要关心的是向客户收取正确的金额。

避免舍入错误

由于报价/价格是在 PHP 中通过获取上传文件的字数并将其乘以客户选择的服务来计算的,因此有时会涉及浮点数。例如。字数为 1000,所选服务为校对 x1.5,因此报价为 1500 => £15.00。

如果我没记错的话,例如,Stripe 表示一磅 (£) 便士 100。这很好,因为它有助于避免舍入错误。另一方面,我相信 Braintree 期望一磅 (£) 用小数点 1.00 表示。

在这种情况下,避免任何舍入错误的最佳方法是什么?

感谢您的任何建议,如果需要,请询问更多详细信息

【问题讨论】:

【参考方案1】:

在会话中设置所选服务的报价/价格是否正确,然后在步骤 2 中将会话中的该值显示给用户,最后将会话中的值作为金额传递给 Braintree_Transaction::sale( )?

是的,这是一种有效的方法。会话值存储在服务器端,因此用户无法直接操作它们,并且旨在跨页面请求携带信息。

另一种解决方案是将购物车之类的东西存储在数据库中。这具有长期存储的优势,因此用户可能会稍后回来完成该过程,您可以轻松地针对它运行报告,并且您可以跟踪诸如辍学率之类的事情。

除了显示值之外,不要相信浏览器。意思是不要将引用存储在浏览器中或在那里执行任何计算,因为它们可以被用户更改。

在这种情况下,避免任何舍入错误的最佳方法是什么?

没有足够多的开发人员在开始项目之前考虑到这一点。如果您不使用整数,则需要使用定点数学。

如果您使用的是关系数据库,请将货币值存储为 DECIMAL。

在 PHP 中,使用正确处理固定位置小数的 bcmath 库计算所有内容。它非常简单,并将数字保存在字符串中。按照你的例子:

$quote = bcmul('1000', '1.5', 2);
// '1500.0'
// Get 2 decimal places for Braintree
$sale = number_format((float)$quote, 2, '.', '');

【讨论】:

非常感谢您的详细解答。另外,关于使用数据库跟踪辍学率的绝佳建议,我没想到!

以上是关于Braintree PHP 设置数量和避免舍入错误的主要内容,如果未能解决你的问题,请参考以下文章

Enumerable#sum 如何避免浮点舍入错误?

vbscript MS Access VBA查询功能将CDec()应用于数字字段(有助于避免舍入错误)

Braintree - 使用过期信用卡创建订阅不会导致错误

如何使用现有的 customerId 处理 Braintree 付款

在 R 中使用 as.numeric() 时如何避免数字舍入?

PHP Braintree 网关 API