I built a web application using the Apple Pay on the Web Interactive Demo with the Payment Request API, but encountered a few issues:
The initiated web Apple Pay interface shows a spinning circle at the bottom and cannot proceed with payment(Bottom display:正在处理). What could be causing this?
How to set up sandbox testing for payments?
How to asynchronously and synchronously retrieve payment results (backend code to fetch payment results)? The demo only shows frontend code using await response.complete("success"); for retrieving payment results
my demo URL: https://shop.wowseer.com/rsolomakhin/pr/applepay/
WebKit
RSS for tagDisplay web content in windows and implement browser features using WebKit.
Posts under WebKit tag
200 Posts
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
我使用Apple Pay on the Web Interactive Demo构建了一个web应用使用的是Payment Request API方式,但是遇到了几个问题:
拉起的web Apple Pay 底部一直转圈圈无法付款,这个是什么问题?
如何设置sandbox测试付款呢?
如何异步、同步获取支付结果(后端代码获取支付结果)?demo只有await response.complete("success");前端代码获取支付结果的操作
demo网址: https://shop.wowseer.com/rsolomakhin/pr/applepay/
Hello,
I'm experiencing an issue where WKWebView consistently fails to load a specific URL on the iOS 18.4 simulator (Xcode 16.3). The error is as follows:
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost."
UserInfo={
_kCFStreamErrorCodeKey=-4,
_kCFStreamErrorDomainKey=4,
NSUnderlyingError=Error Domain=kCFErrorDomainCFNetwork Code=-1005,
NSErrorFailingURLKey=[REDACTED]
}
Key Observations:
This URL fails consistently only on the iOS 18.4 simulator.
The same URL loads without issue in iOS 18.3 and 18.2 simulators.
The backend is serving a valid HTTPS certificate chain, and the server appears to be presenting it properly.
The same application appears to work on a real iPhone running 18.4.
Certificate Chain for the Failing URL
Leaf: WR3 (Valid: Mar 17, 2025 – Jun 15, 2025)
Intermediate 1: GTS Root R1 (Valid: Dec 13, 2023 – Feb 20, 2029)
Intermediate 2: GlobalSign Root CA (Valid: Jun 19, 2020 – Jan 28, 2028)
Other URLs Work Fine in iOS 18.4 Simulator
WKWebView successfully loads the following URLs with similar or more complex certificate chains:
https://google.com → WR2, GTS Root R1, GlobalSign Root CA
https://amazon.com → DigiCert Global CA G2, DigiCert Global Root G2, VeriSign G5
https://stackoverflow.com → E5, ISRG Root X1
https://shopify.com → GlobalSign Root CA, GTS Root R4, WE1
This suggests the issue may not be with general network or certificate trust but instead something specific about how iOS 18.4 handles this domain or certificate configuration in the simulator.
Any insights on how to solve this would be greatly appreciated.
I am developing a web application, I hope to be able to intercept all requests in the loaded web page, match the network request I want to specifically intercept the network request and then obtain the request header information (not the user's personal privacy data interception), if the use is the method of injection, the request header information is incomplete, such as the more important "content-type" field in the request header, so I try to use Swizzling method to intercept all http and https requests, and I can now intercept all the request information. But there is still a problem with my project, when loading x.com, logging in, appearing white screen after the successful landing, and not loading to the page after the successful landing, I don't know where the reason is。
Below is my core code implementation fragment.
import WebKit
// MARK: - WebViewController
class WebViewController: UIViewController {
fileprivate var webView: WKWebView!
private var schemeHandler: WWKProxyWKURLSchemeHandler!
override func viewDidLoad() {
super.viewDidLoad()
Self.initSwizzling
setupWebView()
loadInitialContent()
}
private func setupWebView() {
let config = WKWebViewConfiguration()
schemeHandler = WWKProxyWKURLSchemeHandler()
config.setURLSchemeHandler(self.schemeHandler, forURLScheme: "https")
config.setURLSchemeHandler(self.schemeHandler, forURLScheme: "http")
webView = WKWebView(frame: view.bounds, configuration: config)
webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(webView)
}
private func loadInitialContent() {
if let url = URL(string: "https://x.com") {
let request = URLRequest(url: url,cachePolicy:.reloadIgnoringLocalCacheData,timeoutInterval: 15)
webView.load(request)
}
}
func reloadWebView() {
webView?.reloadFromOrigin()
}
}
class WWKProxyWKURLSchemeHandler: NSObject, WKURLSchemeHandler {
private let lock = NSLock()
private var activeTasks = [ObjectIdentifier: URLSessionDataTask]()
func webView(_ webView: WKWebView, start urlSchemeTask: WKURLSchemeTask) {
lock.lock()
defer { lock.unlock() }
let taskID = ObjectIdentifier(urlSchemeTask)
guard !activeTasks.keys.contains(taskID) else {
print("⚠️ Task already started: \(urlSchemeTask.request.url?.absoluteString ?? "")")
return
}
print("Intercepted URL---:",urlSchemeTask.request.url?.absoluteString ?? "")
print("All requests intercepted----:",urlSchemeTask.request.allHTTPHeaderFields)
let request = urlSchemeTask.request
let dataTask = URLSession.shared.dataTask(with: request) { [weak self] data, response, error in
guard let self = self else { return }
self.lock.lock()
let isActive = self.activeTasks[taskID] != nil
self.lock.unlock()
guard isActive else {
print("🌀 Task already cancelled: \(urlSchemeTask.request.url?.absoluteString ?? "")")
return
}
// Make sure it only handles once
guard self.activeTasks.keys.contains(taskID) else { return }
self.activeTasks.removeValue(forKey: taskID)
DispatchQueue.main.async {
if let error = error {
urlSchemeTask.didFailWithError(error)
print("🔴 Task failed: \(urlSchemeTask.request.url?.absoluteString ?? "") - \(error.localizedDescription)")
return
}
guard let response = response, let data = data else {
urlSchemeTask.didFailWithError(URLError(.unknown))
print("🔴 Invalid response: \(urlSchemeTask.request.url?.absoluteString ?? "")")
return
}
urlSchemeTask.didReceive(response)
urlSchemeTask.didReceive(data)
urlSchemeTask.didFinish()
print("🟢 Task completed: \(urlSchemeTask.request.url?.absoluteString ?? "")")
}
}
self.activeTasks[taskID] = dataTask
dataTask.resume()
}
func webView(_ webView: WKWebView, stop task: WKURLSchemeTask) {}
private func finishTask(taskID: ObjectIdentifier ,task: WKURLSchemeTask, response: URLResponse?, data: Data?, error: Error?) {
lock.lock()
defer { lock.unlock() }
guard activeTasks.keys.contains(taskID) else { return }
activeTasks.removeValue(forKey: taskID)
DispatchQueue.main.async {
if let error = error {
task.didFailWithError(error)
print("🔴 Task failed: \(task.request.url?.absoluteString ?? "") - \(error.localizedDescription)")return}
guard let response = response, let data = data else {
task.didFailWithError(URLError(.unknown))
print("🔴 Invalid response: \(task.request.url?.absoluteString ?? "")") return }
task.didReceive(response)
task.didReceive(data)
task.didFinish()
print("🟢 Task completed: \(task.request.url?.absoluteString ?? "")")
}
}
}
extension WKWebView {
@objc
dynamic class func qm_handlesURLScheme(_ urlScheme: String) -> Bool {
if urlScheme == "https" || urlScheme == "http" {return false}
return self.qm_handlesURLScheme(urlScheme)
}
// Exchange of execution methods
static func setupSwizzling() {
let originalSelector = #selector(handlesURLScheme(_:))
let swizzledSelector = #selector(qm_handlesURLScheme(_:))
// Implemented by Runtime Get Method
guard
let originalMethod = class_getClassMethod(WKWebView.self, originalSelector),
let swizzledMethod = class_getClassMethod(WKWebView.self, swizzledSelector)
else {
return
}
// Implementation of Exchange Methods
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
extension WebViewController {
private static let initSwizzling: Void = {
DispatchQueue.once(token: "com.webview.swizzling") {
WKWebView.setupSwizzling()
}
}()
}
// GCD Once
extension DispatchQueue {
private static var tokens = Set<String>()
class func once(token: String, block: () -> Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
guard !tokens.contains(token) else { return }
tokens.insert(token)
block()
}
}
extension WebViewController: WKNavigationDelegate {
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
decisionHandler(.allow)
}
}
My app started crashing since iOS 18.4 update. Crashes started happening in 18.4 beta and are still happening in the official 18.4 RTM build (22E240). Crash is happening randomly and I cannot reproduce it, but it affects a few percent of users.
As you can see in log, crash happen when NSAttributedString is loading HTML with init(data:options:documentAttributes:) with .html documentType.
Crash-2025-04-02-154720.ips
I have multiple web views of the same domain that share the same local storage, as expected.
One of them though, is loading a .webarchive file.
The web archive is of the same domain, and is loaded using the same base URL.
For some reason, in most cases, the local storage is not shared with this web view when loading the web archive, although if I make that same web view load the actual live web page it does share local storage.
I say in most cases, because for some users it works as expected, but for a significant portion of users it isn't sharing local storage.
I think that the main difference between working and not is iOS version. iOS 17 seems to be able to share the local storage but iOS 18 does not. I can't find anything related in the release notes of iOS 18 versions.
There is nothing in the documentation for load(_:mimeType:characterEncodingName:baseURL:), or the header file, that explains anything specific about local storage and webarchive loading.
Does anyone know for sure how local storage is handled when a webarchive is loaded into a web view, and did something change with iOS 18 in regards to this?
Hi, We are facing a major issue with our application. We are using FolioReaderkit to read epub files. Currently, it's working on the iOS 18.1 device and simulator, but it's not working on the iOS 18.2 and later version devices.
we are facing this error in Folioreaderkit
Apology for repost. I needed to fix the tags for original thread.
https://developer.apple.com/forums/thread/777159
On iOS 18.3, I noted that partition "HTTPCookiePropertyKey: StoragePartition" is not observed to be set for cookies returned from the wkwebview cookie store.
Now on 18.4 beta 4 we are now seeing those same cookies are populated with a partition property. Is there documentation for this change? Is it intended to be suddenly populated in 18.4?
Now that partition property is set, HTTPCookieStorage.shared.cookies(for: serverUri) doesn't seem to return the expected cookies correctly. For context, we are using the cookies extracted from wkwebview, setting them in HTTPCookieStorage.shared and using URLSession to make network calls outside the webivew. Works fine once I forcefully set partition on the cookie to nil.
More details on what the cookie looks like here: https://feedbackassistant.apple.com/feedback/16906526
Hopefully this is on your radar?
On iOS 18.3, I noted that partition "HTTPCookiePropertyKey: StoragePartition" is not observed to be set for cookies returned from the wkwebview cookie store.
Now on 18.4 beta 4 we are now seeing those same cookies are populated with a partition property. Is there documentation for this change? Is it intended to be suddenly populated in 18.4?
Now that partition property is set, HTTPCookieStorage.shared.cookies(for: serverUri) doesn't seem to return the expected cookies correctly. For context, we are using the cookies extracted from wkwebview, setting them in HTTPCookieStorage.shared and using URLSession to make network calls outside the webivew. Works fine once I forcefully set partition on the cookie to nil.
More details on what the cookie looks like here:
https://feedbackassistant.apple.com/feedback/16906526
Hopefully this is on your radar?
After upgrading to Xcode 15.2 or above(Till Xcode 16.2), users are unable to open Site B (HTTP URL) from Site A (HTTP URL) within our Browser app when loaded in WKWebView. Clicking the link to Site B results in a spinning wheel, but the site does not load. This issue is not present when the app is built with Xcode 15.0.1.
Additionally:
Users are connected to a VPN, which is required to access the sites.
Site A and Site B are on different domains (cross-domain request).
Expected Behavior:
Clicking the link to Site B should successfully load the site with user information passed from Site A.
Current Behavior:
Clicking the link results in a spinning wheel, but Site B does not load inside WKWebView.
Technical Details:
Both Site A and Site B use HTTP (not HTTPS).
Site A and Site B have different domains (cross-domain request).
Do not use location.href for transitions. Instead, we temporarily set about:blank in an iframe and then submit data via a form to the target system’s URL within the iframe.
This approach worked in Xcode 15.0.1 but fails in Xcode 15.2 or above.
Users are connected to a VPN, which is required to access the sites.
WKWebview is not receiving navigation delegate callback for Site B
Steps to Reproduce:
Ensure the device is connected to a VPN.
Open the app (using WKWebView) built with Xcode 15.2 or above.
Load Site A (HTTP) within the app in WKWebView.
Click the link to Site B (HTTP), which should open in an iframe.
Observe that a spinning wheel appears, but Site B does not load.
Environment:
Xcode Versions Affected: 15.2 or above (issue present), 15.0.1 (no issue)
iOS Version: All iOS versions
Devices: iPad
Questions:
Has there been any change in WKWebView’s handling of HTTP URLs or VPN-related network traffic in Xcode 15.2?
Are there any new security policies, iframe restrictions, or VPN-related changes in this version that might be affecting this behavior?
Request for Assistance:
Can you confirm if this is a known issue or an intended change?
Are there any workarounds available?
Hi all,
With version 18.4 beta, I have a problem with the display of webviews in the app. In particular, the app of my bank has webviews inside it, and as they are not loading, I am unable to access it. Can you help me? Thank you.
I have an app that has a WKWebView for watching YouTube videos. When the videos are windowed the audio seems fine, positionally as well. All perfectly.
When I fullscreen the video and it goes into the native visionOS video player the audio messes up.
It will suddenly sound like it is in your ears, or maybe even just one ear channel, or the position will be wrong. It might be fine for a moment but the second I touch the controls or move the window the sound jumps across the room, away from the window, or switches to stereo.
Sometimes exiting windows entirely you will still hear the videos playing. Even if you open the window back up and go to another screen and open another video, now you hear 2 videos playing at the same time with no way to stop the first one in the background, requiring to force restart the app.
It is all sorts of glitchy. I haven't the slightest clue what is happening here. I am strongly feeling this is a visionOS bug.
I tried using AVAudioSession to change some of the sound settings, and that makes zero difference in behavior.
Multiple testers have also reported this behavior and it has been seen on both visionOS 2.3 and 2.4 betas.
Thanks for the help! This is driving me mad! It is extremely consistent behavior!
Background
On iOS 18.4 beta, setting a content inset on a WKWebView causes touch events inside the web view to be offset by the content inset amount. In other words, if the web view has a top content inset of 75 points, I must tap 75 points above the intended element for the touch to register correctly. This makes any web content unusable when a content inset is present.
A sample app demonstrating the issue is available here: GitHub - iOS18.4-Webview-Bug.
The issue does not occur in iOS 18.3 or 18.2.
Bug Report
The bug has been reported and fixed at WebKit Bug 289715 and also filed as rdar://147075945.
Question
Will the fix be included in the upcoming iOS 18.4 beta release (Beta 5) or soon thereafter?
Hey team, I've integrated custom WkWebsiteDatastore to manage profiling for different sessions.
upon testing the WkWebsiteDataStore as its mentioned to be persistent But
The storage can be accessed via identifier, But the session data in storage is absent, such as cookies caches all are cleared when app is relaunched
is it the default behavior to be expected or there is some property missing causing the session data to be removed from storage.
I am playing FairPlay + Multi-Key content (fMP4) in Safari browser.
I want to implement the implementation to distinguish between SD and HD video quality, and play it in HD if HDCP is supported, and in SD if HDCP is not supported.
I have already confirmed that HDCP support is the default, and that a black screen is output in non-HDCP environments.
What I want is to improve the user experience by appropriately switching to SD/HD depending on HDCP support when playing DRM content.
Question: Is there an API or function that can detect HDCP support in Safari through JavaScript or other methods? Or is there a way to indirectly guess it?
Topic:
Media Technologies
SubTopic:
Streaming
Tags:
FairPlay Streaming
WebKit
Safari
HTTP Live Streaming
When I open com. apple. developer. web browser, I am unable to inject JavaScript into the webview through methods such as addUserScript. The console will prompt 'ignoring user script injection for non app bound domain'
TLDR: I’m searching for a possibility to allow the usage of passkeys and hardware keys for any website in a wkwebview
INFO: The browser is macOS ONLY
Hi, I couldn’t really find documentation or forums posts on how to implement Webauthn for signin or hardware security keys for a second factor. Or rather where those events are triggered to be handled. In Safari you have that popover, that lets you either authenticate through Passwords or with a security key.
When I visit webauthn.io for testing and click either register or authenticate I get
Told not to present authorization sheet: Error Domain=com.apple.AuthenticationServicesCore.AuthorizationError Code=1 "(null)"
ASAuthorizationController credential request failed with error: Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1004 "(null)"
If I add
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping @MainActor (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
and
func webView(_ webView: WKWebView, authenticationChallenge challenge: URLAuthenticationChallenge, shouldAllowDeprecatedTLS decisionHandler: @escaping @MainActor (Bool) -> Void)
it doesn’t seem to change anything.
I found something about the ASWebAuthenticationSessionWebBrowserSupported entitlement, but by my understanding this is used so a browser can get opened upon some other app calling a ASWebAuthenticationSession.
Has anyone some guidance for me? I feel like webauthn and yubikey support are important security measures for our users.
https://codeberg.org/miakoring/Amethyst/src/branch/main/Amethyst/Shared/ViewComponents/WebKit/WebViewModel.swift
is the code for my webviewmodel.
Delegates are in the Delecate folder https://codeberg.org/miakoring/Amethyst/src/branch/main/Amethyst/Shared/ViewComponents/WebKit
It seems fetch() does not include credentials (cookie) even when credentials: include is used and Safari extension has host_permissions for that domain when using from a non-default Safari profile.
It includes credentials (cookie) when using from the default profile (which has the default name Personal).
Is there anyone who has this problem?
I try to request in popup.js like this:
const response = await fetch(
url,
{
method: 'GET',
mode: 'cors',
credentials: 'include',
referrerPolicy: 'no-referrer',
}
);
and it does not include the credentials (cookie) from host_permissions.
I already posted https://developer.apple.com/forums/thread/764279, and opened feedback assistant (FB15307169).
But it is still not fixed yet. (macOS 15.4 beta 3)
I hope this is fixed soon.
I’m developing a hybrid app (WebView / Turbo Native) that uses getUserMedia to access the back camera for a PPG/heart rate measurement feature (the user places their finger on the camera).
Problem: Even when I specify constraints like:
{
video: {
deviceId: '...',
facingMode: { exact: 'environment' },
advanced: [{ zoom: 1.0 }]
},
audio: false
}
On iPhone 15 (iOS 18), iOS unexpectedly switches between the wide, ultra-wide, and telephoto lenses during the measurement.
This breaks the heart rate detection, and it forces the user to move their finger in the middle of the measurement.
Question: Is there any way, via getUserMedia/WebRTC, to force iOS to use only the wide-angle lens and prevent automatic lens switching?
I know that with AVFoundation (Swift) you can pick .builtInWideAngleCamera, but I’m hoping to avoid building a custom native layer and would prefer to stick with WebView/JavaScript if possible to save time and complexity.
Any suggestions, workarounds, or updates from Apple would be greatly appreciated!
Thanks a lot!
I am encountering an intermittent issue with WKWebView in my iOS app. The problem occurs infrequently, but when it does, the WKWebView consistently displays a white screen and remains in this state until the app is forcefully terminated and relaunched.
To provide more context, here are the key characteristics of the issue:
The white screen problem occurs sporadically and is not easily reproducible.
The WKWebView remains unresponsive despite attempts to interact with it.
Reloading the webpage or navigating to a different URL does not resolve the white screen issue.
The problem persists until the app is terminated and relaunched.
This issue is specific to the WKWebView; other components of the app function correctly.
The WKWebView renders normally, and the main document synchronously loads resources both offline and online without any issues. The bridge and JavaScript execution also work as expected.
However, when interacting with the WKWebView, it becomes unresponsive to user clicks, and the web inspector fails to respond. Additionally, asynchronous network requests also do not receive any response.
The problem occurs exclusively on HTTPS pages, whereas HTTP pages load without any issues. Other components, such as workers, function correctly.
addUserScript injection during WKWebView creation is effective, and evaluateJavaScript during the page loading process works as expected. However, when the document becomes unresponsive, executing evaluateJavaScript only triggers the callback after the WKWebView is destroyed.
I have discovered a reliable method to reproduce the white screen issue in WKWebView. This method involves the following steps and conditions:
Create a WKWebView instance.
Load an HTML page using the loadRequest method(https url request).
Before the WKWebView is attached to the UI (not yet visible to the user), call the evaluateJavaScript function.
This issue has occurred in almost all iOS versions, including the latest iOS 17.x version.