pscbonline-ios/PSCBOnline/Sources/Models/CardData.swift

93 lines
2.8 KiB
Swift

//
// CardData.swift
// PSCB-OOS-iOS
//
// Created by Antonov Ilia on 21.10.2020.
//
import Foundation
import PassKit
public enum CardDataError: Error {
case invalidExiryDate(String)
case invalidCvCode
case invalidPan
}
/// Billing info.
/// Detailed card information
public struct CardData {
let pan: String
let expiryYear: Int
let expiryMonth: Int
let cardholder: String?
let cvCode: String
/// Constructs card data from all necessary for billing fields
///
/// - Parameters:
/// - pan: Card number
/// - expiryYear: A full year number (e.g: `2020`). For production cannot be in the past
/// - expiryMonth: A month number from 1 to 12.
/// - cvCode: CVC/CVV number
/// - cardholder: (Optional) Cardholder name in latin.
///
/// - Returns: optional instance of a new card. If validation fails returns nil
public init?(pan: String, expiryYear: Int, expiryMonth: Int, cvCode: String, cardholder: String? = nil) {
guard expiryMonth >= 1 && expiryMonth <= 12 else {
print("Month can be between 1 and 12")
return nil
}
#if !DEBUG
// todo check year + month in the past
let currentYear = Calendar.current.component(.year, from: Date())
guard expiryYear >= currentYear else {
print("Year must be current or in the future")
return nil
}
#endif
self.pan = pan
self.expiryMonth = expiryMonth
self.expiryYear = expiryYear
self.cvCode = cvCode
self.cardholder = cardholder
}
/// - Returns: A last 2 digits of the expiry year
public func getExpYearString() -> String {
return String(String(expiryYear).dropFirst(2))
}
/// - Returns: A zero padded expiry month string
public func getExpMonthString() -> String {
return expiryMonth < 10 ? "0\(self.expiryMonth)" : String(self.expiryMonth)
}
}
extension CardData {
internal static let pubKey: Data = {
let key = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPQsWyHaynwoc2tuMbengf1SFase9tPnwtPh4o1tR+94xsWztADdhhUaUBk/68ipaoZE8uSnM9UgdEPmOotFXyUCAwEAAQ=="
return Data(base64Encoded: key)!
}()
/// Produces a cryptogram string from given `CardData`
/// See: https://docs.pscb.ru/oos/shpa.html#shlyuz-prozrachnoj-avtorizacii-sozdanie-platezha-otvet
///
/// - Returns: a Base64 encoded cryptogram string
public func toCryptgramString() throws -> String {
let month = self.getExpMonthString()
let year = self.getExpYearString()
let joinedString = "\(self.pan)|\(month)|\(year)|\(cvCode)\(self.cardholder ?? "")"
let base64Encode = try RSAHelper.encryptEncodeBase64(message: joinedString)
return base64Encode
}
}