您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
ENJOY的Apple Pay应用内支付接入实践
 
来源:极客头条 作者:陈乘方 发布于:2016-8-18
  2110  次浏览      17
 

导读: Apple Pay的应用内支付提供了一种全新的在线支付形式,如果将Apple Pay应用内支付自身的特点与App本身的产品形态相结合,用户的在线支付体验将得到大幅提升。ENJOY作为Apple Pay中国区首发的支持ApplePay应用内支付的App之一,在跟Apple Pay的接入时与产品功能做了深度集成,本文基于此对包括可用性、payment sheet、服务器解密、交易处理等在内的Apple Pay技术接入要点进行了经验上的深度分享。 Apple Pay已经在大陆地区正式上线,但大家的关注点大多集中在其线下支付的体验上。对于我们应用开发者而言,Apple Pay的应用内支付给我们提供了一种全新的在线支付形式。如果将Apple Pay应用内支付自身的特点跟App本身的产品形态相结合,用户的在线支付体验可以得到大幅提升。

Apple Pay与现有支付方式对比

在国内开发包含在线支付功能的应用,目前可用的选择就是接入第三方支付平台,比如支付宝或者微信支付。这些支付方式在接入方式上大同小异,就是在App中引入对应平台的SDK,在将支付信息组织好之后,调用对应第三方平台的SDK来完成支付。不同平台的SDK对支付的请求处理各不相同,总的来说完成支付有两种方式:调起对应的App或者打开一个网页。比如微信,就只支持打开微信App来进行支付这一种形式。

Apple Pay与现有第三方支付平台相比的优点有:

系统级支持,支付过程不需要跳转到第三方App;

支付过程可以获取用户信息,比如手机号、送货地址等。

Apple Pay应用内支付的接入方式跟微信等第三方平台不一样。作为iOS系统原生支持的特性,Apple

Pay的相关功能包含在系统的PassKit这个Framework里,不需要引入第三方SDK便可集成。

Apple Pay深度集成

拿我们的产品ENJOY来说,作为Apple Pay中国区首发的支持Apple Pay应用内支付的App之一,在跟Apple Pay的接入时与产品功能做了深度集成。除了Apple Pay有着目前最短的支付路径这一特点,还有一个我们认为的最大优点,就是Apple Pay提供了系统级的由用户自行维护的个人信息。基于这些特点,与我们现有的用户系统和支付系统相结合,应用内支付体验有了很大提升。

ENJOY与Apple Pay集成后特点:

未登录用户通过Apple Pay直接购买商品;

首页商品一键购买;

闪购商品一键购买;

比第三方支付提前一步完成购买。

其中最有亮点的地方就是第一点,未登录用户可以直接购买商品。就目前的电商应用来说,用户只有在登录应用之后,才能购买商品。而ENJOY之所以能做到这一点,是因为对ENJOY来说,只要能够拿到用户的手机号,便可以与我们的用户体系相关联,并完成购买流程。正是利用了手机号可以由Apple Pay提供给应用的这一特性,ENJOY实现了未登录用户通过 Apple Pay可以直接购买商品这一功能(如图1所示)。

图1 未登录状态下购买商品时payment sheet截图,可以看到其中的联系方式字段

Apple Pay技术接入要点

首先来看一下Apple Pay应用内支付的时序图(如图2所示)。

图2 Apple Pay时序图

从时序图中可以清楚地看到,应用内支付流程分为以下几个步骤:

App显示Payment Sheet,提示用户进行支付验证操作(指纹和 PIN 码);

用户支付验证完成,iOS系统与Apple的服务器进行交互,处理支付信息(主要是加密);

App收到系统回调,然后将回调里包含的支付信息传给自己的服务器;

自己服务器收到App发来的信息,进行解密处理后,将需要的信息组织成银联报文,然后调用银联扣款接口,完成扣款;

服务器通知App支付结果,App更新相应的UI。

由上面的步骤可以看出,虽然实际使用时Apple Pay支付的时间很短,但App从显示payment sheet一直到支付成功,其中的过程还是很复杂的。在实际开发中,有很多需要注意的地方,下面具体说明一下。

Apple Pay可用性判断

应用如果显示Apple Pay按钮,需要先判断Apple Pay功能是否可用。这项实现需要结合PassKit Framework中PKPaymentAuthorizationViewController类的两个类函数才能完成判断,它们分别是:

class func canMakePayments() -> Bool
 class func canMakePaymentsUsingNetworks(supportedNetworks: [String]) -> Bool
第一个函数返回值代表当前设备是否支持 Apple Pay,是用来判断设备硬件的。就目前来说,只有iPhone 6、iPhone 6 Plus、iPhone 6s和iPhone 6s Plus这四款设备支持Apple Pay。

第二个函数则是判断指定的支付网络是否支持。Apple Pay在国内的支付网络就是银联,所以需要传入PKPaymentNetworkChinaUnionPay这个值。

同时,需注意API的版本可用性,以上两个函数都是iOS 8才开始支持的API,其中 PKPaymentNetworkChinaUnionPay这个支付网络更是从iOS 9.2才开始支持,所以判断是否支持Apple Pay的最终代码是这样的:

if #available(iOS 9.2, *) {
         if PKPaymentAuthorizationViewController.canMakePayments()
 && PKPaymentAuthorizationViewController.canMakePaymentsUsingNetworks
([PKPaymentNetworkChinaUnionPay])
 {
                // TODO: 支持 Apple Pay
            }
}

注意: 一定要把工程target设置的Capabilities里的Apple Pay选项打开,不然在真机调试的时候,以上代码判断结果肯定是不支持的。

Payment sheet显示

Payment sheet也就是Apple Pay支付的UI,有不少地方是可以自定义的。想要自定义paymentsheet,需要对类PKPaymentAuthorizationViewController的初始化参数paymentRequest做相应的设置。paymentRequest参数是一个PKPaymentRequest类型的对象(如图3所示)。

iOS端Apple Pay结构

图3 iOS端Apple Pay结构

首先,初始化一个PKPaymentRequest对象,并设置必需内容:

 let request = PKPaymentRequest()
request.merchantIdentifier = "merchant.xxxxx”
request.merchantCapabilities = [.Capability3DS, .CapabilityEMV, .CapabilityCredit, .CapabilityDebit]
request.countryCode = "CN"
request.currencyCode = "CNY"
request.supportedNetworks = [PKPaymentNetworkChinaUnionPay]

merchantIdentifier需要与苹果开发者后台的配置相对应。以上代码中还有一个必需属性 paymentSummaryItems没有设置,该属性代表在payment sheet中显示的价格列表,是一个PKPaymentSummaryItem类型的数组。该数组至少要有一个元素,并且最后一个元素所包含的价格,就是实际要支付的价格。如果需要显示手机号或者收货地址,则可以对 requiredShippingAddressFields这个属性做相应的设置。

设置完毕后,通过以下代码可以调起payment sheet:
 let vc = PKPaymentAuthorizationViewController(paymentRequest: request)
vc.delegate = self
presentViewController(vc, animated: true, completion: nil)

关于payment sheet这个UI需要特别说明:这个UI的视图优先级相当高,连alert都会被盖住,App在处理这个UI的时候需要注意。当payment sheet显示和消失时,对应的App也相当于进入后台和切回前台,所以,系统通知和AppDelegate里的回调函数也都会有所响应。

服务器解密流程

在用户输入指纹和PIN码验证之后,回调函数func paymentAuthorizationViewController(_, didAuthorizePayment: completion: )将会被调用,其中参数didAuthorizePayment类型是 PKPayment, 里面包含两类信息。第一种是明文的用户信息,对应的是初始化payment sheet 时的设置。另外一种就是加密过的支付信息,PKPayment有一个token属性,该属性的类型是PKPaymentToken,其中的paymentData属性就是加密过的支付信息。paymentData的内容是一个JSON的二进制流,将其解析之后,结构如下:

 {
    data = "xxxxx";
    header = {
        publicKeyHash = "xxxxx";
        transactionId = bce2f62f92cb1f5b16696f1ea3b1b375cbfe8fe45c9132ae381c77ed45202455;
        wrappedKey = "xxxx";
    };
    signature = "xxx";
    version = "RSA_v1";
}

使用signature字段对消息进行验签,防止信息被篡改。之后取出header.wrappedKey的内容,它是使用非对称加密算法加密过的对称秘钥。用在苹果开发者后台配置merchantID时的私钥进行解密,就能得到这个对称秘钥。然后,使用这个对称秘钥对data所包含的加密数据进行解密,取得Apple返回的支付信息。此支付信息是加密过的,包含了用户支付的卡号和 PIN码等信息,理论上只有银联才能解析出来真正的内容,对我们商户而言其内容是加密的。服务器端需要将这些解密过的信息组织成银联所需的报文内容,随后调用银联的扣款接口,完成扣款。

银联交易状态确认

在调用银联的扣款接口后,有一点非常重要,就是要确保扣款结果是否成功。只有确切的知道了扣款结果,才能正确地设置自己平台的用户订单状态。银联的扣款接口设计是这样的,在调用接口之后,返回同时有同步和异步两种形式。如果同步结果返回成功,只是说明银联成功收到并开始处理扣款请求,并不代表扣款成功。扣款是否成功,是通过异步形式来通知的。而扣款不成功的原因有很多,比如卡被冻结、PIN码错误、余额不足等等。

我们采用的做法是这样的,调用扣款接口后,如果3秒内没有收到本次调用的异步回调,则通过使用同步结果返回的银联流水号,开始轮询银联的另外一个交易状态接口来确保拿到交易结果。

交易失败的处理

如果发生交易失败的情况,App需要做相应的UI处理。按照Apple的交互要求,以下几种失败情况,payment sheet不能退出,其余的情况则需要退出payment sheet后,由App负责通知给用户。

未输入PIN码;

PIN码错误;

PIN码失败次数超过限制。

payment sheet的显示结果是由func paymentAuthorizationViewController(_, didAuthorizePayment: completion: )这个回调函数中的completion这个参数来控制的。该参数是一个closure,它的第一个参数类型是PKPaymentAuthorizationStatus的枚举,打开该枚举的定义,可以看到上面的情况已经由操作系统定义好了,对应起来分别是:

PINRequired

PINIncorrect

PINLockout

UI显示的细节:在调用completion后,如果传入的PKPaymentAuthorizationStatus值是Success 或者Failure,payment sheet在展示出相应的结果之后都会自动dismiss掉。而如果传入的是上面三个有关PIN码的值,则payment sheet并不会消失,用户可以继续选择银行卡,然后进行指纹验证等支付操作。

交易撤销

在payment sheet显示出来到消失的这段时间内的任意时刻,用户都可以通过点击payment sheet右上角的「取消」按钮来手动取消支付,那这就涉及到了交易撤销的问题。交易撤销是由服务器来完成的,那么App要做的首先是把用户取消的事件通知给服务器。由于整个支付过程步骤很多,总的来说,服务器撤销交易要面临以下三种情况:

还未向银联调用扣款接口;

已调用扣款接口,但扣款结果还未返回;

扣款成功。

第一种情况很容易处理,只要服务器之后不再调用银联扣款接口即可。第二种和第三种情况的处理方法一样,区别在于第二种情况的处理时机是在获取到扣款成功结果之后。如果是后两种情况,则调用银联的交易撤销接口,以撤销之前的交易,把已经扣除的用户款项返还给用户。

注意: 由于有些银行不支持交易撤销,所以调用交易撤销接口后需要判断一下返回结果,如果不支持,则还需调用退款接口来返回款项。

总结

pple Pay应用内支付的在技术上并不难,但所涉及的细节非常多,需要花费不少功夫处理好各种情况。如果对Apple Pay应用内支付定制化需求并不强,有不少第三方支付平台目前已经提供了自己封装的SDK来供开发者使用,比如银联的CUP SDK等。这些SDK屏蔽了支付过程中的很多细节,可以方便地接入到App中。但如果需要接入原生的Apple Pay来实现好的应用内支付体验,那么本文可以给你提供一些帮助

   
2110 次浏览       17
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新课程计划
信息架构建模(基于UML+EA)3-21[北京]
软件架构设计师 3-21[北京]
图数据库与知识图谱 3-25[北京]
业务架构设计 4-11[北京]
SysML和EA系统设计与建模 4-22[北京]
DoDAF规范、模型与实例 5-23[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   

Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合

领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...