支付宝支付

写这篇文章的主要目的是做一个学习的备忘,避免同样的坑再爬一遍😄,下面开始正文。
文章的顺序,就是开发的流程
1、将Alipay SDK包,添加到项目中

Alipay SDK

2、编译项目,会出现以下问题:

1)"Unknown type name ‘NSString‘ "或"Unknown type name ‘NSData‘ "

,但是本人并没有遇到,参考网友的时候有这样的问题,一并附上,主要看解释原因

报错信息

这是因为缺少Foundation类库和UIKit类库,支付宝Demo中之所以没有出现此错误,是因为在.pch文件中导入过这些类库

解决办法:只需要在出现错误的文件中导入这些类库即可

需要导入的库

2)‘openssl/asn1.h‘ file not found,这个坑填了几个小时😄

报错信息

这是openssl文件夹头文件链接问题,如果openssl文件夹随意拉进项目中,即使添加头文件链接,也可能解决不了此问题,这也是一开始就将所需要的文件放到一个新建文件夹中再添加到项目中的原因。(试了各种方法添加,最终是先将Alipay拖放到文件中,再将Alipay拖到项目工程中,这样添加的)

解决办法:

Targets->Build Settings->Header Search Path中添加AliPaySDK文件夹的路径

截图

截图

具体怎么写(一个参数设置的时候)
多个参数设置的时候

这个参数需要设置多个值的时候,通过双引号括起来

3)linker command failed with exit code 1 (use -v to see invocation)

这边的解决办法:”Build Settings”->”Enable Bitcode”设置为NO

(附带的将Other Linker Flags下的属性全删除了,可能不删除也是可以跑的,没有试)

4.编译项目,会出现以下问题:

报错信息

解决方法:在xcode中,点击项目名,选择"target"->"Link Binary With Libraries"添加依赖库。

需要添加的库

编辑程序,已经可以成功编译了,接下来就是集成代码了,这边主要做的是直接在前端集成代码
5、添加非https请求


截图

(App Transport Security Settings 和Allow Arbitrary Loads)

6、代码

#import "ViewController.h"
#import "AliOrder.h"
#import "DataSigner.h"
#import <AlipaySDK/AlipaySDK.h>


@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    //添加通知
    //客户端安装支付宝的情况下,支付成功的情况下,在delegate中通过通知进行回传数据
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(aliPaySucceeded) name:ALIPAY_SUCCEEDED object:nil];
    
}
- (void)viewDidUnload
{
    //移除通知
    [[NSNotificationCenter defaultCenter] removeObserver:self name:ALIPAY_SUCCEEDED object:nil];
    
    
    [super viewDidUnload];
}


- (IBAction)zhifubaoPay:(id)sender {
    
    [self payForAlipayWithProductName:@"翼停支付" productDescription:@"翼停支付"];
}
-(void)payForAlipayWithProductName:(NSString *)productName productDescription:(NSString *)productDescription
{
    // 进入跳转支付宝支付流程
    NSString *partner = Partner;
    NSString *seller = Seller;
    NSString *privateKey = PrivateKey;
    
    //partner和seller获取失败,提示
    if ([partner length] == 0 || [seller length] == 0)
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示"
                                                        message:@"缺少partner或者seller。"
                                                       delegate:self
                                              cancelButtonTitle:@"确定"
                                              otherButtonTitles:nil];
        [alert show];
        return;
    }
    
    AliOrder *aliOrder = [[AliOrder alloc] init];
    aliOrder.partner = partner;
    aliOrder.seller = seller;
    aliOrder.tradeNO = [self generateTradeNO];
    aliOrder.productName = productName; //商品标题
    aliOrder.productDescription = productDescription; //商品描述
    
    aliOrder.amount = @"0.01"; //商品价格
    aliOrder.notifyURL = @"http://www.xxx.com"; //回调URL

    aliOrder.service = @"mobile.securitypay.pay";
    aliOrder.paymentType = @"1";
    aliOrder.inputCharset = @"utf-8";
    aliOrder.itBPay = @"30m";
    
    //应用注册scheme,在AlixPayDemo-Info.plist定义URL types
    NSString *appScheme = @"com.leaguerdtv.yuting";
    //将商品信息拼接成字符串
    NSString *orderSpec = [aliOrder description];
//    NSLog(@"orderSpec = %@",orderSpec);
    
    //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循 RSA 签名规范, 并将签名字符串 base64 编码和 UrlEncode
    id<DataSigner> signer = CreateRSADataSigner(privateKey);
    NSString *signedString = [signer signString:orderSpec];
    //将签名成功字符串格式化为订单字符串,请严格按照该格式
    NSString *orderString = nil;
    if (signedString != nil) {
        orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
                       orderSpec, signedString, @"RSA"];
        [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
            //装了支付宝客户端的,这个block不会被执行
            //装了支付宝的,通过在delegate中的通知进行调用
            
            
            NSLog(@"result = %@", resultDic);
            NSLog(@"result = %@", resultDic);
            NSLog(@"[resultDic valueForKey:resultStatus] = %@", [resultDic valueForKey:@"resultStatus"]);
          
            switch ([resultDic[@"resultStatus"] integerValue])
            {
                case 9000: //支付成功
                {
                    NSLog(@"ViewController界面-支付宝支付成功~~~!!!");
                    [self aliPaySucceeded];
                }
                    break;
                case 6001:
                {
                    NSLog(@"ViewController界面-订单已取消~~~!!!");

                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"订单已取消" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                    [alert show];
                }
                    break;
                case 6002:
                {
                    NSLog(@"ViewController界面-网络连接出错~~~!!!");
                    
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"网络连接出错" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                    [alert show];
                }
                    break;
                case 4000:
                {
                    NSLog(@"ViewController界面-订单支付失败~~~!!!");
                    
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"订单支付失败" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                    [alert show];
                }
                    break;
                default:
                {
                    NSLog(@"ViewController界面-未知错误~~~!!!");

                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"未知错误" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                    [alert show];
                }
                    break;
            }
        }];
    }
}
#pragma mark 产生随机订单号
- (NSString *)generateTradeNO {
    static int kNumber = 15;
    
    NSString *sourceStr = @"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    NSMutableString *resultStr = [[NSMutableString alloc] init];
    //    srand(time(0)); // 此行代码有警告:
    srand( (unsigned)time(0) );
    
    
    for (int i = 0; i < kNumber; i++) {
        unsigned index = rand() % [sourceStr length];
        NSString *oneStr = [sourceStr substringWithRange:NSMakeRange(index, 1)];
        [resultStr appendString:oneStr];
    }
    return resultStr;
}

- (void)aliPaySucceeded
{
    // 通知后台充值订单支付成功
    NSLog(@"通知后台消除这个订单或者充值成功");
}

@end

delegate中代码:

#import "AppDelegate.h"
#import <AlipaySDK/AlipaySDK.h>


@interface AppDelegate ()

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    return YES;
}

//支付宝-回调
//9.0之前调用的方法
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [self alipayOrWeiXinCallbackWithOpenUrl:url];
}
//9.0之前调用的方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options
{
    return [self alipayOrWeiXinCallbackWithOpenUrl:url];
}
//9.0之后调用的方法
- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation
{
    return [self alipayOrWeiXinCallbackWithOpenUrl:url];
}

//支付宝回调方法处理
-(BOOL)alipayOrWeiXinCallbackWithOpenUrl:(NSURL *)url
{
    //跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给SDK
    //装了支付宝的,这个方法才会被调用,通过在delegate中的通知进行调用
    
    if ([url.host isEqualToString:@"safepay"]) {//支付宝支付相关操作
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@", resultDic);
            NSLog(@"result = %@", resultDic);
            NSLog(@"[resultDic valueForKey:resultStatus] = %@", [resultDic valueForKey:@"resultStatus"]);
            
            if ([[resultDic valueForKey:@"resultStatus"] integerValue] == 9000 && [[resultDic valueForKey:@"result"] rangeOfString:@"success=\"true\""].length>0) {
                [[NSNotificationCenter defaultCenter] postNotificationName:ALIPAY_SUCCEEDED object:self];
            }else if ([[resultDic valueForKey:@"resultStatus"] integerValue] == 6001){
                
                NSLog(@"delegate-6001");
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"订单已取消" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show];
                
            }else if ([[resultDic valueForKey:@"resultStatus"] integerValue] == 6002){
                NSLog(@"delegate-6002");
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"网络连接出错" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show];
                
            }else if ([[resultDic valueForKey:@"resultStatus"] integerValue] == 4000){
                
                NSLog(@"delegate-4000");
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"订单支付失败" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show];
                
            }else{
                UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"未知错误" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
                [alert show];
            }
            
        }];
    }else if ([url.host isEqualToString:@"pay"]){//微信支付相关操作
        
    }
    return YES;
    
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}


- (void)applicationDidEnterBackground:(UIApplication *)application {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}


- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}


- (void)applicationWillTerminate:(UIApplication *)application {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}


@end

PrefixHeader.pch-配置一下pch文件

#ifndef PrefixHeader_pch
#define PrefixHeader_pch

#define ALIPAY_SUCCEEDED @"alipaySucceeded"
#endif /* PrefixHeader_pch */

7、配置LSApplicationQueriesSchemes


LSApplicationQueriesSchemes配置

LSApplicationQueriesSchemes不配置的话,是在项目内调用支付宝进行支付;
配置了LSApplicationQueriesSchemes参数,它会自动判断当前手机有没有安装支付宝,安装了就跳支付宝应用,没有安装直接应用内跳支付宝支付
(只要设置alipay这一个参数就可以了)

8、配置URL Schemes


URL Schemes plist中配置

这边涂鸦掉的是代码中 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
里面的appScheme参数设置成一样的,这样支付宝回调的时候就知道调用手机中那个标识的应用
一般不在plist文件中设置这个参数,而是在图形界面中,这样比较的方便


URL Schemes图形配置

URL Schemes配置,主要可以让支付宝可以正确的回调当前应用,并传人相关的支付信息(成功、失败、取消)

9、遇到的问题-备注一下,便于理解
1)、在AppDelegate.m中加入这两个方法(对旧版本的支持):

//重要更新,一下两个方法IOS9.0以后被废弃了,所以如果你是Xcode7.2的话,可能会出现不能进入微信的onResp回调方法,原因是下边两个方法没有被调用,所以这里更新一下,改用另外一个方法(并不建议删除这两个方法,新方法是9.0以后的方法,可能系统低版本的用户不支持。所以我三种方法都留下了,如果有人发现不能都留下的话,请简信告诉我一下,再次谢过了)

-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;

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

//改用方法为

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options;

2)、支付宝回调的时候分两种情况,客户端装了支付宝和没有装支付宝两种情况
情况一:客户端装了支付宝
通过在delegate中handleOpenURL或者openURL接受支付回调,支付成功时通过通知去支付界面进行销单处理
情况二、客户端没有安装支付宝
会在支付宝调用界面,执行block,方法如下图


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

推荐阅读更多精彩内容