iOS Native SDK(v3) - PortOne's Checkout
Please follow steps below to setup iOS Native SDK and start accepting payment via PortOne.
For initial setup, go through v2 documentation Native iOS - Payment SDK: v2.
To open the payment link call the checkOutUI method from SDK as below:
```swift
import PortoneSDK
let token = createJWTToken()
let payload = prepareConfig()
checkout?.checkOutUI(config: payload, jwtToken: token, onCompletionHandler: { (result) in
switch result{
case .success(let data):
print("Data", data)
case .failure(let error):
print("error", error)
}
})
```
JWT token Generation:
Generate JWT token by using the payload and portone secretKey
Required payload:
var payload = {iss: 'CHAIPAY',sub: 'lzrYFPfyMLROallZ',iat: new Date().getTime(),exp: new Date().getTime() + 100 * 1000,};var secretKey ="0e94b3232e1bf9ec0e378a58bc27067a86459fc8f94d19f146ea8249455bf242";Parameter Description Values iss Issuer Default Value: "CHAIPAY" sub Subject CHAIPay Key iat Issued Timestamp in sec Timestamp in sec exp Expiry Timestamp in sec Timestamp in sec+100 Algorithm to use for generating token - “HS256”
func createJWTToken() -> String {struct Header: Encodable {let alg = "HS256"let typ = "JWT"}func generateCurrentTimeStamp (extraTime: Int = 0) -> Int {let currentTimeStamp = Date().timeIntervalSince1970 + TimeInterval(extraTime)let token = String(currentTimeStamp)return Int(currentTimeStamp)}struct Payload: Encodable {let iss = "CHAIPAY"let sub = "aiHKafKIbsdUJDOb"let iat = generateCurrentTimeStamp()let exp = generateCurrentTimeStamp(extraTime: 10000)}let secret = "2601efeb4409f7027da9cbe856c9b6b8b25f0de2908bc5322b1b352d0b7eb2f5"let privateKey = SymmetricKey(data: secret.data(using: .utf8)!)let headerJSONData = try! JSONEncoder().encode(Header())let headerBase64String = headerJSONData.urlSafeBase64EncodedString()let payloadJSONData = try! JSONEncoder().encode(Payload())let payloadBase64String = payloadJSONData.urlSafeBase64EncodedString()let toSign = (headerBase64String + "." + payloadBase64String).data(using: .utf8)!let signature = HMAC<SHA256>.authenticationCode(for: toSign, using: privateKey)let signatureBase64String = Data(signature).urlSafeBase64EncodedString()let token = [headerBase64String, payloadBase64String, signatureBase64String].joined(separator: ".")return token}Sample Payload:
func prepareConfig() -> WebTransactionRequest {let billingAddress = BillingAddress(city: "VND", countryCode: "VN", locale: "en", line1: "address1", line2: "address2", postalCode: "400202", state: "Mah")let merchantDetails = MerchantDetails(name: "Downy", logo: "https://upload.wikimedia.org/wikipedia/commons/a/a6/Logo_NIKE.svg", backUrl: "https://demo.portone.cloud/checkout.html", promoCode: "Downy350", promoDiscount: 0, shippingCharges: 0.0)let billingDetails = BillingDetails(billingName: "Test mark", billingEmail: "markweins@gmail.com", billingPhone: UserDefaults.getMobileNumber ?? "", billingAddress: billingAddress)let shippingAddress = ShippingAddress(city: "abc", countryCode: "VN", locale: "en", line1: "address_1", line2: "address_2", postalCode: "400202", state: "Mah")let shippingDetails = ShippingDetails(shippingName: "xyz", shippingEmail: "xyz@gmail.com", shippingPhone: "1234567890", shippingAddress: shippingAddress)var orderDetails: [OrderDetails] = []for details in self.selectedProducts {let product = OrderDetails(id: details.id ?? "", name: details.title ?? "", price: details.price ?? 0, quantity: 1, imageUrl: details.imageName ?? "")orderDetails.append(product)}let transactionRequest = WebTransactionRequest(chaipayKey: selectedEnvironment?.key ?? "", merchantDetails: merchantDetails, merchantOrderId: "MERCHANT\(Int(Date().timeIntervalSince1970 * 1000))", amount: getTotalAmount(), currency: "VND", signatureHash: "123", billingAddress: billingDetails, shippingAddress: shippingDetails, orderDetails: orderDetails, successURL: "https://test-checkout.portone.cloud/success.html", failureURL: "https://test-checkout.portone.cloud/failure.html", redirectURL: "chaipay://checkout", countryCode: "VN", expiryHours: 2, source: "api", description: "test dec", showShippingDetails: true, showBackButton: false, defaultGuestCheckout: false, isCheckoutEmbed: false )print(transactionRequest)return transactionRequest}Should implement the delegate methods as below to get the response of failure and success callbacks from the webView.
extension AppDelegate: CheckoutDelegate {func transactionErrorResponse(_ error: Error?) {print("Eror",error)}var viewController: UIViewController? {return AppDelegate.shared.window?.rootViewController}func transactionResponse(_ webViewResponse: WebViewResponse?) {// receives the response of the transactionNotificationCenter.default.post(name: NSNotification.Name("webViewResponse"), object: webViewResponse)print("webview response", webViewResponse)}}Sample response#
Success callback :
{"merchant_order_ref" : "MERCHANT1630665361511","message" : "","is_success" : "true","order_ref" : "1xcrkpVPNq5vuqQDe3eqrHD3OcG","deep_link" : "","channel_order_ref" : "1xcrkpVPNq5vuqQDe3eqrHD3OcG","additional_data" : null,"redirect_url" : ""}Failure Callback:
{"chaipay_order_ref": "1wa0choxhAy2QtE9ix8aNt8T3Mf","channel_order_ref": "0","merchant_order_ref": "MERCHANT1628681469666","status": "Initiated","status_code": "4000","status_reason": "INVALID_TRANSACTION_ERROR"}