iOS开发 - 开发支付篇
iOS 开发支付篇
随着互联网的发展,电商平台已经成为人们的习惯一种生活方式,电商个人认为站在开发的角度看,也就多了一个购物车和支付,而支付称为很多刚接触电商平台开发人员很向往的一个技术点,那么现在我讲自己了解的当前所有支付方式以及如何使用分享给大家。
支付宝支付:
支付流程 :
(1)先与支付宝签约,获取商户id(partner)和账号id(seller)
(2)下载相应的公私钥文件(加密签名使用),在客户端我们可能只需要私钥
(3)下载支付宝sdk
(4)生成订单信息,可以直接客户端或者自己服务端生存都可以,但是大多是服务端生存的。
(5)调用支付宝客户端,有支付宝客户端跟支付宝打交道
(6)支付完毕之后返回结果给客户端和服务端。
//回到本应用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];
// 商品标题
order.productName=pruduct.subject;
// 商品描述
order.productDescription =pruduct.body;
//商品价格
order.amount=[NSString stringWithFormat:@"%.2f",pruduct.price];
order.notifyURL = @"http%3A%2F%2Fwwww.xxx.com"; //回调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)注册微信开放平台,创建应用获取appid,appSecret,申请支付功能,申请成功之后会返回一些参数详情见图
(2)下载微信支付sdk
(3)客户端请求订单,后台与微信后台交互,返回给客户端支付参数;
(4)调用微信客户端,由微信客户端和微信服务器打交道;
(5)客户端和服务端都会收到支付结果;(前台消息不可靠,我们需要去后台验证,如果后台没有收到支付通知,后台去微信服务器验证然后将结果返回给客户端)
//需要的依赖库,环境搭建可以参见文档,或者直接用cocoapods倒入
/**
* 微信开放平台申请得到的 appid, 需要同时添加在 URL schema
*/
NSString * const WXAppId = @"wxd930ea5d5a258f4f";
/**
* 微信开放平台和商户约定的支付密钥
*
* 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
*/
NSString * const WXAppKey = @"L8LrMqqeGRxST5reouB0K66CaYAWpqhAVsq7ggKkxHCOastWksvuX1uvmvQclxaHoYd3ElNBrNO2DHnnzgfVG9Qs473M3DTOZug5er46FhuGofumV8H2FVR9qkjSlC5K";
/**
* 微信开放平台和商户约定的密钥
*
* 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
*/
NSString * const WXAppSecret = @"db426a9829e4b49a0dcac7b4162da6b6";
/**
* 微信开放平台和商户约定的支付密钥
*
* 注意:不能hardcode在客户端,建议genSign这个过程由服务器端完成
*/
NSString * const WXPartnerKey = @"8934e7d15453e97507ef794cf7b0519d";
/**
* 微信公众平台商户模块生成的ID
*/
NSString * const WXPartnerId = @"1900000109";
调用支付的代码就比较简单了,如下所示
#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];
// 文档: 详细的订单数据放在 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];
//获取到了支付参数
if (error) {
[weakSelf showAlertWithTitle:@"错误" msg:@"获取 PrePayId 失败"];
return;
} else {
NSLog(@"--- %@", [weakRequest responseString]);
}
NSString *prePayId = dict[PrePayIdKey];
if (prePayId) {
NSLog(@"--- PrePayId: %@", prePayId);
// 调起微信支付
//将支付参数传入到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];
// 构造参数列表
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];
// 在支付之前,如果应用没有注册到微信,应该先调用 [WXApi registerApp:appId] 将应用注册到微信
[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,直接调用getAccessToken方法即可完成支付
银联支付:
支付流程:
(1)注册申请就不是前端的事了,直接介入sdk
(2)从自己的服务端获取流水号
(3)然后调用银联sdk,不用跳转,银联sdk直接是内嵌的
(4)支付完成之后会回调代理方法
银联支付在客户端实现起来最简单的,现在介绍一下客户端如何实现 ,以及实现代码
- (void)viewDidLoad {
[super viewDidLoad];
//开始支付
//第一个参数是流水号,又后台返回给我们 第二个参数传00,01,00标示正式环境,01标示测试环境,第三个参数是支付完成回到的控制器,第四个参数是设置代理
[UPPayPlugin startPay:@"57855654" mode:@"01" viewController:self.navigationController delegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
//监听支付结果
- (void)UPPayPluginResult:(NSString *)result
{
}
//银联支付将复杂操作全部放在了后台,我们使用相当方便
当然下面才是最常用的,它集成所有支付功能于一身:Ping++
支付流程:
4,ping++,支持支付宝支付,微信支付,银联支付,百度钱包支付,applepay
(1)根据呢需要介入的支付方式去对应的支付平台申请账号和参数
(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添加这行代码适用于监听支付结果的
- (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;
}
综上所述,你可以跟你的个人需求来选择接入支付方式
第三方支付,终究还是第三方,第三方站着公司和开发者的角度上考虑问题,减少开发难度和成本,不必要如此担心