iOS银联支付相关

开发前的准备工作

1. 打开 https://open.unionpay.com/ ,后续说的文档下载、FAQ查询等都在这个平台操作。
2. 下载规范和开发包。帮助中心-下载-产品接口规范-手机控件支付产品接口规范,帮助中心-下载-产品接口规范-手机控件支付产品技术开发包。
3. 开发人员都请先看下6.2的消费的交易流程。
4. 相关测试参数:
如果已签约,有自己的测试商户,则直接用自己的商户号测试,测试证书开发包里都有。* 尽量用真实商户号测试,防止有时候参数配错能尽早发现。
如果没有签约,或者商户号尚未分配,请在平台里自行获取商户并且开交易权限,方法为:
a) 左上角注册;
b) 登陆后右上角我的测试-测试参数
c) 我的测试-产品-选下自己集成的。

测试卡号信息:
借记卡:6226090000000048
手机号:18100000000
密码:111101
短信验证码:123456
(短信验证码记得点下获取验证码之后再输入)

贷记卡:6226388000000095;
手机号:18100000000;
cvn2:248;
有效期:1219;
短信验证码:123456
(短信验证码记得点下获取验证码之后再输入)

SDK说明

商户开发者在获取到银联提供的开发包后请检查SDK文件所在目录upmp_iphone/paymentcontrol,以下部分提及的文件均在该目录中。银联支付控件静态库,以下简称UPPaymentControl,包含以下两个文件:
UPPaymentControl.h
libPaymentControl.a

接口说明

  • 1、支付接口

     - (BOOL)startPay:(NSString*)tn fromScheme:(NSString*)schemeStr mode:(NSString*)mode viewController:(UIViewController*)viewController
    

各个参数定义如下表:

支付接口
  • 2、检查是否安装银联App的接口

    - (BOOL)isPaymentAppInstalled
    

    此函数无传入参数,主要功能检测用户手机上是否安装银联支付的APP,当用户手机上安装了银联支付APP时候返回YES。

检查是否安装银联App接口
  • 3、返回结果接口
    - (void)handlePaymentResult:(NSURL*)url completeBlock:(UPPaymentResultBlock)completionBlock;

各参数定义如下表:

返回结果接口

添加SDK包

使用UPPaymentControl需要将paymentcontrol/inc目录下UPPaymentControl.h文件和paymentcontrol/libs目录下的libPaymentControl.a文件添加到商户应用的工程中,添加后如图:

工程配置

1、使用UPPaymentControl需要添加CFNetwork.framework、SystemConfiguration.framework 、libz、libPaymentControl.a到工程中

2、在工程info.plist设置中添加一个URL Types回调协议(在UPPayDemo工程中使用“UPPayDemo”作为协议),用于在支付完成后返回商户客户端。

3、http请求设置
在Xcode7.0之后的版本中进行http请求时,需要在工程对应的plist文件中添加NSAppTransportSecurity Dictionary 并同时设置里面NSAllowsArbitraryLoads 属性值为 YES

4、添加协议白名单
在Xcode7.0之后的版本中进行开发,需要在工程对应的plist文件中,添加LSApplicationQueriesSchemes Array并加入uppaysdk、uppaywallet、uppayx1、uppayx2、uppayx3五个item,具体设置可参考以下截图:

或者直接添加如下代码到plist文件中:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>uppaysdk</string>
<string>uppaywallet</string>
<string>uppayx1</string>
<string>uppayx2</string>
<string>uppayx3</string>
</array>

调用插件

在需要调用支付控件接口的代码文件内引用头文件UPPaymentControl.h。
(注意:如果工程的compile source as 选项的值不是Objective–C++,则引用此头文件的文件类型都要改为.mm)

  • 1、支付接口调用
    商户App从商户服务器获取tn,当tn不为空时,调用支付接口。

    //当获得的tn不为空时,调用支付接口
    if (tn != nil && tn.length > 0)
    {
      [[UPPaymentControl defaultControl]startPay:tn  fromScheme:@"UPPayDemo"  mode:self.tnMode  viewController:self]; 
    }
    
  • 2、检测是否已安装银联App接口调用

 if([[UPPaymentControl defaultControl] isPaymentAppInstalled])   
 {
    //当判断用户手机上已安装银联App,商户客户端可以做相应个性化处理
 }
  • 3、返回结果接口调用
    支付控件结果处理函数handlePaymentResult: completeBlock:需要在工程AppDelegate文件的application: openURL: sourceApplication: annotation: 方法中进行调用。
    支付控件结果处理函数handlePaymentResult: completeBlock:包含两个参数,参数1url为支付结果串,由handlePaymentResult: completeBlock:方法解析url内容;参数2completionBlock为商户APP定义的结果处理方法,包含两个传入参数code和data,其中code表示支付结果,取值为suceess,fail,cancel分别表示支付成功、支付失败和支付取消,data表示结果签名数据,商户使用银联公钥验证结果真实性。
    对于新增的签名信息需注意以下几点:
  1. 前台返回的支付结果中包含银联签名,要在商户后台对签名进行校验后才能展示结果。
  2. 前台签名使用的密钥和算法与后台结果中的签名一致。
  3. 如果商户APP在客户端内进行签名验证,要自行实现签名密钥更新的机制,否则更换密钥后会导致验签失败。(不推荐)
  4. 商户订单是否成功支付应该以商户后台收到全渠道返回的支付结果为准,此处支付控件返回的结果仅作为参考。
    调用支付接口后,结果处理方法示例代码:
  - (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
     
    [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
    
       //结果code为成功时,先校验签名,校验成功后做后续处理
        if([code isEqualToString:@"success"]) {
        
            //数据从NSDictionary转换为NSString
            NSDictionary *data;
            NSData *signData = [NSJSONSerialization dataWithJSONObject:data options:0 error:nil];
            NSString *sign = [[NSString alloc] initWithData:signData encoding:NSUTF8StringEncoding];
        
            //判断签名数据是否存在
            if(data == nil) {
                //如果没有签名数据,建议商户app后台查询交易结果
                return;
            }    
          
            //验签证书同后台验签证书
            //此处的verify,商户需送去商户后台做验签
            if([self verify:sign]) {
                //支付成功且验签成功,展示支付成功提示
            }else {
                //验签失败,交易结果数据被篡改,商户app后台查询交易结果
            }

        }else if([code isEqualToString:@"fail"]) {
            //交易失败
        }else if([code isEqualToString:@"cancel"]) {
           //交易取消
        }
    }];

    return YES;

  }

completeBlock中的NSDictionary *data结构如下:

sign —— 签名后做Base64的数据
data —— 用于签名的原始数据,结构如下:

pay_result —— 支付结果success,fail,cancel
tn —— 订单号

Data转换为String后的示例如下:

"{"sign":"ZnZY4nqFGu/ugcXNIhniJh6UDVriWANlHtIDRzV9w120E6tUgpL9Z7jIFzWrSV73hmrkk8BZMXMc/9b8u3Ex1ugnZn0OZtWfMZk2I979dxp2MmOB+1N+Zxf8iHr7KNhf9xb+VZdEydn3Wc/xX/B4jncg0AwDJO/0pezhSZqdhSivTEoxq7KQTq2KaHJmNotPzBatWI5Ta7Ka2l/fKUv8zr6DGu3/5UaPqHhnUq1IwgxEWOYxGWQgtyTMo/tDIRx0OlXOm4iOEcnA9DWGT5hXTT3nONkRFuOSyqS5Rzc26gQE6boD+wkdUZTy55ns8cDCdaPajMrnuEByZCs70yvSgA==","data":"pay_result=success&tn=201512151321481233778"}"


老版控件用户修改说明



添加SDK包
使用老版本银联支付控件的商户请先将老版本银联支付控件从工程中删除,再将新paymentcontrol/inc目录下UPPaymentControl.h文件和paymentcontrol/libs目录下libPaymentControl.a文件添加到商户应用的工程中;添加后如图:

工程配置
1、使用老版本银联支付控件的商户请先将工程配置中老版支付控件对应的三方库删除,再添加CFNetwork.framework、SystemConfiguration.framework 、libPaymentControl.a、libz到工程中;添加后如下图:

2、在工程info.plist设置中添加一个URL Types回调协议(在UPPayDemo工程中使用“UPPayDemo”作为协议),用于在支付控件完成支付后返回到商户客户端。

3、添加协议白名单
在工程对应的plist文件中,添加LSApplicationQueriesSchemes Array并加入uppaysdk、uppaywallet、uppayx1、uppayx2、uppayx3五个item,具体设置可参考以下截图:

或者直接添加以下代码到plist文件中:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>uppaysdk</string>
<string>uppaywallet</string>
<string>uppayx1</string>
<string>uppayx2</string>
<string>uppayx3</string>
</array>

接口说明和调用插件
请参考4.2接口说明和4.4调用插件说明。

常见问题总结
更多请参见https://open.unionpay.com帮助中心-FAQ
怎样加-ObjC宏
选择工程targets——》build settings ->Linking->other linker flags

编译时提示Undefined for architecture XXX 错误
如:

1)由于支付控件使用到了C、C++和OC混编的情况,所以商户工程引入UPPaymentControl.h头文件以后可能会出现链接错误,这个时候可以通过以下三种方式解决:
① 将涉及到引用UPPaymentControl.h的源文件的后缀名都改为.mm;
② 如果商户不想修改源文件的后缀名,可以在工程中添加一个空的继承自NSObject的类,并将文件.m后缀名该改为.mm即可方法为new file->Objective-C class->类名自取->保存->修改后缀名为.mm;
③ 将工程的compile source as 选项的值设置为Objective–C++;

2)由于在UPPayDemo工程中添加了自定义的库文件libPaymentControl.a
,当编译Demo工程时,应该检查工程设置Search Paths里的Framework Search Paths、Header Search Paths、Library Search Paths的路径设置,看设置路径是否正确,另外还要注意里边是否多余一些不确定的路径。

  1. 将xcode工程中Build Setting -> Apple LLVM compiler Language 标签下的C++ Language Dialect 和 C++ Standard Library 属性值修改为 Compiler Default如实在无法解决,尝试添加-ObjC宏的地方修改为 -force_load+空格+控件路径,如:-force_load $(PROJECT_DIR)/ libPaymentControl.a,如果还报错,上下文应该会有libPaymentControl.a文件找不到异常,比如ld: file not found: /Users/apple/Desktop/Communication 2/ libPaymentControl.a
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    请确定libPaymentControl.a文件确实存在于此路径,可能为上下文路径配错。
    控件闪退异常'NSInvalidArgumentException', reason: '-[__NSCFConstantString newSizeWithFont:详略]'
    'NSInvalidArgumentException', reason: '-[__NSCFConstantString newSizeWithFont:以下略]: unrecognized selector sent to instance 0x[随机数]'

出现以上问题是由于添加-ObjC宏的地方没有配置正确,如果配-ObjC实在解决不了的话,可尝试去掉-ObjC,改为-force_load+空格+控件路径,如:-force_load $(PROJECT_DIR)/ libPaymentControl.a。
orientation异常
详细现象为控件崩溃,报错信息:Terminating app due to uncaught exception ‘UIApplicationInvalidInterfaceOrientation’, reason: ‘Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES’ 请勿修改横竖屏配置,iphone控件只能竖屏,ipad控件才支持横竖屏。如果app本身为横屏,请代码控制横竖屏,勿修改配置。
其他第三方静态库(如支付宝、微信等)的文件产生冲突duplicate symbols for architecture XXX
如:

请尝试将添加-ObjC宏的地方修改为 -force_load+空格+控件路径,如:-force_load $(PROJECT_DIR)/ libPaymentControl.a,这样做不会影响支付宝等其他支付渠道功能。
控件界面无限加载

  1. 调用控件的逻辑应当在主线程中执行,子线程中尽量不要进行UI操作,无限加载等待实际是子线程死锁所致。
  2. 请参考控件使用指南iOS “添加SDK包“里“添加-ObjC宏”,特别注意大小写不要弄混。(此步骤操作有问题时也可修改为 -force_load+空格+控件路径,如:-force_load $(PROJECT_DIR)/ libPaymentControl.a)。
  3. Build Setting -> Apple LLVM compiler Language-C++:
    Attempt to present XX on XX while a presentation is in progress!
    Warning: Attempt to present <UPNavController: 0x8bc24d0> on <tttViewController: 0x8b9a390> while a presentation is in progress!animation完成的时候再调用我们的插件,两个present同时起会出警告。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,108评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,699评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,812评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,236评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,583评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,739评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,957评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,704评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,447评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,643评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,133评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,486评论 3 256
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,151评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,889评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,782评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,681评论 2 272

推荐阅读更多精彩内容