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

WKWebView使用addEventListener无法接收Calendly事件问题咨询

解决方案

核心问题点

  • 加载HTML时baseURL传入nil触发跨域限制,Calendly iframe发送的postMessage无法被父页面捕获
  • Calendly初始化配置未添加parent参数,事件消息会被浏览器跨域策略拦截
  • 注入的JS代码存在语法错误:第二个message监听回调中误用了未声明的event变量,应使用回调参数e
  • 直接将对象类型的e.data与字符串拼接,会转为无意义的[object Object],丢失事件数据
  • 重复定义isCalendlyEvent函数,冗余且可能引发逻辑异常

修正后完整代码

import UIKit
import WebKit

class ViewController: UIViewController, WKScriptMessageHandler {
    
    var webView: WKWebView!
    var count = 0
    
    var html = """
    <html>
    <head>
        <meta name='viewport' content='width=device-width' />
    </head>
    <body>
    <!-- Calendly inline widget begin -->
    <div class="calendly-inline-widget" data-auto-load="false">
        <script type="text/javascript" src="https://assets.calendly.com/assets/external/widget.js"></script>
        <script>
        Calendly.initInlineWidget({
            url: 'https://calendly.com/XXX',
            parent: window.location.origin, // 新增parent配置,解决跨域发消息问题
            prefill: {
                name: "John Doe",
                email: "john@joe2.com",
                customAnswers: {
                    a1: "yes"
                }
            }
        });
        </script>
    </div>
    <!-- Calendly inline widget end -->
    </body>
    </html>
    """

    override func viewDidLoad() {
        let config = WKWebViewConfiguration()
        let js =
        """
        function isCalendlyEvent(e) {
          return e.data?.event && e.data.event.indexOf('calendly') === 0;
        };
         
        window.addEventListener('message', function(e) {
            console.log('In listener. Event.type: ' + e.type + ' e.data.event: ' + e.data?.event + ' event: ' + JSON.stringify(e.data));
            if (isCalendlyEvent(e)) {
                console.log('calendly event!!!!');
                // 序列化事件数据后传给原生
                window.webkit.messageHandlers.clickListener.postMessage('Calendly:' + JSON.stringify(e.data));
            } else {
                window.webkit.messageHandlers.clickListener.postMessage('Other:' + JSON.stringify(e.data));
            }
        });
        """

        let script = WKUserScript(source: js, injectionTime: .atDocumentEnd, forMainFrameOnly: false)

        config.userContentController.addUserScript(script)
        config.userContentController.add(self, name: "clickListener")

        webView = WKWebView(frame: view.bounds, configuration: config)
        webView.navigationDelegate = self // 可选,方便排查加载错误
        view.addSubview(webView)
        // 传入有效baseURL解决跨域问题
        self.webView.loadHTMLString(self.html, baseURL: URL(string: "https://calendly.com"))
    }
    
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        count = count + 1
        print("Msg \(count): \(message.body) ")
    }
}

// 可选:实现导航代理排查加载问题
extension ViewController: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        print("页面加载完成")
    }
    
    func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        print("加载失败:\(error)")
    }
}

验证说明

用户完成预约后会收到calendly.event_scheduled类型的事件,可直接从序列化后的字符串中解析出预约相关信息。

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 01:42:01