PAYATHON 2026

PHP+Android 支付确认后如何重新打开 App

支付小周

结论

PHP 需要返回真正的 HTTP 302 重定向,并在 Location 响应头中传递 App 的自定义 URL Scheme。JSON 里的 Location 只是一个普通字段,浏览器不会因此自动跳转。

if ($result->Status == 100) {
    header('Location: url://siteurl.com/?type=profile', true, 302);
    exit;
}

原因

Python 代码返回的是 HTTP 重定向响应:

HTTP/1.1 302 Found
Location: url://siteurl.com/?type=profile

浏览器收到响应后,会尝试打开这个地址。如果 Android App 已注册 url:// Scheme,系统就可以把请求交给 App 处理。

当前 PHP 代码返回的是 JSON:

{
  "Status": true,
  "Message": "ok",
  "Location": "url://siteurl.com/?type=profile"
}

JSON 中的 Location 字段并不是 HTTP Location 响应头,所以无法触发浏览器重定向。

PHP 修改方式

可以直接设置重定向响应头:

<?php

if ($result->Status == 100) {
    header('Location: url://siteurl.com/?type=profile', true, 302);
    exit;
}

也可以分别设置状态码和响应头:

<?php

if ($result->Status == 100) {
    http_response_code(302);
    header('Location: url://siteurl.com/?type=profile');
    exit;
}

设置响应头之前,不要输出 JSON、HTML、空格或调试信息。否则可能出现 headers already sent,导致重定向头无法发送。

Android 端配置

App 需要在 AndroidManifest.xml 中为目标 Activity 注册与该地址匹配的 intent-filter:

<activity
    android:name=".MainActivity"
    android:exported="true">

    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data
            android:scheme="url"
            android:host="siteurl.com" />
    </intent-filter>
</activity>

这段配置匹配以下地址:

url://siteurl.com/?type=profile

App 打开后,可以从 Intent 中读取参数:

Uri data = getIntent().getData();

if (data != null) {
    String type = data.getQueryParameter("type");

    if ("profile".equals(type)) {
        // 打开 profile 页面
    }
}

如果目标 Activity 已经存在,还需要根据实际的 launchMode,在 onNewIntent() 中处理新链接:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);

    Uri data = intent.getData();
    if (data != null) {
        String type = data.getQueryParameter("type");
        // 根据 type 执行页面跳转
    }
}

注意事项

  • PHP 的 header() 必须在输出任何响应正文之前调用。
  • 发送重定向后应立即执行 exit,避免后续代码继续输出内容。
  • 自定义 Scheme 和 Host 必须与 Android Manifest 完全匹配,包括 url 和 siteurl.com。
  • 支付页面需要在能够处理外部 Scheme 的浏览器或 WebView 中打开。部分支付平台、内置浏览器或 WebView 可能会拦截自定义 Scheme。
  • 使用 WebView 时,Android 端可能需要在 WebViewClient 中识别 url://,再通过 Intent 打开,不能只依赖 WebView 的默认行为。
  • 更稳妥的生产方案是使用经过验证的 HTTPS Android App Link,并准备一个普通网页,在 App 未安装时作为回退页面。
  • 跳回 App 只能改善用户体验,不能作为判断支付成功的唯一依据。订单状态仍应通过支付平台的服务端回调、签名校验或服务端主动查询确认。

备注:内容仅供参考。