PAYATHON 2026

Ionic 4 中 SumUp terminal payment callback 无法返回

支付老李

结论

问题出在协议配置不一致。SumUp 返回的是:

com.unmeat.app://result

而 ionic-plugin-deeplinks 的 DEEPLINK_SCHEME 配置成了 https。deeplink 的 scheme 和 host 必须与 callback 完全一致。另一种处理方式是把 SumUp callback 改为当前配置的 HTTPS App Link。

支付完成后的应用回跳通常更适合使用自定义 scheme:

com.unmeat.app://result

此外,还要确认 app-id 与 Android 应用实际使用的 application ID 完全一致,并对 callback 参数进行 URL 编码。

推荐配置

可以将 deeplink 配置改为:

{
  "URL_SCHEME": "com.unmeat.app",
  "DEEPLINK_SCHEME": "com.unmeat.app",
  "DEEPLINK_HOST": "result",
  "ANDROID_PATH_PREFIX": "/"
}

没有使用的第二至第五组配置应直接删除,不要传入空格。" " 并不是空值,而是一个实际字符,可能会生成无效或多余的 intent filter。

不同版本的 ionic-plugin-deeplinks 对 URL_SCHEME 和 DEEPLINK_SCHEME 的用途可能略有不同。某些版本使用 URL_SCHEME 注册自定义协议,而 DEEPLINK_SCHEME 和 DEEPLINK_HOST 用于 Android App Links。因此,修改配置后还要检查生成的 AndroidManifest.xml,确认其中存在能够匹配以下 URI 的 intent filter:

com.unmeat.app://result

关键声明应类似:

<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="com.unmeat.app"
        android:host="result" />
</intent-filter>

调整 SumUp 启动地址

建议使用 encodeURIComponent() 编码 callback,避免嵌套 URI 被错误解析:

const callback = encodeURIComponent('com.unmeat.app://result');

this.options.uri =
  'sumupmerchant://pay/1.0' +
  '?affiliate-key=AFFILIATE_KEY' +
  '&app-id=com.unmeat_test.app' +
  '&total=22' +
  '&currency=CHF' +
  '&title=' + encodeURIComponent('Test Order') +
  '&receipt-mobilephone=' +
  '&receipt-email=' +
  '&callback=' + callback;

this.appLauncher.launch(this.options).then(
  success => {
    console.log('Success Launch', success);
  },
  error => {
    console.log('Fail Launch', error);
  }
);

也可以先把参数放入数组再拼接,减少漏编码的情况:

const params = [
  `affiliate-key=${encodeURIComponent('AFFILIATE_KEY')}`,
  `app-id=${encodeURIComponent('com.unmeat_test.app')}`,
  `total=${encodeURIComponent('22')}`,
  `currency=${encodeURIComponent('CHF')}`,
  `title=${encodeURIComponent('Test Order')}`,
  `callback=${encodeURIComponent('com.unmeat.app://result')}`
];

this.options.uri = `sumupmerchant://pay/1.0?${params.join('&')}`;

检查 app-id

示例中使用了两个不同的标识:

app-id=com.unmeat_test.app
callback=com.unmeat.app://result

callback scheme 不必与 application ID 相同,但 app-id 必须符合 SumUp 接口要求,并对应调用方应用实际使用的 Android application ID。需要检查:

<widget id="com.unmeat_test.app">

以及生成后的 Android 配置。如果应用实际使用的 ID 是 com.unmeat.app,启动参数也要改成:

app-id=com.unmeat.app

不能只根据 deeplink scheme 判断 application ID,应以项目的实际构建配置为准。

Ionic 中接收回调

注册 deeplink 监听时,需要匹配 result host:

this.deeplinks.route({
  '/': {},
  '/result': {}
}).subscribe(
  match => {
    console.log('SumUp callback received', match);
  },
  noMatch => {
    console.log('Unmatched deeplink', noMatch);
  }
);

在 com.unmeat.app://result 中,result 是 URI 的 host,插件不一定会把它识别为 /result 路径。更稳妥的做法是同时记录原始回调,确认当前插件版本对 host 和 path 的解析方式:

this.deeplinks.route({}).subscribe(
  match => {
    console.log('Deep link match', match);
  },
  noMatch => {
    console.log('Deep link received but not matched', noMatch);
  }
);

如果路由插件无法稳定匹配只有 host 的 URI,可以在 callback 中加入明确的路径:

com.unmeat.app://result/payment

对应配置仍为:

scheme = com.unmeat.app
host = result
path = /payment

修改后必须重新构建

Cordova 插件变量会写入 Android 原生配置。只修改 JavaScript 或 config.xml 后进行热更新,通常不会让这些变更生效。需要删除并重新添加插件或 Android 平台,再重新安装 APK。具体命令取决于项目所使用的 Ionic/Cordova 版本。

完成修改后,逐字符核对以下值:

callback scheme: com.unmeat.app
manifest scheme: com.unmeat.app
callback host:   result
manifest host:   result

通过外部测试成功打开应用,只能说明某个 intent filter 可以启动该应用。这不能证明 SumUp 收到的 callback 参数正确,也不能证明当前 deeplink 路由规则能够匹配回调 URI。

备注:内容仅供参考。