银联云闪付

首先sdk
银联开放平台: https://open.unionpay.com/ajweb/product/detail?id=3
添加依赖库 3 个

libz
CFNetwork
SystemConfiguration

拖入需要文件

UPPaymentControl.h
libPayMentControl.a
RSA.h
RSA.m

修改配置

1 URL Types - URL Schemes

2 info plist 添加
LSApplicationQueriesSchemes  <NSArray>
value - uppaysdk uppaywallet uppayx1 uppayx2 uppayx3

3 other link 添加路径
-force_load $(PROJECT_DIR)/upppay/libPaymentControl.a

4 将使用UPPay 的 VC,修改为 .mm
基本上就 差不多

Appdelegate 复制代码

#import "UPPaymentControl.h"
#import "iToast.h"
#import "RSA.h"
#import <CommonCrypto/CommonDigest.h>

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"updateTitleForUPPay" object:nil];
    
}

- (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

    [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code,NSDictionary *data)
     {
         //结果code为成功时,先校验签名,校验成功后做后续处理
         if ([code isEqualToString:@"success"]) {
             //数据从NSDictionary转换为NSString
             NSDictionary *data;
             NSData *signData = [NSJSONSerialization dataWithJSONObject:data options:0 error:nil];
             NSString *sign = [[NSString alloc]initWithData:signData encoding:NSUTF8StringEncoding];
             //判断签名数据是否存在
             if(data ==nil){
                 //如果没有签名数据,建议商户app后台查询交易结果
                 return;
             }
             //验签证书同后台验签证书
             //此处的verify,商户需送去商户后台做验签
             if([self verify:sign]) {
                 //支付成功且验签成功,展示支付成功提示
             }
             else {
                //验签失败,交易结果数据被篡改,商户app后台查询交易结果
             }

         }
         else if([code isEqualToString:@"fail"]) {
             //交易失败
         }
         else if([code isEqualToString:@"cancel"]) {
             //交易取消
         }
     }];
    return YES;
}

- (NSString *) readPublicKey:(NSString *) keyName

{

    if (keyName ==nil || [keyName isEqualToString:@""])return nil;

    NSMutableArray *filenameChunks = [[keyName componentsSeparatedByString:@"."]mutableCopy];

    NSString *extension = filenameChunks[[filenameChunks count] -1];

    [filenameChunks removeLastObject];// remove the extension

    NSString *filename = [filenameChunks componentsJoinedByString:@"."];// reconstruct the filename with no extension

    NSString *keyPath = [[NSBundle mainBundle]pathForResource:filename ofType:extension];
    NSString *keyStr = [NSString stringWithContentsOfFile:keyPath encoding:NSUTF8StringEncoding error:nil];
    return keyStr;

}

-(BOOL) verify:(NSString *) resultStr {
    //验签证书同后台验签证书
    //此处的verify,商户需送去商户后台做验签
    return NO;
}

- (NSString*)sha1:(NSString *)string
{
    unsigned char digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1_CTX context;
    NSString *description;
    
    CC_SHA1_Init(&context);
    
    memset(digest,0,sizeof(digest));

    description = @"";
    
    if (string == nil) {
        return nil;
    }

    // Convert the given 'NSString *' to 'const char *'.
    const char *str = [string cStringUsingEncoding:NSUTF8StringEncoding];

    // Check if the conversion has succeeded.
    if (str == NULL) {
        return nil;
    }

    // Get the length of the C-string.
    int len = (int)strlen(str);
    if (len == 0) {
        return nil;
    }
    if (str == NULL) {
        return nil;
    }
    
    CC_SHA1_Update(&context, str, len);
    CC_SHA1_Final(digest, &context);
    
    description = [NSString stringWithFormat:
                   @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                   digest[ 0], digest[ 1], digest[ 2], digest[ 3],
                   digest[ 4], digest[ 5], digest[ 6], digest[ 7],
                   digest[ 8], digest[ 9], digest[10], digest[11],
                   digest[12], digest[13], digest[14], digest[15],
                   digest[16], digest[17], digest[18], digest[19]];
    
    return description;
}

/*
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    
    [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
        // 此处 可以 自己写个 代理
        //结果code为成功时,先校验签名,校验成功后做后续处理
        if([code isEqualToString:@"success"]) {
            
            NSLog(@"开始交易");
            //判断签名数据是否存在
            if(data == nil){
                //如果没有签名数据,建议商户app后台查询交易结果
                NSLog(@"缺少签名");
                return;
            }
            
            //数据从NSDictionary转换为NSString
            NSData *signData = [NSJSONSerialization dataWithJSONObject:data
                                                               options:0
                                                                 error:nil];
            NSString *sign = [[NSString alloc] initWithData:signData encoding:NSUTF8StringEncoding];
            
            //验签证书同后台验签证书
            //此处的verify,商户需送去商户后台做验签
            if([self verifyLocal:sign]) {
                //支付成功且验签成功,展示支付成功提示
                NSLog(@"支付成功");
            }
            else {
                //验签失败,交易结果数据被篡改,商户app后台查询交易结果
                NSLog(@"支付失败");
            }
        }
        else if([code isEqualToString:@"fail"]) {
            //交易失败
            NSLog(@"交易失败");
        }
        else if([code isEqualToString:@"cancel"]) {
            //交易取消
            NSLog(@"取消交易");
        }
      
        [[iToast makeText:code] show];
    }];
    return YES;
}



- (NSString *) readPublicKey:(NSString *) keyName{

    if (keyName == nil || [keyName isEqualToString:@""]) return nil;
    
    NSMutableArray *filenameChunks = [[keyName componentsSeparatedByString:@"."] mutableCopy];
    NSString *extension = filenameChunks[[filenameChunks count] - 1];
    [filenameChunks removeLastObject]; // remove the extension
    NSString *filename = [filenameChunks componentsJoinedByString:@"."]; // reconstruct the filename with no extension
    
    NSString *keyPath = [[NSBundle mainBundle] pathForResource:filename ofType:extension];
    
    NSString *keyStr = [NSString stringWithContentsOfFile:keyPath encoding:NSUTF8StringEncoding error:nil];
    
    return keyStr;
}

// 验证 签名
//-(BOOL) verify:(NSString *) resultStr {
//
//    //验签证书同后台验签证书
//    //此处的verify,商户需送去商户后台做验签
//    return NO;
//}

// 验证 本地签名
-(BOOL) verifyLocal:(NSString *) resultStr {

    //从NSString转化为NSDictionary
    NSData *resultData = [resultStr dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *data = [NSJSONSerialization JSONObjectWithData:resultData options:0 error:nil];

    //获取生成签名的数据
    NSString *sign = data[@"sign"];
    NSString *signElements = data[@"data"];
    //NSString *pay_result = signElements[@"pay_result"];
    //NSString *tn = signElements[@"tn"];
    //转换服务器签名数据
    NSData *nsdataFromBase64String = [[NSData alloc]
                                      initWithBase64EncodedString:sign options:0];
    //生成本地签名数据,并生成摘要
//    NSString *mySignBlock = [NSString stringWithFormat:@"pay_result=%@tn=%@",pay_result,tn];
    NSData *dataOriginal = [[self sha1:signElements] dataUsingEncoding:NSUTF8StringEncoding];
    //验证签名
#warning    TODO:此处如果是正式环境需要换成public_product.key
    NSString *pubkey =[self readPublicKey:@"public_test.key"];
    OSStatus result= [RSA encryptData:dataOriginal publicKey:pubkey]; //[RSA verifyData:dataOriginal sig:nsdataFromBase64String publicKey:pubkey];

    //签名验证成功,商户app做后续处理
    if(result == 0) {
        //支付成功且验签成功,展示支付成功提示
        return YES;
    }
    else {
        //验签失败,交易结果数据被篡改,商户app后台查询交易结果
        return NO;
    }

    return NO;
}

// 本地签名
- (NSString*)sha1:(NSString *)string {
    unsigned char digest[CC_SHA1_DIGEST_LENGTH];
    CC_SHA1_CTX context;
    NSString *description;
    
    CC_SHA1_Init(&context);
    
    memset(digest, 0, sizeof(digest));
    
    description = @"";
    
    if (string == nil) {
        return nil;
    }
    
    // Convert the given 'NSString *' to 'const char *'.
    const char *str = [string cStringUsingEncoding:NSUTF8StringEncoding];
    
    // Check if the conversion has succeeded.
    if (str == NULL) {
        return nil;
    }
    
    // Get the length of the C-string.
    int len = (int)strlen(str);
    
    if (len == 0) {
        return nil;
    }
    
    if (str == NULL) {
        return nil;
    }
    
    CC_SHA1_Update(&context, str, len);
    CC_SHA1_Final(digest, &context);
    
    description = [NSString stringWithFormat:
                   @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                   digest[ 0], digest[ 1], digest[ 2], digest[ 3],
                   digest[ 4], digest[ 5], digest[ 6], digest[ 7],
                   digest[ 8], digest[ 9], digest[10], digest[11],
                   digest[12], digest[13], digest[14], digest[15],
                   digest[16], digest[17], digest[18], digest[19]];
    
    return description;
}
 */

VC demoPay

#import "ViewController.h"
#import "UPPaymentControl.h"

#include <sys/socket.h> // Per msqr
#include <sys/sysctl.h>
#include <net/if.h>
#include <net/if_dl.h>

#define KBtn_width        200
#define KBtn_height       80
#define KXOffSet          (self.view.frame.size.width - KBtn_width) / 2
#define KYOffSet          80
#define kCellHeight_Normal  50
#define kCellHeight_Manual  145

#define kVCTitle          @"商户测试"
#define kBtnFirstTitle    @"获取订单,开始测试"
#define kWaiting          @"正在获取TN,请稍后..."
#define kNote             @"提示"
#define kConfirm          @"确定"
#define kErrorNet         @"网络错误"
#define kResult           @"支付结果:%@"



#define kMode_Development             @"01"
//在后台开发实现消费(获取tn)请求前,demo里默认由银联的一个商户仿真获取tn(http://202.101.25.178:8080/sim/gettn或http://101.231.204.84:8091/sim/getacptn)之后需要改从商户自己的后台那里获取tn的。
//#define kURL_TN_Normal                @"http://101.231.204.84:8091/sim/getacptn"
//#define kURL_TN_Normal                @"http://202.101.25.178:8080/sim/gettn"
#define kURL_TN_Normal                @"http://www.baidu.com/"

#define kURL_TN_Configure             @"http://101.231.114.217:8080/sim/app.jsp?user=admin"


@interface ViewController ()<UITableViewDataSource, UITableViewDelegate,NSURLConnectionDataDelegate> {
    
    NSMutableData* _responseData;
    UIAlertView* _alertView;
    CGFloat _maxWidth;
    CGFloat _maxHeight;
    
}


@property (nonatomic, strong) NSArray* labels;
@property(nonatomic, copy)NSString *tnMode;
@property (nonnull,strong)UITextField *tnProductText;
@property (nonnull,strong)UITextField *tnPMText;
@property (nonnull,strong)UITextField *tnTestText;

- (void)startNetWithURL:(NSURL *)url;


@end

//@implementation NSURLRequest (NSURLRequestWithIgnoreSSL)
//+ (BOOL)allowsAnyHTTPSCertificateForHost:(NSString *)host
//{
//    return YES;
//}
//@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self extendedLayout];

    self.labels = [NSArray arrayWithObjects:@"DEVELOPER",@"TEST",@"PM",@"RELEASE",@"WALLET",nil];
    
    UITableView* tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, _maxWidth, _maxHeight)];
    [self.view addSubview:tableView];
    
    tableView.delegate = self;
    tableView.dataSource = self;
    
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(updateTitle) name:@"updateTitleForUPPay" object:nil];
    
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:@"updateTitleForUPPay"];

}

- (void)viewDidAppear:(BOOL)animated
{
    [self updateTitle];
}


- (void)updateTitle
{
    self.title=@"银行联调用商户Demo";

}



- (void)extendedLayout
{
    BOOL iOS7 = [UIDevice currentDevice].systemVersion.floatValue >= 7.0;
    if (iOS7) {
        self.edgesForExtendedLayout = UIRectEdgeNone;
        self.automaticallyAdjustsScrollViewInsets = NO;
    }
    
    CGFloat offset = iOS7 ? 64 : 44;
    _maxWidth = CGRectGetWidth([UIScreen mainScreen].bounds);
    _maxHeight = CGRectGetHeight([UIScreen mainScreen].bounds)-offset;
    
    self.navigationController.navigationBar.translucent = NO;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    switch (indexPath.row) {
        case 0:
             [tableView deselectRowAtIndexPath:indexPath animated:YES];
            return;
            break;
            
        case 1:
            [tableView deselectRowAtIndexPath:indexPath animated:YES];
            break;
            
            
        default:
            break;
    }
    
    
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 4;
}

- (void) productVerify {
    self.tnMode = @"00";
    [[UPPaymentControl defaultControl] startPay:self.tnProductText.text fromScheme:@"paydemo" mode:self.tnMode viewController:self];
}

- (void) pmVerify {
    self.tnMode = @"01";
    [[UPPaymentControl defaultControl] startPay:self.tnPMText.text fromScheme:@"paydemo" mode:self.tnMode viewController:self];
}

- (void) testVerify {
    self.tnMode = @"02";
    [[UPPaymentControl defaultControl] startPay:self.tnTestText.text fromScheme:@"paydemo" mode:self.tnMode viewController:self];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    cell.detailTextLabel.font = [UIFont systemFontOfSize:10];
    switch (indexPath.row) {
        case 0:
        {
            UIButton* btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [btnStartPay setTitle:@"生产验证" forState:UIControlStateNormal];
            [btnStartPay addTarget:self action:@selector(productVerify) forControlEvents:UIControlEventTouchUpInside];
            [btnStartPay setFrame:CGRectMake(240, 10, 80, 40)];
            [cell.contentView addSubview:btnStartPay];
            
            self.tnProductText = [[UITextField alloc] initWithFrame:CGRectMake(20,10,210,40)];
            self.tnProductText.placeholder = @"请在此处输入正式环境tn";
            self.tnProductText.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
            [cell.contentView addSubview:self.tnProductText];
            
            cell.accessoryType = UITableViewCellAccessoryNone;

        }
            
            break;
            
        case 1:
        {
            UIButton* btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [btnStartPay setTitle:@"PM验证" forState:UIControlStateNormal];
            [btnStartPay addTarget:self action:@selector(pmVerify) forControlEvents:UIControlEventTouchUpInside];
            [btnStartPay setFrame:CGRectMake(240, 10, 80, 40)];
            [cell.contentView addSubview:btnStartPay];
            
            self.tnPMText = [[UITextField alloc] initWithFrame:CGRectMake(20,10,210,40)];
            self.tnPMText.placeholder = @"请在此处输入PM环境tn";
            self.tnPMText.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
            [cell.contentView addSubview:self.tnPMText];
            
            cell.accessoryType = UITableViewCellAccessoryNone;

        }
            
            break;
            
        case 2:
        {
            UIButton* btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [btnStartPay setTitle:@"测试验证" forState:UIControlStateNormal];
            [btnStartPay addTarget:self action:@selector(testVerify) forControlEvents:UIControlEventTouchUpInside];
            [btnStartPay setFrame:CGRectMake(240, 10, 80, 40)];
            [cell.contentView addSubview:btnStartPay];
            
            self.tnTestText = [[UITextField alloc] initWithFrame:CGRectMake(20,10,210,40)];
            self.tnTestText.placeholder = @"请在此处输入test环境tn";
            self.tnTestText.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
            [cell.contentView addSubview:self.tnTestText];
            
            cell.accessoryType = UITableViewCellAccessoryNone;

        }
            
            break;
        case 3:
        {
            UIButton* btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            btnStartPay = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            [btnStartPay setTitle:@"支付" forState:UIControlStateNormal];
            [btnStartPay addTarget:self action:@selector(testPay) forControlEvents:UIControlEventTouchUpInside];
            [btnStartPay setFrame:CGRectMake(240, 10, 80, 40)];
            [cell.contentView addSubview:btnStartPay];
            
            self.tnTestText = [[UITextField alloc] initWithFrame:CGRectMake(20,10,210,40)];
            self.tnTestText.placeholder = @"直接点击右侧按钮进行支付";
            self.tnTestText.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
            [cell.contentView addSubview:self.tnTestText];
            
            cell.accessoryType = UITableViewCellAccessoryNone;

        }
            
            break;
            
            
        default:
            break;
    }
    
    
    
    return cell;
    
    
}

#pragma mark - Alert

- (void)showAlertWait
{
    [self hideAlert];
    _alertView = [[UIAlertView alloc] initWithTitle:kWaiting message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
    [_alertView show];
    UIActivityIndicatorView* aiv = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
    aiv.center = CGPointMake(_alertView.frame.size.width / 2.0f - 15, _alertView.frame.size.height / 2.0f + 10 );
    [aiv startAnimating];
    [_alertView addSubview:aiv];
}

- (void)showAlertMessage:(NSString*)msg
{
    [self hideAlert];
    _alertView = [[UIAlertView alloc] initWithTitle:kNote message:msg delegate:self cancelButtonTitle:kConfirm otherButtonTitles:nil, nil];
    [_alertView show];
}
- (void)hideAlert
{
    if (_alertView != nil)
    {
        [_alertView dismissWithClickedButtonIndex:0 animated:NO];
        _alertView = nil;
    }
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    _alertView = nil;
}


// 开始 支付
- (void)testPay{
    NSLog(@"支付");
    self.tnMode = kMode_Development;
    [self startNetWithURL:[NSURL URLWithString:kURL_TN_Normal]];
}

#pragma mark UPPayPluginResult - 需要自己 写个 代理 回调 appdelegate 中的 处理。不写 是没有的。
- (void)UPPayPluginResult:(NSString *)result{
    NSString* msg = [NSString stringWithFormat:@"支付结果:%@", result];
    NSLog(@"%@",msg);
}
// 开始 网络请求
- (void)startNetWithURL:(NSURL *)url
{
    NSLog(@"等待请求");
    //    [_curField resignFirstResponder];
    //    _curField = nil;
    [self showAlertWait];
    
    NSURLRequest * urlRequest=[NSURLRequest requestWithURL:url];
    NSURLConnection* urlConn = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];
    [urlConn start];
}

#pragma mark - connection

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse*)response
{
    NSHTTPURLResponse* rsp = (NSHTTPURLResponse*)response;
    NSInteger code = [rsp statusCode];
    if (code != 200)
    {
        NSLog(@"网络错误");
        [self showAlertMessage:kErrorNet];
        [connection cancel];
    }
    else
    {
        _responseData = [[NSMutableData alloc] init];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [_responseData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [self hideAlert];
    NSString* tn = [[NSMutableString alloc] initWithData:_responseData encoding:NSUTF8StringEncoding];
    if (tn != nil && tn.length > 0)
    {//        NSLog(@"tn=%@",tn);   ///UPPayDemo
        [[UPPaymentControl defaultControl] startPay:tn fromScheme:@"paydemo" mode:self.tnMode viewController:self];
    }
    
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"网络错误");
}
@end

RSA.h

@interface RSA : NSObject

// return base64 encoded string
+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey;
// return base64 encoded string
+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey;
// return raw data
+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey;

// decrypt base64 encoded string, convert result to string(not base64 encoded)
+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey;
+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey;
+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey;

@end

RSA.m

#import "RSA.h"
#import <Security/Security.h>

@implementation RSA

/*
static NSString *base64_encode(NSString *str){
    NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
    if(!data){
        return nil;
    }
    return base64_encode_data(data);
}
*/

static NSString *base64_encode_data(NSData *data){
    data = [data base64EncodedDataWithOptions:0];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

static NSData *base64_decode(NSString *str){
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    return data;
}

+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{
    // Skip ASN.1 public key header
    if (d_key == nil) return(nil);
    
    unsigned long len = [d_key length];
    if (!len) return(nil);
    
    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx    = 0;
    
    if (c_key[idx++] != 0x30) return(nil);
    
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
    
    // PKCS #1 rsaEncryption szOID_RSA_RSA
    static unsigned char seqiod[] =
    { 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
        0x01, 0x05, 0x00 };
    if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
    
    idx += 15;
    
    if (c_key[idx++] != 0x03) return(nil);
    
    if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    else idx++;
    
    if (c_key[idx++] != '\0') return(nil);
    
    // Now make a new NSData from this buffer
    return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}

//credit: http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036
+ (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
    // Skip ASN.1 private key header
    if (d_key == nil) return(nil);

    unsigned long len = [d_key length];
    if (!len) return(nil);

    unsigned char *c_key = (unsigned char *)[d_key bytes];
    unsigned int  idx    = 22; //magic byte at offset 22

    if (0x04 != c_key[idx++]) return nil;

    //calculate length of the key
    unsigned int c_len = c_key[idx++];
    int det = c_len & 0x80;
    if (!det) {
        c_len = c_len & 0x7f;
    } else {
        int byteCount = c_len & 0x7f;
        if (byteCount + idx > len) {
            //rsa length field longer than buffer
            return nil;
        }
        unsigned int accum = 0;
        unsigned char *ptr = &c_key[idx];
        idx += byteCount;
        while (byteCount) {
            accum = (accum << 8) + *ptr;
            ptr++;
            byteCount--;
        }
        c_len = accum;
    }

    // Now make a new NSData from this buffer
    return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
}

+ (SecKeyRef)addPublicKey:(NSString *)key{
    NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
    NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        key = [key substringWithRange:range];
    }
    key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];
    
    // This will be base64 encoded, decode it.
    NSData *data = base64_decode(key);
    data = [RSA stripPublicKeyHeader:data];
    if(!data){
        return nil;
    }

    //a tag to read/write keychain storage
    NSString *tag = @"RSAUtil_PubKey";
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    
    // Delete any old lingering key with the same tag
    NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
    [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)publicKey);
    
    // Add persistent version of the key to system keychain
    [publicKey setObject:data forKey:(__bridge id)kSecValueData];
    [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
     kSecAttrKeyClass];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
     kSecReturnPersistentRef];
    
    CFTypeRef persistKey = nil;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
    if (persistKey != nil){
        CFRelease(persistKey);
    }
    if ((status != noErr) && (status != errSecDuplicateItem)) {
        return nil;
    }

    [publicKey removeObjectForKey:(__bridge id)kSecValueData];
    [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
    status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
    if(status != noErr){
        return nil;
    }
    return keyRef;
}

+ (SecKeyRef)addPrivateKey:(NSString *)key{
    NSRange spos;
    NSRange epos;
    spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    if(spos.length > 0){
        epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
    }else{
        spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];
        epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];
    }
    if(spos.location != NSNotFound && epos.location != NSNotFound){
        NSUInteger s = spos.location + spos.length;
        NSUInteger e = epos.location;
        NSRange range = NSMakeRange(s, e-s);
        key = [key substringWithRange:range];
    }
    key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];

    // This will be base64 encoded, decode it.
    NSData *data = base64_decode(key);
    data = [RSA stripPrivateKeyHeader:data];
    if(!data){
        return nil;
    }

    //a tag to read/write keychain storage
    NSString *tag = @"RSAUtil_PrivKey";
    NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];

    // Delete any old lingering key with the same tag
    NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
    [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    SecItemDelete((__bridge CFDictionaryRef)privateKey);

    // Add persistent version of the key to system keychain
    [privateKey setObject:data forKey:(__bridge id)kSecValueData];
    [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
     kSecAttrKeyClass];
    [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
     kSecReturnPersistentRef];

    CFTypeRef persistKey = nil;
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
    if (persistKey != nil){
        CFRelease(persistKey);
    }
    if ((status != noErr) && (status != errSecDuplicateItem)) {
        return nil;
    }

    [privateKey removeObjectForKey:(__bridge id)kSecValueData];
    [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];

    // Now fetch the SecKeyRef version of the key
    SecKeyRef keyRef = nil;
    status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
    if(status != noErr){
        return nil;
    }
    return keyRef;
}

/* START: Encryption & Decryption with RSA private key */

+ (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef isSign:(BOOL)isSign {
    const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    size_t srclen = (size_t)data.length;
    
    size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    void *outbuf = malloc(block_size);
    size_t src_block_size = block_size - 11;
    
    NSMutableData *ret = [[NSMutableData alloc] init];
    for(int idx=0; idx<srclen; idx+=src_block_size){
        //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
        size_t data_len = srclen - idx;
        if(data_len > src_block_size){
            data_len = src_block_size;
        }
        
        size_t outlen = block_size;
        OSStatus status = noErr;
        
        if (isSign) {
            status = SecKeyRawSign(keyRef,
                                   kSecPaddingPKCS1,
                                   srcbuf + idx,
                                   data_len,
                                   outbuf,
                                   &outlen
                                   );
        } else {
            status = SecKeyEncrypt(keyRef,
                                   kSecPaddingPKCS1,
                                   srcbuf + idx,
                                   data_len,
                                   outbuf,
                                   &outlen
                                   );
        }
        if (status != 0) {
            NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
            ret = nil;
            break;
        }else{
            [ret appendBytes:outbuf length:outlen];
        }
    }
    
    free(outbuf);
    CFRelease(keyRef);
    return ret;
}

+ (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{
    NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];
    NSString *ret = base64_encode_data(data);
    return ret;
}

+ (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{
    if(!data || !privKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPrivateKey:privKey];
    if(!keyRef){
        return nil;
    }
    return [RSA encryptData:data withKeyRef:keyRef isSign:YES];
}

+ (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
    const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    size_t srclen = (size_t)data.length;
    
    size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    UInt8 *outbuf = malloc(block_size);
    size_t src_block_size = block_size;
    
    NSMutableData *ret = [[NSMutableData alloc] init];
    for(int idx=0; idx<srclen; idx+=src_block_size){
        //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
        size_t data_len = srclen - idx;
        if(data_len > src_block_size){
            data_len = src_block_size;
        }
        
        size_t outlen = block_size;
        OSStatus status = noErr;
        status = SecKeyDecrypt(keyRef,
                               kSecPaddingNone,
                               srcbuf + idx,
                               data_len,
                               outbuf,
                               &outlen
                               );
        if (status != 0) {
            NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
            ret = nil;
            break;
        }else{
            //the actual decrypted data is in the middle, locate it!
            int idxFirstZero = -1;
            int idxNextZero = (int)outlen;
            for ( int i = 0; i < outlen; i++ ) {
                if ( outbuf[i] == 0 ) {
                    if ( idxFirstZero < 0 ) {
                        idxFirstZero = i;
                        break;
                    } else {
//                      idxNextZero = i;
//                      break;
                    }
                }
            }
            
            [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
        }
    }
    
    free(outbuf);
    CFRelease(keyRef);
    return ret;
}


+ (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    data = [RSA decryptData:data privateKey:privKey];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

+ (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
    if(!data || !privKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPrivateKey:privKey];
    if(!keyRef){
        return nil;
    }
    return [RSA decryptData:data withKeyRef:keyRef];
}

/* END: Encryption & Decryption with RSA private key */

/* START: Encryption & Decryption with RSA public key */

+ (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
    NSData *data = [RSA encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
    NSString *ret = base64_encode_data(data);
    return ret;
}

+ (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
    if(!data || !pubKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPublicKey:pubKey];
    if(!keyRef){
        return nil;
    }
    return [RSA encryptData:data withKeyRef:keyRef isSign:NO];
}

+ (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{
    NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    data = [RSA decryptData:data publicKey:pubKey];
    NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    return ret;
}

+ (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{
    if(!data || !pubKey){
        return nil;
    }
    SecKeyRef keyRef = [RSA addPublicKey:pubKey];
    if(!keyRef){
        return nil;
    }
    return [RSA decryptData:data withKeyRef:keyRef];
}

/* END: Encryption & Decryption with RSA public key */

@end

实际 wk web中接入h5
如果用按自己的项目改
https://juejin.cn/post/6908989251690430472

WKWebView

#define ScriptMessageNameCallNative @"CallNativePay"

- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration {
    
    self = [super initWithFrame:frame configuration:configuration];
    if (self) {
        JDBMWeakScriptMessageHandler *weakScriptMessageHandler = [[JDBMWeakScriptMessageHandler alloc] initWithScriptMessageHandler:self];
        [configuration.userContentController addScriptMessageHandler:weakScriptMessageHandler name:ScriptMessageNameCallNative];
        // 设置进度条
        _progressBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 3)];
        _progressBar.backgroundColor = JDUtils.getColorByHex(@"FB4E38");
        [self addSubview:_progressBar];
        
        // 设置相关代理
        self.navigationDelegate = self;
        self.UIDelegate = self;
        
        [self addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld context:nil];
    }
    return self;
}



- (instancetype)initWithFrame:(CGRect)frame {
    JDBMWeakScriptMessageHandler *weakScriptMessageHandler = [[JDBMWeakScriptMessageHandler alloc] initWithScriptMessageHandler:self];
    WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
    // 设置偏好设置
    config.preferences = [[WKPreferences alloc] init];
    // 默认为0
    config.preferences.minimumFontSize = 10;
    // 默认认为YES
    config.preferences.javaScriptEnabled = YES;
    // 在iOS上默认为NO,表示不能自动通过窗口打开
    config.preferences.javaScriptCanOpenWindowsAutomatically = NO;
    // web内容处理池
    config.processPool = [JDWJWebView sharedProcessPool];
    // 通过JS与webview内容交互
    config.userContentController = [[WKUserContentController alloc] init];

    NSString *configUA = [WJRouter openURL:@"xxxxx" arg:nil error:nil completion:nil];
    config.applicationNameForUserAgent = [config.applicationNameForUserAgent stringByAppendingString:[NSString stringWithFormat:@";%@", configUA]];
    config.allowsInlineMediaPlayback = YES;
    // 注入JS对象名称AppModel,当JS通过AppModel来调用时,
    // 我们可以在WKScriptMessageHandler代理中接收到

    [config.userContentController addScriptMessageHandler:weakScriptMessageHandler name:@"AppShareModel"];
    [config.userContentController addScriptMessageHandler:weakScriptMessageHandler name:ScriptMessageNameCallNative];
    self = [super initWithFrame:frame configuration:config];
    if (self) {
        // 设置进度条
        _progressBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 3)];
        _progressBar.backgroundColor = JDUtils.getColorByHex(@"FB4E38");
        [self addSubview:_progressBar];
        
        // 设置相关代理
        self.navigationDelegate = self;
        self.UIDelegate = self;
        
        [self addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew| NSKeyValueObservingOptionOld context:nil];
        
    }
    return self;
}

WebViewController (xxx)

+ (void)load{
    
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        
        //要特别注意你替换的方法到底是哪个性质的方法
        //When swizzling a Instance method, use the following:
        //Class class = [self class];
        
        //When swizzling a class method, use the following:
        //Class class = object_getClass((id)self);
        
        Class class = [self class];
        
//        /* 交换方法 */
//        SEL originalSelector = @selector(xxx_webView:decidePolicyForNavigationAction:decisionHandler:);
//        SEL swizzledSelector = @selector(swizz_xxx_webView:decidePolicyForNavigationAction:decisionHandler:);
//        
//        Method originalMethod = class_getInstanceMethod(class, originalSelector);
//        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
//        
//        //给一个类增加方法的实现,如果这个类有这个方法的实现,那么添加失败,如果没有这个方法的实现,那么添加成功
//        //如果这个类的父类有这个类的方法实现,那么也会添加成功,只有当这个类本身有这个方法的实现的时候,才不会添加成功
//        BOOL didAddMethod = class_addMethod(class,
//                                            originalSelector,
//                                            method_getImplementation(swizzledMethod),
//                                            method_getTypeEncoding(swizzledMethod));
//        
//        //didAddMethod = YES
//        if (didAddMethod) {
//            
//            //有class_addMethod和method_setImplementation两个作用
//            class_replaceMethod(class,
//                                swizzledSelector,
//                                method_getImplementation(originalMethod),
//                                method_getTypeEncoding(originalMethod));
//        } else {
//            
//            method_exchangeImplementations(originalMethod, swizzledMethod);
//        }
//        
//        /* 交换方法 */
//        originalSelector = @selector(xxx_UserContentController:didReceiveScriptMessage:);
//        swizzledSelector = @selector(swizz_xxx_UserContentController:didReceiveScriptMessage:);
//        
//        originalMethod = class_getInstanceMethod(class, originalSelector);
//        swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
//        
//        didAddMethod = class_addMethod(class,
//                                       originalSelector,
//                                       method_getImplementation(swizzledMethod),
//                                       method_getTypeEncoding(swizzledMethod));
//        
//        //didAddMethod = YES
//        if (didAddMethod) {
//            
//            //有class_addMethod和method_setImplementation两个作用
//            class_replaceMethod(class,
//                                swizzledSelector,
//                                method_getImplementation(originalMethod),
//                                method_getTypeEncoding(originalMethod));
//        } else {
//            
//            method_exchangeImplementations(originalMethod, swizzledMethod);
//        }

        /* 交换方法 xxx_webView:didFinishNavigation: */
        SEL webFinishNavigationSelector = @selector(xxx_webView:didFinishNavigation:);
        SEL swizzledFinishNavigationSelector = @selector(swizz_xxx_webView:didFinishNavigation:);

        
        Method originalFinishNavMethod = class_getInstanceMethod(class, webFinishNavigationSelector);
        Method swizzledFinishNavMethod = class_getInstanceMethod(class, swizzledFinishNavigationSelector);

        //给一个类增加方法的实现,如果这个类有这个方法的实现,那么添加失败,如果没有这个方法的实现,那么添加成功
        //如果这个类的父类有这个类的方法实现,那么也会添加成功,只有当这个类本身有这个方法的实现的时候,才不会添加成功
        BOOL didAddFinishNavMethod = class_addMethod(class,
                                                     webFinishNavigationSelector,
                                            method_getImplementation(swizzledFinishNavMethod),
                                            method_getTypeEncoding(swizzledFinishNavMethod));
        
        //didAddFinishNavMethod = YES
        if (didAddFinishNavMethod) {
            
            //有class_addMethod和method_setImplementation两个作用
            class_replaceMethod(class,
                                swizzledFinishNavigationSelector,
                                method_getImplementation(originalFinishNavMethod),
                                method_getTypeEncoding(originalFinishNavMethod));
        } else {
            
            method_exchangeImplementations(originalFinishNavMethod, swizzledFinishNavMethod);
        }/* 交换方法 xxx_webView:didFinishNavigation: end  */
        
    });
}

/**
 页面加载完成之后调用
 
 @param webView webView
 @param navigation navigation
 */
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (void)swizz_xxx_webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
    [self swizz_xxx_webView:webView didFinishNavigation:navigation];
    NSString *jsonStr = @{@"payWays":@"JdPay;UnionPay;WechatPay", @"APPVersion":@"1.0.1", @"OS":@"ios"}.yy_modelToJSONString ;
    NSString *onReady = [NSString stringWithFormat:@"ListenerNative.onReady('%@')",jsonStr];
    [self.webView evaluateJavaScript:onReady completionHandler:^(id _Nullable value, NSError * _Nullable error) {
        
    }];
    [self.webView evaluateJavaScript:@"window.CallNative = {Cashier : function (type,data) {window.webkit.messageHandlers.xxxCallNativePay.postMessage({\"type\":type,\"data\":data})}}" completionHandler:^(id _Nullable value, NSError * _Nullable error) {
        
    }];
}
- (void)swizz_xxx_UserContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message {
    
    [self swizz_xxx_UserContentController:userContentController didReceiveScriptMessage:message];
    
    NSDictionary *params = message.body;
    NSDictionary *dic = [self handleScriptMessage:params];

        if ([message.name isEqualToString:ScriptMessageNameCallNative]) {
            NSString *schemeStr = @"openapp.xxx";
#if DEBUG
            schemeStr = @"openapp.xxx-test";
#endif
            NSDictionary *dataTnDic = [self dictionaryWithJsonString:params[@"data"]];
            if (JDUtils.validateDictionary(dataTnDic)) {
                [[UPPaymentControl defaultControl] startPay:[dataTnDic objectForKey:@"tn"] fromScheme:schemeStr mode:@"00" viewController:self];
            }
        }
}

application Appdelegate

+ (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
    [QQApiInterface handleOpenURL:url delegate:[self shared]];
    [WXApi handleOpenURL:url delegate:[self shared]];
    
    if ([url.scheme isEqualToString:@"openapp.jdbmall"] || [url.scheme isEqualToString:@"openapp.jdbmall-test"] ) {
        if([url.host isEqualToString:@"mobileChecker"]){
            //埋点SDK进入调试模式
            [JDMTA setDebuggerWithData:url.query];
        }else if ([url.scheme containsString:WX_APP_ID]){
            [QQApiInterface handleOpenURL:url delegate:[self shared]];
            [WXApi handleOpenURL:url delegate:[self shared]];
        } else {
            [OpenAppHandle openURL:url.absoluteString arg:nil error:nil completion:nil];
            [self handlerOpenAppSchemeURL:url];
        }
        NSArray *urlCom = [url pathComponents];
        if([url.host isEqualToString:@"uppayresult"] || [urlCom.lastObject isEqualToString:@"uppayresult"]){
            [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code,NSDictionary *data)
             {
                NSInteger status = 2;//服务端标识 支付失败
                NSString *payMsg = @"";
                //结果code为成功时,先校验签名,校验成功后做后续处理
                if ([code isEqualToString:@"success"]) {
                    status = 1;
                    payMsg = @"支付成功";
                }
                else if([code isEqualToString:@"fail"]) {//交易失败
                    status = 2;
                    payMsg = @"支付失败";
                }
                else if([code isEqualToString:@"cancel"]) {//交易取消
                    status = 3;
                    payMsg = @"支付取消";
                }
                JDWJWebViewController *vc;
                JDBMTabbarController *tabVC = [UIApplication sharedApplication].keyWindow.rootViewController;
                JDBMNavigationController *nav = (JDBMNavigationController *)tabVC.selectedViewController;
                for (UIViewController *childVC in nav.viewControllers) {
                    if ([childVC isKindOfClass:[JDWJWebViewController class]]) {
                        vc = (JDWJWebViewController *)childVC;
                    }
                }
                if(vc.webView){
                    NSString *payStatusJsonStr = @{@"status":[NSNumber numberWithInteger:status], @"msg":payMsg, @"object":(data)?:@""}.yy_modelToJSONString ;//object返回对象
                    NSString *PaymentStatus = [NSString stringWithFormat:@"ListenerNative.PaymentStatus('%@')",payStatusJsonStr];
                    [ vc.webView evaluateJavaScript:PaymentStatus completionHandler:^(id _Nullable value, NSError * _Nullable error) {
                        
                    }];
                }//if vc.webView end
            }];//UPPaymentControl end
        }//url.host uppayresult end
    }
    
    return YES;
    
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容