[UnionPay]银联支付

文章涉及的demo在Github LQThirdParty, 欢迎Star | Fork

本文主要是介绍银联支付相关的一些

一. 前期准备

  1. 打开银联开放平台:https://open.unionpay.com/tjweb/index;
  2. 选择“产品API”-->商户专区-->手机支付控件;
[UnionPay]银联支付_第1张图片

打开后,在“产品简介”中有我要入网我要测试,均需要注册账号,根据提示完成注册即可!

二. 适配iOS9

在iOS9下,默认使用的是HTTPS协议,系统会拦截对HTTP协议接口的访问,因此无法获取HTTP协议接口的数据,

解决方案

具体方法:
在项目的Info.plist中添加一个Key:NSAppTransportSecurity,类型为字典类型。
然后给它添加一个Key:NSAllowsArbitraryLoads,类型为Boolean类型,值为YES

[UnionPay]银联支付_第2张图片
配置Info.plist文件

三. 导入银联SDK

在SDK&Demo下载页,可以下载相关的iOS开发包,里面有后台说明,app说明等,在app开发包 中有iOS 相关SDK和集成文档,将paymentcontrol文件夹内文件添加到项目中:

libPaymentControl.aUPPaymentControl.hUPAPayPlugin.hUPAPayPluginDelegate.h

添加依赖库:

Build Phases -> Link Binary With Libraries添加依赖库:

SystemConfiguration.framework,liz.tbd,CFNetwork.framework

注意看下有没有libPaymentControl.a,一般添加到项目的时候会自动加进去,这里只需要注意下有没有即可:

[UnionPay]银联支付_第3张图片

设置URL scheme

[UnionPay]银联支付_第4张图片

这里的URL Scheme 是自定义的传递给银联sdk的回调scheme,在完成支付后返回app,一般以项目名称命名即可;

编译运行,如果报以下错误:

Undefined symbols for architecture armv7:  
  "_OBJC_CLASS_$_CTTelephonyNetworkInfo", referenced from:  
      objc-class-ref in libWeChatSDK.a(MTAHelper.o)  

这是因为还需要添加库文件:CoreTelephony.framework

配置SSO白名单

在iOS9以上系统需要增加一个可跳转App的白名单,即LSApplicationQueriesSchemes, 否则将在SDK判断是否跳转时用到的canOpenURL时返回NO,进而只进行webview授权或授权/分享失败.
在项目中的info.plist中加入应用白名单,右键info.plist选择source code打开,添加以下内容:

LSApplicationQueriesSchemes

        uppaysdk
        uppaywallet
        uppayx1
        uppayx2
        uppayx3


[UnionPay]银联支付_第5张图片

四. 使用银联的API

在需要使用银联支付的地方导入:

#import "UPPaymentControl.h"  
  • 判断是否安装 银联 App
+ (BOOL) isUnionAppInstall {
    
    return [[UPPaymentControl defaultControl] isPaymentAppInstalled];
}

这个判断可加可不加, 如果用户没有安装银联app, 则会调用 SDK 内置的收银台进行收款.

  • 发起支付
/**
 *  支付接口
 *
 *  @param tn             订单信息
 *  @param schemeStr      调用支付的app注册在info.plist中的scheme
 *  @param mode           支付环境
 *  @param viewController 启动支付控件的viewController
 *  @return 返回成功失败
 */
- (BOOL)startPay:(NSString*)tn
      fromScheme:(NSString *)schemeStr
            mode:(NSString*)mode
  viewController:(UIViewController*)viewController;

首先调用商户后台接口, 完成下单, 返回交易流水号(TN), 然后调用 SDK 的 startPay 方法进行支付:

+ (void) startPayWithTN:(NSString *)tn onViewController:(UIViewController *) vc {
    
    [[UPPaymentControl defaultControl] startPay:tn fromScheme:@"LQUnionPayDemo" mode:@"01" viewController:vc];
}

该方法有四个参数:
参数一: tn, 交易流水号, 由商户后台向银联后台提交订单信息后, 由银联后台生成下发;
参数二: schemeStr, app端定义的回调scheme
参数三: mode ,接入模式, 有两个可选值, @“00” 生产环境, @“01” 测试环境
参数四: viewController, 发起调用支付控件的视图控制器
返回值: 是否吊起支付成功

  • 处理支付结果
/**
 *  处理钱包或者独立快捷app支付跳回商户app携带的支付结果Url
 *
 *  @param url              支付结果url,传入后由SDK解析
 *  @param completionBlock  结果回调,保证跳转钱包支付过程中,即使调用方app被系统kill时,能通过这个回调取到支付结果。
 */

- (void)handlePaymentResult:(NSURL*)url completeBlock:(UPPaymentResultBlock)completionBlock;

在工程AppDelegate文件的application: openURL: options: 和 application: openURL: sourceApplication:annotation: 方法中进行调用:

- (BOOL) application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    

    [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
        
       if ([url.host isEqualToString:@"paydemo"]) { 
    [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
        
        if([code isEqualToString:@"success"]) {
            //结果code为成功时,去商户后台查询一下确保交易是成功的再展示成功
        }
        else if([code isEqualToString:@"fail"]) {
            //交易失败
        }
        else if([code isEqualToString:@"cancel"]) {
            //交易取消
        }
    }];
}
    
    return YES;
}

// NOTE: 9.0以后使用新API接口
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options
{
if ([url.host isEqualToString:@"paydemo"]) { 
    [[UPPaymentControl defaultControl] handlePaymentResult:url completeBlock:^(NSString *code, NSDictionary *data) {
        
        if([code isEqualToString:@"success"]) {
            //结果code为成功时,去商户后台查询一下确保交易是成功的再展示成功
        }
        else if([code isEqualToString:@"fail"]) {
            //交易失败
        }
        else if([code isEqualToString:@"cancel"]) {
            //交易取消
        }
    }];
}
    
    
    return YES;
}

PS:这里回调的url.host是 paydemo ,感觉有点奇怪

然后, 在上面的回调 Block 中进行支付结果的验证;

到此,一个完整的支付流程就完成了...

支付页面

如果已安装 云闪付 app,则会跳转到云闪付的支付页:


[UnionPay]银联支付_第6张图片
安装 云闪付 app

如果未安装 云闪付 app,则会app内吊起支付控件


[UnionPay]银联支付_第7张图片
未安装 云闪付 app

附加

  • 银联应答码

https://open.unionpay.com/ajweb/help/respCode/respCodeList

在调试中出现问题, 一般都会附有应答码, 可根据应答码在这里进行查询, 定位问题;

  • 支付结果验证

关于支付结果验证, 官方提供的 demo 中本地验证的方法, 需要用到开放平台生成的签名证书, 而且在验证前需要保证该签名证书是最新的, 所以, 一般将验证的过程放在服务端, 即, 在支付完成后, 调用后台提供的结果查询接口进行验证.

文章涉及的demo在Github LQThirdParty, 欢迎Star | Fork

(完)

你可能感兴趣的:([UnionPay]银联支付)