Skip to content

技术问题


解决集成与系统故障的常见技术问题

全球收单

1. WebView 打开收银台的推荐方式

适用场景: 使用「全量支付方式收银台」或「指定支付方式收银台」的商户。

建议: 优先使用用户移动端系统浏览器打开 Checus 收银台,尽量避免在 App 内使用 WebView 打开收银台页面。

部分支付方式在交易过程中需要跳转到电子钱包、银行 App 或渠道页面。系统浏览器对外部 App 跳转、Deep Link、Universal Link 等行为的兼容性更好,能降低支付链路被 WebView 容器拦截的风险。

如果业务上必须使用 WebView,请确保 WebView 允许以下渠道链接正常重定向。

地区目标机构重定向 URL - 跳转 Web重定向 URL - 跳转 App
印度尼西亚DANAhttps://m.dana.id/-
印度尼西亚GOPAYhttps://gopay.co.id/gopay.co.id/*
*.gopay.co.id/*
印度尼西亚SHOPEEPAYhttps://app.shopeepay.co.id/shopeepayid://
马来西亚TNGhttps://m.tngdigital.com.my/-
菲律宾GCASHhttps://payments.gcash.com/-
俄罗斯SBERPAYhttps://securepayments.sberbank.ru/
https://epay.sberbank.ru/
sberpay://
俄罗斯TPAYhttps://pay.tbank.ru/
https://securepay.tinkoff.ru/
https://o.tbank.ru/tpay/

俄罗斯支付方式中,SberPay 和 T‑Pay 均可能涉及外部 App 跳转或移动端重定向。若商户 App 使用 WebView 打开收银台,请确保 WebView 不会拦截上述域名、HTTPS App Link 或自定义 scheme;实际生产链路中需要放行的完整 URL 以 Checus 收银台返回的跳转地址为准。

2. WebView 无法拉起第三方 App(ERR_UNKNOWN_URL_SCHEME 等)

现象: 使用 GoPay、LinePay 等支付方式时,WebView 页面提示 ERR_UNKNOWN_URL_SCHEME,或无法拉起对应第三方 App。

原因: WebView 默认只处理 httphttps 等常规链接。渠道返回 intent:// 或自定义 scheme 时,如果商户 App 未拦截并转交系统处理,就会导致跳转失败。

解决: 如果打开收银台的容器是 Android WebView,需要复写 WebViewClientshouldOverrideUrlLoading,对 intent:// 和非 http/https scheme 做系统跳转或 fallback 处理。

核心示例:

java
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
    String url = request != null && request.getUrl() != null
            ? request.getUrl().toString()
            : "";
    return handleExternalUrl(view, url) || super.shouldOverrideUrlLoading(view, request);
}

private boolean handleExternalUrl(WebView view, String url) {
    if (TextUtils.isEmpty(url)) {
        return false;
    }

    Uri uri = Uri.parse(url);
    String scheme = uri.getScheme();

    if ("intent".equals(scheme)) {
        try {
            Intent intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME);
            if (intent.resolveActivity(context.getPackageManager()) != null) {
                context.startActivity(intent);
                return true;
            }

            String fallbackUrl = intent.getStringExtra("browser_fallback_url");
            if (!TextUtils.isEmpty(fallbackUrl)) {
                view.loadUrl(fallbackUrl);
                return true;
            }
        } catch (Exception ignored) {
        }
    }

    if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
        try {
            context.startActivity(new Intent(Intent.ACTION_VIEW, uri));
            return true;
        } catch (Exception ignored) {
        }
    }

    return false;
}

如果打开收银台的容器是 iOS WKWebView,需要在导航决策中拦截非 http/https scheme,并交给系统打开。

Objective-C 示例:

objective-c
- (void)webView:(WKWebView *)webView
decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {

    NSURL *requestUrl = navigationAction.request.URL;
    NSString *scheme = requestUrl.scheme;

    if (scheme && ![scheme isEqualToString:@"http"] && ![scheme isEqualToString:@"https"]) {
        decisionHandler(WKNavigationActionPolicyCancel);

        UIApplication *application = [UIApplication sharedApplication];
        if (@available(iOS 10.0, *)) {
            [application openURL:requestUrl options:@{} completionHandler:nil];
        } else {
            [application openURL:requestUrl];
        }
        return;
    }

    decisionHandler(WKNavigationActionPolicyAllow);
}

Swift 示例:

swift
func webView(_ webView: WKWebView,
             decidePolicyFor navigationAction: WKNavigationAction,
             decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {

    guard let url = navigationAction.request.url,
          let scheme = url.scheme else {
        decisionHandler(.allow)
        return
    }

    if scheme != "http" && scheme != "https" {
        decisionHandler(.cancel)
        UIApplication.shared.open(url, options: [:], completionHandler: nil)
        return
    }

    decisionHandler(.allow)
}

如果打开失败,可按业务需要引导用户安装对应 App,或跳转到 App Store / 应用市场搜索页。

3. DANA 支付页面空白或提示网络不稳定

现象: API 标准入款接入方式打开 DANA 支付时,页面可能显示空白。滑动页面后可看到错误信息:The network connection is unstable. Please try again later.

原因: Android WebView 未开启必要的存储或视口配置,导致渠道页面资源加载异常。

解决: 初始化 WebView 时确认以下配置已开启:

java
webSettings.setDomStorageEnabled(true);
webSettings.setTextZoom(100);
webSettings.setUseWideViewPort(true);

4. 支付成功后如何返回商户 App

说明: 支付完成后,Checus 会打开商户传入的前端回调地址 frontCallBackUrl

  • 如果收银台是在商户 App 内部 WebView 打开的,frontCallBackUrl 通常也会在当前 App 容器内打开。
  • 如果收银台是在外部浏览器打开的,frontCallBackUrl 会在外部浏览器打开。此时如需回到商户 App,需要将回调地址设计为 scheme、Deep Link 或 Universal Link。

建议商户在支付结果页中同时处理「App 回跳」和「浏览器内展示结果」两种场景,避免用户无法回到业务流程。

5. 异步回调通知注意事项

适用场景: 商户通过服务端异步通知获取支付结果。

请确认以下事项:

  1. 回调地址真实存在,且外部网络可访问。
  2. 回调接口支持 application/json
  3. 回调处理需要校验签名,并做好幂等处理。
  4. 如果商户服务器设置了 IP 白名单,需要放行 Checus 回调服务器 IP。
  5. 回调响应内容请参考异步通知

注意:支付最终状态建议以服务端异步通知或主动查询结果为准,不建议仅以前端跳转结果判断。

6. 点击"确认支付"后未打开后续支付页面

现象: API 标准入款接入方式中,点击"确认支付"按钮后没有打开后续支付页面。

原因: Android WebView 未设置 WebViewClient,或相关跳转被默认容器行为拦截。

解决: 至少需要为 WebView 设置 WebViewClient

java
mWebView.setWebViewClient(new WebViewClient());

如果支付方式需要拉起第三方 App,请同时参考"WebView 无法拉起第三方 App"的处理方式。

7. 收银台提示"请求参数格式错误"

现象: 进入收银台后页面提示"请求参数格式错误"。

常见原因: 商户使用设备默认区域格式化金额,例如:

java
String.format(Locale.getDefault(), "%.2f", price)

不同地区的 Locale 可能产生不同的小数分隔符或格式,导致金额不符合接口要求。

解决: 金额格式化建议固定使用英文 locale:

java
String.format(Locale.ENGLISH, "%.2f", price)

8. 收银台支付方式展示不全或样式混乱

现象: 收银台页面支付方式展示不全、排版错乱或字体异常。

原因: Android WebView 字体缩放跟随系统设置,可能影响页面布局。

解决: 建议固定 WebView 字体缩放比例:

java
mWebView.getSettings().setTextZoom(100);

9. 支付时软键盘覆盖输入框

现象: 支付过程中需要输入手机号、邮箱等信息时,点击输入框后软键盘遮挡输入区域。

处理建议:

  1. 不要将支付页面容器设置为全屏模式。
  2. windowSoftInputMode 可以不设置,或设置为 adjustResize
  3. 不建议使用 adjustPan
  4. 如果使用沉浸式状态栏,布局中需要设置 fitSystemWindows=true

10. URI scheme 自动变为小写

现象: 商户传入的 URI 为 APP://,跳转时变成了 app://

原因: 浏览器和 WebView 通常会按 URL 规范处理 scheme。scheme 本身不区分大小写,部分容器会统一转为小写。

解决: AndroidManifest 中配置的 schemehost 建议全部使用小写,避免因大小写不一致导致 App 无法被拉起。

11. 页面报 X-Frame-Options

现象: 页面加载时报 X-Frame-Options 相关错误。

原因: 渠道侧页面不允许被 iframe 嵌套。

解决: 不要在 iframe 中打开该页面,改为直接打开页面地址。

12. Android WebView 推荐配置

如果商户必须在 Android WebView 中打开 Checus 收银台,建议至少确认以下配置:

java
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
webSettings.setTextZoom(100);
webSettings.setUseWideViewPort(true);
webSettings.setLoadWithOverviewMode(true);
webSettings.setSupportMultipleWindows(true);
webSettings.setJavaScriptCanOpenWindowsAutomatically(true);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
    CookieManager.getInstance().setAcceptThirdPartyCookies(mWebView, true);
}

mWebView.setWebViewClient(new WebViewClient());

同时建议确认:

  • Activity 已开启硬件加速:android:hardwareAccelerated="true"
  • 若支付链路涉及第三方 App,已处理 intent:// 和自定义 scheme。
  • 若商户对缓存策略有自定义处理,请避免禁用收银台静态资源缓存。
  • 若项目仍兼容旧版本 Android,可结合实际情况处理 allowFileAccessallowUniversalAccessFromFileURLs、缩放控件、多窗口能力等配置。
  • 如项目支持较低版本 Android,建议移除系统默认注入的高风险 JS 接口,例如 searchBoxJavaBridge_accessibilityaccessibilityTraversal

13. 收银台域名预连接建议

适用场景: 商户希望优化首次打开收银台的耗时。

建议: 在 App 启动后,或用户进入订单待支付页面但尚未点击支付时,提前对 Checus 收银台域名做连接预热,减少正式打开收银台时的 DNS 与 TLS 握手耗时。

  • Android:可引入 androidx.browser:browser,使用 CustomTabsClient.warmup()mayLaunchUrl(Uri.parse("https://cashier.checus.com")) 预热底层连接池。
  • iOS:可在进入支付前对 https://cashier.checus.com 发起轻量 HTTPS 请求,或按当前 iOS SDK 支持的公开能力进行预连接处理。

14. 页面报 net::ERR_CACHE_MISS

原因: Android 网络权限配置异常时,WebView 可能出现 net::ERR_CACHE_MISS

解决: 检查 AndroidManifest.xml 中的网络权限,权限名称需要使用大写 INTERNET

错误示例:

xml
<uses-permission android:name="android.permission.internet"/>

正确示例:

xml
<uses-permission android:name="android.permission.INTERNET"/>

15. iOS WKWebView 跳转失败,但系统浏览器正常

现象: 同一个链接在系统浏览器中可以正常打开,但在 iOS WKWebView 中跳转失败。

可能原因: WKWebView 对 URL 做编码处理后,链接中的 # 被编码为 %23,导致渠道页面识别异常。

解决: 对 URL 编码逻辑做兼容处理,确保 # 保持为允许字符。

Objective-C 示例:

objective-c
-(NSString *)WM_FUNC_urlEncode:(NSString *)urlStr {
    NSMutableCharacterSet *set = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
    [set addCharactersInString:@"#"];
    return [urlStr stringByAddingPercentEncodingWithAllowedCharacters:set];
}

Swift 示例:

swift
func WM_FUNC_urlEncode(_ urlStr: String) -> String {
    if urlStr.isEmpty {
        return ""
    }

    var charSet = CharacterSet.urlQueryAllowed
    charSet.insert(charactersIn: "#")
    return urlStr.addingPercentEncoding(withAllowedCharacters: charSet) ?? ""
}

16. Android 9.0 以上无法打开 http 页面

现象: Android 9.0 以上设备无法打开 http 页面,Android 9.0 以下设备正常。

原因: Android P 起默认限制 HTTP 明文流量,非加密请求可能被系统拦截。

解决: 优先将相关 API 或页面改为 HTTPS。

如业务仍需使用 HTTP,可通过以下方式允许明文流量。

方式一:新增 res/xml/network_security_config.xml

xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <base-config cleartextTrafficPermitted="true" />
</network-security-config>

并在 AndroidManifest.xml 中引用:

xml
<application android:networkSecurityConfig="@xml/network_security_config">
  <uses-library android:name="org.apache.http.legacy" android:required="false" />
</application>

方式二:在 AndroidManifest.xml 中配置:

xml
<application android:usesCleartextTraffic="true">

17. WebView 加载页面报 net::ERR_BLOCKED_BY_RESPONSE

原因: 目标页面不支持在 iframe 中打开,或响应头策略阻止页面被嵌入。

解决: 不要通过 iframe 嵌入该页面,改为直接打开页面地址。

参数配置

1. 如何生成密钥?

商户可登录商户平台,在「开发参数」中生成或重置密钥。

配置时请注意区分测试环境和正式环境,不同环境的密钥不可混用。

2. 如何添加回调地址?

Checus 支持两种方式设置回调地址:

  1. 拥有开发参数权限的操作员或超级管理员,可在商户平台「开发参数」中配置回调地址。
  2. 商户可在下单时传入回调地址。

如果下单时传入的回调地址与商户平台配置的回调地址不一致,以接口传入的回调地址为准。

3. 为什么没有收到回调通知?

请按以下顺序排查:

  1. 是否已配置回调地址。
  2. 回调地址是否填写正确。
  3. 回调地址是否可以被外部网络访问。
  4. 商户服务器是否配置 IP 白名单;如有,需要放行 Checus 回调服务器 IP。
  5. 商户服务是否正常返回 Checus 要求的响应内容。

若以上配置均正常仍未收到回调,请联系 Checus 平台协助排查。

基于 MIT 许可发布