刨了3天的坑特来分享
公司要求用reactnative开发,本iOS小菜瓜开始学习reactnative,最近做到支付要求用微信、支付宝、银联支付,由于比较懒集成银联的时候就去GitHub上找 reactnative unionpay相关的来操作,结果。。。找到5个都被各种报错,,最后决定自己动手。
1.首先在xcode上集成iOS版的银联支付
2.在ReactNative端调用
废话结束,开始干
一.集成iOS银联支付
1.到银联技术开发平台下载开发包

然后:

下载完毕后打开这个:

然后看这里(没时间你也可以不看,我来带你操作)

OK,打开上图控件开发包,找到下图俩文件


2.把这两个文件添加到Xcode项目中,如图:
截屏2020-05-10 17.58.09.png
3.接着把CFNetwork.framework
、SystemConfiguration.framework
、libz.tbd
、libPaymentControl.a
添加到工程中

4.再然后,去添加URL Schemes

5.接下来,在测试环境测试时,需要在工程对应的plist文件中添加NSAppTransportSecurity Dictionary 并同时设置里面NSAllowsArbitraryLoads 属性值为 YES.发生产环境可删除此设置。向Apple发布正式版本时请删除此设置

6.在Xcode7.0之后的版本中进行开发,需要在工程对应的plist文件中,添加LSApplicationQueriesSchemes Array并加入uppaysdk
、uppaywallet
、uppayx1
、uppayx2
、uppayx3
五个item,如图:
截屏2020-05-10 18.13.27.png
7.8.按照步骤集成完毕后,其中中国银联手机支付控件接入指南iOS中说的在需要调用支付控件接口的代码文件内引用头文件UPPaymentControl.h。 (注意:如果工程的compile source as 选项的值不是Objective–C++,则引用此头文件的文件类型都要改为.mm)下面几个图是别人验证的拿来分享下:



接下来就是主要使用方法了,由于我们要用reactnative调用iOS的银联支付,建议没有用reactnative掉过原生的小盆友去reactnative文档里看看reactnative与原生交互最好先操作一下它的例子避免后面的坑,
1.在xcode创建银联文件,如图

UPPayControl.h文件:
#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"
@interface UPPayControl : NSObject <RCTBridgeModule>
@end
UPPayControl.m文件:
#import "UPPayControl.h"
#import "UPPaymentControl.h"
static RCTPromiseResolveBlock UPPay_resolve;
static RCTPromiseRejectBlock UPPay_reject;
@implementation UPPayControl
//MARK:必须实现协议,指定模块名,如果不规定模块名,那么将以类名作为模块名(UPPayControl);
RCT_EXPORT_MODULE();
//这个方法将会被reactnative调用
RCT_REMAP_METHOD(pay, payTN:(NSString *)tn isProduction:(BOOL)isProduction resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
NSLog(@"%@",tn);
}
@end
2.接着去reactnative中你要调用的js文件中调用一下看看,能否调通
UPPayControl.js文件:
import React, { Component } from 'react';
import {
View,
Button,
NativeModules
} from 'react-native';
var UPPayControl = NativeModules.UPPayControl;
export default class AllCommentsPage extends React.Component {
render() {
return (
<View >
<Button title='支付'
onPress={()=>{
this.iosLoad();
}}
/>
</View>
);
}
iosLoad(){
UPPayControl.pay('527786897964432783704',false).then((resp)=>{
console.log("支付成功:"+resp);
},(err)=>{
console.log("支付失败:"+err);
});
}
}
如果iOS那边能把527786897964432783704打印出来,那么恭喜你,调通了,接下来继续:
3.到xcode的UPPayControl.mm里添加:
#import "UPPayControl.h"
#import "UPPaymentControl.h"
static RCTPromiseResolveBlock UPPay_resolve;
static RCTPromiseRejectBlock UPPay_reject;
@implementation UPPayControl
//MARK:必须实现协议,指定模块名,如果不规定模块名,那么将以类名作为模块名(UPPayControl);
RCT_EXPORT_MODULE();
RCT_REMAP_METHOD(pay, payTN:(NSString *)tn isProduction:(BOOL)isProduction resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
NSLog(@"%@",tn);
//取URL Schemes
NSArray *urls = [[NSBundle mainBundle] infoDictionary][@"CFBundleURLTypes"];
NSMutableString *appScheme = [NSMutableString string];
BOOL multiUrls = [urls count] > 1;
for (NSDictionary *url in urls) {
NSArray *schemes = url[@"CFBundleURLSchemes"];
if (!multiUrls ||
//unionpay需要和你的设置的一致,如代码下方的图
(multiUrls && [@"unionpay" isEqualToString:url[@"CFBundleURLName"]])) {
[appScheme appendString:schemes[0]];
break;
}
}
if ([appScheme isEqualToString:@""]) {
NSString *error = @"url scheme cannot be empty";
reject(@"10000", error, [NSError errorWithDomain:error code:10000 userInfo:NULL]);
return;
}
UPPay_resolve = resolve;
UPPay_reject = reject;
NSString *model = isProduction?@"00":@"01";//00对应正式环境,01对应测试环境
dispatch_async(dispatch_get_main_queue(), ^{
[[UPPaymentControl defaultControl] startPay:tn fromScheme:appScheme mode:model viewController:[UIApplication sharedApplication].keyWindow.rootViewController];
});
}

到这里不出意外就能调起云闪付啦,然后到xcode端完善一下代码
1.UPPayControl.h文件中,添加回调成功后的方法
#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"
@interface UPPayControl : NSObject <RCTBridgeModule>
//调起银联成功后要调用的方法
+ (void)handleCallBack:(NSURL *)url;//前端的孩子们这行代码的加号不能去掉
@end
2.UPPayControl.m文件中,添加回调成功后的方法
#import "UPPayControl.h"
#import "UPPaymentControl.h"
static RCTPromiseResolveBlock UPPay_resolve;
static RCTPromiseRejectBlock UPPay_reject;
@implementation UPPayControl
//MARK:必须实现协议,指定模块名,如果不规定模块名,那么将以类名作为模块名(UPPayControl);
RCT_EXPORT_MODULE();
RCT_REMAP_METHOD(pay, payTN:(NSString *)tn isProduction:(BOOL)isProduction resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{
NSLog(@"%@",tn);
//取URL Schemes
NSArray *urls = [[NSBundle mainBundle] infoDictionary][@"CFBundleURLTypes"];
NSMutableString *appScheme = [NSMutableString string];
BOOL multiUrls = [urls count] > 1;
for (NSDictionary *url in urls) {
NSArray *schemes = url[@"CFBundleURLSchemes"];
if (!multiUrls ||
(multiUrls && [@"unionpay" isEqualToString:url[@"CFBundleURLName"]])) {
[appScheme appendString:schemes[0]];
break;
}
}
if ([appScheme isEqualToString:@""]) {
NSString *error = @"url scheme cannot be empty";
reject(@"10000", error, [NSError errorWithDomain:error code:10000 userInfo:NULL]);
return;
}
UPPay_resolve = resolve;
UPPay_reject = reject;
NSString *model = isProduction?@"00":@"01";//00对应正式环境,01对应测试环境
dispatch_async(dispatch_get_main_queue(), ^{
[[UPPaymentControl defaultControl] startPay:tn fromScheme:appScheme mode:model viewController:[UIApplication sharedApplication].keyWindow.rootViewController];
});
}
//调起银联成功后的方法:
//MARK:处理银联支付回调逻辑
+(void)handleCallBack:(NSURL *)url
{
if ([url.host hasPrefix:@"uppayresult"]) {
[[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
if ([code isEqual:@"cancel"]) {
//交易取消
NSString *error = @"cancel";
UPPay_reject(@"10003",error, [NSError errorWithDomain:error code:10003 userInfo:data]);
}else if ([code isEqual:@"success"]){
//交易成功
UPPay_resolve(@[data]);
}else if ([code isEqual:@"fail"]){
//交易失败
NSString *error = @"fail";
UPPay_reject(@"10002",error, [NSError errorWithDomain:error code:10002 userInfo:data]);
}else{
//交易出错
NSString *error = @"error";
UPPay_reject(@"10001",error, [NSError errorWithDomain:error code:10001 userInfo:data]);
}
}];
}
}
@end
3.到AppDelegate.m文件中添加支付回调以后的方法
//支付回调9以后
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options {
//hasPrefix方法是判断字符串是否以‘uppayresult’开头
if ([url.host hasPrefix:@"uppayresult"]) {
//这里调用我们刚刚写的处理银联支付回调逻辑方法
[UPPayControl handleCallBack:url];
return YES;
}
return NO;
}
OK,结束,操作时发现问题可以随时提出来,一起探讨,加油💪
网友评论