Skip to content

fix(processor): take into account fraction digits with Adyen #288

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

joey-koster-ct
Copy link
Contributor

@joey-koster-ct joey-koster-ct commented Jan 6, 2025

https://commercetools.atlassian.net/browse/SCC-2800

Introduction

This PR ensures that the connector takes into account fraction digits when sending and receiving data to and back from Adyen.

Dependencies 🛠️

It relies on https://github.com/commercetools/connect-payments-sdk/pull/272 to be merged and this PR needs to include that new version of the package. Locally I have developed and tested it using a local dependency reference. I will update this PR once it's possible but it can already be reviewed.

Background

For the most part Adyen adheres to the https://en.wikipedia.org/wiki/ISO_4217 standard. However they have some deviations for a handful of currencies. As specified https://docs.adyen.com/development-resources/currency-codes/#note.

This means that some conversions are required when sending and receiving data to and from Adyen. An example:

  1. CLP officially has 0 fraction digits
  2. CoCo thus also uses 0 fraction digits when creating carts with currency code CLP
  3. Adyen deviates from this and instead expects 2 fraction digits
  4. Thus if we have a CLP amount of 1100, CoCo also gives back 1100 as well as 0 fraction digit. If we send this value unmodified to Adyen it will interpret it as 11 value.
  5. Thus a conversion is required from 0 to 2 fraction digits before sending the data to Adyen. So 1100 becomes 110000 when sending the amounts to Adyen.
  6. In any place we receive the value from Adyen (in an notification for example) it needs to be converted back again. From 110000 to 1100 before it gets processed further on our side.

@joey-koster-ct joey-koster-ct force-pushed the joey-koster-ct/SCC-2800-fix-amount-fraction-digits branch from faae62b to 5532213 Compare January 7, 2025 15:13
Comment on lines +3 to +17
const CURRENCIES_FROM_ISO_TO_ADYEN_MAPPING = new Map<string, number>([
['CLP', 2],
['CVE', -2],
['IDR', -2],
['ISK', 2],
['CVE', -2],
]);

const CURRENCIES_FROM_ADYEN_TO_ISO_MAPPING = new Map<string, number>([
['CLP', -2],
['CVE', 2],
['IDR', 2],
['ISK', -2],
['CVE', 2],
]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As described in https://github.com/commercetools/connect-payments-sdk/pull/272, positive fraction digits moves the decimal to the right and negative to the left.

So the official standard for CLP is 0 but in the mapping from ISO to Adyen it says 2. And the same thing in reserve happens when mapping from Adyen to ISO.

@@ -23,7 +25,11 @@ export const mapCoCoLineItemToAdyenLineItem = (lineItem: CoCoLineItem): LineItem
amountExcludingTax: getItemAmount(getAmountExcludingTax(lineItem), lineItem.quantity),
amountIncludingTax: getItemAmount(getAmountIncludingTax(lineItem), lineItem.quantity),
taxAmount: getItemAmount(getTaxAmount(lineItem), lineItem.quantity),
taxPercentage: convertTaxPercentageToCentAmount(lineItem.taxRate?.amount),
taxPercentage: convertTaxPercentageToAdyenMinorUnits(
Copy link
Contributor Author

@joey-koster-ct joey-koster-ct Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to properly convert the taxPercentage we need to have access to the fraction digits and the currency code which the tax object does not have directly. Since that is locked into the cart I used the line item totalPrice objects fraction digits and currency code values for this.

};

const convertTaxPercentageToCentAmount = (decimalTaxRate?: number): number => {
return decimalTaxRate ? decimalTaxRate * 100 * 100 : 0;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the previous implementation it was assumed there was always a 2 fraction digits. So for example a tax rate of 0.21 percent in CoCo resulted 0.21 * 100 * 100 = 2100. Which is what Adyen expects, see the following snippet from the Adyen docs:

{
      "quantity": 1,
      "amountExcludingTax": 331,
      "taxPercentage": 2100,
      "description": "Shoes",
      "id": "Item #1",
      "taxAmount": 69,
      "amountIncludingTax": 400,
      "productUrl": "URL_TO_PURCHASED_ITEM",
      "imageUrl": "URL_TO_PICTURE_OF_PURCHASED_ITEM"
    },

However if the fraction digits is not 2 then doing the second multiplication by 100 results in the incorrect minor units conversion.

@joey-koster-ct joey-koster-ct marked this pull request as ready for review January 9, 2025 14:08
@joey-koster-ct joey-koster-ct requested review from a team as code owners January 9, 2025 14:08
@joey-koster-ct joey-koster-ct force-pushed the joey-koster-ct/SCC-2800-fix-amount-fraction-digits branch from ab592d7 to 6b78367 Compare January 10, 2025 09:15
@joey-koster-ct joey-koster-ct merged commit 8a96107 into main Jan 13, 2025
2 checks passed
@joey-koster-ct joey-koster-ct deleted the joey-koster-ct/SCC-2800-fix-amount-fraction-digits branch January 13, 2025 13:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants