Skip to content

Allow underscores in font names on Android for PaymentSheet appearance #1637

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

goguda
Copy link

@goguda goguda commented Apr 5, 2024

Summary

Changed regex expression to allow for underscores in fonts on Android as well, and updated the error to reflect this.

Motivation

See #1636

Testing

  • I tested this manually
  • I added automated tests

Documentation

Select one:

  • I have added relevant documentation for my changes.
  • This PR does not result in any developer-facing changes.

@goguda
Copy link
Author

goguda commented May 27, 2024

Hey, this is still an issue in the latest versions and we're having to work around it with patch-package. We would appreciate if this PR could be considered when someone has a chance. Thank you!

@mahcloud-tinker
Copy link

Same issue here

@jaynewstrom-stripe
Copy link

Hi @goguda Sorry it took us so long to take a look at this. The PR seems reasonable.

Could you rebase, and I'll approve and merge?

@iM-GeeKy
Copy link

iM-GeeKy commented Apr 21, 2025

@goguda @jaynewstrom-stripe I've applied the patch, but I'm using Nunito_400Regular which obviously isn't lowercase. However converting it to lowercase causes errors as I use @expo-google-fonts/nunito and Nunito_400Regular.ttf is the file in the package. I can not set a font for android as mentioned in the issue comment, but it would be ideal to be able to not need platform specific logic for this, given it works fine on iOS.

@goguda
Copy link
Author

goguda commented Apr 25, 2025

@goguda @jaynewstrom-stripe I've applied the patch, but I'm using Nunito_400Regular which obviously isn't lowercase. However converting it to lowercase causes errors as I use @expo-google-fonts/nunito and Nunito_400Regular.ttf is the file in the package. I can not set a font for android as mentioned in the issue comment, but it would be ideal to be able to not need platform specific logic for this, given it works fine on iOS.

If you apply the patch with regex "[^a-zA-Z0-9_]", does it work properly in your case?

I plan on rebasing, but if this fixes your issue as well I think I should adjust the regex to allow for capital letters too before doing so.

@iM-GeeKy
Copy link

iM-GeeKy commented Apr 26, 2025

@goguda @jaynewstrom-stripe I've applied the patch, but I'm using Nunito_400Regular which obviously isn't lowercase. However converting it to lowercase causes errors as I use @expo-google-fonts/nunito and Nunito_400Regular.ttf is the file in the package. I can not set a font for android as mentioned in the issue comment, but it would be ideal to be able to not need platform specific logic for this, given it works fine on iOS.

If you apply the patch with regex "[^a-zA-Z0-9_]", does it work properly in your case?

I plan on rebasing, but if this fixes your issue as well I think I should adjust the regex to allow for capital letters too before doing so.

Unfortunately, I'm still getting an error. I've applied the patch and I'll put it here. I'm using bun patch and here is my file @stripe%[email protected].

diff --git a/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt b/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt
index 7e983caca6c1abe6ef744082ff6a4e1ce60ca61f..e666b30ce85e3729183b9696894fd11354aea228 100644
--- a/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt
+++ b/android/src/main/java/com/reactnativestripesdk/PaymentSheetAppearance.kt
@@ -285,9 +285,9 @@ private fun getFontResId(
       ?: throw PaymentSheetAppearanceException(
         "$fontErrorPrefix expected String for font.$key, but received null.",
       )
-  if (Regex("[^a-z0-9]").containsMatchIn(fontFileName)) {
+  if (Regex("[^a-zA-Z0-9_]").containsMatchIn(fontFileName)) {
     throw PaymentSheetAppearanceException(
-      "$fontErrorPrefix appearance.font.$key should only contain lowercase alphanumeric characters on Android, but received '$fontFileName'. This value must match the filename in android/app/src/main/res/font",
+      "$fontErrorPrefix appearance.font.$key should only contain lowercase alphanumeric characters and underscores on Android, but received '$fontFileName'. This value must match the filename in android/app/src/main/res/font"
     )
   }

Here is a screenshot of the error in my app

And here is a screen grab of the particular font file causing the error with @expo-google-fonts/nunito.

Screenshot 2025-04-26 at 1 05 45 PM

My current workaround at the moment is as follows:

font: {
  family:
    Platform.OS === "ios"
      ? tokens.md.ref.typeface.brandRegular
      : undefined,
},

@iM-GeeKy
Copy link

@goguda Any update on this?

@goguda
Copy link
Author

goguda commented Apr 29, 2025

@goguda Any update on this?

Do you want to try the lowercase version of your font name? As an example, I just realized in our app, we have a font named CrimsonPro-Bold.ttf, but it's being accessed from Android Kotlin code as R.font.crimsonpro_bold.

In your case, maybe try setting the font name as nunito_400regular.

@goguda goguda requested review from a team as code owners April 29, 2025 18:54
@iM-GeeKy
Copy link

iM-GeeKy commented May 4, 2025

@goguda @jaynewstrom-stripe Any guidance on how to resolve this issue using @expo-google-fonts/nunito?

@goguda
Copy link
Author

goguda commented May 6, 2025

@goguda @jaynewstrom-stripe Any guidance on how to resolve this issue using @expo-google-fonts/nunito?

Hm, not too sure then to be honest. Are you sure your issue is being caused by this library? That looks more like a generic expo error to me.

Is this font working in other places in your app?

@iM-GeeKy
Copy link

iM-GeeKy commented May 6, 2025

Yeah it works great in Expo on iOS and Android and the font is being applied to the PaymentSheet on iOS, but can't be found on Android, so I'm fairly certain it is this library. Which is why I have to use the following in the config

font: {
  family:
    Platform.OS === "ios"
      ? tokens.md.ref.typeface.brandRegular
      : undefined,
},

If I use getLoadedFonts I can see the loaded fonts are ["Nunito_400Regular", "Nunito_500Medium", "Nunito_700Bold", "ionicons", "material-community", "material"].

@iM-GeeKy
Copy link

iM-GeeKy commented May 13, 2025

__@goguda I'm just curious, are you using Expo? I'm under the impression the font can't be found because Expo puts fonts in a different location than where Stripe is looking potentially.

Update

I was finally able to get the font to work, but had to apply your fix via a patch along with a custom plugin in Expo to get the font working. I'll leave the custom plugin file I used below in case others may find it helping until this issue is fully resolved.

Custom Expo Plugin File

Some Javascript

// withCustomFontsToRes.js
const { withDangerousMod } = require("@expo/config-plugins");
const fs = require("fs");
const path = require("path");

module.exports = function withCustomFontsToRes(config) {
return withDangerousMod(config, [
  "android",
  async (config) => {
    try {
      const projectRoot = config.modRequest.projectRoot;

      // Log the project root for debugging
      console.log("Project root:", projectRoot);

      // Exact path to Nunito_400Regular.ttf
      const sourceFile = path.join(
        projectRoot,
        "node_modules",
        "@expo-google-fonts",
        "nunito",
        "400Regular",
        "Nunito_400Regular.ttf",
      );

      // Log the source file path for debugging
      console.log("Source file path:", sourceFile);

      // Check if source file exists
      if (!fs.existsSync(sourceFile)) {
        console.error("Source file not found:", sourceFile);
        return config;
      }

      // Destination in Android resources
      const destDir = path.join(
        projectRoot,
        "android",
        "app",
        "src",
        "main",
        "res",
        "font",
      );

      // Log the destination directory for debugging
      console.log("Destination directory:", destDir);

      // Create destination directory if it doesn't exist
      if (!fs.existsSync(destDir)) {
        console.log("Creating destination directory:", destDir);
        fs.mkdirSync(destDir, { recursive: true });
      }

      // Copy the file
      const destFile = path.join(destDir, "nunito_400regular.ttf");
      console.log("Copying to:", destFile);

      fs.copyFileSync(sourceFile, destFile);
      console.log("Successfully copied font file");

      return config;
    } catch (error) {
      console.error("Error in withCustomFontsToRes:", error);
      // Return the config even if there's an error to prevent build failure
      return config;
    }
  },
]);
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants