寫這篇文章的主要目的是做一個學習的備忘,避免同樣的坑再爬一遍??,下面開始正文。
文章的順序,就是開發(fā)的流程
1、將Alipay SDK包,添加到項目中
2、編譯項目,會出現(xiàn)以下問題:
1)"Unknown type name ‘NSString‘ "或"Unknown type name ‘NSData‘ "
,但是本人并沒有遇到,參考網友的時候有這樣的問題,一并附上,主要看解釋原因
這是因為缺少Foundation類庫和UIKit類庫,支付寶Demo中之所以沒有出現(xiàn)此錯誤,是因為在.pch文件中導入過這些類庫
解決辦法:只需要在出現(xiàn)錯誤的文件中導入這些類庫即可
2)‘openssl/asn1.h‘ file not found,這個坑填了幾個小時??
這是openssl文件夾頭文件鏈接問題,如果openssl文件夾隨意拉進項目中,即使添加頭文件鏈接,也可能解決不了此問題,這也是一開始就將所需要的文件放到一個新建文件夾中再添加到項目中的原因。(試了各種方法添加,最終是先將Alipay拖放到文件中,再將Alipay拖到項目工程中,這樣添加的)
解決辦法:
Targets->Build Settings->Header Search Path中添加AliPaySDK文件夾的路徑
截圖
這個參數(shù)需要設置多個值的時候,通過雙引號括起來
3)linker command failed with exit code 1 (use -v to see invocation)
這邊的解決辦法:”Build Settings”->”Enable Bitcode”設置為NO
(附帶的將Other Linker Flags下的屬性全刪除了,可能不刪除也是可以跑的,沒有試)
4.編譯項目,會出現(xiàn)以下問題:
解決方法:在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中通過通知進行回傳數(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
{
// 進入跳轉支付寶支付流程
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);
//獲取私鑰并將商戶信息簽名,外部商戶可以根據(jù)情況存放私鑰和簽名,只需要遵循 RSA 簽名規(guī)范, 并將簽名字符串 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不會被執(zhí)行
//裝了支付寶的,通過在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參數(shù),它會自動判斷當前手機有沒有安裝支付寶,安裝了就跳支付寶應用,沒有安裝直接應用內跳支付寶支付
(只要設置alipay這一個參數(shù)就可以了)
8、配置URL Schemes
這邊涂鴉掉的是代碼中 [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
里面的appScheme參數(shù)設置成一樣的,這樣支付寶回調的時候就知道調用手機中那個標識的應用
一般不在plist文件中設置這個參數(shù),而是在圖形界面中,這樣比較的方便
URL Schemes配置,主要可以讓支付寶可以正確的回調當前應用,并傳人相關的支付信息(成功、失敗、取消)
9、遇到的問題-備注一下,便于理解
1)、在AppDelegate.m中加入這兩個方法(對舊版本的支持):
//重要更新,一下兩個方法IOS9.0以后被廢棄了,所以如果你是Xcode7.2的話,可能會出現(xiàn)不能進入微信的onResp回調方法,原因是下邊兩個方法沒有被調用,所以這里更新一下,改用另外一個方法(并不建議刪除這兩個方法,新方法是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)、支付寶回調的時候分兩種情況,客戶端裝了支付寶和沒有裝支付寶兩種情況
情況一:客戶端裝了支付寶
通過在delegate中handleOpenURL或者openURL接受支付回調,支付成功時通過通知去支付界面進行銷單處理
情況二、客戶端沒有安裝支付寶
會在支付寶調用界面,執(zhí)行block,方法如下圖