iOS 開發(fā)支付篇
隨著互聯(lián)網(wǎng)的發(fā)展教翩,電商平臺已經(jīng)成為人們的習(xí)慣一種生活方式,電商個人認(rèn)為站在開發(fā)的角度看签夭,也就多了一個購物車和支付尝艘,而支付稱為很多剛接觸電商平臺開發(fā)人員很向往的一個技術(shù)點,那么現(xiàn)在我講自己了解的當(dāng)前所有支付方式以及如何使用分享給大家炕吸。
支付寶支付:
支付流程 :
(1)先與支付寶簽約伐憾,獲取商戶id(partner)和賬號id(seller)
(2)下載相應(yīng)的公私鑰文件(加密簽名使用),在客戶端我們可能只需要私鑰
(3)下載支付寶sdk
(4)生成訂單信息算途,可以直接客戶端或者自己服務(wù)端生存都可以塞耕,但是大多是服務(wù)端生存的蚀腿。
(5)調(diào)用支付寶客戶端嘴瓤,有支付寶客戶端跟支付寶打交道
(6)支付完畢之后返回結(jié)果給客戶端和服務(wù)端。
//回到本應(yīng)用urlScheme
NSString *appScheme=@"Practice";
NSString * orderInfo=[self getOrderInfo:indexPath.row];
NSString * signedStr=[self doRsa:orderInfo];
NSString*orderString=[NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",orderInfo,signedStr,@"RSA"];
[AlixLibService payOrder:orderString AndScheme:appScheme seletor:_result target:self];
-(NSString *)doRsa:(NSString *)orderInfo
{
idsigner;
signer=CreateRSADataSigner(PartnerPrivKey);
NSString * signedString=[signer signString:orderInfo];
return signedString;
}
-(NSString *)getOrderInfo:(NSInteger)index
{
//點擊獲取product實例莉钙,并初始化訂單信息
Pruduct *pruduct=[_dataArray objectAtIndex:index];
AlixPayOrder * order=[[AlixPayOrder alloc]init];
order.partner=PartnerID;
order.seller=SellerID;
//訂單ID
order.tradeNO=[self generateTradeNO];
// 商品標(biāo)題
order.productName=pruduct.subject;
// 商品描述
order.productDescription =pruduct.body;
//商品價格
order.amount=[NSString stringWithFormat:@"%.2f",pruduct.price];
order.notifyURL = @"http%3A%2F%2Fwwww.xxx.com"; //回調(diào)URL
return order.description;
}
-(NSString *)generateTradeNO
{
const int N =15;
NSString * sourceString=@"SSSSSSSSSSSSSSSS";
NSMutableString *re=[[NSMutableString alloc]init];
srand(time(0));
for (int i=0; i unsigned index=rand()%[sourceString length];
NSString * s=[sourceString substringWithRange:NSMakeRange(index, 1)];
[re appendString:s];
}
return re;
}
-(void)paymentResultDelegate:(NSString *)result
{
NSLog(@"%@",result);
}
//支付寶也就這么幾行代碼而已廓脆,所謂的高大上是不是讓朋友們失望了
微信支付:
支付流程:
(1)注冊微信開放平臺,創(chuàng)建應(yīng)用獲取appid磁玉,appSecret停忿,申請支付功能,申請成功之后會返回一些參數(shù)詳情見圖
(2)下載微信支付sdk
(3)客戶端請求訂單蚊伞,后臺與微信后臺交互席赂,返回給客戶端支付參數(shù);
(4)調(diào)用微信客戶端时迫,由微信客戶端和微信服務(wù)器打交道颅停;
(5)客戶端和服務(wù)端都會收到支付結(jié)果;(前臺消息不可靠掠拳,我們需要去后臺驗證癞揉,如果后臺沒有收到支付通知,后臺去微信服務(wù)器驗證然后將結(jié)果返回給客戶端)
//需要的依賴庫溺欧,環(huán)境搭建可以參見文檔喊熟,或者直接用cocoapods倒入
/**
*? 微信開放平臺申請得到的 appid, 需要同時添加在 URL schema
*/
NSString * const WXAppId = @"wxd930ea5d5a258f4f";
/**
* 微信開放平臺和商戶約定的支付密鑰
*
* 注意:不能hardcode在客戶端,建議genSign這個過程由服務(wù)器端完成
*/
NSString * const WXAppKey = @"L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K";
/**
* 微信開放平臺和商戶約定的密鑰
*
* 注意:不能hardcode在客戶端姐刁,建議genSign這個過程由服務(wù)器端完成
*/
NSString * const WXAppSecret = @"db426a9829e4b49a0dcac7b4162da6b6";
/**
* 微信開放平臺和商戶約定的支付密鑰
*
* 注意:不能hardcode在客戶端聂使,建議genSign這個過程由服務(wù)器端完成
*/
NSString * const WXPartnerKey = @"8934e7d15453e97507ef794cf7b0519d";
/**
*? 微信公眾平臺商戶模塊生成的ID
*/
NSString * const WXPartnerId = @"1900000109";
調(diào)用支付的代碼就比較簡單了,如下所示
#pragma mark - 主體流程
- (void)getAccessToken
{
NSString *getAccessTokenUrl = [NSString stringWithFormat:@"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%@&secret=%@", WXAppId, WXAppSecret];
NSLog(@"--- GetAccessTokenUrl: %@", getAccessTokenUrl);
self.request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:getAccessTokenUrl]];
__weak WXPayClient *weakSelf = self;
__weak ASIHTTPRequest *weakRequest = self.request;
[self.request setCompletionBlock:^{
NSError *error = nil;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[weakRequest responseData]
options:kNilOptions
error:&error];
if (error) {
[weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 AccessToken 失敗"];
return;
} else {
NSLog(@"--- %@", [weakRequest responseString]);
}
NSString *accessToken = dict[AccessTokenKey];
if (accessToken) {
NSLog(@"--- AccessToken: %@", accessToken);
__strong WXPayClient *strongSelf = weakSelf;
[strongSelf getPrepayId:accessToken];
} else {
NSString *strMsg = [NSString stringWithFormat:@"errcode: %@, errmsg:%@", dict[errcodeKey], dict[errmsgKey]];
[weakSelf showAlertWithTitle:@"錯誤" msg:strMsg];
}
}];
[self.request setFailedBlock:^{
[weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 AccessToken 失敗"];
}];
[self.request startAsynchronous];
}
- (void)getPrepayId:(NSString *)accessToken
{
//token傳入到此鏈接
NSString *getPrepayIdUrl = [NSString stringWithFormat:@"https://api.weixin.qq.com/pay/genprepay?access_token=%@", accessToken];
NSLog(@"--- GetPrepayIdUrl: %@", getPrepayIdUrl);
NSMutableData *postData = [self getProductArgs];
// 文檔: 詳細(xì)的訂單數(shù)據(jù)放在 PostData 中,格式為 json
self.request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:getPrepayIdUrl]];
[self.request addRequestHeader:@"Content-Type" value:@"application/json"];
[self.request addRequestHeader:@"Accept" value:@"application/json"];
[self.request setRequestMethod:@"POST"];
[self.request setPostBody:postData];
__weak WXPayClient *weakSelf = self;
__weak ASIHTTPRequest *weakRequest = self.request;
[self.request setCompletionBlock:^{
NSError *error = nil;
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:[weakRequest responseData]
options:kNilOptions
error:&error];
//獲取到了支付參數(shù)
if (error) {
[weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 PrePayId 失敗"];
return;
} else {
NSLog(@"--- %@", [weakRequest responseString]);
}
NSString *prePayId = dict[PrePayIdKey];
if (prePayId) {
NSLog(@"--- PrePayId: %@", prePayId);
// 調(diào)起微信支付
//將支付參數(shù)傳入到sdk,喚起微信客戶端
PayReq *request? = [[PayReq alloc] init];
request.partnerId = WXPartnerId;
request.prepayId? = prePayId;
request.package? = @"Sign=WXPay";? ? ? // 文檔為 `Request.package = _package;` , 但如果填寫上面生成的 `package` 將不能支付成功
request.nonceStr? = weakSelf.nonceStr;
request.timeStamp = [weakSelf.timeStamp longLongValue];
// 構(gòu)造參數(shù)列表
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:WXAppId forKey:@"appid"];
[params setObject:WXAppKey forKey:@"appkey"];
[params setObject:request.nonceStr forKey:@"noncestr"];
[params setObject:request.package forKey:@"package"];
[params setObject:request.partnerId forKey:@"partnerid"];
[params setObject:request.prepayId forKey:@"prepayid"];
[params setObject:weakSelf.timeStamp forKey:@"timestamp"];
request.sign = [weakSelf genSign:params];
// 在支付之前街佑,如果應(yīng)用沒有注冊到微信,應(yīng)該先調(diào)用 [WXApi registerApp:appId] 將應(yīng)用注冊到微信
[WXApi safeSendReq:request];
} else {
NSString *strMsg = [NSString stringWithFormat:@"errcode: %@, errmsg:%@", dict[errcodeKey], dict[errmsgKey]];
[weakSelf showAlertWithTitle:@"錯誤" msg:strMsg];
}
}];
[self.request setFailedBlock:^{
[weakSelf showAlertWithTitle:@"錯誤" msg:@"獲取 PrePayId 失敗"];
}];
[self.request startAsynchronous];
}
//這是微信官方給的demo,直接調(diào)用getAccessToken方法即可完成支付
銀聯(lián)支付:
支付流程:
(1)注冊申請就不是前端的事了,直接介入sdk
(2)從自己的服務(wù)端獲取流水號
(3)然后調(diào)用銀聯(lián)sdk,不用跳轉(zhuǎn),銀聯(lián)sdk直接是內(nèi)嵌的
(4)支付完成之后會回調(diào)代理方法
銀聯(lián)支付在客戶端實現(xiàn)起來最簡單的这难,現(xiàn)在介紹一下客戶端如何實現(xiàn) ,以及實現(xiàn)代碼
- (void)viewDidLoad {
[super viewDidLoad];
//開始支付
//第一個參數(shù)是流水號赖草,又后臺返回給我們 第二個參數(shù)傳00,01乎折,00標(biāo)示正式環(huán)境骂澄,01標(biāo)示測試環(huán)境,第三個參數(shù)是支付完成回到的控制器矩桂,第四個參數(shù)是設(shè)置代理
[UPPayPlugin startPay:@"57855654" mode:@"01" viewController:self.navigationController delegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
//監(jiān)聽支付結(jié)果
- (void)UPPayPluginResult:(NSString *)result
{
}
//銀聯(lián)支付將復(fù)雜操作全部放在了后臺,我們使用相當(dāng)方便
當(dāng)然下面才是最常用的网沾,它集成所有支付功能于一身:Ping++
支付流程:
4癞蚕,ping++,支持支付寶支付辉哥,微信支付桦山,銀聯(lián)支付,百度錢包支付醋旦,applepay
(1)根據(jù)呢需要介入的支付方式去對應(yīng)的支付平臺申請賬號和參數(shù)
(2)(恨不得直接上代碼了)恒水,傳說中的7行代碼搞定支付
Ping++有著前所未有的簡單,號稱7行代碼搞定支付
NSDictionary* dict = @{? ? @"channel" : channel, // 渠道 alipay, wx, upacp, bfb
@"amount"? : amount? // 金額};
NSData* data = [NSJSONSerialization dataWithJSONObject:dict options:NSJSONWritingPrettyPrinted error:nil];
NSString *bodyData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
[postRequest setHTTPBody:[NSData dataWithBytes:[bodyData UTF8String] length:strlen([bodyData UTF8String])]];
[postRequest setHTTPMethod:@"POST"];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:postRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSString* charge = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];? ? // ...
[Pingpp createPayment:charge viewController:viewController appURLScheme:kUrlScheme withCompletion:^(NSString *result, PingppError *error) {? ?
?if ([result isEqualToString:@"success"]) {? ? ? ? // ...
} else {? ? ??
? NSLog(@"PingppError: code=%lu msg=%@", error.code, [error getMsg]);
}
}];
}];
//AppDelegate添加這行代碼適用于監(jiān)聽支付結(jié)果的
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[Pingpp handleOpenURL:url withCompletion:^(NSString *result, PingppError *error) {? ? ? ? if ([result isEqualToString:@"success"]) {? ? ? ? ? ? // ...
} else {? ? ? ? ? ? NSLog(@"PingppError: code=%lu msg=%@", error.code, [error getMsg]);
}
}];? ? return? YES;
}
綜上所述饲齐,你可以跟你的個人需求來選擇接入支付方式
第三方支付钉凌,終究還是第三方,第三方站著公司和開發(fā)者的角度上考慮問題捂人,減少開發(fā)難度和成本御雕,不必要如此擔(dān)心。