支付宝支付流程

在iOS应用里集成支付宝支付,需要公司和支付宝签约,然后生成相应的密钥。密钥的生成支付宝的开发文档里已经说的非常清楚。

官方的文档和SDK:

https://doc.open.alipay.com/doc2/detail.htm?spm=a219a.7629140.0.0.zpWFOY&treeId=59&articleId=104352&docType=1


接口名称:AlipaySDK

接口描述:提供支付功能。

Alipay接口主要为商户提供订单支付功能。接口所提供的方法,如下表所示:

方法名称 方法描述
+(Alipay *)defaultService; 获取服务实例。
-(BOOL)isLogined; 检测本地是否曾登录使用过。
-(void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock; 支付并通过回调返回结果。

//【callback处理支付结果】

快捷订单支付iOS

方法名称:pay方法

方法原型:(void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;

方法功能:提供给商户快捷订单支付功能。

参数名称 参数描述
NSString* scheme 商户程序注册的URL protocol,供支付完成后回调商户程序使用。
(CompletionBlock)completionBlock 快捷支付开发包回调函数,返回免登、支付结果。本地未安装支付宝客户端,或未成功调用支付宝客户端进行支付的情况下(走H5收银台),会通过该completionBlock返回支付结果。相应的结果参考“同步通知参数说明”。
NSString* orderStr 主要包含商户的订单信息,key=“value”形式,以&连接。

支付参数示例如下,参数说明见“请求参数说明”:

1
partner= "2088101568358171" &seller_id= "[email protected]" &out_trade_no= "0819145412-6177" &subject= "测试" &body= "测试测试" &total_fee= "0.01" ¬ify_url= "http://notify.msp.hk/notify.htm" &service= "mobile.securitypay.pay" &payment_type= "1" &_input_charset= "utf-8" &it_b_pay= "30m" &sign= "lBBK%2F0w5LOajrMrji7DUgEqNjIhQbidR13GovA5r3TgIbNqv231yC1NksLdw%2Ba3JnfHXoXuet6XNNHtn7VE%2BeCoRO1O%2BR1KugLrQEZMtG5jmJIe2pbjm%2F3kb%2FuGkpG%2BwYQYI51%2BhA3YBbvZHVQBYveBqK%2Bh8mUyb7GM1HxWs9k4%3D" &sign_type= "RSA"


必须的参数:

service 接口名称 String 接口名称,固定值。 不可空 mobile.securitypay.pay 接口名称 String 接口名称,固定值
partner 合作者身份ID String(16) 签约的支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。 不可空 2088101568358171
     
_input_charset 参数编码字符集 String 商户网站使用的编码格式,固定为utf-8。 不可空 utf-8
sign_type 签名方式 String 签名类型,目前仅支持RSA。 不可空 RSA
sign 签名 String 请参见签名。 不可空
notify_url 服务器异步通知页面路径 String(200) 支付宝服务器主动通知商户网站里指定的页面http路径。 不可空 http://notify.msp.hk/notify.htm
out_trade_no 商户网站唯一订单号 String(64) 支付宝合作商户网站唯一订单号。 不可空 0819145412-6177
subject 商品名称 String(128) 商品的标题/交易标题/订单标题/订单关键字等。该参数最长为128个汉字。 不可空 测试
payment_type 支付类型 String(4) 支付类型。默认值为:1(商品购买)。 不可空 1
seller_id 卖家支付宝账号 String(16) 卖家支付宝账号(邮箱或手机号码格式)或其对应的支付宝唯一用户号(以2088开头的纯16位数字)。 不可空 [email protected]
total_fee 总金额 Number 该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。 不可空 0.01
body 商品详情 String(512) 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 不可空 测试测试

处理客户端返回url

方法名称:处理客户端方法

方法原型:-(void)processOrderWithPaymentResult:(NSURL*)resultUrl standbyCallback:(CompletionBlock)completionBlock;

方法功能:设备已安装支付宝客户端情况下,处理支付宝客户端返回的url。

注意:该方法必须实现,否则将会导致在安装手机支付宝的情况下,支付结果无法正常同步返回。

参数名称 参数描述
NSURL *resultUrl 支付宝客户端回传的url
CompletionBlock completionBlock 本地安装了支付宝客户端,且成功调用支付宝客户端进行支付的情况下,会通过该completionBlock返回支付结果

备注:请在APPDelegate的 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 中调用该方法,iOS9.0以上(包括iOS9.0)请在- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options 中调用该方法,具体可参见Demo。

回调接口

在支付过程结束后,会通过callbackBlock同步返回支付结果。

返回结果需要通过resultStatus以及result字段的值来综合判断并确定支付结果。在resultStatus=9000,并且success=“true”以及sign=“xxx”校验通过的情况下,证明支付成功。其它情况归为失败。较低安全级别的场合,也可以只通过检查resultStatus以及success=“true”来判定支付结果。以下为订单支付成功的完成信息示例:

1
2
3
4
5
{
     memo = "" ;
     result = "partner=\"2088101568358171\"&seller_id=\"[email protected]\"&out_trade_no=\"0819145412-6177\"&subject=\"测试\"&body=\"测试测试\"&total_fee=\"0.01\"¬ify_url=\"http://notify.msp.hk/notify.htm\"&service=\"mobile.securitypay.pay\"&payment_type=\"1\"&_input_charset=\"utf-8\"&it_b_pay=\"30m\"&success=\"true\"&sign_type=\"RSA\"&sign=\"hkFZr+zE9499nuqDNLZEF7W75RFFPsly876QuRSeN8WMaUgcdR00IKy5ZyBJ4eldhoJ/2zghqrD4E2G2mNjs3aE+HCLiBXrPDNdLKCZgSOIqmv46TfPTEqopYfhs+o5fZzXxt34fwdrzN4mX6S13cr3UwmEV4L3Ffir/02RBVtU=\"" ;
     resultStatus = "9000" ;
}

注意:

支付结果的提取,必须通过CompletionBlock获取,禁止开发者私自解析支付结果返回的URL。获取值的Key对应resultStatus、memo与result(result中的值,开发者可以自行解析);

为了保障已有商户的正常使用,返回参数ResultStatus首字母为大写。在新的SDK中已经用统一的工具类实现了ResultStatus到resultStatus的转换,商户从CompletionBlock中获取resultStatus即可。



其中参数说明:

请求参数说明:

  1. 商户在请求参数中,自己附属的一些额外参数,不要和支付宝系统中约定的key(下表中)重名,否则将可能导致未知的异常。
    比如请求参数格式 out_trade_no="1234566"&total_fee="123.5"&rn_check="TRE" 其中out_trade_no、total_fee、rn_check都是支付业务处理关键key,这个里面商户自己将out_trade_no、total_fee认为是支付宝必须传输的参数,rn_check=“TRE”是商户自己的业务数据,但是由于rn_check也是支付宝关键key,支付宝将会认为这个rn_check是支付宝业务的参数,将导致误解析,导致支付出现不可预料的异常。
  2. 支付宝建议,商户不要在请求参数中添加除了支付宝指定的关键key外,还有其他的key用&连接。
    比如 out_trade_no="1234566"&total_fee="123.5"&homepage="http://www.***.com" ,其中homepage是商户自己的业务key,支付宝建议不要在请求参数中附带和支付无关的业务系统自身的key相关数据。
  3. 商户的请求参数中,所有的key(支付宝关键key或者商户自己的key),其对应的value中都不应该出现支付宝关键key,比如out_trade_no、total_fee、seller_id等,否则该类交易将可能被支付宝拦截,禁止支付。
    比如如下的请求 out_trade_no="1234566"&total_fee="123.5"&homepage="http://www.***.com"&body="这个辣条不错 out_trade_no=123 total_fee=123.5"&memo="备忘seller_id=2088123213" 这个请求里面的body对应的value值中有支付宝关键key“out_trade_no”以及“total_fee”,请求中对于memo字段中含有seller_id,这样的业务请求参数支付宝将会拦截。
参数 参数名称 类型(字节长度) 参数说明 是否可为空 样例
service 接口名称 String 接口名称,固定值。 不可空 mobile.securitypay.pay
partner 合作者身份ID String(16) 签约的支付宝账号对应的支付宝唯一用户号。以2088开头的16位纯数字组成。 不可空 2088101568358171
_input_charset 参数编码字符集 String 商户网站使用的编码格式,固定为utf-8。 不可空 utf-8
sign_type 签名方式 String 签名类型,目前仅支持RSA。 不可空 RSA
sign 签名 String 请参见签名。 不可空 lBBK%2F0w5LOajrMrji7DUgEqNjIhQbidR13GovA5r3TgIbNqv231yC1NksLdw%2Ba3JnfHXoXuet6XNNHtn7VE%2BeCoRO1O%2BR1KugLrQEZMtG5jmJI
notify_url 服务器异步通知页面路径 String(200) 支付宝服务器主动通知商户网站里指定的页面http路径。 不可空 http://notify.msp.hk/notify.htm
app_id 客户端号 String 标识客户端。 可空 external
appenv 客户端来源 String 标识客户端来源。参数值内容约定如下:appenv=”system=客户端平台名^version=业务系统版本” 可空 appenv=”system=android^version=3.0.1.2”
out_trade_no 商户网站唯一订单号 String(64) 支付宝合作商户网站唯一订单号。 不可空 0819145412-6177
subject 商品名称 String(128) 商品的标题/交易标题/订单标题/订单关键字等。该参数最长为128个汉字。 不可空 测试
payment_type 支付类型 String(4) 支付类型。默认值为:1(商品购买)。 不可空 1
seller_id 卖家支付宝账号 String(16) 卖家支付宝账号(邮箱或手机号码格式)或其对应的支付宝唯一用户号(以2088开头的纯16位数字)。 不可空 [email protected]
total_fee 总金额 Number 该笔订单的资金总额,单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位。 不可空 0.01
body 商品详情 String(512) 对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 不可空 测试测试
goods_type 商品类型 String(1) 具体区分本地交易的商品类型。
1:实物交易;
0:虚拟交易。
默认为1(实物交易)。
可空 1
hb_fq_param 花呗分期参数 String Json格式。
hb_fq_num:花呗分期数,比如分3期支付;
hb_fq_seller_percent:卖家承担收费比例,比如100代表卖家承担100%。
两个参数必须一起传入。
具体花呗分期期数和卖家承担收费比例可传入的数值请咨询支付宝。
可空 {“hb_fq_num”:“3”,“hb_fq_seller_percent”:“100”}
rn_check 是否发起实名校验 String(1) T:发起实名校验;
F:不发起实名校验。
可空 T
it_b_pay 未付款交易的超时时间 String 设置未付款交易的超时时间,一旦超时,该笔交易就会自动被关闭。当用户输入支付密码、点击确认付款后(即创建支付宝交易后)开始计时。取值范围:1m~15d,或者使用绝对时间(示例格式:2014-06-13 16:00:00)。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。该参数数值不接受小数点,如1.5h,可转换为90m。 可空 30m
extern_token 授权令牌 String(32) 开放平台返回的包含账户信息的token(授权令牌,商户在一定时间内对支付宝某些服务的访问权限)。通过授权登录后获取的alipay_open_id,作为该参数的value,登录授权账户即会为支付账户。 可空 1b258b84ed2faf3e88b4d979ed9fd4db

说明:部分参数类型为String,未指明长度范围,表明系统不校验该参数的长度。

 

客户端返回码

更新时间:2015/10/15 访问次数:72374
返回码 含义
9000 订单支付成功
8000 正在处理中
4000 订单支付失败
6001 用户中途取消
6002 网络连接出错

导入代码

更新时间:2016/04/19 访问次数:78963

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

1
2
AlipaySDK.bundle
AlipaySDK.framework

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

image

其中,需要注意的是:

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

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

1
# import

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
NSAppTransportSecurity
    
         NSExceptionDomains
        
             alipay.com
            
                 NSIncludesSubdomains
                 < true />
                 NSTemporaryExceptionAllowsInsecureHTTPLoads
                 < true />
                 NSTemporaryExceptionMinimumTLSVersion
                 TLSv1. 0
                 NSTemporaryExceptionRequiresForwardSecrecy
                 < false />
            
             alipayobjects.com
            
                 NSIncludesSubdomains
                 < true />
                 NSTemporaryExceptionAllowsInsecureHTTPLoads
                 < true />
                 NSTemporaryExceptionMinimumTLSVersion
                 TLSv1. 0
                 NSTemporaryExceptionRequiresForwardSecrecy
                 < false />
            
        
    

说明:

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

1
2
3
4
NSAppTransportSecurity
        
         NSAllowsArbitraryLoads< true />
    

则上述的NSAppTransportSecurity可以不配置。

步骤4:配置请求信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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 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];
}
  • liSDKDemo\Order.m

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

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

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

1
# import

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (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;
}


步骤4:配置请求信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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 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文件中,增加引用代码:

1
# import

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (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;
}

你可能感兴趣的:(Objective-C)