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

如何在.NET MAUI Blazor应用中处理iFrame支付回调与页面跳转?

.NET MAUI Blazor支付回调处理方案(Android/iOS)

针对你集成支付iFrame后,需要处理支付完成重定向的需求,以下是Android和iOS平台的具体实现方案,分为处理外部HTTPS页面内容和跳转回应用内Blazor页面两种场景:


通用前置说明

BlazorWebView在MAUI中底层基于Android的WebView和iOS的WKWebView,核心思路是通过拦截WebView的导航事件,识别支付回调URL后执行对应逻辑。推荐使用MessagingCenter或WeakReferenceMessenger(CommunityToolkit.Mvvm)实现原生层与Blazor层的通信。


Android平台实现

场景1:处理重定向后的HTTPS页面内容

  1. 自定义WebViewClient拦截导航
    在项目Platforms/Android目录下的MainActivity.cs中,添加自定义WebViewClient并绑定到BlazorWebView:
protected override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);
    var blazorWebView = FindViewById<BlazorWebView>(Resource.Id.blazorWebView);
    
    blazorWebView.HandlerChanged += (s, e) =>
    {
        if (blazorWebView.PlatformView is Android.Webkit.WebView androidWebView)
        {
            androidWebView.SetWebViewClient(new PaymentWebViewClient());
            // 启用JavaScript(解析页面内容必备)
            androidWebView.Settings.JavaScriptEnabled = true;
        }
    };
}

// 自定义WebViewClient处理导航
public class PaymentWebViewClient : Android.Webkit.WebViewClient
{
    public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
    {
        var callbackUrl = request.Url.ToString();
        // 匹配支付完成的回调URL前缀
        if (callbackUrl.StartsWith("https://your-payment-callback-domain.com/complete"))
        {
            // 允许加载页面,后续在OnPageFinished中获取内容
            return false;
        }
        return base.ShouldOverrideUrlLoading(view, request);
    }

    public override void OnPageFinished(Android.Webkit.WebView view, string url)
    {
        base.OnPageFinished(view, url);
        if (url.StartsWith("https://your-payment-callback-domain.com/complete"))
        {
            // 执行JS获取页面HTML内容
            view.EvaluateJavascript("document.body.innerHTML", new JsResultCallback(html =>
            {
                // 将内容传递给Blazor层
                MessagingCenter.Send<object, string>(this, "PaymentContentReceived", html.Trim('"'));
            }));
        }
    }
}

// JS结果回调类
public class JsResultCallback : Java.Lang.Object, IValueCallback
{
    private readonly Action<string> _callback;
    public JsResultCallback(Action<string> callback) => _callback = callback;
    public void OnReceiveValue(Java.Lang.Object value) => _callback?.Invoke(value?.ToString());
}
  1. Blazor页面接收并处理内容
    在目标Blazor页面中订阅消息:
@code {
    protected override void OnInitialized()
    {
        MessagingCenter.Subscribe<object, string>(this, "PaymentContentReceived", (sender, htmlContent) =>
        {
            // 解析HTML中的支付结果,比如订单状态、金额等
            Console.WriteLine($"支付页面内容:{htmlContent}");
            InvokeAsync(StateHasChanged);
        });
    }

    public void Dispose()
    {
        MessagingCenter.Unsubscribe<object, string>(this, "PaymentContentReceived");
    }
}

场景2:跳转至应用内Blazor页面

  1. 拦截回调URL并通知Blazor
    修改PaymentWebViewClient的ShouldOverrideUrlLoading方法:
public override bool ShouldOverrideUrlLoading(Android.Webkit.WebView view, IWebResourceRequest request)
{
    var callbackUrl = request.Url.ToString();
    if (callbackUrl.StartsWith("https://your-payment-callback-domain.com/complete"))
    {
        // 解析URL中的支付参数(比如订单ID、状态)
        var uri = new Uri(callbackUrl);
        var orderId = uri.Query.Split('&').FirstOrDefault(q => q.StartsWith("orderId="))?.Split('=')[1];
        var status = uri.Query.Split('&').FirstOrDefault(q => q.StartsWith("status="))?.Split('=')[1];

        // 通知Blazor跳转至内部页面
        MessagingCenter.Send<object, (string OrderId, string Status)>(this, "PaymentCompleted", (orderId, status));
        
        // 阻止WebView加载外部页面
        return true;
    }
    return base.ShouldOverrideUrlLoading(view, request);
}
  1. Blazor页面执行导航
    注入NavigationManager并处理跳转:
@inject NavigationManager NavManager

@code {
    protected override void OnInitialized()
    {
        MessagingCenter.Subscribe<object, (string OrderId, string Status)>(this, "PaymentCompleted", (sender, data) =>
        {
            // 导航至应用内的支付结果页面,传递参数
            NavManager.NavigateTo($"/payment-result?orderId={data.OrderId}&status={data.Status}");
        });
    }

    public void Dispose()
    {
        MessagingCenter.Unsubscribe<object, (string OrderId, string Status)>(this, "PaymentCompleted");
    }
}

iOS平台实现

场景1:处理重定向后的HTTPS页面内容

  1. 自定义WKNavigationDelegate拦截导航
    在项目Platforms/iOS目录下的AppDelegate.cs中配置:
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());

    var blazorWebView = Window.RootViewController.View.FindViewById<BlazorWebView>();
    blazorWebView.HandlerChanged += (s, e) =>
    {
        if (blazorWebView.PlatformView is WKWebView wkWebView)
        {
            wkWebView.NavigationDelegate = new PaymentNavigationDelegate();
            // 启用JavaScript
            wkWebView.Configuration.Preferences.JavaScriptEnabled = true;
        }
    };

    return base.FinishedLaunching(app, options);
}

// 自定义导航代理
public class PaymentNavigationDelegate : WKNavigationDelegate
{
    public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler)
    {
        var callbackUrl = navigationAction.Request.Url.AbsoluteString;
        if (callbackUrl.StartsWith("https://your-payment-callback-domain.com/complete"))
        {
            // 允许加载页面,后续获取内容
            decisionHandler(WKNavigationActionPolicy.Allow);
            return;
        }
        decisionHandler(WKNavigationActionPolicy.Allow);
    }

    public override void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
    {
        var currentUrl = webView.Url.AbsoluteString;
        if (currentUrl.StartsWith("https://your-payment-callback-domain.com/complete"))
        {
            // 执行JS获取页面内容
            webView.EvaluateJavaScript("document.body.innerHTML", (result, error) =>
            {
                if (error == null && result != null)
                {
                    var htmlContent = result.ToString();
                    MessagingCenter.Send<object, string>(this, "PaymentContentReceived", htmlContent);
                }
            });
        }
    }
}
  1. Blazor页面处理逻辑同Android场景1

场景2:跳转至应用内Blazor页面

  1. 拦截回调URL并通知Blazor
    修改PaymentNavigationDelegate的DecidePolicy方法:
public override void DecidePolicy(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler)
{
    var callbackUrl = navigationAction.Request.Url.AbsoluteString;
    if (callbackUrl.StartsWith("https://your-payment-callback-domain.com/complete"))
    {
        // 解析支付参数
        var uri = new Uri(callbackUrl);
        var orderId = uri.Query.Split('&').FirstOrDefault(q => q.StartsWith("orderId="))?.Split('=')[1];
        var status = uri.Query.Split('&').FirstOrDefault(q => q.StartsWith("status="))?.Split('=')[1];

        // 通知Blazor跳转
        MessagingCenter.Send<object, (string OrderId, string Status)>(this, "PaymentCompleted", (orderId, status));
        
        // 取消加载外部页面
        decisionHandler(WKNavigationActionPolicy.Cancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicy.Allow);
}
  1. Blazor页面处理逻辑同Android场景2

注意事项

  • 权限配置:Android需在AndroidManifest.xml中添加<uses-permission android:name="android.permission.INTERNET" />;iOS若回调URL为HTTP,需在Info.plist中添加ATS例外(HTTPS无需)。
  • 内存泄漏:建议使用WeakReferenceMessenger替代MessagingCenter,需安装CommunityToolkit.Mvvm包,避免订阅未释放导致的内存问题。
  • 测试验证:务必通过真实支付流程或模拟回调URL测试拦截逻辑,确保参数传递和跳转正常。

内容的提问来源于stack exchange,提问作者N. OZER SENOL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 23:10:00