iOS端移动支付的一些坑

已经很久没有写博客了,最近刚好工作比较轻松,希望能重新捡起来。

那么来简单说一下在iOS上做支付的一些东西 ( ̄▽ ̄*) 这里主要说支付宝和微信这样的第三方支付,像iOS本身的支付不做探究,话说,这个30%的过路费。。。简直不人道啊。。。。

  • 简单介绍
  • 支付宝SDK接入
  • 微信支付接入

简单介绍

移动支付在iOS中主要指使用支付宝或则微信支付(调起app进行支付),那么期间整体的流程应该是这样的:

iOS发起订单生成请求 -> 服务器生成订单信息 -> iOS端根据订单信息调用第三方支付的SDK -> 等待第三方SDK唤起app执行回调 -> 回调里获取支付的结果(支付成功/失败) -> 与服务器进行校验,确定交易是否成功(有可能支付成功了,但是交易失败)

流程确定好了,在最开始生成订单信息的时候,因为支付宝跟微信支付所需要的订单信息完全不同,当然,如果做银联支付或者内购功能的话,所需生成的订单信息也是完全不同的,毕竟是不同的第三方提供的SDK么ㄟ( ▔ —— ▔ )ㄏ

所以支付宝跟微信我接下来分开聊


支付宝SDK接入

iOS集成支付宝,其实在众多的第三方SDK中,支付宝的开发文档是真的很良心的,基本只要跟着开发文档走就能做完整个支付模块,开发文档要去蚂蚁金服里面找,这里给一下URL地址:支付宝开发文档

在这里我简单归纳一下下,就是在你需要进行支付的时候,支付模块需要访问一个API接口来获取订单信息,具体到支付宝所需要的订单信息有:

  1. appid :这个是申请的时候获取的,是支付模块的一个常量
  2. privateKey :跟appid一样,也是申请的时候拿到的,这个比较长,是一大串字符,注重安全的话,这些应该放到服务器上,然后做加密
  3. notify_url :这是一个坑(敲黑板),因为不写也可以走完支付的流程,但是支付成功之后你的服务端不会受到回调,也就是说付了钱,但是没有通知你的服务器说用户付钱啦.
  4. timestamp :时间戳,当前时间点,这个跟着demo走就行,没下demo的话就去看看开发文档的吧,要求yyyy-MM-dd HH:mm:ss这样的formatter
  5. version :这个是写好的1.0
  6. sign_type :RSA,这个指的是RSA签名规范,跟着demo走就好
  7. biz_content:商品的数据(这个是一个单独的类,而不是像上面的是一些NSString)

特别指出商品数据应该怎么来构建

// NOTE: 商品数据
order.biz_content = [BizContent new];
order.biz_content.body = @"我是测试数据";
order.biz_content.subject = @"1";
order.biz_content.out_trade_no = [self generateTradeNO]; //订单ID(由商家自行制定)
order.biz_content.timeout_express = @"30m"; //超时时间设置
order.biz_content.total_amount = [NSString stringWithFormat:@"%.2f", 0.01]; //商品价格

到这里其实订单的数据就已经准备好了,接下来做的是加密部分,加密完就可以调起支付宝SDK了

//将商品信息拼接成字符串
NSString *orderInfo = [order orderInfoEncoded:NO];
NSString *orderInfoEncoded = [order orderInfoEncoded:YES];

// NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露;
//       需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(privateKey);
NSString *signedString = [signer signString:orderInfo];

从上面的代码可以看到,加密之后字符串(orderInfoEncoded)与未加密的(orderInfo)是下面调起支付宝SDK要用到的,而signer只是用来判断是否订单信息是不是已经正确填写了if (signedString != nil)

//应用注册scheme,在AliSDKDemo-Info.plist定义URL types
NSString *appScheme = @"alisdkdemo";

// NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式
NSString *orderString = [NSString stringWithFormat:@"%@&sign=%@",
                             orderInfoEncoded, signedString];
// NOTE: 调用支付结果开始支付
[[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
    NSLog(@"reslut = %@",resultDic);
}];

上面代码块中的appScheme就是你app的scheme,当正确设置的时候,使用Safari打开网址scheme://会打开你的app,这里填写时为了在支付之后重新唤醒你的app.

调用SDK的callback回调block在支付宝回调你的app时并不会执行,app的回调我们接下来讲,这里的回调block会在当用户的iPhone并没有安装支付宝的时候,也就是支付宝SDK调起网页进行支付,不论用户直接返回还是正常进行支付流程,
当返回的时候会执行这个block里面的代码.

支付宝app的回调会执行AppDelgate的下面两个方法

//(iOS版本不同执行不同方法,iOS9以上会执行第一个方法....)
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
//iOS8调用这个方法
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;

但是两者的返回处理是一致的,返回方法参数里面url可以用来识别是不是支付宝调起的返回

if ([url.host isEqualToString:@"safepay"]){
    //是支付宝调起的返回,处理返回结果
    [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
     }];
}

那么iOS集成支付宝就说到这里.


微信支付接入

相对于支付宝专门做的支付SDK,微信支付是从属于微信SDK的一个功能模块,与微信SDK的交互其实跟使用微信SDK来做分享是一样一样的,都是使用了‘[WXApi sendReq:req];’这个方法。

但是跟微信分享不一样的地方在于,传入的req不再是SendMessageToWXReq了,而是PayReq了,当然PayReq也是继续至BaseReq的,照着开发文档来就好,这个如果是在已经有微信分享功能的app里面添加,甚至看看SDK代码和注释就好,根本用不着仔细看开发文档ㄟ( ▔, ▔ )ㄏ 。

下面来看看PayReq要怎么构造

PayReq* req             = [[PayReq alloc] init];
req.partnerId           = [data objectForKey:@"partnerid"];
req.prepayId            = [data objectForKey:@"prepayid"];
req.nonceStr            = [data objectForKey:@"noncestr"];
req.timeStamp           = [[data objectForKey:@"timestamp"] intValue];
req.package             = [data objectForKey:@"package"];
req.sign                = [data objectForKey:@"sign"];

跟支付宝不一样,微信支付的订单生成是服务端去做的(支付宝实际上服务端是生成订单信息,然后由支付宝的SDK调用来进行订单生成),所以在支付订单信息里面的timeStamp需要服务端生成订单时候的时间戳,而不是手机系统的时间戳。

构建好了request之后,调用WXApi来发送

    [WXApi sendReq:req];

接下来说说回调

跟支付宝的回到类似,微信SDK通过微信app唤起你的app,来进行回调,所以入口同样是下面的两个

//(iOS版本不同执行不同方法,iOS9以上会执行第一个方法....)
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
//iOS8调用这个方法
-(BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options;

而分辨方法在于:传参的url里面,微信的回调会返回你申请时候获取的APPID

/*** 微信回调(支付、登录、分享) ***/
//if is has prefix wx
if ([url.absoluteString hasPrefix:@"你的微信appId"]) {
    return[WXApi handleOpenURL:url delegate:self];
}

从上面的代码块可以看到,其实微信的支付、登录和分享都会共享回调,而分辨则是通过delegate来实现的,也就是说上面的代码块[WXApi handleOpenURL:url delegate:self];,你传入的delegate必须实现WXApiDelegate协议。

最重要的是实现下面的方法

/*! @brief 发送一个sendReq后,收到微信的回应
 *
 * 收到一个来自微信的处理结果。调用一次sendReq后会收到onResp。
 * 可能收到的处理结果有SendMessageToWXResp、SendAuthResp等。
 * @param resp具体的回应内容,是自动释放的
 */
-(void) onResp:(BaseResp*)resp;

其中,可以通过resp的类型判断来识别是什么操作的回调

if([resp isKindOfClass:[PayResp class]]){

    //支付成功!
    //这里只返回支付过程是否成功,但支付过后,可能会出现别的原因,导致交易失败,但是支付过程是成功的...
    if (resp.errCode == 0) {
    }
    else {

    }
    //这里应该拿着支付结果再进行API访问,校验交易结果
}

那么第三方支付这块就聊到这里吧。

猜你喜欢

转载自blog.csdn.net/u1031/article/details/73546617