Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IOS支付回调不成功 #53

Open
shizhihuang opened this issue May 10, 2023 · 7 comments
Open

IOS支付回调不成功 #53

shizhihuang opened this issue May 10, 2023 · 7 comments

Comments

@shizhihuang
Copy link

iOS端调用支付宝返回应用后不走回调

@gujintao1900
Copy link

gujintao1900 commented Jun 5, 2023

我也有相同问题,之前好的,SDK没升级,前几周开始有用户反馈不行了,是不是支付宝的SDK升级了,需要同步适配啊。安卓是正常回调的。
测试过最新的 6.0.0 也有这个问题

@droplet-js
Copy link
Collaborator

昨天已经升级sdk了

@droplet-js
Copy link
Collaborator

另外,支付宝sdk新增了一个应用链接回调,不过没给文档也没有demo … 故而通用链接回调没敢用 …

@droplet-js
Copy link
Collaborator

我这边没有iOS支付宝应用,你们能配合debug一下不?我这边新建一个分支来调试 …

@droplet-js
Copy link
Collaborator

droplet-js commented Jun 8, 2023

试试我这代码,用了这么久基本没翻车 ...

import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:math';

import 'package:alipay_kit/alipay_kit_platform_interface.dart';
import 'package:crypto/crypto.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
import 'package:wechat_kit/wechat_kit.dart';

class SocialClub with WidgetsBindingObserver {
  SocialClub._() {
    WidgetsBinding.instance.addObserver(this);
  }

  static SocialClub get instance => _instance ??= SocialClub._();
  static SocialClub? _instance;

  StreamSubscription<WechatAuthResp>? _wechatAuthSub;

  StreamSubscription<WechatPayResp>? _wechatPaySub;
  StreamSubscription<AlipayResp>? _alipayPaySub;

  void init() {
    WechatKitPlatform.instance.registerApp(
      appId: appId,
      universalLink: universalLink,
    );
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    // super.didChangeAppLifecycleState(state);
    if (state == AppLifecycleState.resumed) {
      _clearSubscription();
    }
  }

  Future<void> _clearSubscription() async {
    final StreamSubscription<WechatAuthResp>? maybeIncompleteWechatAuthSub = _wechatAuthSub;
    final StreamSubscription<WechatPayResp>? maybeIncompleteWechatPaySub = _wechatPaySub;
    await Future<void>.delayed(const Duration(seconds: 1));
    //
    if (_wechatAuthSub != null && _wechatAuthSub == maybeIncompleteWechatAuthSub) {
      await _wechatAuthSub?.cancel();
      _wechatAuthSub = null;
    }
    //
    if (_wechatPaySub != null && _wechatPaySub == maybeIncompleteWechatPaySub) {
      await _wechatPaySub?.cancel();
      _wechatPaySub = null;
    }
  }

  // --- apple

  Future<bool> isAppleAvailable() async {
    return Platform.isIOS && await SignInWithApple.isAvailable();
  }

  Future<AuthorizationCredentialAppleID?> appleAuth() async {
    //
    String generateNonce([int length = 32]) {
      const String charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._';
      final Random random = Random.secure();
      return List<String>.generate(length, (int index) => charset[random.nextInt(charset.length)]).join();
    }

    String sha256ofString(String input) {
      final List<int> bytes = utf8.encode(input);
      final Digest digest = sha256.convert(bytes);
      return digest.toString();
    }

    //
    final String rawNonce = generateNonce();
    final String nonce = sha256ofString(rawNonce);
    try {
      final AuthorizationCredentialAppleID appleID = await SignInWithApple.getAppleIDCredential(
        scopes: <AppleIDAuthorizationScopes>[
          AppleIDAuthorizationScopes.email,
          AppleIDAuthorizationScopes.fullName,
        ],
        nonce: nonce,
      );
      return appleID;
    } on SignInWithAppleException catch (e) {
      if (e is SignInWithAppleAuthorizationException && e.code == AuthorizationErrorCode.canceled) {
        return null;
      } else {
        rethrow;
      }
    }
  }

  // --- wechat

  Future<bool> isWechatAvailable() {
    return WechatKitPlatform.instance.isInstalled();
  }

  // 在华为 nova 4 上,因微信在其他手机上登录了,重新登录,会造成无法接收 resumed 事件,从而无法正常完成授权流程。
  // 因此,需在调用授权时,不能阻塞用户后续再次发起授权登录行为
  Future<WechatAuthResp?> wechatAuth(bool isInstalled) {
    _wechatAuthSub?.cancel();
    _wechatAuthSub = null;
    //
    final Completer<WechatAuthResp?> completer = Completer<WechatAuthResp?>();
    _wechatAuthSub = WechatKitPlatform.instance.respStream().where((WechatResp event) => event is WechatAuthResp).cast<WechatAuthResp>().listen(
      (WechatAuthResp event) {
        if (completer.isCompleted) {
          return;
        }
        completer.complete(event);
      },
      onError: (Object error, [StackTrace? stackTrace]) {
        if (completer.isCompleted) {
          return;
        }
        completer.completeError(error, stackTrace);
      },
      cancelOnError: true,
    );
    WechatKitPlatform.instance.auth(
      scope: <String>[WechatScope.kSNSApiUserInfo],
      state: 'auth',
      type: Platform.isIOS && !isInstalled ? WechatAuthType.kWeb : WechatAuthType.kNormal,
    );
    return completer.future.whenComplete(() {
      _wechatAuthSub?.cancel();
      _wechatAuthSub = null;
    });
  }

  Future<void> wechatShareWebpage({
    required int scene,
    required String url,
    String? title,
    String? desc,
    Uint8List? thumbData,
  }) {
    return WechatKitPlatform.instance.shareWebpage(
      scene: scene,
      webpageUrl: url,
      title: title,
      description: desc,
      thumbData: thumbData,
    );
  }

  Future<void> wechatShareImage({
    required int scene,
    required Uri imageUri,
    String? title,
    String? description,
    Uint8List? thumbData,
    Uint8List? imageData,
  }) {
    return WechatKitPlatform.instance.shareImage(
      scene: scene,
      imageUri: imageUri,
      title: title,
      description: description,
      thumbData: thumbData,
      imageData: imageData,
    );
  }

  Future<void> wechatCustomerServiceChat({
    required String corpId,
    required String url,
  }) {
    return WechatKitPlatform.instance.openCustomerServiceChat(
      corpId: corpId,
      url: url,
    );
  }

  Future<WechatPayResp> wechatPay({
    required String appId,
    required String partnerId,
    required String prepayId,
    required String package,
    required String nonceStr,
    required String timeStamp,
    required String sign,
  }) {
    _wechatPaySub?.cancel();
    _wechatPaySub = null;
    //
    final Completer<WechatPayResp> completer = Completer<WechatPayResp>();
    _wechatPaySub = WechatKitPlatform.instance.respStream().where((WechatResp event) => event is WechatPayResp).cast<WechatPayResp>().listen(
      (WechatPayResp event) {
        if (completer.isCompleted) {
          return;
        }
        completer.complete(event);
      },
      onError: (Object error, [StackTrace? stackTrace]) {
        if (completer.isCompleted) {
          return;
        }
        completer.completeError(error, stackTrace);
      },
      cancelOnError: true,
    );
    WechatKitPlatform.instance.pay(
      appId: appId,
      partnerId: partnerId,
      prepayId: prepayId,
      package: package,
      nonceStr: nonceStr,
      timeStamp: timeStamp,
      sign: sign,
    );
    return completer.future.whenComplete(() {
      _wechatPaySub?.cancel();
      _wechatPaySub = null;
    });
  }

  // --- alipay

  Future<bool> isAlipayAvailable() {
    return AlipayKitPlatform.instance.isInstalled();
  }

  Future<AlipayResp> alipayUnsafePay({
    required String orderInfo,
    required String rsaPrivate,
  }) {
    return alipayPay(
      orderInfo:
          '$orderInfo&sign="${Uri.encodeQueryComponent(base64.encode(RsaSigner.sha1Rsa('-----BEGIN PRIVATE KEY-----\n$rsaPrivate\n-----END PRIVATE KEY-----').sign(utf8.encode(orderInfo))))}"&sign_type="RSA"',
    );
  }

  Future<AlipayResp> alipayPay({
    required String orderInfo,
  }) {
    _alipayPaySub?.cancel();
    _alipayPaySub = null;
    //
    final Completer<AlipayResp> completer = Completer<AlipayResp>();
    _alipayPaySub = AlipayKitPlatform.instance.payResp().listen(
      (AlipayResp event) {
        if (completer.isCompleted) {
          return;
        }
        completer.complete(event);
      },
      onError: (Object error, [StackTrace? stackTrace]) {
        if (completer.isCompleted) {
          return;
        }
        completer.completeError(error, stackTrace);
      },
      cancelOnError: true,
    );
    AlipayKitPlatform.instance.pay(orderInfo: orderInfo);
    return completer.future.whenComplete(() {
      _alipayPaySub?.cancel();
      _alipayPaySub = null;
    });
  }
}

@gujintao1900
Copy link

我这边解决了, 看了下源码。

  1. 执行 pod install 的时候从 pubspec.yaml 提取 scheme 配置
  2. 然后通过 alipay_setup.rb 把 scheme 写到宿主当前 xxx.plist 中的 CFBundleURLTypes 里面
  3. 插件侧通过 ALIPAY_KIT_SCHEME 绑定 scheme 信息

原因:老版本中手动配置的 scheme,与后来在 pubspec.yaml 中配置的不一致

我在执行 pod install 的时候会提示找不到 plist

Analyzing dependencies
alipaysdk utdid
Runner/Info-$(CONFIGURATION).plist is not exist
Runner/Info-$(CONFIGURATION).plist is not exist
wechatsdk pay
Runner/Info-$(CONFIGURATION).plist is not exist
Downloading dependencies
Generating Pods project
Integrating client project

实际目录下是有的,这里暂时不清楚怎么解决
image

所以我手动修改文件,重新编译后就正常

<dict>
	<key>CFBundleTypeRole</key>
	<string>Editor</string>
	<key>CFBundleURLName</key>
	<string>alipay</string>
	<key>CFBundleURLSchemes</key>
	<array>
		<string>必须和pubspec.yaml中的alipay_kit.scheme一致</string>
	</array>
</dict>

@droplet-js
Copy link
Collaborator

我这边解决了, 看了下源码。

  1. 执行 pod install 的时候从 pubspec.yaml 提取 scheme 配置

  2. 然后通过 alipay_setup.rb 把 scheme 写到宿主当前 xxx.plist 中的 CFBundleURLTypes 里面

  3. 插件侧通过 ALIPAY_KIT_SCHEME 绑定 scheme 信息

原因:老版本中手动配置的 scheme,与后来在 pubspec.yaml 中配置的不一致

我在执行 pod install 的时候会提示找不到 plist


Analyzing dependencies

alipaysdk utdid

Runner/Info-$(CONFIGURATION).plist is not exist

Runner/Info-$(CONFIGURATION).plist is not exist

wechatsdk pay

Runner/Info-$(CONFIGURATION).plist is not exist

Downloading dependencies

Generating Pods project

Integrating client project

实际目录下是有的,这里暂时不清楚怎么解决

image

所以我手动修改文件,重新编译后就正常

<dict>

	<key>CFBundleTypeRole</key>

	<string>Editor</string>

	<key>CFBundleURLName</key>

	<string>alipay</string>

	<key>CFBundleURLSchemes</key>

	<array>

		<string>必须和pubspec.yaml中的alipay_kit.scheme一致</string>

	</array>

</dict>

ruby代码里明确了不支持这种动态配置info.plist … pod install过程中是无法获取 configuration 变量的 … 所以,你这才报错了 … 建议配置一个 info.plist,变量通过 xconfig 文件来配置,参考 debug.xconfig 等 …

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants