ios - 添加 AllInOneSDKSwiftWrapper.swift 后,如何在一个 sdk 中实现 Paytm all in react native 给出错误
问题描述
我已经创建了这个 AllInOneSDKSwiftWrapper.swift 类,然后 xcode 要求我提供桥接头,我在添加了 paytm doc中给出的代码后允许它,它在文件中给出了多个错误。我还添加了 AllInOneSDKSwiftWrapper.m 文件。我不是 ios 开发人员,所以我不知道如何修复以及我应该在空生成的桥接头文件中写什么。
解决方案
Paytm 对 iOS 和 Android 的原生支持文档非常差,因为它没有在原生端设置和运行代码所需的完整信息集。
下面是运行Xcode v12.0、Swift 5、RN v0.63.2的 iOS 的实现
将框架复制并粘贴到“ ios/YourApp ”文件夹中
打开您的工作区并单击文件 -> 添加文件
导航到框架,选择它并单击添加(这很重要,不要像 Paytm 文档中提到的那样拖放)
在General 选项卡下的TARGETS/YourApp中,框架应链接到Frameworks、Libraries 和 Embedded Content部分
将嵌入选项更改为嵌入并签名
在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))
})
}
}
推荐阅读
- flutter - 在小部件被移除之前应用动画
- python - 检查行值是否等于列名并访问列的值
- c# - 如何从 C# 运行多个查询 postgresql 语句
- android - android gradle 收集依赖资源列表名称
- solidity - 如何避免 Remix IDE 中出现 Out of Mem 错误,运行solidity 智能合约?
- go - 为什么curl命令在golang中不起作用
- ssis - 在 Sql Server 表中使用动态 Excel 表导出动态 Excel 文件
- spring-boot - 当我使用 redisTemplate.setHashKeySerializer(new StringRedisSerializer()) 时无法成功反序列化整数
- ios - 如何设置 backBarButtonItem 的边距?
- javascript - 如何使用 ajax 加载快速启动页面或使用路由发布