Alipay, China's leading third-party online payment solutionAlipay, China's leading third-party online payment solutionDOCS

      iOS

      #导入代码

      步骤1: 启动IDE(如Xcode),把iOS包中的压缩文件中以下文件拷贝到项目文件夹下,并导入到项目工程中。

      copy
      AlipaySDK.bundle
      AlipaySDK.framework

      在Build Phases选项卡的Link Binary With Libraries中,增加以下依赖:

      iOS

      其中,需要注意的是:

      ·      如果是Xcode 7.0之后的版本,需要添加libc++.tbd、libz.tbd;

      ·      如果是Xcode 7.0之前的版本,需要添加libc++.dylib、libz.dylib(如下图)。

      iOS

      步骤2:在需要调用AlipaySDK的文件中,增加头文件引用。

      copy
      #import <AlipaySDK/AlipaySDK.h>

      步骤3:如果你的app基于9.0编译,那么为了适配iOS9.0中的App Transport Security(ATS)对http的限制,这里需要对支付宝的请求地址alipay.com、alipayobjects.com做例外,在app对应的info.list中添加如下配置(文中以XML格式描述)。

      copy
      <key>NSAppTransportSecurity</key>
          <dict>
              <key>NSExceptionDomains</key>
              <dict>
                  <key>alipay.com</key>
                  <dict>
                      <key>NSIncludesSubdomains</key>
                      <true/>
                      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                      <true/>
                      <key>NSTemporaryExceptionMinimumTLSVersion</key>
                      <string>TLSv1.0</string>
                      <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
                      <false/>
                  </dict>
                  <key>alipayobjects.com</key>
                  <dict>
                      <key>NSIncludesSubdomains</key>
                      <true/>
                      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                      <true/>
                      <key>NSTemporaryExceptionMinimumTLSVersion</key>
                      <string>TLSv1.0</string>
                      <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
                      <false/>
                  </dict>
              </dict>
          </dict>

      注意:

      如果商户配置了如下的配置:

      copy
      <key>NSAppTransportSecurity</key>
          <dict>
              <key>NSExceptionDomains</key>
              <dict>
                  <key>alipay.com</key>
                  <dict>
                      <key>NSIncludesSubdomains</key>
                      <true/>
                      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                      <true/>
                      <key>NSTemporaryExceptionMinimumTLSVersion</key>
                      <string>TLSv1.0</string>
                      <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
                      <false/>
                  </dict>
                  <key>alipayobjects.com</key>
                  <dict>
                      <key>NSIncludesSubdomains</key>
                      <true/>
                      <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
                      <true/>
                      <key>NSTemporaryExceptionMinimumTLSVersion</key>
                      <string>TLSv1.0</string>
                      <key>NSTemporaryExceptionRequiresForwardSecrecy</key>
                      <false/>
                  </dict>
              </dict>
          </dict>

      则上述的NSAppTransportSecurity可以不配置。

      步骤 4: 配置请求信息。

      copy
      Order *order = [[Order alloc] init];
      order.partner = partner;
      order.seller = seller;
      order.tradeNO = [self generateTradeNO]; //订单 ID (由商家自行制定)
      order.productName = product.subject; //商品标题
      order.productDescription = product.body; //商品描述
      order.amount = [NSString stringWithFormat:@"%.2f",product.price]; //商品价格
      order.notifyURL = @"http://www.test.com"; //回调 URL 
      order.service = @"mobile.securitypay.pay";
      order.paymentType = @"1";
      order.inputCharset = @"utf-8";
      order.itBPay = @"30m";
       
      //应用注册scheme,在AlixPayDemo-Info.plist定义URL types
      NSString *appScheme = @"alisdkdemo";
          
      //将商品信息拼接成字符串
      NSString *orderSpec = [order description];
      NSLog(@"orderSpec = %@",orderSpec);
       
      //获取私钥并将商户信息签名,外部商户可以根据情况存放私钥和签名,只需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
      id<DataSigner> signer = CreateRSADataSigner(privateKey);
      NSString *signedString = [signer signString:orderSpec];
          
      //将签名成功字符串格式化为订单字符串,请严格按照该格式
      NSString *orderString = nil;
      if (signedString != nil) {
         orderString = [NSString stringWithFormat:@"%@&sign=\"%@\"&sign_type=\"%@\"",
                             orderSpec, signedString, @"RSA"];
               
         [[AlipaySDK defaultService] payOrder:orderString fromScheme:appScheme callback:^(NSDictionary *resultDic) {
      //【callback处理支付结果】
                  NSLog(@"reslut = %@",resultDic);
         }];
               
         [tableView deselectRowAtIndexPath:indexPath animated:YES];
      }

      详细可参见Demo中示例文件

      ·      AliSDKDemo\APViewController.h

      ·      AliSDKDemo\APViewController.m

      ·      AliSDKDemo\Order.h

      ·      AliSDKDemo\Order.m


      步骤 5: 配置支付宝客户端返回url处理方法。

      (外部存在支付包钱包,支付宝钱包将处理结果通过url返回。)

      如示例AliSDKDemo\APAppDelegate.m文件中,增加引用代码:

      copy
      #import <AlipaySDK/AlipaySDK.h>

      在@implementation AppDelegate中增加如下代码:

      copy
      - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
      {
       
          //如果极简开发包不可用,会跳转支付宝钱包进行支付,需要将支付宝钱包的支付结果回传给开发包 
          if ([url.host isEqualToString:@"safepay"]) {
              [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
          //【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
                  NSLog(@"result = %@",resultDic);
              }];
          }
          if ([url.host isEqualToString:@"platformapi"]){支付宝钱包快登授权返回authCode
        
              [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
                   //【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
                  NSLog(@"result = %@",resultDic);
              }];
          }
          return YES;
      }

      #针对Demo的运行注意

      1、关于签名代码问题


      ·      AliSDKDemo\Util and all files thereunder

      ·      AliSDKDemo\openssl and all files thereunder

      ·      libcrypto.a

      ·      libssl.a

      这些文件是为示例签名所在客户端本地使用。出于安全考虑,请商户尽量把私钥保存在服务端,在服务端进行签名验签。

      2、如果遇到运行后报错,类似于以下提示信息:

      copy
      Cannot find API declaration for 'NSObject', superclass of 'Base64'

      那么需要打开报错了的文件,增加头文件。

      copy
      #import <Foundation/Foundation.h>

      3、 如果商户要在某个文件中使用支付宝的开发包类库,需增加引用头文件。

      copy
      #import <AlipaySDK/AlipaySDK.h>

      4、点击项目名称,点击“Build Settings”选项卡,在搜索框中,以关键字“search”搜索,对“Header Search Paths”增加头文件路径:$(SRCROOT)/项目名称。如果头文件信息已增加,可不必再增加。

      iOS


      5、点击项目名称,点击“Build Phases”选项卡,在“Link Binary with Librarles”选项中,新增“AlipaySDK.framework”和“SystemConfiguration.framework”两个系统库文件。如果商户项目中已有这两个库文件,可不必再增加。

      iOS


      6、点击项目名称,点击“Info”选项卡,在“URL Types”选项中,点击“+”,在“URL Schemes”中输入“alisdkdemo”。“alisdkdemo”来自于文件“APViewController.m”的NSString *appScheme = @“alisdkdemo”;。

      注意:

      这里的URL Schemes中输入的alisdkdemo,为测试demo,实际商户的app中要填写独立的scheme,建议跟商户的app有一定的标示度,要做到和其他的商户app不重复,否则可能会导致支付宝返回的结果无法正确跳回商户app。

      iOS

      #配置基本信息

      打开“APViewController.m”文件,对以下三个参数进行编辑:

      copy
      NSString *partner = @"";
      NSString *seller = @"";
      NSString *privateKey = @"";

      iOS基本信息配置表:

      ParametersImplication
      partner合作身份者ID,以2088开头由16位纯数字组成的字符串。
      seller支付宝收款账号,手机号码或邮箱格式。
      private_key商户方的私钥,pkcs8格式。请参考RSA私钥及公钥生成

      注意:

      这些参数配置是为客户端签名功能服务的,仅作为示例使用。商户在接入支付宝产品时,请把这些信息通过商户项目自己的服务端传递。

      #代码示例运行逻辑

      步骤 1: 调用order.m里的函数description将商品信息拼接成字符串作为待签名字符串,如:

      copy
      "partner=\"2088101568353491\"&seller_id=\"2088101568353491\"&out_trade_no=\"YR2VGG3G1I31XDZ\"&subject=\"1\"&body=\"test\"&total_fee=\"0.02\"&notify_url=\"http://www.test.com\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\""

      步骤 2: 使用类CreateRSADataSigner,调用signString签名函数做签名,如:

      copy
      "GsSZgPloF1vn52XAItRAldwQAbzIgkDyByCxMfTZG%2FMapRoyrNIJo4U1LUGjHp6gdBZ7U8jA1kljLPqkeGv8MZigd3kH25V0UK3Jc3C94Ngxm5S%2Fz5QsNr6wnqNY9sx%2Bw6DqNdEQnnks7PKvvU0zgsynip50lAhJmflmfHvp%2Bgk%3D"

      步骤 3: 把签名结果赋值给参数sign,并把sign加入之前的待签名数组中,此时得到的便是要请求给支付宝的全部数据。

      copy
      "partner=\"2088101568353491\"&seller_id=\"2088101568353491\"&out_trade_no=\"YR2VGG3G1I31XDZ\"&subject=\"1\"&body=\"test\"&total_fee=\"0.02\"&notify_url=\"http://www.test.com\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\"&sign=\"GsSZgPloF1vn52XAItRAldwQAbzIgkDyByCxMfTZG%2FMapRoyrNIJo4U1LUGjHp6gdBZ7U8jA1kljLPqkeGv8MZigd3kH25V0UK3Jc3C94Ngxm5S%2Fz5QsNr6wnqNY9sx%2Bw6DqNdEQnnks7PKvvU0zgsynip50lAhJmflmfHvp%2Bgk%3D\"&sign_type=\"RSA\""

      步骤 4: 调用(AlipaySDK *)defaultService类下面的支付接口函数,唤起支付宝支付页面。

      copy
      (void)payOrder:(NSString *)orderStr
        fromScheme:(NSString *)schemeStr
          callback:(CompletionBlock)completionBlock

      appScheme为app在info.plist注册的scheme。

      支付宝支付页面:

      iOS

      后面的动作全由买家在支付宝收银台中操作完成。如果设备中有支付宝客户端,会优先调用支付宝客户端进行支付,支付完成后会重新唤起商户app。


      步骤 5: 当这笔交易被买家支付成功后支付宝收银台上显示该笔交易成功,并提示用户“返回”。此时在APAppDelegate.m的 - (BOOL)application:(UIApplication )application openURL:(NSURL )url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 中调用获取返回数据的代码:

      copy
      [[AlipaySDK defaultService]
      processOrderWithPaymentResult:url
      standbyCallback:^(NSDictionary *resultDic) {
      NSLog(@"result = %@",resultDic);//返回的支付结果
      //【由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理,就是在这个方法里面处理跟callback一样的逻辑】
      }];

      #拿到返回数据

      点击取消返回

      copy
      "alisdkdemo://safepay/?%7B%22memo%22:%7B%22result%22:%22%22,%22memo%22:%22%E7%94%A8%E6%88%B7%E4%B8%AD%E9%80%94%E5%8F%96%E6%B6%88%22,%22ResultStatus%22:%226001%22%7D,%22requestType%22:%22safepay%22%7D"
        • 对其做 URLDecode
      copy
      "alisdkdemo://safepay/?{"memo":{"result":"","memo":"用户中途取消","ResultStatus":"6001"},"requestType":"safepay"}"
        • 点确认后返回
      copy
      "alisdkdemo://safepay/?%7B%22memo%22:%7B%22result%22:%22partner=%5C%222088101568353491%5C%22&seller_id=%5C%222088101568353491%5C%22&out_trade_no=%5C%22QU6ZOD85K4HVQFN%5C%22&subject=%5C%221%5C%22&body=%5C%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%5C%22&total_fee=%5C%220.02%5C%22&notify_url=%5C%22http:%5C/%5C/www.test.com%5C%22&service=%5C%22mobile.securitypay.pay%5C%22&payment_type=%5C%221%5C%22&_input_charset=%5C%22utf-8%5C%22&it_b_pay=%5C%2230m%5C%22&success=%5C%22true%5C%22&sign_type=%5C%22RSA%5C%22&sign=%5C%22pg16DPA%5C/cIRg1iUFCl8lYZG54de+kfw+vCj32hGWye97isZ1A4bW6RNaDXHhZXVaI5Vk2YDxhNUl85EHRd+EL7%5C/+ogQTnsaEHl+D13PuZExIXRKGBnkYqaNV6kH6hDygnf5IOtoojHWLQyem7oRBVzB0vlF%5C/+YGFpzFHZyTVpM8=%5C%22%22,%22memo%22:%22%22,%22ResultStatus%22:%229000%22%7D,%22requestType%22:%22safepay%22%7D"
        • 对其做 URLDecode
      copy
      "alisdkdemo://safepay/?{"memo":{"result":"partner=\"2088101568353491\"&seller_id=\"2088101568353491\"&out_trade_no=\"QU6ZOD85K4HVQFN\"&subject=\"1\"&body=\"test\"&total_fee=\"0.02\"&notify_url=\"http:\/\/www.test.com\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\"&success=\"true\"&sign_type=\"RSA\"&sign=\"pg16DPA\/cIRg1iUFCl8lYZG54de+kfw+vCj32hGWye97isZ1A4bW6RNaDXHhZXVaI5Vk2YDxhNUl85EHRd+EL7\/+ogQTnsaEHl+D13PuZExIXRKGBnkYqaNV6kH6hDygnf5IOtoojHWLQyem7oRBVzB0vlF\/+YGFpzFHZyTVpM8=\"","memo":"","ResultStatus":"9000"},"requestType":"safepay"}"
        • 之后,对这些数据做处理。

      注意:

      由于在跳转支付宝客户端支付的过程中,商户app在后台很可能被系统kill了,所以pay接口的callback就会失效,请商户对standbyCallback返回的回调结果进行处理;

      同步返回数据时,建议通过服务端的验签功能代码做验签处理,之后再对返回的数据做业务逻辑处理;

      须以服务器异步通知的结果数据为准,并对其做业务逻辑处理;

      SDK付款有两种模式:如果外部存在支付宝钱包,则直接跳转到支付宝钱包付款;不存在的场景下,在SDK内部进行H5支付。测试同学需要关注这两类测试场景。