Swiftui中的格子Oauth oauth深层链接集成

发布于 2025-01-22 06:13:44 字数 6094 浏览 3 评论 0 原文

是否有关于如何使用纯Swiftui在iOS中实施OAuth的教程?

我在这里阅读了所有文档( https://plaid.com/docs/link/link/link/link/oauth/ )并在此处研究了代码( https://github.com/plaid/plaid/plaid/plaid-link-link -ios )。

上面的格子示例的问题在于,它显示了基于OAuth的Uikit ViewController的SwiftUI实现。我的应用程序是100%SwiftUi,我们不使用ViewControllers。

当我在沙箱中测试格子oauth(使用鸭嘴兽帐户)时,我可以从他们的测试网站重定向到我的应用程序,但是我无法阅读深链接参数中通过的参数(oauth_state_id = 21a91b98 -06AC-4C2C-9E5F-83C5FE9CBBA5)。这是我目前这样做的方式:

1/以下是我们的bankAccountview的简化版本,在我们的应用程序中启动了格子模式。 的一些注释:

有关此文件 如您所见,我在.fullscreencover()修饰符中打开格子模式。

b。 linkController对象是以下的复制/粘贴: https://github.com/plaid/plaid-link-ios/blob/master/linkdemo-swift/linkdemo-swift/linkdemo-swift/linkkitswiftuisupport.swift.swift.swift

import SwiftUI
import LinkKit
import FirebaseFunctions

protocol LinkOAuthHandling {
    var linkHandler: Handler? { get }
    var oauthRedirectUri: URL? { get }
}

struct BankAccountsView: View, LinkOAuthHandling {
            
    @State var configurationForCreate: LinkTokenConfiguration?
    @State var configurationForUpdate: LinkTokenConfiguration?
    @State var plaidModal: LinkController?
    
    @State var linkHandler: Handler?
    var oauthRedirectUri: URL? = { URL(string: "https://cruisedevelopment.page.link") }()
    
    var body: some View {
        VStack {
            
            // BUTTON TO OPEN PLAID MODAL
            Button("Link bank account") {
                configurationForCreate = createLinkTokenConfigurationForCreate(with: plaid.tokenForCreate)
                plaidModal = LinkController(configuration: .linkToken(configurationForCreate!), openOptions: [:]) { (error) in
                    print("Handle error: \(error)!")
                }
            }
            
            // OPEN PLAID MODAL
            if plaidModal != nil { Rectangle().frame(width: 0, height: 0).onAppear { isPlaidModalOpen = true } }
            
            // ... MORE CONTENT
        
        }
        .onAppear {
            plaid.getLinkTokenForCreate()
        }
        // PLAID MODAL
        .fullScreenCover(isPresented: $isPlaidModalOpen, onDismiss: {
            isPlaidModalOpen = false
        }, content: {
            plaidModal
        })
    }
    
    private func createLinkTokenConfigurationForCreate(with linkToken: String) -> LinkTokenConfiguration {
        var linkConfiguration = LinkTokenConfiguration(token: linkToken) { success in
            print("public-token: \(success.publicToken) metadata: \(success.metadata)")
            self.handleSuccessForCreate(success.publicToken, metadata: success.metadata)
        }
        linkConfiguration.onExit = { exit in
            if let error = exit.error {
                print("LinkTokenConfigurationForCreate exit with \(error)\n\(exit.metadata)")
            } else {
                print("LinkTokenConfigurationForCreate exit with \(exit.metadata)")
            }
            hidePlaidModal()
        }
        return linkConfiguration
    }
    
    private func handleSuccessForCreate(_ publicToken: String, metadata: SuccessMetadata) {
        let bankId = metadata.institution.id
        let bankName = metadata.institution.name
        var accountsIds = [String]()
        for account in metadata.accounts { accountsIds.append(account.id) }
        let payload: [String: Any] = [
            "publicToken": publicToken,
            "bankId": bankId,
            "bankName": bankName,
            "accountsIds": accountsIds
        ]
        isFinishingPlaidSetup = true
        Functions.functions().httpsCallable(finishPlaidSetupPath).call(payload) { (result, error) in
            if let error = error {
                print("Error finishing Plaid setup: \(error.localizedDescription)")
            } else {
                print("Success finishing Plaid setup: \(result!)")
            }
            isFinishingPlaidSetup = false
            hidePlaidModal()
        }
    }
}

2/app2app oauth oauth oauth flow and the app2app oauth oauth flow termines及用户被重定向到我的应用程序(同时Plaid FullScreenCover仍然打开),我使用.onopenurl()修饰符处理深层链接(这是使用SwiftUi进行的新方法 - 请参阅此处:)。我正在附上显示我们使用的代码的屏幕截图。

的注释:

有关此文件 我的目标是复制以下内容: https://github.com/plaid/plaid-link-ios/blob/master/linkdemo-swift/linkdemo-swift/appdelegate%2boauthsupport.swift.swift

b。该代码当前按预期执行,直到“失败1”行。也就是说,我从Platypus Bank网站上收到看起来像正确的深链接URL,并且可以抓住KeyWindow,但是我无法使用该KeyWindow创建link0authhandler的link0authhandler(即使应用程序仍然仍然是应用程序,格子全屏幕上的右屏幕上是否打开)。

import SwiftUI
import LinkKit

@main
struct CruiseApp: App {
    
    @UIApplicationDelegateAdaptor var delegate: AppDelegate
        
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    let window = UIApplication.shared.connectedScenes.flatMap {($0 as? UIWindowScene)?.windows ?? [] }.first { $0.isKeyWindow }
                    guard let linkOAuthHandler = window?.rootViewController as? LinkOAuthHandling else { let _ = print(">> FAIL 1"); return }
                    guard let handler = linkOAuthHandler.linkHandler else { let _ = print(">> FAIL 2"); return }
                    handler.continue(from: url)                    
                }
        }
    }
}

我认为问题与上述过程有关。

Is there a tutorial on how to implement OAuth in iOS using pure SwiftUI?

I read all the docs here (https://plaid.com/docs/link/oauth/) and studied the code here (https://github.com/plaid/plaid-link-ios).

The problem with the Plaid example above is that it shows a SwiftUI implementation of OAuth based a UIKit ViewController. My app is 100% SwiftUI and we don't use a ViewControllers.

When I test the Plaid OAuth in sandbox (using the platypus account), I'm able to redirect to my app from their test website, but I'm unable to read the arguments passed in the parameters of the deep link (oauth_state_id=21a91b98-06ac-4c2c-9e5f-83c5fe9cbba5). Here is how I currently do it:

1/ Below is a simplified version of our bankAccountView, where the Plaid modal is launched within our app. A few notes about this file:

a. As you can see, I open the Plaid modal inside a .fullScreenCover() modifier.

b. The LinkController object is a copy/paste of this: https://github.com/plaid/plaid-link-ios/blob/master/LinkDemo-Swift/LinkDemo-Swift/LinkKitSwiftUISupport.swift

import SwiftUI
import LinkKit
import FirebaseFunctions

protocol LinkOAuthHandling {
    var linkHandler: Handler? { get }
    var oauthRedirectUri: URL? { get }
}

struct BankAccountsView: View, LinkOAuthHandling {
            
    @State var configurationForCreate: LinkTokenConfiguration?
    @State var configurationForUpdate: LinkTokenConfiguration?
    @State var plaidModal: LinkController?
    
    @State var linkHandler: Handler?
    var oauthRedirectUri: URL? = { URL(string: "https://cruisedevelopment.page.link") }()
    
    var body: some View {
        VStack {
            
            // BUTTON TO OPEN PLAID MODAL
            Button("Link bank account") {
                configurationForCreate = createLinkTokenConfigurationForCreate(with: plaid.tokenForCreate)
                plaidModal = LinkController(configuration: .linkToken(configurationForCreate!), openOptions: [:]) { (error) in
                    print("Handle error: \(error)!")
                }
            }
            
            // OPEN PLAID MODAL
            if plaidModal != nil { Rectangle().frame(width: 0, height: 0).onAppear { isPlaidModalOpen = true } }
            
            // ... MORE CONTENT
        
        }
        .onAppear {
            plaid.getLinkTokenForCreate()
        }
        // PLAID MODAL
        .fullScreenCover(isPresented: $isPlaidModalOpen, onDismiss: {
            isPlaidModalOpen = false
        }, content: {
            plaidModal
        })
    }
    
    private func createLinkTokenConfigurationForCreate(with linkToken: String) -> LinkTokenConfiguration {
        var linkConfiguration = LinkTokenConfiguration(token: linkToken) { success in
            print("public-token: \(success.publicToken) metadata: \(success.metadata)")
            self.handleSuccessForCreate(success.publicToken, metadata: success.metadata)
        }
        linkConfiguration.onExit = { exit in
            if let error = exit.error {
                print("LinkTokenConfigurationForCreate exit with \(error)\n\(exit.metadata)")
            } else {
                print("LinkTokenConfigurationForCreate exit with \(exit.metadata)")
            }
            hidePlaidModal()
        }
        return linkConfiguration
    }
    
    private func handleSuccessForCreate(_ publicToken: String, metadata: SuccessMetadata) {
        let bankId = metadata.institution.id
        let bankName = metadata.institution.name
        var accountsIds = [String]()
        for account in metadata.accounts { accountsIds.append(account.id) }
        let payload: [String: Any] = [
            "publicToken": publicToken,
            "bankId": bankId,
            "bankName": bankName,
            "accountsIds": accountsIds
        ]
        isFinishingPlaidSetup = true
        Functions.functions().httpsCallable(finishPlaidSetupPath).call(payload) { (result, error) in
            if let error = error {
                print("Error finishing Plaid setup: \(error.localizedDescription)")
            } else {
                print("Success finishing Plaid setup: \(result!)")
            }
            isFinishingPlaidSetup = false
            hidePlaidModal()
        }
    }
}

2/ After the App2App OAuth flow finishes and the user is redirected to my app (while the Plaid fullScreenCover is still open), I handle the deep link using the .onOpenUrl() modifier (this is the new way of doing it with SwiftUI - see here: https://www.donnywals.com/handling-deeplinks-in-ios-14-with-onopenurl/). I'm attaching a screenshot that shows the code we use.

Notes about this file:

a. My goal here is to replicate this: https://github.com/plaid/plaid-link-ios/blob/master/LinkDemo-Swift/LinkDemo-Swift/AppDelegate%2BOAuthSupport.swift

b. The code currently executes as expected until the "Fail 1" line. That is, I receive what looks like the right deep link URL from the platypus bank website and I'm able to grab the keyWindow, but I am unable to create a link0AuthHandler of type "Link0AuthHandling" using that keyWindow (even though the app still has the Plaid fullScreenCover open on the right screen).

import SwiftUI
import LinkKit

@main
struct CruiseApp: App {
    
    @UIApplicationDelegateAdaptor var delegate: AppDelegate
        
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    let window = UIApplication.shared.connectedScenes.flatMap {($0 as? UIWindowScene)?.windows ?? [] }.first { $0.isKeyWindow }
                    guard let linkOAuthHandler = window?.rootViewController as? LinkOAuthHandling else { let _ = print(">> FAIL 1"); return }
                    guard let handler = linkOAuthHandler.linkHandler else { let _ = print(">> FAIL 2"); return }
                    handler.continue(from: url)                    
                }
        }
    }
}

I think the issue has to do with the process described above.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

桃气十足 2025-01-29 06:13:44

这听起来很奇怪,但是在检查 userDefaults 之后,我都会引用所有格子链接功能,这引起了问题。可能与上面提到的线程问题有关,但只是以为我会为我提供解决方案。

if let name_of_bank = UserDefaults.standard.string(forKey: "variable") {
    presentPlaidLinkUsingLinkToken()
}

将此功能移动到其他地方解决了问题。

This is going to sound odd but I had all the Plaid Link functionality being referenced after I checked the UserDefaults and that was causing the issue. Likely related to a thread issue mentioned above but just thought I would offer what fixed it for me.

if let name_of_bank = UserDefaults.standard.string(forKey: "variable") {
    presentPlaidLinkUsingLinkToken()
}

Moving this function elsewhere solved the issue.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文