secux-paymentkit-v2
Example
To run the example project, clone the repo, and run pod install
from the Example directory first.
Requirements
Installation
secux-paymentkit-v2 is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod 'secux-paymentkit-v2'
Add bluetooth privacy permissions in the plist
Import the module
import secux_paymentkit_v2
Usage
1. Initializations
All the three init functions should be done when app starts up.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions... {
//Initialization functions here
}
Use SecuXAccountManager object to do the operations below.
let accManager = SecuXAccountManager()
1.1 Set server URL
Set server URL before using the APIs below
Declaration
func setBaseServer(url:String)
Parameters
Server URL. e.g. https://pmsweb-test.secux.io
Sample
let accMgr = SecuXAccountManager()
let serverUrl = "https://pmsweb-test.secux.io"
accMgr.setBaseServer(url: serverUrl)
1.2 Set administractor account and password
Set the administractor account, which is assigned to customers by SecuX
Declaration
func setAdminAccount(name:String, password:String)
Parameters
name: Administractor account name.
password: Administractor account password.
Sample
let accMgr = SecuXAccountManager()
accMgr.setAdminAccount(name:"testAccount", password:"12345678")
2. SecuXAccount related operations
Use SecuXAccountManager object to do the operations below
let accManager = SecuXAccountManager()
2.1 Get supported coin/token
Declaration
func getSupportedCoinTokenArray()
-> (SecuXRequestResult, Data?, [(coin:String, token:String)]?)
Return value
SecuXRequestResult shows the operation result, if the result is
SecuXRequestResult.SecuXRequestOK, the returned array contains all the supported
coin and token pairs, otherwise data might contain an error message.
Sample
let (ret, data, coinTokenArray) = accManager.getSupportedCoinTokenArray()
guard ret == SecuXRequestResult.SecuXRequestOK else{
var error = ""
if let data = data{
error = String(data: data, encoding: .utf8) ?? ""
}
print("Error: \(error)")
return
}
if let coinTokenArr = coinTokenArray{
for item in coinTokenArr{
print("coin=\(item.coin) token=\(item.token)")
}
}
2.2 Registration
Register a new user account with specified coin/token account. Please note the registration operation may take around 15 seconds to set up.
Declaration
func registerUserAccount(userAccount: SecuXUserAccount,
coinType: String,
token: String) -> (SecuXRequestResult, Data?)
Parameters
userAccount: A SecuXUserAccount object with login name and password
coinType: Coin type string
token: Token string
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
registration is successful, otherwise data might contain an error message.
Note: if return result is SecuXRequestNoToken, the administractor account is not correct.
Sample
let usrAcc = SecuXUserAccount(email: name, password: pwd)
var (ret, data) = accManager.registerUserAccount(userAccount: usrAcc,
coinType: "DCT",
token: "SPC")
if ret == SecuXRequestResult.SecuXRequestOK{
//Login the account
...
}else{
var errorMsg = ""
if let data = data, let error = String(data: data, encoding: String.Encoding.utf8){
errorMsg = error
}
print("Registration failed! error \(error)")
}
2.3 Login
Note: Login session is valid for 30 minutes. To continue use after 30 minutes, relogin is required.
Declaration
func loginUserAccount(userAccount:SecuXUserAccount) -> (SecuXRequestResult, Data?)
Parameter
userAccount: A SecuXUserAccount object with login name and password
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
login is successful, otherwise data might contain an error message.
Sample
let accManager = SecuXAccountManager()
let usrAcc = SecuXUserAccount(email: name, password: pwd)
var (ret, data) = accManager.loginUserAccount(userAccount: usrAcc)
if ret == SecuXRequestResult.SecuXRequestOK{
//Login successfully
...
}else{
var errorMsg = "Invalid email/password!"
if let data = data, let error = String(data: data, encoding: String.Encoding.utf8){
errorMsg = error
}
print("Login failed! error \(error)")
}
2.4 Get coin/token account list
Must successfully login the server before calling the function. Return all the coin/token accounts belongs to the login user.
Declaration
func getCoinAccountList(userAccount:SecuXUserAccount) -> (SecuXRequestResult, Data?)
Parameter
userAccount: Successfully logined user account.
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
getting coin/token account information is successful and coin/token account
information is in the user account's coinAccountArray, otherwise data might contain
an error message.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample
let (ret, data) = accManager.getCoinAccountList(userAccount: usrAcc)
if ret == SecuXRequestResult.SecuXRequestOK{
for coinAcc in usrAcc.coinAccountArray{
let tokenArr = coinAcc.tokenBalanceDict.keys
for token in tokenArr{
print("coin/token account: \(coinAcc.coinType) \(token)")
}
}
}else{
var errorMsg = ""
if let data = data, let error = String(data: data, encoding: String.Encoding.utf8){
errorMsg = error
}
print("Get coin/token info. failed! error \(error)")
}
2.5 Get coin/token account balance
Must successfully login the server before calling the function. Return the coin/token account balance
Declaration
func getAccountBalance(userAccount:SecuXUserAccount,
coinType: String? = nil,
token: String? = nil) -> (SecuXRequestResult, Data?)
Parameter
userAccount: A SecuXUserAccount object with login name and password
coinType: CoinType string
token: Token string
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
getting coin/token account balance is successful and coin/token account balance can
be found in the user account's coinAccountArray, otherwise data might contain
an error message.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample
let (ret, data) = accManager.getAccountBalance(userAccount: usrAcc,
coinType: "DCT", token: "SPC")
guard ret == SecuXRequestResult.SecuXRequestOK else{
print("get \(coinAcc.coinType) \(token) balance failed")
if let data = data{
print("Error: \(String(data: data, encoding: String.Encoding.utf8) ?? "")")
}
continue
}
let coinAcc = usrAcc.getCoinAccount(coinType: "DCT")
if let tokenBal = coinAcc.tokenBalanceDict["SPC"]{
print("\(coinAcc.coinType) \(token) \(tokenBal.theBalance)
\(tokenBal.theFormattedBalance) \(tokenBal.theUsdBalance)")
}
2.6 Change user login password
Must successfully login the server before calling the function.
Declaration
func changePassword(oldPwd: String, newPwd: String) -> (SecuXRequestResult, Data?)
Parameter
oldPwd: User current login password.
newPwd: User new login password.
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
password is changed successfully, otherwise data might contain
an error message.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample
DispatchQueue.global(qos: .default).async {
let accMgr = SecuXAccountManager()
let (ret, data) = accMgr.changePassword(oldPwd: oldpwd, newPwd: pwd)
if ret == SecuXRequestResult.SecuXRequestOK{
//Change password done
}else{
var error = ""
if let errData = data{
error = String(data: errData, encoding: String.Encoding.utf8) ?? ""
}
self.showMessageInMainThread(title: "Change password failed", message:error)
}
}
3. SecuXPayment related operations
Use SecuXPaymentManager object to do the operations below
let paymentManager = SecuXPaymentManager()
3.1 Parsing payment QRCode / NFC message
Declaration
func getPaymentInfo(paymentInfo: String)->(SecuXRequestResult, Data?)
Parameter
paymentInfo: Payment QRCode from P20/P22, or NFC string from P20/P22
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
parsing payment information is successful and data contains decoded payment
information in JSON format , otherwise data might contain an error message.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample return JSON format
{
"amount": "10",
"coinType": "DCT:SPC",
"deviceID": "4ab10000726b",
"deviceIDhash": "41193D32D520E114A3730D458F4389B5B9A7114D"
}
Note: "amount" and "coinType" are optional, QRCode from P20 will not generate
these items.
Sample
let (ret, data) = paymentManager.getPaymentInfo(paymentInfo: paymentInfo)
if ret == SecuXRequestResult.SecuXRequestOK, let data = data{
print("get payment info. done")
guard let responseJson = try? JSONSerialization.jsonObject(with: data, options: []) as? [String:Any] else{
print("Invalid json response from server")
return
}
guard let devIDHash = responseJson["deviceIDhash"] as? String else{
print("Response has no hashed devID")
return
}
var amount = "0"
if let amountinfo = payinfoJson["amount"] as? String, amountinfo != "null"{
amount = amountinfo
}
var cointype = ""
var token = ""
if let type = payinfoJson["coinType"] as? String, type != "null"{
if let pos = type.firstIndex(of: ":"){
cointype = String(type[..<pos])
token = String(type[type.index(after: pos)...])
}
}
}
3.2 Get store information
Declaration
func getStoreInfo(devID:String) -> (SecuXRequestResult, String, SecuXStoreInfo?)
Parameter
devID: Hashed device ID from the "getPaymentInfo" function
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
getting store information is successful, retuned store info. object contrains all the store related information, e.g. name, logo..., otherwise data might contain an error message.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample
let (reqRet, error, info) = paymentManager.getStoreInfo(devID: devIDHash)
guard reqRet == SecuXRequestResult.SecuXRequestOK,
let storeInfo = info,
let imgStore = storeInfo.logo,
storeInfo.coinTokenArray.count > 0,
storeInfo.name.count > 0 else {
self.showMessageInMainThread(title: "Get store information from server failed!", message: error)
return
}
3.3 Do payment
Declaration
func doPaymentAsync(storeInfo: String, paymentInfo: String)
Parameter
storeInfo: Store information JSON string from the info value of the SecuXStoreInfo object
paymentInfo: Payment information JSON string.
Delegate
protocol SecuXPaymentManagerDelegate{
func paymentDone(ret: Bool, transactionCode:String, errorMsg: String)
func updatePaymentStatus(status: String)
}
paymentDone: Called when payment is completed.
Returns payment result and an error message.
updatePaymentStatus: Called when payment status is changed.
Payment status are:
"Device connecting...",
"DCT transferring..."
"Device verifying..."
Note: You must implement the SecuXPaymentManagerDelegate and set it to the
SecuXPayment delegate, e.g. self.paymentManager.delegate = self
Sample
class ViewController: UIViewController {
...
func doPayment(){
...
let (reqRet, error, info) = paymentManager.getStoreInfo(devID: devIDHash)
guard reqRet == SecuXRequestResult.SecuXRequestOK,
let storeInfo = info,
let imgStore = storeInfo.logo,
storeInfo.coinTokenArray.count > 0,
storeInfo.name.count > 0 else {
self.showMessageInMainThread(title: "Get store information from server failed!", message: error)
return
}
var payinfoDict = [String : String]()
payinfoDict["amount"] = "12"
payinfoDict["coinType"] = "DCT"
payinfoDict["token"] = "SPC"
payinfoDict["deviceID"] = deviceID
guard let jsonData = try? JSONSerialization.data(withJSONObject: payinfoDict, options: []),
let paymentInfo = String(data: jsonData, encoding: String.Encoding.utf8) else{
self.showMessage(title: "Invalid payment information", message: "Payment abort!")
return
}
paymentManager.doPaymentAsync(storeInfo: storeInfo.info,
paymentInfo: paymentInfo)
}
}
extension ViewController: SecuXPaymentManagerDelegate{
func paymentDone(ret: Bool, transactionCode: String, errorMsg: String) {
print("paymentDone \(ret) \(transactionCode) \(errorMsg)")
if ret{
showMessage(title: "Payment success!", message: "")
let (ret, payhis) = self.paymentManager.getPaymentHistory(token:"SPC", transactionCode: transactionCode)
if ret == SecuXRequestResult.SecuXRequestOK, let his = payhis{
print("payment detail: \(his.amount) \(his.storeName) \(his.storeID) \(his.storeTel) \(his.storeAddress)")
}
}else{
showMessage(title: "Payment fail!", message:errorMsg)
}
}
func updatePaymentStatus(status: String) {
print("updatePaymentStatus \(status)")
}
}
3.4 Get all payment history
Declaration
func getPaymentHistory(token:String, pageIdx:Int, pageItemCount: Int)
->(SecuXRequestResult, [SecuXPaymentHistory])
Parameter
token: Payment token, can be empty
pageIdx: History item page index starts from 0, e.g. 0,1,2,3...
pageItemCount: Number of history items request, e.g. 5, 10, 20 ...
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
SecuXPaymentHistory objects are in the returned array. If number of the history
objects in the return array less than the input pageItemCount, there is no
more history items.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample
var pageIdx = 0
let pageItemCount = 20
while (true){
let (ret, payHisArr) = paymentManager.getPaymentHistory(token: "",
pageIdx: pageIdx,
pageItemCount: pageItemCount)
if ret != SecuXRequestResult.SecuXRequestOK{
print("get payment history failed \(ret)")
return
}
var idx = 0
for payHis in payHisArr{
print("\(idx) \(payHis.coinType) \(payHis.token) \(payHis.transactionTime)
\(payHis.amount) \(payHis.detailsUrl)")
idx += 1
}
if payHisArr.count < pageItemCount{
break
}
pageIdx += 1
}
3.5 Get payment history from transaction code
Declaration
func getPaymentHistory(token:String, transactionCode:String)
->(SecuXRequestResult, SecuXPaymentHistory?)
Parameter
token: Payment token, e.g. SPC, DCT
transactionCode: Payment transaction code from SecuXPaymentManagerDelegate when
payment done
Return value
SecuXRequestResult shows the operation result. If the result is SecuXRequestOK,
payment history is in the returned SecuXPaymentHistory object.
Note: if return result is SecuXRequestNoToken / SecuXRequestUnauthorized, the login
session is timeout, please relogin the system.
Sample
let (ret, payhis) = self.paymentManager.getPaymentHistory(token:"SPC",
transactionCode: transactionCode)
if ret == SecuXRequestResult.SecuXRequestOK, let his = payhis{
print("payment detail: \(his.amount) \(his.storeName) \(his.storeID)
\(his.storeTel) \(his.storeAddress)")
}
Author
maochuns, [email protected]
License
secux-paymentkit is available under the MIT license. See the LICENSE file for more info.