作为一名后端程序员,整个API链的调用联调是否能摒除所有的外部依赖是非常重要的,测试的流程贯通关系到整个开发的顺畅程度。支付系统的联调麻烦就麻烦在有外部系统的依赖。虽然在做开发的时候可以在单元测试代码中进行Mock来绕过外部的依赖,但真实的e2e测试还是必须的,这个时候就需要引入外部支付系统的接口了。
目前国内的支付系统主要就是支付宝和维信支付。微信支付有点忘记了,但支付宝的app支付和网页支付是分开的2个独立的功能,也就是说公司的app可能只签了app支付而没有签网页支付。这种情况下在测试的时候,后端下单之后就无法使用自己生成的二维码然后用手机扫码支付测试了,必须是直接在手机的app内进行测试。这就很麻烦。所以本文会做一个教程,简单教下如何创建一个简单的app,可以使用后端下单生成的返回字串来唤醒支付宝进行支付,以打通整个支付流程。
首先需要注册一个Apple开发者账号,因为没有任何账号的话,是无法对App进行打包和部署到手机上进行测试的。注册去:https://developer.apple.com/,点右上角的Account
,按引导注册即可。然后打开xocde,点开Perferences -> Accounts
,点左下角的+
添加自己的账号。
然后打开xcode,创建新项目。
题外:如果想认真学习下Swift的话,官方Tutorials教程在:SwiftUI Tutorials。此外,还有The swift programming language。
cocospods
是iOS项目的依赖管理工具,类似nodejs的npm,基本上做项目都需要。最方便的的一点是这东西在安装的时候,会把一些对应的配置文件都更新好,对于我这样的新手来说就少了很多事情。
几篇参考:
# 安装cocospods本体
$ brew update --verbose
$ brew install cocospods --verbose
# 安装数据库,这个repo超级大,一共有将近1个GB的数据,建议用代理加速
$ git clone https://github.com/CocoaPods/Specs.git ~/.cocoapods/repos/trunk
# 完成后测试下效果,是否可以搜到dep,有结果返回就OK了
$ pod search Alamofire
到刚才创建的新项目的根目录下,首先需要创建pod的配置文件,类似package.json
$ pod init
会生成一个Podfile
,然后编辑该文件,添加Alipay SDK,添加在# Pods for AlipayTest
这行下:pod 'AlipaySDK-iOS'
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
target 'AlipayTest' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for AlipayTest
pod 'AlipaySDK-iOS'
target 'AlipayTestTests' do
inherit! :search_paths
# Pods for testing
end
target 'AlipayTestUITests' do
# Pods for testing
end
end
最后在repo的根目录下执行安装命令
$ pod install
安装完成的dep都放在:Pods/
下,Alipay SDK在:/Pods/AlipaySDK-iOS
。
后续需要关闭xcode,使用新生成的AlipayTest.xcworkspace
文件来打开项目。
更多细节可以看支付宝官方的:客户端 iOS 集成流程。
因为Alipay SDK是使用ObjC写的,所以在Swift项目中使用需要做一步工作:引入桥接的Header文件。
执行创建文件操作,选择ObjC文件,名字随意,实际上这个ObjC文件我们后续可以直接删除,没用。IDE会问是否需要创建桥接Header,点击蓝色按钮选是,这才是我们创建ObjC文件的真正目的。
操作完成后,删除ObjC文件,打开桥接Header文件,并添加:# import <AlipaySDK/AlipaySDK.h>
。
打开创建新项目时默认生成的:ContentView
。页面上添加一个 TextEditor 用来输入后端下单之后生成的sign字符串
,然后一个 Button 来执行确认唤起。
要正确唤起支付宝,并能够正确支付,需要注意几个点:
Input the sign here
,我是没找到这个控件应该怎么加Placeholder…AlipaySDK.defaultService().payOrder
的fromScheme
需要替换成第二点中提到的真正业务app的项目名字,也就是支付宝支付完成后的回调app
//
// ContentView.swift
// honors
//
// Created by Jonathan Dai on 2022/4/14.
//
import SwiftUI
struct ContentView: View {
@State var editor: String = "Input the sign here"
@State var console: String = "Console:\n"
var body: some View {
VStack {
SwiftUI.Group {
Text("Pay with order sign").padding().frame(width: nil).border(Color.black, width: 2)
TextEditor(text: $editor)
.padding()
.border(Color.black, width: 1)
Button(action: {
print("Button 'Go to Alipay' clicked")
gotoAlipay()
}) {
Text("Go to Alipay")
}
.padding(.all)
TextEditor(text: $console)
.padding()
.border(Color.black, width: 1)
}
}
}
func gotoAlipay() {
self.console += "gotoAlipay\n"
print("gotoAlipay: sign: " + self.editor)
AlipaySDK.defaultService().payOrder(self.editor, fromScheme: "YourBusinessAppNameHere", callback: { (resultDic) -> Void in
print("Alipay reslut = \(String(describing: resultDic))");
let resultDic = resultDic! as Dictionary
if let resultStatus = resultDic["resultStatus"] as? String {
if resultStatus == "9000" {
self.console += "支付成功\n"
} else {
self.console += "支付失败\n"
}
}
})
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
Group {
ContentView()
}
}
}
UI长这样
操作:
Go to Alipay
EOF