1.支付寶集成
第一步:先簽約支付寶,申請應(yīng)用(別忘了生成的 RSA 密鑰的上傳)
https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.6i3qlX&treeId=58&articleId=103542&docType=1
第二步:下載支付寶官方的 SDK, 把第一步申請得到的 sellID,partnerID,私鑰(privateKey)放到代碼中,為了測試我們配置的 key 是否正確,如果支付寶 demo 能支付成功,就代表我們配置的 key 成功了,反之去重復(fù)第一步吧
L:148
NSString *partner = @"xxxxxxx";
NSString *seller = @"xxxxxxx";
NSString *privateKey = @"xxxxxxx" ;//注意空格!!
第三步:配置支付寶到 app
1>配置庫,看支付寶官方的就好,比哪都詳細(xì)
https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.l0wbHb&treeId=59&articleId=103676&docType=1
但要注意: "Header Search Paths”增加頭文件路徑:$(SRCROOT)/項(xiàng)目名稱!!!!
還有記得設(shè)置回調(diào)
2>把下圖的文件從支付寶官方 demo 中拷貝過來
編譯,如果有報(bào)錯(cuò),缺庫就導(dǎo)庫,頭文件就 header search paths,
我還需要一個(gè)報(bào)錯(cuò),導(dǎo)了一個(gè) demo 里沒有的庫:libstdc++.6.0.9. tbd
3>處理支付的商品信息,簽名等等
導(dǎo)入頭文件
#import "Order.h"
#import <AlipaySDK/AlipaySDK.h>
#import "DataSigner.h"
處理支付業(yè)務(wù)
/**
* 1.生成訂單信息
*/
Order *order = [[Order alloc]init];
order.partner = PARTNER;
order.seller = SELLER;
order.tradeNO = self.orderCode;
order.productName = @"這是一個(gè)支付寶測試";
order.productDescription = @"我說了這是一個(gè)測試數(shù)據(jù)";
order.amount = [NSString stringWithFormat:@"%.2f",0.01];
//回調(diào) URL
order.notifyURL = @"url url url ";
order.service = @"mobile.securitypay.pay";
order.paymentType = @"1";
order.inputCharset = @"utf-8";
order.itBPay = @"30m";
order.showUrl = @"m.alipay.com";
// 應(yīng)用注冊scheme,在當(dāng)前項(xiàng)目的Info.plist定義URL types
NSString *appScheme = @"";//同 url types
//將訂單信息拼接成在字符串
NSString *orderSpec = [order description];
第一步基本上和官方 demo 一樣,比微信好多了(不得不吐槽一下)
/**
* 2.簽名加密
* 獲取私鑰并將商戶信息簽名, 外部商戶可以根據(jù)情況存放私鑰和簽名, 只需要遵循 RSA 簽名規(guī)范, 并將簽名字符串 base64 編碼和 UrlEncode
*/
NSString *str = PRIVATE;
id<DataSigner> signer = CreateRSADataSigner(str);
NSString *signedString = [signer signString:orderSpec];
請直接copy demo 這一部分
/**
* 3. 將簽名成功字符串格式化為訂單字符串,請嚴(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) {
//處理你的支付結(jié)果
NSLog(@"resuly===%@",resultDic);
}
}];
}
appDelegate里面需要設(shè)置
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
/**
* Alipay
*/
//如果極簡開發(fā)包不可用,會跳轉(zhuǎn)支付寶錢包進(jìn)行支付,需要將支付寶錢包的支付結(jié)果回傳給開 發(fā)包
if ([url.host isEqualToString:@"safepay"]) {
[[AlipaySDK defaultService]processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic) {
#warning ======支付結(jié)果處理
NSLog(@"ewsult====%@",resultDic);
}];
}
//支付寶錢包快登授權(quán)返回
if ([url.host isEqualToString:@"platformapi"]) {
[[AlipaySDK defaultService]processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
#warning ======支付結(jié)果處理
NSLog(@"ewsult====%@",resultDic);
}];
}
}
支付寶就這么多了,很簡單的代碼,一般的配置,復(fù)雜的申請....
2.微信支付
做微信支付是有挺多小坑的,這個(gè)坑主要取決于你的后臺怎么樣,微信不同于支付寶的是,它把支付過程分成了兩步,就到導(dǎo)致了后臺需要先做第一步,再傳數(shù)據(jù)給前端,然后前端去完成第二步.
第一步是:向微信注冊你的應(yīng)用程序 ID
這一步?jīng)]什么技術(shù),按照流程就好了(這都是產(chǎn)品經(jīng)理做的吧.....)
https://open.weixin.qq.com/cgi-bin/showdocument?action=dir_list&t=resource/res_list&verify=1&id=open1419317780&token=f6e95c1f1c5fd970d5fb3b2425e2d612b6cbce47&lang=zh_CN
照這個(gè)流程來就好
第二步:下載官方 demo
https://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=11_1
其實(shí)不推薦官方的 demo...而且微信的官方 demo 不像支付寶一樣還可以用來去檢查 appId,等等值是否配好
第三步:配置微信 SDK
需要配置的庫好像跟支付寶差不多...
第四步:調(diào)用微信支付 SDK
這個(gè)第四步就要分情況討論了
微信的支付流程是先獲取prePayid,再加appid,appkey,noncestr,package,partnerId,timestamp去簽名完成支付.
第一種情況:如果你的后臺去完成獲取預(yù)支付訂單
這種是微信支付官方推薦的,而且這樣更加安全,相關(guān)的配置信息和 key 都存在服務(wù)器更加安全.
這種情況前端需要在用戶發(fā)起微信支付后吧訂單信息傳給服務(wù)器(傳遞的信息需要溝通),返回值為
// 調(diào)起微信支付
PayReq *request = [[PayReq alloc]init];
request.partnerId = _WXPayModel.partnerid;
request.prepayId = _WXPayModel.prepayid;
request.package = @"Sign=WXPay";
request.nonceStr = _WXPayModel.noncestr;
request.timeStamp = [_WXPayModel.timestamp intValue];
package 一定要寫成那樣!
package 一定要寫成那樣!
package 一定要寫成那樣!
// 這里要注意key里的值一定要填對, 微信官方給的參數(shù)名是錯(cuò)誤的,不是第二個(gè)字母大寫
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: _WXPayModel.appid forKey:@"appid"];
[signParams setObject: _WXPayModel.partnerid forKey:@"partnerid"];
[signParams setObject: request.nonceStr forKey:@"noncestr"];
[signParams setObject: request.package forKey:@"package"];
[signParams setObject: _WXPayModel.timestamp forKey:@"timestamp"];
[signParams setObject: request.prepayId forKey:@"prepayid"];
//生成簽名
NSString *sign = [MyUtil genSign:signParams];
NSLog(@"sign===%@",sign);
//添加簽名
request.sign = sign;
[WXApi sendReq:request];
基本上調(diào)起支付的代碼就這樣...這當(dāng)然是在服務(wù)端完成第一步的情況下.
第二種情況:(如果你家后臺又懶又不會而且你又比較閑的話)
//微信支付
- (void)wxpay
{
//商戶號
NSString *PARTNER_ID = @"1900000109";
//商戶密鑰
NSString *PARTNER_KEY = @"8934e7d15453e97507ef794cf7b0519d";
//APPID
NSString *APPI_ID = @"wxd930ea5d5a258f4f";
//appsecret
NSString *APP_SECRET = @"db426a9829e4b49a0dcac7b4162da6b6";
//支付密鑰
NSString *APP_KEY = @"L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K";
NSLog(@"%ld,%ld,%ld",PARTNER_KEY.length,APP_SECRET.length,APP_KEY.length);
//支付結(jié)果回調(diào)頁面
NSString *NOTIFY_URL = @"http://localhost/pay/wx/notify_url.asp";
//訂單標(biāo)題
NSString *ORDER_NAME = @"Ios客戶端簽名支付 測試";
//訂單金額,單位(分)
NSString *ORDER_PRICE = @"1";
//創(chuàng)建支付簽名對象
payRequsestHandler *req = [payRequsestHandler alloc];
//初始化支付簽名對象
[req init:APPI_ID app_secret:APP_SECRET partner_key:PARTNER_KEY app_key:APP_KEY];
//判斷Token過期時(shí)間咳燕,10分鐘內(nèi)不重復(fù)獲取,測試帳號多個(gè)使用蔼两,可能造成其他地方獲取后不能用侵浸,需要即時(shí)獲取
time_t now;
time(&now);
//if ( (now - token_time) > 0 )//非測試帳號調(diào)試請啟用該條件判斷
{
//獲取Token
Token = [req GetToken];
//設(shè)置Token有效期為10分鐘
token_time = now + 600;
//日志輸出
NSLog(@"獲取Token: %@\n",[req getDebugifo]);
}
if ( Token != nil){
//================================
//預(yù)付單參數(shù)訂單設(shè)置
//================================
NSMutableDictionary *packageParams = [NSMutableDictionary dictionary];
[packageParams setObject: @"WX" forKey:@"bank_type"];
[packageParams setObject: ORDER_NAME forKey:@"body"];
[packageParams setObject: @"1" forKey:@"fee_type"];
[packageParams setObject: @"UTF-8" forKey:@"input_charset"];
[packageParams setObject: NOTIFY_URL forKey:@"notify_url"];
[packageParams setObject: [NSString stringWithFormat:@"%ld",time(0)] forKey:@"out_trade_no"];
[packageParams setObject: PARTNER_ID forKey:@"partner"];
[packageParams setObject: @"196.168.1.1" forKey:@"spbill_create_ip"];
[packageParams setObject: ORDER_PRICE forKey:@"total_fee"];
NSString *package, *time_stamp, *nonce_str, *traceid;
//獲取package包
package = [req genPackage:packageParams];
//輸出debug info
NSString *debug = [req getDebugifo];
NSLog(@"gen package: %@\n",package);
NSLog(@"生成package: %@\n",debug);
//設(shè)置支付參數(shù)
time_stamp = [NSString stringWithFormat:@"%ld", now];
nonce_str = [TenpayUtil md5:time_stamp];
traceid = @"mytestid_001";
NSMutableDictionary *prePayParams = [NSMutableDictionary dictionary];
[prePayParams setObject: APPI_ID forKey:@"appid"];
[prePayParams setObject: APP_KEY forKey:@"appkey"];
[prePayParams setObject: nonce_str forKey:@"noncestr"];
[prePayParams setObject: package forKey:@"package"];
[prePayParams setObject: time_stamp forKey:@"timestamp"];
[prePayParams setObject: traceid forKey:@"traceid"];
//生成支付簽名
NSString *sign;
sign = [req createSHA1Sign:prePayParams];
//增加非參與簽名的額外參數(shù)
[prePayParams setObject: @"sha1" forKey:@"sign_method"];
[prePayParams setObject: sign forKey:@"app_signature"];
//獲取prepayId
NSString *prePayid;
prePayid = [req sendPrepay:prePayParams];
//輸出debug info
debug = [req getDebugifo];
NSLog(@"提交預(yù)付單: %@\n",debug);
if ( prePayid != nil) {
//重新按提交格式組包,微信客戶端5.0.3以前版本只支持package=Sign=***格式,須考慮升級后支持?jǐn)y帶package具體參數(shù)的情況
//package = [NSString stringWithFormat:@"Sign=%@",package];
package = @"Sign=WXPay";
//簽名參數(shù)列表
NSMutableDictionary *signParams = [NSMutableDictionary dictionary];
[signParams setObject: APPI_ID forKey:@"appid"];
[signParams setObject: APP_KEY forKey:@"appkey"];
[signParams setObject: nonce_str forKey:@"noncestr"];
[signParams setObject: package forKey:@"package"];
[signParams setObject: PARTNER_ID forKey:@"partnerid"];
[signParams setObject: time_stamp forKey:@"timestamp"];
[signParams setObject: prePayid forKey:@"prepayid"];
//生成簽名
sign = [req createSHA1Sign:signParams];
//輸出debug info
debug = [req getDebugifo];
NSLog(@"調(diào)起支付簽名: %@\n",debug);
//調(diào)起微信支付
PayReq* req = [[PayReq alloc] init];
req.openID = APPI_ID;
req.partnerId = PARTNER_ID;
req.prepayId = prePayid;
req.nonceStr = nonce_str;
req.timeStamp = now;
req.package = package;
req.sign = sign;
[WXApi safeSendReq:req];
}else{
/*long errcode = [req getLasterrCode];
if ( errcode == 40001 )
{//Token實(shí)效,重新獲取
Token = [req GetToken];
token_time = now + 600;
NSLog(@"獲取Token: %@\n",[req getDebugifo]);
};*/
NSLog(@"獲取prepayid失敗\n");
[self alert:@"提示信息" msg:debug];
}
}else{
NSLog(@"獲取Token失敗\n");
[self alert:@"提示信息" msg:@"獲取Token失敗"];
}
}
第四步:設(shè)置 url回調(diào)以及等等瑣碎的東西
1.info URL Types 設(shè)置app回調(diào)
2.appdelegate中注冊 app
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
[WXApi registerApp:@"xxxxxxxxxxxx" withDescription:@"xxxxxx"];
微信支付完成后會通過 appdelegate 中的代理方法發(fā)送通知,處理支付結(jié)果
if ([resp isKindOfClass:[PayResp class]]) {
PayResp *response = (PayResp *)resp;
NSLog(@"response.errCoderesponse.errCoderesponse.errCode%d",response.errCode);
switch (response.errCode) {
case WXSuccess:{
NSLog(@"successWXPay");
NSNotification *notification = [NSNotification notificationWithName:@"orderPay" object:@"success"];
[[NSNotificationCenter defaultCenter]postNotification:notification];
break;
}
case WXErrCodeCommon:
[SVProgressHUD showErrorWithStatus:@"發(fā)送錯(cuò)誤"];
break;
case WXErrCodeUserCancel:
[SVProgressHUD showErrorWithStatus:@"支付已取消"];
break;
case WXErrCodeSentFail:
[SVProgressHUD showErrorWithStatus:@"發(fā)送失敗"];
break;
case WXErrCodeUnsupport:
[SVProgressHUD showErrorWithStatus:@"微信不支持"];
break;
// WXErrCodeCommon = -1, /**< 普通錯(cuò)誤類型 */
// WXErrCodeUserCancel = -2, /**< 用戶點(diǎn)擊取消并返回 */
// WXErrCodeSentFail = -3, /**< 發(fā)送失敗 */
// WXErrCodeAuthDeny = -4, /**< 授權(quán)失敗 */
// WXErrCodeUnsupport = -5, /**< 微信不支持 */
default:{
NSLog(@"wxpay");
break;
}
}
}
到這里微信支付就差不多完成了,如果出現(xiàn)微信的各種報(bào)錯(cuò),簡書上有很多,就不啰嗦了.
再說說做第三方支付的感受吧,其實(shí)我以后打算直接用 ping++了.......