You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaFX集成Stripe支付网关时WebView非法访问错误求助

JavaFX WebView集成Stripe支付时模块权限错误的解决方案

问题背景

Stripe支付服务功能正常,但在JavaFX控制器中使用WebView打开Stripe结账页面时,抛出以下模块访问权限错误:

Caused by: java.lang.IllegalAccessError: superclass access check failed: class com.sun.javafx.sg.prism.web.NGWebView (in unnamed module @0xeb8f1c5) cannot access class com.sun.javafx.sg.prism.NGGroup (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.sg.prism to unnamed module @0xeb8f1c5 

正常运行的Stripe支付服务代码:

public class StripePaymentService {

    public static String createCheckoutSession(double amount) throws Exception {
        // Récupérer la clé API depuis les variables d'environnement
        String stripeApiKey = "STRIPE_API_KEY";
        if (stripeApiKey == null || stripeApiKey.isEmpty()) {
            throw new RuntimeException("La clé API Stripe n'est pas configurée.");
        }

        // Initialiser Stripe avec la clé API
        Stripe.apiKey = stripeApiKey;

        // Créer une session de paiement
        SessionCreateParams params = SessionCreateParams.builder()
                .setMode(SessionCreateParams.Mode.PAYMENT)
                .setSuccessUrl("http://localhost:8080/success")
                .setCancelUrl("http://localhost:8080/cancel")
                .addLineItem(
                        SessionCreateParams.LineItem.builder()
                                .setQuantity(1L)
                                .setPriceData(
                                        SessionCreateParams.LineItem.PriceData.builder()
                                                .setCurrency("eur")
                                                .setUnitAmount((long) (amount * 100)) // Stripe travaille en centimes
                                                .setProductData(
                                                        SessionCreateParams.LineItem.PriceData.ProductData.builder()
                                                                .setName("Réservation Événement")
                                                                .build()
                                                )
                                                .build()
                                )
                                .build()
                )
                .build();

        // Créer la session de paiement
        Session session = Session.create(params);
        return session.getUrl(); // Retourne l'URL de la session de paiement
    }
}

JavaFX控制器中触发错误的支付按钮代码:

public void paymentButton() {
        String displayedPrice = totalPriceLabel.getText().replace("Total Price: ", "").trim();

        // Remove non-numeric characters (assuming "dt" is always at the end)
        if (displayedPrice.endsWith("dt")) {
            displayedPrice = displayedPrice.substring(0, displayedPrice.length() - 3).trim();
        }


        try {
            // Convertir la chaîne en double
            double amount = Double.parseDouble(displayedPrice);

            // Créer une session de paiement Stripe
            String paymentUrl = StripePaymentService.createCheckoutSession(amount);

            // Ouvrir l'URL de paiement dans un WebView
            WebView webView = new WebView();
            webView.getEngine().load(paymentUrl);

            // Afficher le WebView dans une nouvelle fenêtre
            Stage stage = new Stage();
            stage.setScene(new Scene(webView, 800, 600));
            stage.setTitle("Paiement Stripe");
            stage.show();
        } catch (NumberFormatException e) {
            alert.errorMessage("Erreur de saisie"); 
            System.out.println(e.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            alert.errorMessage("Erreur de paiement");
            System.out.println(e.getMessage());
        }
    }

错误原因

该错误由Java模块系统的访问控制机制导致:com.sun.javafx.sg.prism.web.NGWebView属于未命名模块,尝试访问javafx.graphics模块内部的com.sun.javafx.sg.prism.NGGroup类,但javafx.graphics未将此内部包导出给未命名模块,从而触发权限检查失败。

解决方案

方案1:添加JVM启动参数(推荐)

在运行应用时添加以下JVM参数,允许javafx.graphics和javafx.web模块将内部包导出给未命名模块:

--add-exports javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED
--add-exports javafx.web/com.sun.javafx.sg.prism.web=ALL-UNNAMED

如果使用Maven的javafx-maven-plugin,可在插件配置中嵌入这些参数:

<plugin>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-maven-plugin</artifactId>
    <version>0.0.8</version>
    <configuration>
        <mainClass>你的主类全路径</mainClass>
        <options>
            <option>--add-exports</option>
            <option>javafx.graphics/com.sun.javafx.sg.prism=ALL-UNNAMED</option>
            <option>--add-exports</option>
            <option>javafx.web/com.sun.javafx.sg.prism.web=ALL-UNNAMED</option>
        </options>
    </configuration>
</plugin>

方案2:将应用转为模块化项目

创建module-info.java文件,明确声明对JavaFX和Stripe模块的依赖:

module 你的模块名 {
    requires javafx.controls;
    requires javafx.web;
    requires stripe.java; // 根据Stripe依赖的实际模块名调整

    // 导出控制器所在包(若需要)
    exports 你的控制器包路径;
}

模块化运行可避免未命名模块的权限限制,同时提升应用的封装性。

方案3:改用系统默认浏览器打开结账链接(备选)

Stripe官方更推荐在独立浏览器中处理支付流程,可替换WebView代码为:

// 替换原WebView相关代码
try {
    if (Desktop.isDesktopSupported()) {
        Desktop.getDesktop().browse(new URI(paymentUrl));
    } else {
        alert.errorMessage("无法自动打开浏览器,请手动访问:" + paymentUrl);
    }
} catch (URISyntaxException e) {
    e.printStackTrace();
    alert.errorMessage("URL格式错误");
}

这种方式无需处理模块权限问题,同时能保证支付页面的兼容性与安全性。

注意事项

  • 确保JavaFX版本与JDK版本匹配(如JDK 17对应JavaFX 17)。
  • 避免硬编码Stripe API密钥,建议通过环境变量或配置文件加载。

内容的提问来源于stack exchange,提问作者Mohamed Hedi ben salah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 22:33:20