我有一个React Native应用程序,一切正常,我需要在Objective-C中集成iOS的SDK。我已经创建了一个网桥,可以在React Native中调用本机iOS方法,并通过发射器将响应接收回我的React Native应用中。
问题在于,SDK的其中一个方法调用是要求传递呈现视图控制器,因为SDK似乎具有要显示的预编译情节提要。但是,我一直无法使用要传入的视图控制器。我认为SDK的故事板将在该控制器上显示,直到将其关闭为止。
有人可以从下面的代码中告诉我我所缺少的内容吗?由于我对Objective-C不太熟悉,所以我可能错过了一些基本知识。
我的桥接文件如下:
#import "AuthorizeNet.h"
// import RCTBridge
#if __has_include(<React/RCTBridge.h>)
#import <React/RCTBridge.h>
#elif __has_include(“RCTBridge.h”)
#import “RCTBridge.h”
#else
#import “React/RCTBridge.h”
#endif
// import RCTEventDispatcher
#if __has_include(<React/RCTEventDispatcher.h>)
#import <React/RCTEventDispatcher.h>
#elif __has_include(“RCTEventDispatcher.h”)
#import “RCTEventDispatcher.h”
#else
#import “React/RCTEventDispatcher.h”
#endif
#import <AuthNet.h>
#import <MobileDeviceLoginRequest.h>
#import <React/RCTLog.h>
#import <AnetEMVManager.h>
#import <AnetBTObject.h>
@implementation AuthorizeNet
@synthesize bridge = _bridge;
// Export a native module
RCT_EXPORT_MODULE();
// Export constants
- (NSDictionary *)constantsToExport
{
return @{
@"EXAMPLE": @"example"
};
}
- (NSArray<NSString *> *)supportedEvents
{
return @[
@"SCAN_DEVICES",
@"DEVICE_CONNECTION",
];
}
// Return the native view that represents your React component
- (UIView *)view
{
return [[UIView alloc] init];
}
// Export methods to a native module
RCT_EXPORT_METHOD(login)
{
RCTLogInfo(@"Trying to login to gateway");
[self loginToGateway];
}
RCT_EXPORT_METHOD(scanDevices)
{
dispatch_async(dispatch_get_main_queue(), ^{
RCTLogInfo(@"Trying to scan devices");
[self scanBTDevices];
});
}
RCT_EXPORT_METHOD(connectToDevice:(NSInteger *)index)
{
dispatch_async(dispatch_get_main_queue(), ^{
RCTLogInfo(@"Trying to connect to device");
[self connectToBTDevice:index];
});
}
RCT_EXPORT_METHOD(disconnectDevice)
{
dispatch_async(dispatch_get_main_queue(), ^{
RCTLogInfo(@"Disconnecting device");
[self disconnectBTDevice];
});
}
RCT_EXPORT_METHOD(swipeAndSend:(NSString *)amount :(NSString *)paymentId)
{
dispatch_async(dispatch_get_main_queue(), ^{
RCTLogInfo(@"Swipe and send transaction");
[self swipeAndSendTransaction:amount :paymentId];
});
}
#pragma mark - Private methods
NSString* sessionToken;
AnetEMVManager *AnetMan;
// Implement methods that you want to export to the native module
- (void) emitDeviceListToRN: (NSString *)eventName :(NSArray *)foundDevices {
[self sendEventWithName: eventName body: foundDevices];
}
- (void) emitDeviceConnectionToRN: (NSString *)eventName :(NSNumber *)connected {
[self sendEventWithName: eventName body: connected];
}
// API methods
- (void) loginToGateway {
RCTLogInfo(@"login to gateway called");
[AnetMan setLoggingEnabled:TRUE];
MobileDeviceLoginRequest *mobileDeviceLoginRequest =
[MobileDeviceLoginRequest mobileDeviceLoginRequest];
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.name = @"xxxxx";
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.password = @"xxxxx";
mobileDeviceLoginRequest.anetApiRequest.merchantAuthentication.mobileDeviceId = @"xxxxx";
AuthNet *an = [AuthNet getInstance];
[an setDelegate:self];
[an setLoggingEnabled:true];
[an mobileDeviceLoginRequest: mobileDeviceLoginRequest];
}
- (void) scanBTDevices {
RCTLogInfo(@"Scan devices called");
AnetEMVTerminalMode iTerminalMode = AnetEMVModeInsertOrSwipe;
AnetEMVConnectionMode iConnectionMode = AnetEMVConnectionModeBluetooth;
AnetMan = [AnetEMVManager initWithCurrecyCode:@"USD" terminalID:@"xxxxx" skipSignature:TRUE showReceipt: FALSE];
[AnetMan setLoggingEnabled:TRUE];
RCTLogInfo(([AnetMan loggingEnabled]) ? @"True" : @"False" );
[AnetMan setTerminalMode:iTerminalMode];
[AnetMan setConnectionMode:iConnectionMode];
BTScanDeviceListBlock deviceListBlock = ^void(NSArray * _Nullable iBTDeviceList, AnetBTDeviceStatusCode status) {
RCTLogInfo(@"Scanned devices");
NSMutableArray *foundDevices = [NSMutableArray array];
for (AnetBTObject *object in iBTDeviceList) {
RCTLogInfo(object.name);
[foundDevices addObject:object.name];
}
[self emitDeviceListToRN:@"SCAN_DEVICES" :foundDevices];
};
[AnetMan setDeviceListBlock:deviceListBlock];
[AnetMan scanBTDevicesList];
}
- (void) connectToBTDevice:(NSInteger)index {
BTDeviceConnected deviceConnectedBlock = ^void(BOOL isConnectionSuccessful, NSString * _Nullable iDeviceName, AnetBTDeviceStatusCode status) {
RCTLogInfo(@"Device connected block called");
if (status == AnetBTDeviceConnected) {
RCTLogInfo(@"Device connected");
} else if (status == AnetBTDeviceDisconnected) {
RCTLogInfo(@"Device disconnected");
} else if (status == AnetBTDeviceConnectionTimeout) {
RCTLogInfo(@"Device timeout");
} else if (status == AnetBTDeviceAlreadyConnectedError) {
RCTLogInfo(@"Device already connected");
} else if (status == AnetBTDeviceFailToStart) {
RCTLogInfo(@"Device fail to start");
} else if (status == AnetBTDeviceIllegalStateException) {
RCTLogInfo(@"Device illegal state exception");
} else if (status == AnetBTDeviceGenericError) {
RCTLogInfo(@"Device generic error");
} else {
RCTLogInfo(@"Different error");
}
[self emitDeviceConnectionToRN:@"DEVICE_CONNECTION" :@(isConnectionSuccessful)];
};
[AnetMan setDeviceConnectedBlock:deviceConnectedBlock];
[AnetMan connectBTDeviceAtIndex:index];
[self loginToGateway];
}
- (void) disconnectBTDevice {
[AnetMan disconnectBTDevices];
[self emitDeviceConnectionToRN:@"DEVICE_CONNECTION" :0];
}
- (void) swipeAndSendTransaction:(NSString *)amount :(NSString *)paymentId {
RCTLogInfo(@"Swipe and send starting");
AnetEMVTransactionRequest *request = [AnetManShared transactionRequest];
request.emvTransactionType = EMVTransactionType_Payment;
request.amount = amount;
request.anetApiRequest.merchantAuthentication.sessionToken = sessionToken;
request.anetApiRequest.merchantAuthentication.mobileDeviceId = @"xxxxx";
request.order.invoiceNumber = paymentId;
request.order.orderDescription = @"xxxxx";
request.retail.marketType = @"2";
request.retail.deviceType = @"7";
RequestCompletionBlock completionBlock = ^void(AnetEMVTransactionResponse * _Nullable response, AnetEMVError *_Nullable error) {
if (error) {
RCTLogInfo(@"Error!");
}
RCTLogInfo(response.responseCode);
};
CancelActionBlock andCancelActionBlock = ^void {
RCTLogInfo(@"Cancelled");
};
[AnetMan startQuickChipWithTransactionRequest:request forPaperReceiptCase:FALSE presentingViewController:###WHAT SHOULD I PASS IN HERE?### completionBlock:completionBlock andCancelActionBlock:andCancelActionBlock];
}
- (void) mobileDeviceLoginSucceeded:(MobileDeviceLoginResponse *)response {
RCTLogInfo(@"Login succeeded");
sessionToken = response.sessionToken;
};
@end
方法“ scanBTDevices”,“ connectToBTDevice”,“ disconnectBTDevice”和“ loginToGateway”均按预期工作,但方法“ swipeAndSendTransaction”无效。注销“轻扫并发送开始”到控制台后,绝对没有其他事情发生。它不会运行完成块,不会运行取消块,并且不会出错。我只能认为这是因为我尝试传递的视图控制器不正确,并且无法显示它想要的情节提要。
SDK文档非常差,这就是有关此方法的全部说明:
/**
* Start a Quick Chip transaction with EMV request, presenting view controller and completion block.
* @param iTransactionRequest A request object of AnetEMVTransactionRequest
* @param iPaperReceiptCase if this is true then the Merchant needs to get the paper receipt signed by the customer and settle the transaction later on.
AnetEMVManager will leave the trasaction in Auth_Only state.
* @param iPresentingController A presenting controller object. EMV controller will be presented on top of it
* @param iRequestCompletionBlock A completion block. Block will be executed on success or failure of EMV transaction
* @param iCancelActionBlock A Cancel block. Block will be executed when cancel action is taken
*/
- (void)startQuickChipWithTransactionRequest:(AnetEMVTransactionRequest * _Nonnull)iTransactionRequest
forPaperReceiptCase:(BOOL)iPaperReceiptCase
presentingViewController:(UIViewController * _Nonnull)iPresentingController
completionBlock:(RequestCompletionBlock _Nonnull)iRequestCompletionBlock
andCancelActionBlock:(CancelActionBlock _Nonnull)iCancelActionBlock;
我要实现的SDK可以在以下位置找到: https://github.com/AuthorizeNet/inperson-sdk-ios
有一个示例应用程序(可以运行),但是它是用Swift编写的,因此我无法确切地知道它在做什么,而且它不需要与React Native进行通信,因此不会增加复杂性。 / p>
如果有人需要更多信息才能提供帮助,请告诉我。感谢您的阅读!