iOS之app中接入支付宝的流程解析(一)

第一步:创建应用并获取APPID,添加应用功能

要在您的应用中使用支付宝开放产品的接口能力,您需要先去蚂蚁金服开放平台(open.alipay.com),在开发者中心中创建登记您的应用,并提交审核,审核通过后会为您生成应用唯一标识(APPID),并且可以申请开通开放产品使用权限,通过APPID您的应用才能调用开放产品的接口能力。

1.添加应用功能

某些功能必须签约才能使用:签约 如下:





























              应用上线后,可选择自己使用和推广给他人使用。供他人使用指的是应用开发者和应用使用者不是同一个人。使用者在使用应用前,需要做两件事情:授权、签约(如果应用中包含需要签约的功能则需要签约,不包含则不需要)
开发者和使用者的区别,开发者:应用(功能或者服务)的开发人员(或者企业),使用者:购买和使用应用(功能或者服务)的人员(或者企业)。当开发者自己使用自己开发的应用时,开发者和使用者的两个身份是重合的。

商户(例如:是某个电商网站)对开发者进行应用授权后,开发者可以帮助商户完成相应的业务逻辑,例如代替商户发起当面付的收单请求。

2、授权采用标准的OAuth 2.0流程。

3、要进行第三方调用,开发者需要在应用中添加对应功能并获得商户授权,商户需要申请开通相应的权限(例如对于当面付,开发者只需在应用中添加“当面付”功能并获得商户授权,商户则需要开通“当面付”产品,之后开发者就可以帮助商户发起当面付的收单请求)。










必须填写“接口加密方式”(加密方式只需填写一个),才可以提交审核。


第二步:配置密钥


上传应用公钥并获取支付宝公钥,(https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.TvAv9s&treeId=291&articleId=105972&docType=1);支付宝公钥内容,在代码中验签使用。


服务端的SDK,签名和验签(https://doc.open.alipay.com/docs/doc.htm?treeId=54&articleId=103419&docType=1);


开发者调用接口前需要先生成RSA密钥,RSA密钥包含应用私钥(APP_PRIVATE_KEY)、应用公钥(APP_PUBLIC_KEY)。生成密钥后在开放平台开发者中心进行密钥配置,配置完成后可以获取支付宝公钥(ALIPAY_PUBLIC_KEY)。


生成RSA密钥

支付宝提供一键生成工具便于开发者生成一对RSA密钥,可通过下方链接下载密钥生成工具:

WINDOWS

MAC_OSX

下载该工具后,解压打开文件夹,运行“RSA签名验签工具.bat”(WINDOWS)或“RSA签名验签工具.command”(MAC_OSX)。

界面示例:

详细步骤:

1.根据开发语言选择密钥格式。

2.选择密钥长度,建议使用2048位。

3.点击 “生成密钥”,会自动生成商户应用公钥和应用私钥。

4.点击“打开密钥文件路径”,即可找到生成的公私钥。如图:

生成的私钥需妥善保管,避免遗失,不要泄露。应用私钥需填写到代码中供签名时使用。应用公钥需提供给支付宝账号管理者上传到支付宝开放平台

除了使用支付宝提供的一键生成密钥工具外,也可以使用OpenSSL工具命令生成密钥。步骤如下:

使用OpenSSL工具生成密钥

更新时间:2016/12/22  访问次数:5028

除了使用支付宝提供的一键生成工具外,也可以使用OpenSSL工具(下载地址https://www.openssl.org/source/?spm=a219a.7629140.0.0.b0VRLV)命令生成密钥。

第一步 生成RSA密钥

首先进入OpenSSL工具,输入以下命令。

1
2
3
4
OpenSSL> genrsa -out app_private_key.pem   1024  #生成私钥
OpenSSL> pkcs8 -topk8 -inform PEM -in app_private_key.pem -outform PEM -nocrypt -out app_private_key_pkcs8.pem #Java开发者需要将私钥转换成PKCS8格式
OpenSSL> rsa -in app_private_key.pem -pubout -out app_public_key.pem #生成公钥
OpenSSL> exit #退出OpenSSL程序

经过以上步骤,开发者可以在当前文件夹中(OpenSSL运行文件夹),看到app_private_key.pem(开发者RSA私钥,非Java语言适用)、app_private_key_pkcs8.pem(pkcs8格式开发者RSA私钥,Java语言适用)和app_public_key.pem(开发者RSA公钥)3个文件。开发者将私钥保留,将公钥提交给支付宝配置到开发平台,用于验证签名。以下为私钥文件和公钥文件示例。

TIPS:对于使用Java的开发者,需将生成的pkcs8格式的私钥去除头尾、换行和空格,作为私钥填入代码中,对于.NET和PHP的开发者来说,无需进行pkcs8命令行操作。 

标准的私钥文件示例(PHP、.NET使用)

1
2
3
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC+L0rfjLl3neHleNMOsYTW8r0QXZ5RVb2p/vvY3fJNNugvJ7lo4+fdBz+LN4mDxTz4MTOhi5e2yeAqx+v3nKpNmPzC5LmDjhHZURhwbqFtIpZD51mOfno2c3MDwlrsVi6mTypbNu4uaQzw/TOpwufSLWF7k6p2pLoVmmqJzQiD0QIDAQABAoGAakB1risquv9D4zX7hCv9MTFwGyKSfpJOYhkIjwKAik7wrNeeqFEbisqv35FpjGq3Q1oJpGkem4pxaLVEyZOHONefZ9MGVChT/MNH5b0FJYWl392RZy8KCdq376Vt4gKVlABvaV1DkapL+nLh7LMo/bENudARsxD55IGObMU19lkCQQDwHmzWPMHfc3kdY6AqiLrOss+MVIAhQqZOHhDe0aW2gZtwiWeYK1wB/fRxJ5esk1sScOWgzvCN/oGJLhU3kipHAkEAysNoSdG2oWADxlIt4W9kUiiiqNgimHGMHPwp4JMxupHMTm7D9XtGUIiDijZxunHv3kvktNfWj3Yji0661zHVJwJBAM8TDf077F4NsVc9AXVs8N0sq3xzqwQD/HPFzfq6hdR8tVY5yRMb4X7+SX4EDPORKKsgnYcur5lk8MUi7r072iUCQQC8xQvUne+fcdpRyrR4StJlQvucogwjTKMbYRBDygXkIlTJOIorgudFlrKP/HwJDoY4uQNl8gQJb/1LdrKwIe7FAkBl0TNtfodGrDXBHwBgtN/t3pyi+sz7OpJdUklKE7zMSBuLd1E3O4JMzvWP9wEE7JDb+brjgK4/cxxUHUTkk592
-----END RSA PRIVATE KEY-----

PKCS8处理后的私钥文件示例(Java使用)

1
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN0yqPkLXlnhM+2H/57aHsYHaHXazr9pFQun907TMvmbR04wHChVsKVgGUF1hC0FN9hfeYT5v2SXg1WJSg2tSgk7F29SpsF0I36oSLCIszxdu7ClO7c22mxEVuCjmYpJdqb6XweAZzv4Is661jXP4PdrCTHRdVTU5zR9xUByiLSVAgMBAAECgYEAhznORRonHylm9oKaygEsqQGkYdBXbnsOS6busLi6xA+iovEUdbAVIrTCG9t854z2HAgaISoRUKyztJoOtJfI1wJaQU+XL+U3JIh4jmNx/k5UzJijfvfpT7Cv3ueMtqyAGBJrkLvXjiS7O5ylaCGuB0Qz711bWGkRrVoosPM3N6ECQQD8hVQUgnHEVHZYtvFqfcoq2g/onPbSqyjdrRu35a7PvgDAZx69Mr/XggGNTgT3jJn7+2XmiGkHM1fd1Ob/3uAdAkEA4D7aE3ZgXG/PQqlm3VbE/+4MvNl8xhjqOkByBOY2ZFfWKhlRziLEPSSAh16xEJ79WgY9iti+guLRAMravGrs2QJBAOmKWYeaWKNNxiIoF7/4VDgrcpkcSf3uRB44UjFSn8kLnWBUPo6WV+x1FQBdjqRviZ4NFGIP+KqrJnFHzNgJhVUCQFzCAukMDV4PLfeQJSmna8PFz2UKva8fvTutTryyEYu+PauaX5laDjyQbc4RIEMU0Q29CRX3BA8WDYg7YPGRdTkCQQCG+pjU2FB17ZLuKRlKEdtXNV6zQFTmFc1TKhlsDTtCkWs/xwkoCfZKstuV3Uc5J4BNJDkQOGm38pDRPcUDUh2/

公钥文件示例

1
2
3
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQWiDVZ7XYxa4CQsZoB3n7bfxLDkeGKjyQPt2FUtm4TWX9OYrd523iw6UUqnQ+Evfw88JgRnhyXadp+vnPKP7unormYQAfsM/CxzrfMoVdtwSiGtIJB4pfyRXjA+KL8nIa2hdQy5nLfgPVGZN4WidfUY/QpkddCVXnZ4bAUaQjXQIDAQAB
-----END PUBLIC KEY-----

第二步 处理应用公钥格式

将公钥文件去除头尾、换行和空格,转成一行字符串。把该字符串提供给支付宝账号管理者,登录开放平台上传应用公钥并获取支付宝公钥。教程

例如转换前公钥pem文件格式:

1
2
3
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQWiDVZ7XYxa4CQsZoB3n7bfxLDkeGKjyQPt2FUtm4TWX9OYrd523iw6UUqnQ+Evfw88JgRnhyXadp+vnPKP7unormYQAfsM/CxzrfMoVdtwSiGtIJB4pfyRXjA+KL8nIa2hdQy5nLfgPVGZN4WidfUY/QpkddCVXnZ4bAUaQjXQIDAQAB
-----END PUBLIC KEY-----

转换后得到的字符串为:

1
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQWiDVZ7XYxa4CQsZoB3n7bfxLDkeGKjyQPt2FUtm4TWX9OYrd523iw6UUqnQ+Evfw88JgRnhyXadp+vnPKP7unormYQAfsM/CxzrfMoVdtwSiGtIJB4pfyRXjA+KL8nIa2hdQy5nLfgPVGZN4WidfUY/QpkddCVXnZ4bAUaQjXQIDAQAB

第三步 处理支付宝公钥格式(针对文本读取方式)

上一步获取到支付宝公钥,用于支付宝返回数据的验签。

对于支付宝公钥,看到的是一个字符串,如下:

1
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB

如果需要使用文件方式(如PHP/.NET版本)读取支付宝公钥,需要在头尾加入标示后保存至文件,文件内容如下:

1
2
3
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB
-----END PUBLIC KEY-----

第三步:搭建和配置开发环境

接入移动支付需要集成两个SDK,客户端SDK需要集成在商户自己的APP中,用于唤起支付宝APP并发送交易数据,并在支付宝APP返回商户APP时获得支付结果。服务端SDK需要商户集成在自己的服务端系统中,用于协助解析并验证客户端同步返回的支付结果和异步通知。

SDK调用前需要进行初始化,代码示例如下:

1
AlipayClient alipayClient = new DefaultAlipayClient(URL, APP_ID, APP_PRIVATE_KEY, FORMAT, CHARSET, ALIPAY_PUBLIC_KEY, SIGN_TYPE);

关键参数说明:

配置参数 示例值解释 获取方式/示例值
URL 支付宝网关(固定) https://openapi.alipay.com/gateway.do
APP_ID APPID即创建应用后生成 获取见上面创建应用并获取APPID
APP_PRIVATE_KEY 开发者应用私钥,由开发者自己生成 获取见上面配置密钥
FORMAT 参数返回格式,只支持json json(固定)
CHARSET 请求和签名使用的字符编码格式,支持GBK和UTF-8 开发者根据实际工程编码配置
ALIPAY_PUBLIC_KEY 支付宝公钥,由支付宝生成 获取详见上面配置密钥
SIGN_TYPE 商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2 RSA2

接下来,就可以用alipayClient来调用具体的API了。alipayClient只需要初始化一次,后续调用不同的API都可以使用同一个alipayClient对象。


注意:App支付不支持第三方授权,不能代商家发起请求。



=========

应用开发完成后,请开发者自行进行验收并完成安全性检查。

开放平台第三方应用安全开发指南(https://doc.open.alipay.com/docs/doc.htm?treeId=275&articleId=105912&docType=1)。


//支付宝中验签的解释:


说一下简单支付流程:你提交等待支付的订单信息给支付宝,支付宝返回订单支付结果给你(这里暂时先不考虑服务器)。但是这里就有安全问题了,支付宝怎么知道你提交的订单信息商家的真实性?你又怎么知道支付宝返回的结果是支付宝官方操作而不是被篡改过的呢?

所以就有了安全验证一说,也就是私钥和公钥了。商家和支付宝都有一对公钥和私钥,支付宝的公钥提供给了每个商家(现在是统一的),商家的公钥在生成时也是应该提交到了支付宝的。私钥都是自己留着,不给别人。私钥用来数字签名,公钥用来对私钥签过名的信息做验证。

所以为了安全,你需要在发送订单信息的时候用你的私钥签名,发送给支付宝,支付宝用你的公钥去验证你的订单是否是本人。然后支付宝返回用支付宝私钥签名过的支付结果给你,你这个时候就需要用支付宝公钥去验证到底是不是真正的支付宝返回的信息。

    /*

     *生成订单信息及签名

     */

    //将商品信息赋予AlixPayOrder的成员变量

    Order* order = [Ordernew];

    

    // NOTE: app_id设置

    order.app_id = appID;

    

    // NOTE: 支付接口名称

    order.method =@"alipay.trade.app.pay";

    

    // NOTE: 参数编码格式

    order.charset =@"utf-8";

    

    // NOTE: 当前时间点

    NSDateFormatter* formatter = [NSDateFormatternew];

    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];

    order.timestamp = [formatterstringFromDate:[NSDatedate]];

    

    // NOTE: 支付版本

    order.version =@"1.0";

    

    // NOTE: sign_type设置

    order.sign_type =@"RSA";

    

    // NOTE: 商品数据

    order.biz_content = [BizContentnew];

    order.biz_content.body =@"我是测试数据";

    order.biz_content.subject =@"1";

    order.biz_content.out_trade_no = [selfgenerateTradeNO];//订单ID(由商家自行制定)

    order.biz_content.timeout_express =@"30m";//超时时间设置

    order.biz_content.total_amount = [NSStringstringWithFormat:@"%.2f",0.01];//商品价格

    

    //将商品信息拼接成字符串

    NSString *orderInfo = [orderorderInfoEncoded:NO];

    NSString *orderInfoEncoded = [orderorderInfoEncoded:YES];

    NSLog(@"orderSpec = %@",orderInfo);

    

    // NOTE: 获取私钥并将商户信息签名,外部商户的加签过程请务必放在服务端,防止公私钥数据泄露;

    // 需要遵循RSA签名规范,并将签名字符串base64编码和UrlEncode

    id<DataSigner> signer =CreateRSADataSigner(privateKey);//生成签名器

    NSString *signedString = [signersignString:orderInfo];

    

    // NOTE: 如果加签成功,则继续执行支付

    if (signedString !=nil) {

        //应用注册scheme,AliSDKDemo-Info.plist定义URL types

        NSString *appScheme =@"alisdkdemo";

        

        // NOTE: 将签名成功字符串格式化为订单字符串,请严格按照该格式

        NSString *orderString = [NSStringstringWithFormat:@"%@&sign=%@",

                                 orderInfoEncoded, signedString];

        

        // NOTE: 调用支付结果开始支付

        [[AlipaySDKdefaultService]payOrder:orderStringfromScheme:appSchemecallback:^(NSDictionary *resultDic) {

//这里的支付结果是在没有安装支付宝客服端的情况下跳转网页支付时,会在这回调
            NSLog(@"返回结果resultDic = %@",resultDic);
            if (resultDic)
            {
                /*
                 9000 订单支付成功
                 8000 正在处理中
                 4000 订单支付失败
                 6001 用户中途取消
                 6002 网络连接出错
                 */
                if ([resultDic[@"resultStatus"]integerValue] == 9000)
//网上很多教程到这里就结束了,因为他们没有验证返回订单签名
                {
                   //验签
                   //去掉返回字典中result值里面的“\\”
                   NSString *result = [resultDic[@"result"] stringByReplacingOccurrencesOfString:@"\\\\" withString:@""];
                    //分割字符串获取订单信息和签名
                    NSArray *array = [result componentsSeparatedByString:@"&sign_type=\\"RSA\\"&sign=\\""];
                    //返回的订单信息
                    NSString *orderString = array[0];
                    //返回的订单签名
                    NSString *signedString = [array[1] substringToIndex:[array[1]length]-1];
            id<DataVerifier> dataVeri = CreateRSADataVerifier(@"public");//用支付宝公钥生成签名器
//支付宝公钥匙验证返回信息与签名 if ([dataVeri verifyString:orderString withSign:signedString]) { //验证签名成功,交易结果无篡改 NSLog(@"------------支付成功---------------"); } else { //验签错误 } } } else { //交易失败 } }]; }

        }];

    }

}


下面是appdelegate中的方法:

//跳转支付宝支付(安装了支付宝客户端的情况)时,支付完成之后重新回到本app会调用此方法,在此可以根据resultDic提示支付结果
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options
{
    if ([url.host isEqualToString:@"safepay"]) {
  [[AlipaySDK defaultService] processOrderWithPaymentResult:url standbyCallback:^(NSDictionary *resultDic) { 
**验证方式同上面的网页支付**
}];
}
        //这个是进程KILL掉之后也会调用,这个只是第一次授权回调,同时也会返回支付信息,//处理支付宝客户端返回的url(在app被杀模式下,通过这个方法获取支付结果)。
        [[AlipaySDK defaultService]processAuth_V2Result:url standbyCallback:^(NSDictionary *resultDic) {
            NSString * str = resultDic[@"result"];
            NSLog(@"result = %@",str);
        }];

return YES;}
不推荐客户端验证,应该由后台来做(后台做更安全)。
由于同步通知和异步通知都可以作为支付完成的凭证,且异步通知支付宝一定会确保发送给商户服务端。为了简化集成流程,商户可以将同步结果仅仅作为一个支付结束的通知(忽略执行校验),实际支付是否成功,完全依赖服务端异步通知。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值