支付宝业务相关(一) —— 支付宝支付集成(一)

版本记录

版本号 时间
V1.0 2017.05.24

前言

很多app都有支付和提现功能,而移动支付中支付宝、微信无疑是国内重要的支付平台和工具,最近有一个项目需要增加支付宝支付功能,这里就讲述下关于支付宝集成的问题,感兴趣的可以看一下。

支付宝支付业务流程

在说明支付宝原理之前,首先需要看的是支付宝支付的开发文档。
支付宝支付开发文档

下面我们就进入正题。

  • 创建应用:在开发平台创建一个应用,接入App支付能力,需要在开放平台创建一个应用,通过该应用来接入各种能力。可以根据下面:
    了解应用创建步骤
    开始创建应用
  • 配置应用
    • 为创建的应用添加所需功能。给应用添加App支付功能,这样就可以在你的应用里使用App支付能力。
      了解如何添加APP支付功能
      立即开始添加
    • 签约:在使用这些能力的时候,需要在开放平台里进行签约,这时候约定的合同就生效了。也可以代替商户签约。
    • 配置密匙:为了保证交易双方的身份和数据安全,需要配置双方密钥。
  • 设计
    • 接入设计:常用的接入方式与架构建议。在开始开发前,需要了解接入的方式或者材料等
    • 安全设计:为了保证交易安全,支付宝采用了一系列的安全手段。
  • 开发
    • SDK和开发语言:App支付为开发者提供了Android和iOS的客户端SDK, 为了验证交易数据的来源,开发者需要在商家后台对交易数据进行加签, 验签,那么就需要集成开放平台服务端SDK。
    • 集成客户端SDK:在集成App支付能力时,为主流移动平台的App提供集成方式。
    • 支付主流程:在集成App支付能力时,建议实现如下支付场景:(创建订单并支付,根据支付结果确定支付状态,并且做异常处理,必要时候关闭订单)。
    • 退款流程:商户由于业务原因可能需要退款,退款的途径按照支付途径原路返回. 支付渠道为花呗、余额等退款即时到账。银行卡的退款时间以银行退款时间为准,一般情况下2小时内可到账。也可以在商户门户(b.alipay.com)中退款。
    • 对账:为了保障交易的正确性,支付宝提供了交易账单数据提供给商户对账。
  • 调试应用:沙箱环境供调试使用,支付能力直接涉及到交易与资金,为了方便开放者调试支付能力,我们已经准备好沙箱环境,包括沙箱环境账号和沙箱版支付宝钱包,这样就可以在沙箱环境调试了。
  • 上线应用:上线应用所需步骤,商户本身应用上线时候,也要把支付宝开放平台的应用上线。

下面看一下支付流程图。

支付宝支付流程图

下面看一下支付原理图。

支付原理图

支付宝支付SDK和集成流程

下面我们先看一下支付宝的SDK。

支付宝SDK

下面说一下SDK的集成流程。

一、导入代码

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

AlipaySDK.bundle
AlipaySDK.framework

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

添加依赖库

其中,需要注意的是:

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

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

#import <AlipaySDK/AlipaySDK.h>

步骤3:组装请求信息。

这里需要注意:这一步应在商户服务端完成,商户服务端直接将组装和签名后的请求串orderString传给客户端,客户端直接传给SDK发起请求。文档和Demo是为了示例效果在客户端实现。

//将商品信息赋予AlixPayOrder的成员变量
Order* order = [Order new];
 
// NOTE: app_id设置
order.app_id = appID;
 
// NOTE: 支付接口名称
order.method = @"alipay.trade.app.pay";
 
// NOTE: 参数编码格式
order.charset = @"utf-8";
 
// NOTE: 当前时间点
NSDateFormatter* formatter = [NSDateFormatter new];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
order.timestamp = [formatter stringFromDate:[NSDate date]];
 
// NOTE: 支付版本
order.version = @"1.0";
 
// NOTE: sign_type设置
order.sign_type = @"RSA";
 
// 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]; //商品价格
 
//将商品信息拼接成字符串
NSString *orderInfo = [order orderInfoEncoded:NO];
NSString *orderInfoEncoded = [order orderInfoEncoded:YES];
NSLog(@"orderSpec = %@",orderInfo);
 
// NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露;
//       需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode
id<DataSigner> signer = CreateRSADataSigner(privateKey);
NSString *signedString = [signer signString:orderInfo];
 
// NOTE: 如果加签成功,则继续执行支付
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);
    }];
}

步骤4: 配置支付宝客户端返回url处理方法。(外部存在支付包钱包,支付宝钱包将处理结果通过url返回。)如示例AliSDKDemo\APAppDelegate.m文件中,增加引用代码:

#import <AlipaySDK/AlipaySDK.h>

在@implementation AppDelegate中以下代码中的NSLog改为实际业务处理代码:

- (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) {
            NSLog(@"result = %@",resultDic);
        }];
    }
    return YES;
}
 
// NOTE: 9.0以后使用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString*, id> *)options
{
    if ([url.host isEqualToString:@"safepay"]) {
        //跳转支付宝钱包进行支付,处理支付结果
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
        }];
    }
    return YES;
}

二、配置基本信息

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

SString *appid = @"";
NSString *privateKey = @"";

iOS基本信息配置表:

参数 含义
appid 应用ID,调用API时用来识别开发者。请参考创建应用并获取APPID
private_key 应用私钥,pkcs8格式。请参考配置密钥

注意:这些参数配置仅作为客户端示例使用。商户实际支付过程中参数需要放置在服务端,且整个签名过程必须在服务端进行。

三、代码示例运行逻辑

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

app_id=2015052600090779&biz_content={"timeout_express":"30m","seller_id":"","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.02","subject":"1","body":"我是测试数据","out_trade_no":"ZQLM3O56MJD4SK3"}&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2016-07-28 20:36:11&version=1.0

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

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

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

app_id=2015052600090779&biz_content={"timeout_express":"30m","seller_id":"","product_code":"QUICK_MSECURITY_PAY","total_amount":"0.02","subject":"1","body":"我是测试数据","out_trade_no":"ZQLM3O56MJD4SK3"}&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2016-07-28 20:36:11&version=1.0&sign=*********

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

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

步骤5:当这笔交易被买家支付成功后支付宝收银台上显示该笔交易成功,并提示用户“返回”。此时在APAppDelegate.m的 - (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<NSString, id> *)options 中执行 】。

[[AlipaySDK defaultService]
processOrderWithPaymentResult:url
standbyCallback:^(NSDictionary *resultDic) {
NSLog(@"result = %@",resultDic);//返回的支付结果
}];

注意:

  • 同步返回数据校验逻辑请参考
  • SDK付款有两种模式:如果外部存。

支付宝支付iOS调用说明

一、支付全部接口

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

二、快捷订单支付iOS

  • 方法名称:pay方法
  • 方法原型:(void)payOrder:(NSString *)orderStr fromScheme:(NSString *)schemeStr callback:(CompletionBlock)completionBlock;
  • 方法功能:提供给商户快捷订单支付功能。
快捷订单接口

orderStr示例如下:

app_id=2015052600090779&biz_content=%7B%22timeout_express%22%3A%2230m%22%2C%22seller_id%22%3A%22%22%2C%22product_code%22%3A%22QUICK_MSECURITY_PAY%22%2C%22total_amount%22%3A%220.02%22%2C%22subject%22%3A%221%22%2C%22body%22%3A%22%E6%88%91%E6%98%AF%E6%B5%8B%E8%AF%95%E6%95%B0%E6%8D%AE%22%2C%22out_trade_no%22%3A%22314VYGIAGG7ZOYY%22%7D&charset=utf-8&method=alipay.trade.app.pay&sign_type=RSA2&timestamp=2016-08-15%2012%3A12%3A15&version=1.0&sign=MsbylYkCzlfYLy9PeRwUUIg9nZPeN9SfXPNavUCroGKR5Kqvx0nEnd3eRmKxJuthNUx4ERCXe552EV9PfwexqW%2B1wbKOdYtDIb4%2B7PL3Pc94RZL0zKaWcaY3tSL89%2FuAVUsQuFqEJdhIukuKygrXucvejOUgTCfoUdwTi7z%2BZzQ%3D

三、处理客户端返回url

  • 方法名称:处理客户端方法
  • 方法原型:-(void)processOrderWithPaymentResult:(NSURL*)resultUrl standbyCallback:(CompletionBlock)completionBlock;
  • 方法功能:设备已安装支付宝客户端情况下,处理支付宝客户端返回的url。

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

处理客户端返回URL

备注:请在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<NSString, id> *)options 中调用该方法。

四、回调接口

在支付过程结束后,会通过callbackBlock同步返回支付结果(callbackBlock是调用支付同步的回调)。支付结果中参数的提取,必须通过CompletionBlock获取,禁止开发者私自解析支付结果返回的URL。


支付宝支付工程代码

下面我就以我写的代码说明支付宝支付的集成和实现。先看代码。

//从后台获取签名数据

- (void)requesstAlipaySignedString
{
    NSMutableDictionary *mutableDict = [NSMutableDictionary dictionary];
    [mutableDict setObject:@"0" forKey:@"chargeType"];
    [mutableDict setObject:self.cashNumTextField.text forKey:@"totalAmount"];
    
    [[JJNetWorkManager manager] requestByPostNetworkWithPayUrl:kalipayPharchase parameters:mutableDict success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        NSLog(@"responseObject--%@",responseObject);
        
        if ([[responseObject objectForKey:@"code"] integerValue] == 0) {
            self.dataDictM = [responseObject objectForKey:@"data"];
            self.alipayOrderStr = [self.dataDictM objectForKey:@"sign"];
            
            if (self.alipayOrderStr) {
                // NOTE: 调用支付结果开始支付
                [[AlipaySDK defaultService] payOrder:self.alipayOrderStr fromScheme:@"ZebraChat" callback:^(NSDictionary *resultDic) {
                    NSLog(@"resultDic = %@",resultDic);                    
                }];
            }
        }
        
    } error:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"error--%@",error);
    }];
}

下面的代码就是的AppDelegate中了。

//配置支付宝客户端返回url处理方法

- (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) {
            NSLog(@"result = %@",resultDic);
        //在这里获得支付结果,发送通知给相应的服务器更新余额
        }];
        return YES;
    }
    
    if ([url.host isEqualToString:@"platformapi"])//支付宝钱包快登授权返回 authCode
    {
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
        }];
        
        return YES;
    }
    return NO;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
    //支付宝
    if ([url.host isEqualToString:@"safepay"]) {
        //跳转支付宝钱包进行支付,处理支付结果
        [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
        }];
        return YES;
    }
    
    if ([url.host isEqualToString:@"platformapi"])//支付宝钱包快登授权返回 authCode
    {
        [[AlipaySDK defaultService] processAuthResult:url standbyCallback:^(NSDictionary *resultDic) {
            NSLog(@"result = %@",resultDic);
        }];
        
        return YES;
    }
    //这里判断是否发起的请求为微信支付,如果是的话,用WXApi的方法调起微信客户端的支付页面(://pay 之前的那串字符串就是你的APPID,)
    return  [WXApi handleOpenURL:url delegate:self];
}

下面看结果图。

输入充值金额
确认订单信息
输入支付密码
交易记录查询

后记

  到此为止,主要的和支付相关的我都写完了,涉及到微信,内购,支付宝这三种支付方式,后续如有需要我还会添加其他的支付方式,比如银联支付等,有什么不对的地方希望大家能够批评指出。

山水之乐
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,487评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,621评论 2 374
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,611评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,659评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,509评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,380评论 1 274
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,799评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,443评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,739评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,781评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,554评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,400评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,811评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,043评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,330评论 1 253
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,775评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,978评论 2 337

推荐阅读更多精彩内容