寫這篇文章的主要目的是做一個(gè)學(xué)習(xí)的備忘器紧,避免同樣的坑再爬一遍??耀销,下面開始正文。
文章的順序铲汪,就是開發(fā)的流程
1熊尉、將Alipay SDK包,添加到項(xiàng)目中
2掌腰、編譯項(xiàng)目狰住,會出現(xiàn)以下問題:
1)"Unknown type name ‘NSString‘ "或"Unknown type name ‘NSData‘ "
,但是本人并沒有遇到齿梁,參考網(wǎng)友的時(shí)候有這樣的問題催植,一并附上,主要看解釋原因
這是因?yàn)槿鄙貴oundation類庫和UIKit類庫勺择,支付寶Demo中之所以沒有出現(xiàn)此錯(cuò)誤创南,是因?yàn)樵?pch文件中導(dǎo)入過這些類庫
解決辦法:只需要在出現(xiàn)錯(cuò)誤的文件中導(dǎo)入這些類庫即可
2)‘openssl/asn1.h‘ file not found,這個(gè)坑填了幾個(gè)小時(shí)??
這是openssl文件夾頭文件鏈接問題省核,如果openssl文件夾隨意拉進(jìn)項(xiàng)目中稿辙,即使添加頭文件鏈接,也可能解決不了此問題气忠,這也是一開始就將所需要的文件放到一個(gè)新建文件夾中再添加到項(xiàng)目中的原因邻储。(試了各種方法添加檩奠,最終是先將Alipay拖放到文件中祖娘,再將Alipay拖到項(xiàng)目工程中,這樣添加的)
解決辦法:
Targets->Build Settings->Header Search Path中添加AliPaySDK文件夾的路徑
截圖
這個(gè)參數(shù)需要設(shè)置多個(gè)值的時(shí)候,通過雙引號括起來
3)linker command failed with exit code 1 (use -v to see invocation)
這邊的解決辦法:”Build Settings”->”Enable Bitcode”設(shè)置為NO
(附帶的將Other Linker Flags下的屬性全刪除了在岂,可能不刪除也是可以跑的嘴瓤,沒有試)
4.編譯項(xiàng)目场梆,會出現(xiàn)以下問題:
解決方法:在xcode中摹芙,點(diǎn)擊項(xiàng)目名,選擇"target"->"Link Binary With Libraries"添加依賴庫袱瓮。
編輯程序缤骨,已經(jīng)可以成功編譯了,接下來就是集成代碼了尺借,這邊主要做的是直接在前端集成代碼
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中通過通知進(jìn)行回傳數(shù)據(jù)
[[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
{
// 進(jìn)入跳轉(zhuǎn)支付寶支付流程
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; //商品標(biāo)題
aliOrder.productDescription = productDescription; //商品描述
aliOrder.amount = @"0.01"; //商品價(jià)格
aliOrder.notifyURL = @"http://www.xxx.com"; //回調(diào)URL
aliOrder.service = @"mobile.securitypay.pay";
aliOrder.paymentType = @"1";
aliOrder.inputCharset = @"utf-8";
aliOrder.itBPay = @"30m";
//應(yīng)用注冊scheme,在AlixPayDemo-Info.plist定義URL types
NSString *appScheme = @"com.leaguerdtv.yuting";
//將商品信息拼接成字符串
NSString *orderSpec = [aliOrder description];
// NSLog(@"orderSpec = %@",orderSpec);
//獲取私鑰并將商戶信息簽名,外部商戶可以根據(jù)情況存放私鑰和簽名,只需要遵循 RSA 簽名規(guī)范, 并將簽名字符串 base64 編碼和 UrlEncode
id<DataSigner> signer = CreateRSADataSigner(privateKey);
NSString *signedString = [signer signString:orderSpec];
//將簽名成功字符串格式化為訂單字符串,請嚴(yán)格按照該格式
NSString *orderString = nil;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
orderSpec, signedString, @"RSA"];
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
//裝了支付寶客戶端的栅表,這個(gè)block不會被執(zhí)行
//裝了支付寶的笋鄙,通過在delegate中的通知進(jìn)行調(diào)用
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界面-訂單已取消~~~O袈洹!!");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"訂單已取消" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
}
break;
case 6002:
{
NSLog(@"ViewController界面-網(wǎng)絡(luò)連接出錯(cuò)~~~O捶 找岖!!");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"網(wǎng)絡(luò)連接出錯(cuò)" 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界面-未知錯(cuò)誤~~~!绎晃!!");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"未知錯(cuò)誤" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
}
break;
}
}];
}
}
#pragma mark 產(chǎn)生隨機(jī)訂單號
- (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(@"通知后臺消除這個(gè)訂單或者充值成功");
}
@end
delegate中代碼:
#import "AppDelegate.h"
#import <AlipaySDK/AlipaySDK.h>
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
return YES;
}
//支付寶-回調(diào)
//9.0之前調(diào)用的方法
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
return [self alipayOrWeiXinCallbackWithOpenUrl:url];
}
//9.0之前調(diào)用的方法
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options
{
return [self alipayOrWeiXinCallbackWithOpenUrl:url];
}
//9.0之后調(diào)用的方法
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
return [self alipayOrWeiXinCallbackWithOpenUrl:url];
}
//支付寶回調(diào)方法處理
-(BOOL)alipayOrWeiXinCallbackWithOpenUrl:(NSURL *)url
{
//跳轉(zhuǎn)支付寶錢包進(jìn)行支付,需要將支付寶錢包的支付結(jié)果回傳給SDK
//裝了支付寶的庶艾,這個(gè)方法才會被調(diào)用,通過在delegate中的通知進(jìn)行調(diào)用
if ([url.host isEqualToString:@"safepay"]) {//支付寶支付相關(guān)操作
[[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:@"網(wǎng)絡(luò)連接出錯(cuò)" 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:@"未知錯(cuò)誤" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
[alert show];
}
}];
}else if ([url.host isEqualToString:@"pay"]){//微信支付相關(guān)操作
}
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不配置的話朱转,是在項(xiàng)目內(nèi)調(diào)用支付寶進(jìn)行支付积暖;
配置了LSApplicationQueriesSchemes參數(shù),它會自動判斷當(dāng)前手機(jī)有沒有安裝支付寶夺刑,安裝了就跳支付寶應(yīng)用,沒有安裝直接應(yīng)用內(nèi)跳支付寶支付
(只要設(shè)置alipay這一個(gè)參數(shù)就可以了)
8遍愿、配置URL Schemes
這邊涂鴉掉的是代碼中 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
里面的appScheme參數(shù)設(shè)置成一樣的存淫,這樣支付寶回調(diào)的時(shí)候就知道調(diào)用手機(jī)中那個(gè)標(biāo)識的應(yīng)用
一般不在plist文件中設(shè)置這個(gè)參數(shù),而是在圖形界面中沼填,這樣比較的方便
URL Schemes配置桅咆,主要可以讓支付寶可以正確的回調(diào)當(dāng)前應(yīng)用,并傳人相關(guān)的支付信息(成功坞笙、失敗岩饼、取消)
9、遇到的問題-備注一下薛夜,便于理解
1)籍茧、在AppDelegate.m中加入這兩個(gè)方法(對舊版本的支持):
//重要更新,一下兩個(gè)方法IOS9.0以后被廢棄了梯澜,所以如果你是Xcode7.2的話寞冯,可能會出現(xiàn)不能進(jìn)入微信的onResp回調(diào)方法,原因是下邊兩個(gè)方法沒有被調(diào)用腊徙,所以這里更新一下简十,改用另外一個(gè)方法(并不建議刪除這兩個(gè)方法,新方法是9.0以后的方法撬腾,可能系統(tǒng)低版本的用戶不支持螟蝙。所以我三種方法都留下了,如果有人發(fā)現(xiàn)不能都留下的話民傻,請簡信告訴我一下胰默,再次謝過了)
-(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)、支付寶回調(diào)的時(shí)候分兩種情況喧半,客戶端裝了支付寶和沒有裝支付寶兩種情況
情況一:客戶端裝了支付寶
通過在delegate中handleOpenURL或者openURL接受支付回調(diào)奴迅,支付成功時(shí)通過通知去支付界面進(jìn)行銷單處理
情況二、客戶端沒有安裝支付寶
會在支付寶調(diào)用界面挺据,執(zhí)行block取具,方法如下圖