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
相关产品推荐
相关产品推荐

