首页 > 解决方案 > 添加 AllInOneSDKSwiftWrapper.swift 后,如何在一个 sdk 中实现 Paytm all in react native 给出错误

问题描述

我已经创建了这个 AllInOneSDKSwiftWrapper.swift 类,然后 xcode 要求我提供桥接头,我在添加了 paytm doc中给出的代码后允许它,它在文件中给出了多个错误。我还添加了 AllInOneSDKSwiftWrapper.m 文件。我不是 ios 开发人员,所以我不知道如何修复以及我应该在空生成的桥接头文件中写什么。

在此处输入图像描述

标签: iosswiftreact-nativeflutterpaytm

解决方案


Paytm 对 iOS 和 Android 的原生支持文档非常差,因为它没有在原生端设置和运行代码所需的完整信息集。

下面是运行Xcode v12.0Swift 5RN v0.63.2的 iOS 的实现

  1. 下载AppInvokeSDK.framework

  2. 将框架复制并粘贴到“ ios/YourApp ”文件夹中

  3. 打开您的工作区并单击文件 -> 添加文件

  4. 导航到框架,选择它并单击添加(这很重要,不要像 Paytm 文档中提到的那样拖放)

  5. 在General 选项卡下的TARGETS/YourApp中,框架应链接到Frameworks、Libraries 和 Embedded Content部分

  6. 将嵌入选项更改为嵌入并签名

  7. 在PROJECT -> YourApp -> Build settings中添加以下路径链接。搜索标题搜索路径并添加以下路径

    $(SRCROOT)/../node_modules/react-native/Libraries/LinkingIOS

在Bridging-Header.h中导入标头

#import "React/RCTBridgeModule.h"
#import "React/RCTEventEmitter.h"

AllInOneSDKSwiftWrapper.h

#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"
#if __has_include("RCTEventEmitter.h")
#import "RCTEventEmitter.h"
#else
#import <React/RCTEventEmitter.h>
#endif

@interface RCT_EXTERN_MODULE(AllInOneSDKSwiftWrapper, RCTEventEmitter)

RCT_EXTERN_METHOD(openPaytm:(NSString *)mid
orderId:(NSString *)oid
transactionToken:(NSString *)txnTkn
amount:(NSString *)amt
callbackUrl:(NSString *)url
isStaging: (BOOL)isStaging)
@end

AllInOneSDKSwiftWrapper.swift

import Foundation
import AppInvokeSDK
import UIKit

class EventEmitter {
    /// Shared Instance.
    public static var sharedInstance = EventEmitter()

    // ReactNativeEventEmitter is instantiated by React Native with the bridge.
    private static var eventEmitter: AllInOneSDKSwiftWrapper!

    private init() {}

    // When React Native instantiates the emitter it is registered here.
    func registerEventEmitter(eventEmitter: AllInOneSDKSwiftWrapper) {
        EventEmitter.eventEmitter = eventEmitter
    }

    func dispatch(name: String, body: Any?) {
       EventEmitter.eventEmitter.sendEvent(withName: name, body: body)
    }

    /// All Events which must be support by React Native.
    lazy var allEvents: [String] = {
        var allEventNames: [String] = ["responseIfNotInstalled", "responseIfPaytmInstalled"]
        // Append all events here
        return allEventNames
    }()
}

@objc(AllInOneSDKSwiftWrapper)
class AllInOneSDKSwiftWrapper: RCTEventEmitter, AIDelegate {

    private let handler = AIHandler()

    var viewController = UIApplication.shared.windows.first?.rootViewController

    override static func moduleName() -> String! {
        return "AllInOneSDKSwiftWrapper"
    }

    override init() {
        super.init()

        EventEmitter.sharedInstance.registerEventEmitter(eventEmitter: self)

        NotificationCenter.default.addObserver(self, selector:   #selector(getAppInvokeResponse(notification:)), name:  NSNotification.Name(rawValue: "appInvokeNotification"), object: nil)
    }

    @objc func getAppInvokeResponse(notification: NSNotification) {
        if let userInfo = notification.userInfo {
            let url = userInfo["appInvokeNotificationKey"] as? String
            let response = self.separateDeeplinkParamsIn(url: url, byRemovingParams: nil)
            let alert = UIAlertController(title: "Response", message: response.description, preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
            self.viewController?.present(alert, animated: true, completion: nil)
            sendEvent(withName: "responseIfPaytmInstalled", body: response)
        }
     }

     /// Base overide for RCTEventEmitter.
     ///
     /// - Returns: all supported events
     @objc open override func supportedEvents() -> [String] {
         return EventEmitter.sharedInstance.allEvents
     }

     @objc override static func requiresMainQueueSetup() -> Bool {
         return true
     }

     @objc(openPaytm:orderId:transactionToken:amount:callbackUrl:isStaging:)
     func openPaytm(_ mid: String, orderId: String, transactionToken: String, amount: String, callbackUrl: String?, isStaging: Bool) {
         DispatchQueue.main.async {
             var env:AIEnvironment = .production
                 if isStaging {
                     env = .staging
                 } else {
                     env = .production
                 }
    
             self.handler.openPaytm(merchantId: mid, orderId: orderId, txnToken: transactionToken, amount: amount, callbackUrl: callbackUrl, delegate: self, environment: env)
          }
      }

      @objc func separateDeeplinkParamsIn(url: String?, byRemovingParams rparams: [String]?)  -> [String: String] {
          guard let url = url else {
              return [String : String]()
          }

          /// This url gets mutated until the end. The approach is working fine in current scenario. May need a revisit.
          var urlString = stringByRemovingDeeplinkSymbolsIn(url: url)
          var paramList = [String : String]()
          let pList = urlString.components(separatedBy:   CharacterSet.init(charactersIn: "&?"))
          for keyvaluePair in pList {
              let info = keyvaluePair.components(separatedBy: CharacterSet.init(charactersIn: "="))
              if let fst = info.first , let lst = info.last, info.count == 2 {
                  paramList[fst] = lst.removingPercentEncoding
                  if let rparams = rparams, rparams.contains(info.first!) {
                      urlString = urlString.replacingOccurrences(of: keyvaluePair + "&", with: "")
                      
                      //Please dont interchage the order
                      urlString = urlString.replacingOccurrences(of: keyvaluePair, with: "")
                  }
               }
           }

           if let trimmedURL = pList.first {
               paramList["trimmedurl"] = trimmedURL
           }

           return paramList
       }

       func stringByRemovingDeeplinkSymbolsIn(url: String) -> String {
           var urlString = url.replacingOccurrences(of: "$", with: "&")
           
           // This may need a revisit. This is doing more than just removing the deeplink symbol.
           if let range = urlString.range(of: "&"), urlString.contains("?") == false {
               urlString = urlString.replacingCharacters(in: range, with: "?")
           }

           return urlString
       }

       func openPaymentWebVC(_ controller: UIViewController?) {
           if let vc = controller {
               DispatchQueue.main.async {[weak self] in self?.viewController?.present(vc, animated: true, completion: nil)}
           }
       }

       func didFinish(with status: AIPaymentStatus, response: [String : Any]) {
           sendEvent(withName: "responseIfNotInstalled", body: response)
           let alert = UIAlertController(title: "(status)", message: String(describing: response), preferredStyle: .alert)
           alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
           DispatchQueue.main.async { self.viewController?.present(alert, animated: true, completion: nil) }
       }
 }

AppDelegate.m

#import "RCTLinkingManager.h" // Import this header

// Add the below function
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url
    options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{

    NSString *urlString = url.absoluteString;
    NSDictionary *userInfo =
    [NSDictionary dictionaryWithObject:urlString forKey:@"appInvokeNotificationKey"];
    [[NSNotificationCenter defaultCenter] postNotificationName:@"appInvokeNotification" object:nil userInfo:userInfo];
    return [RCTLinkingManager application:app openURL:url options:options];
}

PaytmT.ts

import { NativeModules, NativeEventEmitter, Alert } from 'react-native'

export class PaytmT {

    /** Call this function to invoke the Paytm Flow for iOS */
    invoke() {
        const allInOnePaytmSDK = NativeModules.AllInOneSDKSwiftWrapper
        allInOnePaytmSDK.openPaytm('MERCHANT_ID', 'ORDER_ID', 'TXN_TOKEN', 'AMOUNT', 'CALLBACKURL', true) // If production environment, change it to false

        const CounterEvents = new NativeEventEmitter(NativeModules.AllInOneSDKSwiftWrapper)
        CounterEvents.addListener('responseIfNotInstalled', (response) => {
            Alert.alert(PaytmT.name, JSON.stringify(response))
        })
        CounterEvents.addListener('responseIfPaytmInstalled', (response) => {
            Alert.alert(PaytmT.name, JSON.stringify(response))
        })
    }
}

推荐阅读