網(wǎng)上看了好多博客文章,與關(guān)于支付寶支付的我攏了攏主要的,可以看看
#import "AppDelegate.h"#import "ViewController.h"#import#import "DataVerifier.h"
#import "AlixPayResult.h"
#import "PartnerConfig.h"
#import "SBJSON.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
跳轉(zhuǎn)支付寶客戶端進(jìn)行支付,處理支付結(jié)果
// 9.0之后//- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary*)options
//{
//
//}
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation {
// 跳轉(zhuǎn)支付寶客戶端進(jìn)行支付,處理支付結(jié)果
[[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
// NSLog(@"回調(diào)結(jié)果 = %@", resultDic);
// 用SBJSON 或者 JSONKit 將回調(diào)信息(字典)轉(zhuǎn)成字符串
SBJSON *sbJson = [[SBJSON alloc] init];
NSString *resultDicToString = [sbJson stringWithObject:resultDic error:nil];
[self paymentResult:resultDicToString];
}];
return YES;
}
#pragma mark - 對(duì)獨(dú)立客戶端回調(diào)結(jié)果驗(yàn)證
- (void)paymentResult:(NSString *)resultDicToString
{
//結(jié)果處理
AlixPayResult *result = [[AlixPayResult alloc] initWithString:resultDicToString];
if (result)
{
if (result.statusCode == 9000) {
/** * 支付成功用公鑰驗(yàn)證簽名 嚴(yán)格驗(yàn)證請(qǐng)使用result.resultString與result.signString驗(yàn)簽
*/
// 就是在生產(chǎn)訂單時(shí),需要使用私鑰生成簽名值;在處理返回的支付結(jié)果時(shí),需要使用公鑰驗(yàn)證返回結(jié)果是否被篡改了。
// resultDic 返回結(jié)果所對(duì)應(yīng)的值可以到支付寶開發(fā)平臺(tái)上去查
// 在處理結(jié)果之前應(yīng)該先對(duì)支付結(jié)果進(jìn)行簽名驗(yàn)證,防止支付數(shù)據(jù)被篡改。
// 返回的支付結(jié)果中的result字段里是帶有訂單信息和簽名信息的,所以簽名驗(yàn)證就是需要這個(gè)字段的值。 // 分發(fā)出得公鑰
// 驗(yàn)證的步驟:首先把訂單信息和簽名值分別提取出來(lái)
// 訂單信息就是sign_type的連字符&之前的所有字符串
// 簽名值是sign后面雙引號(hào)內(nèi)的內(nèi)容,注意簽名的結(jié)尾也是=,所以不要用split字符串的方式提取
NSString* key = AlipayPublicKey;//簽約帳戶后獲取到的支付寶公鑰
id<DataVerifier>verifier;
verifier = CreateRSADataVerifier(key);
// 參數(shù)1:訂單信息
// 參數(shù)2:簽名值
if ([verifier verifyString:result.resultString withSign:result.signString])
{
// 驗(yàn)證簽名成功,交易結(jié)果無(wú)篡改
NSLog(@"支付成功!");
}
}
else
{
// 支付失敗
NSLog(@"%d%@", result.statusCode, result.statusMessage);
}
}
else
{
// 支付失敗
NSLog(@"支付失敗!");
}
}
import "ViewController.h"
#import#import "Order.h" // 訂單信息
#import "DataSigner.h" // 簽名
#import "PartnerConfig.h" // 配置信息
// 以下的類是驗(yàn)證支付結(jié)果用的 不驗(yàn)證不需要引用
#import "DataVerifier.h" // 驗(yàn)證簽名
#import "AlixPayResult.h" // 支付結(jié)果處理
#import "SBJSON.h"
/**
* 官方接入流程、SDK下載請(qǐng)參考這里:http://doc.open.alipay.com/doc2/detail?treeId=59&articleId=103563&docType=1
* 這篇博文說(shuō)的也是很好,參考這里:http://www.itdecent.cn/p/fe56e122663e
*/
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.title = @"支付寶支付";
UIButton *payButton = [UIButton buttonWithType:UIButtonTypeCustom];
payButton.frame = CGRectMake(50, 100, self.view.frame.size.width - 100, 60);
payButton.layer.cornerRadius = 5;
payButton.backgroundColor = [UIColor lightGrayColor];
[payButton setImage:[UIImage imageNamed:@"payNow_alipay"] forState:UIControlStateNormal];
[payButton setImageEdgeInsets:UIEdgeInsetsMake(5, -20, 0, 0)];
[payButton setTitle:@"支付寶支付" forState:UIControlStateNormal];
[payButton addTarget:self action:@selector(alipayAction) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:payButton];
}
#pragma mark - 點(diǎn)擊支付
/**
* 如果安裝了支付寶客戶端會(huì)直接調(diào)起客戶端,沒(méi)有安裝會(huì)調(diào)起wap頁(yè)面
*/
- (void)alipayAction
{
/**
* 商戶的唯一的parnter和seller。商戶簽約成功后,支付寶會(huì)為每
* 個(gè)商戶分配一個(gè)唯一的 parnter(appID) 和 seller(支付寶賬號(hào))。
* privateKey生成的私鑰,可放在本地,建議放在服務(wù)器端
*/
NSString *partner = PartnerID;
NSString *seller = SellerID;
// 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;
}
// 應(yīng)用注冊(cè)scheme,在Info.plist定義URL types URL scheme
NSString *appScheme = @"test";//程序間通信 app 調(diào) 支付寶
// 將商品信息拼接成字符串
NSString *orderSpec = [self createOrderInfoWithPartner:partner Seller:seller];
// 進(jìn)行簽名并將簽名成功后的字符串格式化為訂單字符串
NSString *signedString = [self doRsa:orderSpec];
// 調(diào)用支付寶SDK發(fā)送數(shù)據(jù)
[self sendValueToAliPayWithOrderString:signedString FromScheme:appScheme];
}
#warning 1.生成預(yù)支付訂單信息
- (NSString *)createOrderInfoWithPartner:(NSString *)partner
Seller:(NSString *)seller
{
/**
*由于demo的局限性,采用了將私鑰放在本地簽名的方法,商戶可以根據(jù)自身情況選擇簽名方法(為安全起
*見,在條件允許的前提下,推薦從自己的服務(wù)器獲取完整的訂單信息)
*/
// 將商品信息賦予Order的成員變量
Order *order = [[Order alloc] init];
order.partner = partner;
order.seller = seller;
order.tradeNO = @"123432121222"; //訂單ID(由商家自行制定)
order.productName = @"商品標(biāo)題"; //商品標(biāo)題
order.productDescription = @"商品描述"; //商品描述
order.amount = @"0.01"; //商品價(jià)格
order.notifyURL = @""; //回調(diào)URL 退款功能
// 這以下是固定形式每個(gè)app都是這么寫
order.service = @"mobile.securitypay.pay";
order.paymentType = @"1";
order.inputCharset = @"utf-8";
order.itBPay = @"30m";
order.showUrl = @"m.alipay.com";
return [order description];
}
#warning 2.將訂單信息用私鑰進(jìn)行簽名// 獲取私鑰并將商戶信息簽名,外部商戶可以根據(jù)情況存放私鑰和簽名,只需要遵循RSA簽名規(guī)范,并將簽名字符串base64編碼和UrlEncode// 此demo是在app內(nèi)部做的簽名// 訂單簽名應(yīng)該用私鑰,但是把私鑰放到app里其實(shí)本身就不安全,因?yàn)槟愕腶pp是分發(fā)到用戶手里的,私鑰應(yīng)該放在自己的手里,分發(fā)出去的應(yīng)該是公鑰。所以私鑰最好是放在自己的服務(wù)器上,訂單加密這個(gè)工作放在服務(wù)器端來(lái)做,服務(wù)器將包含簽名的訂單信息返回給app,app再通過(guò)SDK發(fā)送給支付寶,這樣會(huì)更安全些;而且服務(wù)器也能掌握所有的訂單狀況
- (NSString *)doRsa:(NSString *)orderInfo{ idsigner;
signer = CreateRSADataSigner(PartnerPrivateKey);
NSString *signedString = [signer signString:orderInfo];
// 將簽名成功字符串格式化為訂單字符串,請(qǐng)嚴(yán)格按照該格式
NSString *orderString = nil;
if (signedString != nil) {
orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",orderInfo, signedString, @"RSA"];
NSLog(@"orderString ==== %@\nsignerString ========== %@", orderString, signedString);
}
return orderString;
}
#warning 3.調(diào)用支付寶SDK發(fā)送請(qǐng)求數(shù)據(jù)
- (void)sendValueToAliPayWithOrderString:(NSString *)orderString FromScheme:(NSString *)appScheme
{
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
// 用SBJSON 或者 JSONKit 將回調(diào)信息(字典)轉(zhuǎn)成字符串
SBJSON *sbJson = [[SBJSON alloc] init];
NSString *resultDicToString = [sbJson stringWithObject:resultDic error:nil];
[self paymentResult:resultDicToString];
NSLog(@"回調(diào)結(jié)果reslut = %@",resultDic);
// NSLog(@"%d%@", [[resultDic objectForKey:@"resultStatus"] intValue], [resultDic objectForKey:@"memo"]);
}];
}
#warning 4.對(duì)支付回調(diào)的結(jié)果進(jìn)行驗(yàn)證(這一步加上是確保數(shù)據(jù)的安全,不加不影響支付)
// 就是在生產(chǎn)訂單時(shí),需要使用私鑰生成簽名值;在處理返回的支付結(jié)果時(shí),需要使用公鑰驗(yàn)證返回結(jié)果是否被篡改了。
// resultDic 返回結(jié)果所對(duì)應(yīng)的值可以到支付寶開發(fā)平臺(tái)上去查
// 在處理結(jié)果之前應(yīng)該先對(duì)支付結(jié)果進(jìn)行簽名驗(yàn)證,防止支付數(shù)據(jù)被篡改。
// 返回的支付結(jié)果中的result字段里是帶有訂單信息和簽名信息的,所以簽名驗(yàn)證就是需要這個(gè)字段的值。
// 驗(yàn)證的步驟:首先把訂單信息和簽名值分別提取出來(lái)
// 訂單信息就是sign_type的連字符&之前的所有字符串
// 簽名值是sign后面雙引號(hào)內(nèi)的內(nèi)容,注意簽名的結(jié)尾也是=
// 此demo我是用SBJSON 或者 JSONKit 將回調(diào)信息(字典)轉(zhuǎn)成字符串
// 也可以不使用SBJSON或者JSONKit處理回調(diào)信息,直接在回調(diào)結(jié)果中截取需要的字符串也可以,直接調(diào)用可以直接使用Util目錄下的DataVerifier來(lái)作簽名驗(yàn)證"- (BOOL)verifyString:(NSString *)string withSign:(NSString *)signString"第一個(gè)參數(shù)就是訂單信息,第二個(gè)參數(shù)就是簽名值。
- (void)paymentResult:(NSString *)resultDicToString{
//結(jié)果處理
AlixPayResult *result = [[AlixPayResult alloc] initWithString:resultDicToString];
if (result) {
/** * 狀態(tài)碼 * 9000 訂單支付成功 * 8000 正在處理中 * 4000 訂單支付失敗 * 6001 用戶中途取消 * 6002 網(wǎng)絡(luò)連接出錯(cuò) */
if (result.statusCode == 9000) {
/**363918 *用公鑰驗(yàn)證簽名 嚴(yán)格驗(yàn)證請(qǐng)使用result.resultString與result.signString驗(yàn)簽 */ // 交易成功
NSString* key = AlipayPublicKey;
id<DataVerifier >idverifier**;**
verifier = CreateRSADataVerifier(key);
// 參數(shù)1:訂單信息
// 參數(shù)2:簽名值
/**< resultString.訂單信息以及驗(yàn)證簽名信息*/
/*如果你不想做簽名驗(yàn)證,那這個(gè)字段可以忽略了*/
if ([verifier verifyString:result.resultString withSign:result.signString])
{
// 驗(yàn)證簽名成功,交易結(jié)果無(wú)篡改
NSLog(@"支付成功!");
} else {
NSLog(@"此單被篡改無(wú)效!!");
}
}
else
{
// 支付失敗
NSLog(@"%d%@", result.statusCode, result.statusMessage);
}
}
else
{
// 支付失敗
NSLog(@"支付失敗!");
}
}