From eaf77eb6fb01f177504ed5e7afc77dd2e57e8a45 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Diego=20Mu=C3=B1io?= <muniodiego@gmail.com>
Date: Thu, 30 Apr 2020 10:16:25 -0300
Subject: [PATCH] Fix #196 - Recurring contributions with incorrect amount per
 default currency in stripe

---
 CRM/Core/Payment/Stripe.php    |  5 +----
 CRM/Core/Payment/StripeIPN.php | 10 ++++++++--
 CRM/Stripe/Api.php             | 16 ++++++++++++++++
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/CRM/Core/Payment/Stripe.php b/CRM/Core/Payment/Stripe.php
index 3c856783..8e04d134 100644
--- a/CRM/Core/Payment/Stripe.php
+++ b/CRM/Core/Payment/Stripe.php
@@ -725,14 +725,11 @@ class CRM_Core_Payment_Stripe extends CRM_Core_Payment {
           }
           if (($stripeCharge['currency'] !== $stripeBalanceTransaction['currency'])
               && (!empty($stripeBalanceTransaction['exchange_rate']))) {
-            $newParams['fee_amount'] = ($stripeBalanceTransaction->fee / $stripeBalanceTransaction['exchange_rate']) / 100;
+            $newParams['fee_amount'] = CRM_Stripe_Api::currencyConversion($stripeBalanceTransaction->fee, $stripeBalanceTransaction['exchange_rate'], $stripeCharge['currency']);
           }
           else {
             $newParams['fee_amount'] = $stripeBalanceTransaction->fee / 100;
           }
-          // We must round to currency precision otherwise payments may fail because Contribute BAO saves but then
-          // can't retrieve because it tries to use the full unrounded number when it only got saved with 2dp.
-          $newParams['fee_amount'] = round($newParams['fee_amount'], CRM_Utils_Money::getCurrencyPrecision($stripeCharge['currency']));
           // Success!
           // Set the desired contribution status which will be set later (do not set on the contribution here!)
           $params['contribution_status_id'] = CRM_Core_PseudoConstant::getKey('CRM_Contribute_BAO_Contribution', 'contribution_status_id', 'Completed');
diff --git a/CRM/Core/Payment/StripeIPN.php b/CRM/Core/Payment/StripeIPN.php
index 6dcb1b59..89eab6b7 100644
--- a/CRM/Core/Payment/StripeIPN.php
+++ b/CRM/Core/Payment/StripeIPN.php
@@ -442,9 +442,15 @@ class CRM_Core_Payment_StripeIPN extends CRM_Core_Payment_BaseIPN {
     $this->fee = 0.0;
     if ($balanceTransactionID) {
       try {
+        $currency = $this->retrieve('currency', 'String', FALSE);
         $balanceTransaction = \Stripe\BalanceTransaction::retrieve($balanceTransactionID);
-        $this->amount = $balanceTransaction->amount / 100;
-        $this->fee = $balanceTransaction->fee / 100;
+        if ($currency !== $balanceTransaction->currency && !empty($balanceTransaction->exchange_rate)) {
+          $this->amount = CRM_Stripe_Api::currencyConversion($balanceTransaction->amount, $balanceTransaction->exchange_rate, $currency);
+          $this->fee = CRM_Stripe_Api::currencyConversion($balanceTransaction->fee, $balanceTransaction->exchange_rate, $currency);
+        } else {
+          $this->amount = $balanceTransaction->amount / 100;
+          $this->fee = $balanceTransaction->fee / 100;
+        }
       }
       catch(Exception $e) {
         $this->exception('Error retrieving balance transaction. ' . $e->getMessage());
diff --git a/CRM/Stripe/Api.php b/CRM/Stripe/Api.php
index c0a1a96f..239bfcac 100644
--- a/CRM/Stripe/Api.php
+++ b/CRM/Stripe/Api.php
@@ -192,4 +192,20 @@ class CRM_Stripe_Api {
     }
     return NULL;
   }
+   
+  /**
+   * Convert amount to a new currency
+   * 
+   * @param type $amount
+   * @param type $exchangeRate
+   * @param type $currency
+   * @return type
+   */
+  public static function currencyConversion($amount, $exchangeRate, $currency) {
+    $amount = ($amount / $exchangeRate) / 100;
+    // We must round to currency precision otherwise payments may fail because Contribute BAO saves but then
+    // can't retrieve because it tries to use the full unrounded number when it only got saved with 2dp.
+    $amount = round($amount, CRM_Utils_Money::getCurrencyPrecision($currency));
+    return $amount;
+  }
 }
-- 
GitLab