写这篇文章的主要目的是做一个学习的备忘,避免同样的坑再爬一遍😄,下面开始正文。
文章的顺序,就是开发的流程
1、将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参数,它会自动判断当前手机有没有安装支付宝,安装了就跳支付宝应用,没有安装直接应用内跳支付宝支付
(只要设置alipay这一个参数就可以了)
8、配置URL Schemes
这边涂鸦掉的是代码中 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
里面的appScheme参数设置成一样的,这样支付宝回调的时候就知道调用手机中那个标识的应用
一般不在plist文件中设置这个参数,而是在图形界面中,这样比较的方便
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,方法如下图