ios支付寶花唄分期利息計算有誤差

前段時間,項目里需要集成支付寶的花唄分期功能,然后沒有多想,就參照著支付寶的集成文檔開始進行(其實大部分都是服務端的工作),按照分期數6期,12期這兩種分期數來實現,6期和12期的費率分別是4.5%和7.5%,一開始在計算總的手續費和對應的每個月手續費時,大意的以為,可以直接用float或者double類型的數據直接去計算,然后采用四舍五入的方式就可以了,最后發現,理想和現實還是有差距的,計算出來的數值與支付寶的app中,采用花唄分期功能計算出來的數值總是會有一定的誤差,于是開始找原因,仔細的去閱讀支付寶關于花唄分期這一塊的文檔,看到了關于分期費率計算的內容,官方文檔具體內容如下:

買家分期費用計算規則

具體計算方式如下:

計算精度

計算中涉及金額均以分為單位,即保留兩位小數;

用戶每期本金

用戶每期本金=商品金額/期數(計算過程以 Java 代碼為例)

把金額單位轉化成分 cent;

計算每期本金(用總金額/總期數,結果以分表示,向下取整);

BigDecimal eachPrin=BigDecimal.valueOf(payAmount).divide(newBigDecimal(“期數”),BigDecimal.ROUND_DOWN)

用戶每期手續費

用戶每期手續費=(商品金額*手續費率)/期數 (計算過程以 Java 代碼為例)

1.把金額單位轉化成分 cent 。

2.用轉化為分后的金額乘以買家費率,得到以分表示的買家總費用。

BigDecimal totalFeeInDecimal=BigDecimal.valueOf(cent).multiply(feeRate)

3.對費用進行取整(取整規則為 ROUND_HALF_EVEN )。

long totalFeeInLong=totalFeeInDecimal.setScale(0,BigDecimal.ROUND_HALF_EVEN).longValue()

4.計算每期費用(用總費用/總期數,結果以分表示,向下取整)。

BigDecimal eachFee=BigDecimal.valueOf(totalFeeInLong).divide(newBigDecimal(“期數”),BigDecimal.ROUND_DOWN)

用戶每期總費用

根據上述用戶每期本金、用戶每期手續費計算結果,將兩者相加,結果以分表示(計算過程以 Java 代碼為例)。

BigDecimal prinAndFee=eachFee.add(eachPrin);

應用案例

例:商品金額為 1111.11 元,用戶選擇 3 期分期,用戶承擔手續費,3 期分期費率為 2.3% :

用戶每期本金=111111/3=37037(370.37 元)。

用戶每期手續費=(111111*2.3%)/3=852(8.52 元)。

用戶每期總費用=37037+852=37889(378.89 元)。

以上計算以“分”為單位。

注意:

花唄分期的總手續費實行“四舍五入”的原則進行計算;

當商品金額不能被分期的期數整除時,金額按分取整,除不盡的余數加入到第一期。無論是本金還是手續費,都依此規則執行。


于是豁然開朗,首先,我們注意到,并不是單純的去計算浮點類型或者double類型的數據,而是轉換成Decimal類型,而且注意到,在對計算的費用進行取整的時候,分別用到了ROUND_DOWN和ROUND_HALF_EVEN算法.這個時候,就已經完全明白該如何去計算對應的費用了.

在iOS中,提供了NSDecimalNumber數據類型來對應Java中的Decimal類型.下面我將以一個計算的實例來展示ios端代碼如何計算花唄分期所需展示的所有費用:


/**總金額轉化成分為單位*/

? ? CGFloat originTotalMoney = [self.resultTextF.text floatValue]*100;(輸入框是自己輸入的花唄分期自定義金額)


? ? /**總金額decimal格式*/

? ? NSDecimalNumber *total = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",originTotalMoney]];


? ? /**分期6個月費率*/

? ? NSDecimalNumber *sixRate = [NSDecimalNumber decimalNumberWithString:@"0.045"];


? ? /**分期12個月的費率*/

? ? NSDecimalNumber *yearRate = [NSDecimalNumber decimalNumberWithString:@"0.075"];

????NSDecimalNumber *hundred = [NSDecimalNumber decimalNumberWithString:@"100"];



? ? /**分期6個月總手續費*/

? ? NSDecimalNumber *sixResult = [[total decimalNumberByMultiplyingBy:sixRate] decimalNumberByDividingBy:hundred withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];


? ? /**分期12個月總手續費*/

? ? NSDecimalNumber *yearResult = [[total decimalNumberByMultiplyingBy:yearRate] decimalNumberByDividingBy:hundred withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];



? ? /**每期本金(不含手續費)*/

????NSDecimalNumber *sixBaseMoney = [total decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"600"] withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];

??NSDecimalNumber *yearBaseMoney = [total decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"1200"] withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];

? ? /**每期的手續費*/

? ? NSDecimalNumber *sixEachFee = [sixResult decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"6"] withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];


? ? NSDecimalNumber *yearEachFee = [yearResult decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"12"] withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];



? ? /**每期總費用(包含手續費)*/

? ? NSDecimalNumber *sixMonthEachMoney = [sixBaseMoney decimalNumberByAdding:sixEachFee withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];


? ? NSDecimalNumber *yearMonthEachMoney = [yearBaseMoney decimalNumberByAdding:yearEachFee withBehavior:[NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO]];


上述代碼,NSRoundDown對應支付寶文檔RoundDown算法,NSRoundBankers對應ROUND_HALF_EVEN算法,在計算對應的費用時保證使用支付寶文檔所要求的對應算法,基本上就不會有什么問題啦.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。