From 7e3b0e0d2a0c30872d8e5b52fc0d445045460b78 Mon Sep 17 00:00:00 2001 From: PayHereDevs Date: Wed, 18 May 2022 12:56:21 +0530 Subject: [PATCH] SDK crashes for Pre-approval & Recurring type, when payment UI is not loaded fully (#16) * Add missing images and changed default mid on demoapp * Add handling of waiting for payment UI * Bump versions Co-authored-by: Thisura98 --- demoapp/ViewController.swift | 7 +- payHereSDK.podspec | 2 +- payHereSDK.xcodeproj/project.pbxproj | 4 + payHereSDK/Sources/Model/PaymentUI.swift | 4 + .../Sources/PHBottomViewController.swift | 123 +++++++++++------- payHereSDK/Sources/WaitUntil.swift | 68 ++++++++++ .../warning.imageset/Contents.json | 23 ++++ .../warning.imageset/warning.png | Bin 0 -> 3860 bytes .../warning.imageset/warning@2x.png | Bin 0 -> 8421 bytes .../warning.imageset/warning@3x.png | Bin 0 -> 4728 bytes 10 files changed, 181 insertions(+), 50 deletions(-) create mode 100644 payHereSDK/Sources/WaitUntil.swift create mode 100644 payHereSDK/Sources/image.xcassets/warning.imageset/Contents.json create mode 100644 payHereSDK/Sources/image.xcassets/warning.imageset/warning.png create mode 100644 payHereSDK/Sources/image.xcassets/warning.imageset/warning@2x.png create mode 100644 payHereSDK/Sources/image.xcassets/warning.imageset/warning@3x.png diff --git a/demoapp/ViewController.swift b/demoapp/ViewController.swift index 2cf2ea5..fa6805e 100644 --- a/demoapp/ViewController.swift +++ b/demoapp/ViewController.swift @@ -13,7 +13,7 @@ class ViewController: UIViewController { - let merchantID = "1211149" //"1211149" //"210251" + let merchantID = "210251" //"1211149" //"210251" var initRequest : PHInitialRequest? @@ -157,6 +157,11 @@ extension ViewController : PHViewControllerDelegate{ func onErrorReceived(error: Error) { print("✋ Error",error) + + let ac = UIAlertController(title: "Error Occurred", message: error.localizedDescription, preferredStyle: .alert) + let okAction = UIAlertAction(title: "OK", style: .default, handler: nil) + ac.addAction(okAction) + present(ac, animated: true, completion: nil) } func onResponseReceived(response: PHResponse?) { diff --git a/payHereSDK.podspec b/payHereSDK.podspec index 9d8e72d..16c591b 100644 --- a/payHereSDK.podspec +++ b/payHereSDK.podspec @@ -8,7 +8,7 @@ s.summary = "Mobile SDK for payHere" s.requires_arc = true # 2 -s.version = "3.0.3" +s.version = "3.0.4" # 3 s.license = { :type => "MIT", :file => "LICENSE" } diff --git a/payHereSDK.xcodeproj/project.pbxproj b/payHereSDK.xcodeproj/project.pbxproj index 394664d..f0775bf 100644 --- a/payHereSDK.xcodeproj/project.pbxproj +++ b/payHereSDK.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ C7E9F6C1277C76B70013D2D4 /* PHBottomSheetTableViewSectioHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = C7E9F6C0277C76B70013D2D4 /* PHBottomSheetTableViewSectioHeader.xib */; }; D68AD170D5E2B0BDB07655F7 /* Pods_demoapp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C5C73F5CCE9DE42DB20A5A09 /* Pods_demoapp.framework */; }; F503041127E4744C008844E5 /* PHUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F503041027E4744C008844E5 /* PHUtils.swift */; }; + F505EC902833418C00F6AC4F /* WaitUntil.swift in Sources */ = {isa = PBXBuildFile; fileRef = F505EC8F2833418C00F6AC4F /* WaitUntil.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -144,6 +145,7 @@ D10E7597F9AFFB0D66AE7793 /* Pods_payHereSDK.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_payHereSDK.framework; sourceTree = BUILT_PRODUCTS_DIR; }; E98AA3326CB2BEE8C4106D35 /* Pods-payHereSDK.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-payHereSDK.debug.xcconfig"; path = "Pods/Target Support Files/Pods-payHereSDK/Pods-payHereSDK.debug.xcconfig"; sourceTree = ""; }; F503041027E4744C008844E5 /* PHUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PHUtils.swift; sourceTree = ""; }; + F505EC8F2833418C00F6AC4F /* WaitUntil.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WaitUntil.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -292,6 +294,7 @@ C746D50F234C9A7300F9D06F /* PHPrecentController.swift */, C799349323A8E72B005E5A7B /* PHBottomViewController.swift */, C72750CC23A75B8A00AE9037 /* image.xcassets */, + F505EC8F2833418C00F6AC4F /* WaitUntil.swift */, ); path = Sources; sourceTree = ""; @@ -492,6 +495,7 @@ buildActionMask = 2147483647; files = ( C7A7DA3323C5D6F90029210E /* HeaderCollectionReusableView.swift in Sources */, + F505EC902833418C00F6AC4F /* WaitUntil.swift in Sources */, C7E9F6B8277C2FA20013D2D4 /* PayWithHelaPayTableViewCell.swift in Sources */, C72A13D12784500D00F08E22 /* PaymentOptionTableViewCell.swift in Sources */, 8A74D7FC20528E5C00CF10AB /* Address.swift in Sources */, diff --git a/payHereSDK/Sources/Model/PaymentUI.swift b/payHereSDK/Sources/Model/PaymentUI.swift index 4f7a3d1..1fdf9b6 100644 --- a/payHereSDK/Sources/Model/PaymentUI.swift +++ b/payHereSDK/Sources/Model/PaymentUI.swift @@ -17,6 +17,10 @@ import Foundation var status: Int? var msg: String? var data: [String: Datum]? + + func getDataCount() -> Int{ + return data?.keys.count ?? 0 + } } // MARK: - Datum diff --git a/payHereSDK/Sources/PHBottomViewController.swift b/payHereSDK/Sources/PHBottomViewController.swift index 8d5a4b0..ce13875 100644 --- a/payHereSDK/Sources/PHBottomViewController.swift +++ b/payHereSDK/Sources/PHBottomViewController.swift @@ -55,6 +55,7 @@ internal class PHBottomViewController: UIViewController { private var statusResponse : StatusResponse? private var timer : Timer? private var isBackPressed : Bool = false + private var waitUntilPaymentUI: WaitUntil! private let net = NetworkReachabilityManager() private var bankAccount : [PaymentMethod] = [] @@ -772,31 +773,15 @@ internal class PHBottomViewController: UIViewController { if let url = submitResponse.data?.url{ - self.tableView.isHidden = true - self.webView.isHidden = false - - self.webView.contentMode = .scaleAspectFill - self.webView.uiDelegate = self - self.webView.navigationDelegate = self - - self.calculateWebHeight() - - if let URL = URL(string: url){ - - let request = URLRequest(url: URL) - self.webView.load(request) - self.progressBar.isHidden = false - self.webView.isHidden = true - - - }else{ - //MARK:TODO - //ERROR HANDLING - self.close { - let error = NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) - self.delegate?.onErrorReceived(error: error) + waitUntilPaymentUI = WaitUntil( + condition: { [weak self] in + return (self?.paymentUI.getDataCount() ?? 0) > 0 + }, + onCompletion: { [weak self] in + self?.loadPayHereSubmitUI(url: url) } - } + ) + }else{ self.close { let error = NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) @@ -806,39 +791,51 @@ internal class PHBottomViewController: UIViewController { } - private func initWebView(_ submitResponse : PayHereInitnSubmitResponse){ + private func loadPayHereSubmitUI(url: String){ + self.tableView.isHidden = true + self.webView.isHidden = false + self.webView.contentMode = .scaleAspectFill + self.webView.uiDelegate = self + self.webView.navigationDelegate = self + self.calculateWebHeight() + + if let URL = URL(string: url){ + + let request = URLRequest(url: URL) + self.webView.load(request) + self.progressBar.isHidden = false + self.webView.isHidden = true + + + }else{ + //MARK:TODO + //ERROR HANDLING + self.close { + let error = NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) + self.delegate?.onErrorReceived(error: error) + } + } + } + + private func initWebView(_ submitResponse : PayHereInitnSubmitResponse){ // MARK: TODO Remove comment when submit API Precent if let url = submitResponse.data?.redirection?.url{ // self.collectionView.isHidden = true - self.webView.isHidden = false - - self.webView.contentMode = .scaleAspectFill - self.webView.uiDelegate = self - self.webView.navigationDelegate = self - self.calculateWebHeight() - - if let URL = URL(string: url){ - - let request = URLRequest(url: URL) - self.webView.load(request) - self.progressBar.isHidden = false - self.webView.isHidden = true - - - }else{ - //MARK:TODO - //ERROR HANDLING - self.close { - let error = NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) - self.delegate?.onErrorReceived(error: error) + waitUntilPaymentUI = WaitUntil( + condition: { [weak self] in + return (self?.paymentUI.getDataCount() ?? 0) > 0 + }, + onCompletion: { [weak self] in + self?.loadPayHereInitAndSubmitUI(url: url) } - } + ) + }else{ self.close { let error = NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) @@ -848,6 +845,33 @@ internal class PHBottomViewController: UIViewController { } + private func loadPayHereInitAndSubmitUI(url: String){ + self.webView.isHidden = false + + self.webView.contentMode = .scaleAspectFill + self.webView.uiDelegate = self + self.webView.navigationDelegate = self + + self.calculateWebHeight() + + if let URL = URL(string: url){ + + let request = URLRequest(url: URL) + self.webView.load(request) + self.progressBar.isHidden = false + self.webView.isHidden = true + + + }else{ + //MARK:TODO + //ERROR HANDLING + self.close { + let error = NSError(domain: "", code: 401, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"]) + self.delegate?.onErrorReceived(error: error) + } + } + } + func calculateWebHeight(){ var viewSize : ViewSize? @@ -1174,7 +1198,10 @@ internal class PHBottomViewController: UIViewController { } } - case .failure(_): + case .failure(let error): + self.close { + self.delegate?.onErrorReceived(error: error) + } break } diff --git a/payHereSDK/Sources/WaitUntil.swift b/payHereSDK/Sources/WaitUntil.swift new file mode 100644 index 0000000..fb9e4e0 --- /dev/null +++ b/payHereSDK/Sources/WaitUntil.swift @@ -0,0 +1,68 @@ +// +// WaitUntil.swift +// payHereSDK +// +// Created by Thisura Dodangoda on 2022-05-17. +// Copyright © 2022 PayHere. All rights reserved. +// + +import Foundation + +/** + Wait until a condition is true to execute a handler + */ +internal class WaitUntil{ + + private let condition: (() -> Bool)! + private let completion: (() -> Void)! + private let timeout: TimeInterval! + + init( + condition: @escaping () -> Bool, + onCompletion: @escaping () -> Void, + timeout: TimeInterval = 5.0 + ){ + self.condition = condition + self.completion = onCompletion + self.timeout = timeout + + run() + } + + private func run(){ + guard !condition() else { + completion() + return + } + + DispatchQueue.global().async { [weak self] in + guard let `self` = self else { return } + + let start = Date().timeIntervalSince1970 + var shouldBreak = false + var isTimeout = false + + while(!shouldBreak){ + usleep(80000) + + DispatchQueue.main.async { + if self.condition(){ + shouldBreak = true + } + } + + if ((Date().timeIntervalSince1970 - start) > self.timeout){ + shouldBreak = true + isTimeout = true + } + } + + guard !isTimeout else { return } + + DispatchQueue.main.async { + self.completion() + } + } + } + +} diff --git a/payHereSDK/Sources/image.xcassets/warning.imageset/Contents.json b/payHereSDK/Sources/image.xcassets/warning.imageset/Contents.json new file mode 100644 index 0000000..acb4256 --- /dev/null +++ b/payHereSDK/Sources/image.xcassets/warning.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "warning.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "warning@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "warning@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/payHereSDK/Sources/image.xcassets/warning.imageset/warning.png b/payHereSDK/Sources/image.xcassets/warning.imageset/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..af8ac97db591a7c33c9788c93bed6ceb1d097dba GIT binary patch literal 3860 zcmbVPS2&#A+J1G>yCEWs65Sw(8l6ER2GK5jDbR5Jnp%Q9_Io z3`Q5d6Sn-KotOLk(3v9B-ftHK?n8#0D}1e;B`0voLxt+R{_8e0s!l_03e?Z0IbimP=<=v z2Z2szQ0E5^0HJG54iFQt1Akv2xP~&p&40BPfdD}Ce>oulL_GzF|J!+Z&3`4=-|;UK ze`Tme{~xwn9MaLAk~9 z?AOtm(zemkp|w#sDZL&GLELN2cCamd4Y?Vy2;u)&37$OrE%6^)zScA5Nhv~xk`L>t z+@4*i8?O6#9r%9<+E+;Q2RS%c!yu>ze}s-J-*Xg)+G^B&`bui|*%hlTpXB>@P-_HV z{5ISq?Af8F)(;^lexEi0c=b$ zyZ}#bZPUiznz(Sl#J>)_9b>^0oGYLNRl2%()+mC$vUT+%=wBX>)unYAp{UcxVL~+V zRSKG79JDWzB#HVuwl;qW?u}}5=UIbixb87X3#YIX|F(GJDckIH^cG1&O44C48sW^Ww|v4V3Yu&P6$^*4 zLQb@ivHCfVm+~FH{Y;61?={UZJgA9L!=@;Gu8FS5z zy>)zAZt`klswT6RhIa1p0r#hUv$T|a_+RSq^F4;tjLA9-Ns8r(YQK%X`;9?vC5ut} z{qbO?UDi zJzJlCn3$9Xd`17j>J-`1rCX6;{R34X2VKiUjBN7t`(-tQh*MQdb#x8V_xN0X&UVd> z_aTJ*(cA7CPf8IxCS9lE-e2I&!=Gge!Au3jE(1KWqYlkbrn$RYGT}XPTZoNg^ zVVkFlB{?ps8ytEbiAnHdoul(5ER){UTVn5&waUzlVTjis8tcG`le0~lal7IYy@;3B)=}j0JM5yDnIQD)4MtQ=)DWb?gY-~pB2I}8>PHmR&H4o3BAWX0V=9&NLp z{uu?+f;ILBFq-~t*vpx!qo2gL2nwY~9e0M^rmI2Q;uB#hxiuM^w5)5)E(4RIQW;Vx zGOz?v$)4)f3-_&HQ^!A~iN~|05t5n1)w#VC#Ih?^lm3;*UfZ{XHE3@2dm1+(zpn)p zeL!h=OdXg{GcO81i0pCkBdg~VXL_4^v!eoVcXB#+8NR$&wF^HZ@U6}PEA3({(t77R z!L;gm+YO8}@DHXooMY?{!;^hd?=ErG?io#z6qY(_b>OPqN0{t8zTLOp-Q``$}wYA@1@AZe@cdmP-Bh<^YdFz!v&+h`hSY3R_31g&J`6f)NoR=4~9f z!zEpCyI!YM!ZcrcSRcBTx7UT%DE%H$sSo|*hYn4skX}Q3i!`EIUA8LN(DON1F4HWauvM7?10_#b1t+UM(Fb)lQ7@FUAXeHUPqS zH3HGrk%?HuLT{TS?E6;=k}_k1k-=cI?7DfQhPO`B4Wyvy0m~*#nw1DlTGX4Zej0Zm zlo*%)PXt_sCa_{K>-AK_w722?WKBr$9^R(F=w^G+*H=~B2Om>Kou1d0srr4CG*I`n za6XginXA}p_pkH`I@GmqSq_V-HCh{aal`+V(c-C|wHE$je*xch(5(y~Ys{A}j}fch z^}&CrmGFDJk3>(9RM7<5{R*N5*%GEm?2df=&>crbi|^)17_t}#<+OGLR_(g!qt08C zbaUD0sEiVqtwp_i*mmPll{OQyK|9mz*wBXwbYzMc{aT8i?}ONNu_D@~DClt@UdM+# zRa|ta)NT2u%>`U$jGZq4)q?3Y`GimvaTQgpHTp-no-XaJ=EQ0?V!@ly!QJYIxAJBD z_(4DrGO=xf_)VA6N&8@j3VHYn_-;!Yw>enwu0v$+y`8S5pFFbeiy~ba)FB&z0xW2* z;4GHxY2aAu)hs$AJ3@xTb75mLak>0WLa}kmSH2N!xN}kS z-QT#H7lF=#CBb^fFz>rxK0nET2Hd?c99HSVf)bC8=f4cpjq>Q|l@Ja47uZG=c_-Ke z7(UShgUYKaFv_@(?R~t~1|{4-$24Rk`*jmVOs`{l4-1rjrmuu8CcpwQ*PJ`?jzXFfCSqs)R>EJra2p z>XQO(h%OL6TJ#A2Gu5Yo<`{Ipw;U~~mYgZ45a?T5lno^?h?MeR;U7QQrT>gvPVc)K zegm%l4KWbO4HhDfV1z2Kv+_xNkueh9TY>MH%N>lv$_2f5Ami{L#r`eu%*=efCqR>G z6NZ&6(S$hW82Bokk%Jp~3h+vo4az4#3?d+o;{uVBvG!#Cqfc}3T5q@O`H?|^z0g$g zC-^pVx@u7VJ3UuQ#$y!f(LEMUgKte>7q?Zv5?JAG)^}`>o-tE~?ZLrXP1kx3%LDGH zyYCcVFUVo~)UY-VJ$Ux3WmPYeN9)gyHR>Bip58n`A-X+gk(Kg@gQ!G%=dsh##E3oC2>1p9r^+cbt$}oS|5RZv@fxMX5 zly2E8tFFHMi5J|SbU2c-I@d8Z0~}5#}%s z=1PfWP12Cf=|0K`sc2wCX_>Uf_+a@1c!PcSC{Br#D`#W)%gh%&eDenK>YkQ_qJ&rW z2z-cOXKG>KR{iI&!sFNuo498xM=ur0^3x(;d*q{Y6`_vn$u%K+Mr#x}{m#o2TF z77M0f?b|Vmr^%)ae^MM4L6+LNa4y4|)pR36#K__fArWu4YScbaX#?aix%72}l+Y{F z-CX6_+aWOqc5zID8=lc2r%vmw zHmhL~K~S~4e8v;C?Pzn+&CjBHfr87>m4+!%kwr5yS_);j!-s1e!H8=iv&W&P4JbsU{=UbIr9K;`Uqkh(_H~8`D=5B0n$rd{ zCC8crVwrGWkRSL3>FHVk4?gDi8GcI#BJ2>JF?ZhGf57fFtY4&fh?)4)5Q$8~8?PR= zM01sJu1|&ZcJe*r4_d&E7}**UcE{}eNdUKn!tljy(K|P!NF~_Z@if`bJUF_RJ~*t5 z{_w>r!Mrn%Yd@Pl5zelh>iH8wZSqS)!ROq2U!a>C6io4^$<8{fL)=Mso4QPl5r4GB zJb48T;+hYlO?&T69#N%$*?LtKB^={@$;cAFgFx?h(CN>z7QZ;_D+LdEPz>l{D~~sQ zz`6Ephs|5^0U%H4mG*>c1najjBC|(J3GMtzoOA)x3Rj$|xmBh}htTx^)$JkoPjl@& zzneR01nOqy@D?ui)IzV^!syy9} zMHJ*;RUsv-=Jt}br=}dyaB-hOT604^P;kb(rQj0VtwuN1bE5Eg+DdC#En?0Oo;atl zI~OSV@~A$_0UKn2&Z23$0KcbdoZytef=tx4jJVhRP(`(&Q(I;LG};dK<(tGdUu$0 k{UQIeDgFO#Kcf8#*wiI=iB-)r`@1eeH6LnJso5g_18H9`Z~y=R literal 0 HcmV?d00001 diff --git a/payHereSDK/Sources/image.xcassets/warning.imageset/warning@2x.png b/payHereSDK/Sources/image.xcassets/warning.imageset/warning@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..724f6e59dcf2569ee6c9b1f4252377e0ef28d201 GIT binary patch literal 8421 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 literal 0 HcmV?d00001 diff --git a/payHereSDK/Sources/image.xcassets/warning.imageset/warning@3x.png b/payHereSDK/Sources/image.xcassets/warning.imageset/warning@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..3d96c8cc7a11daab5c6232645873b61d346a4b61 GIT binary patch literal 4728 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 C`?B=_ literal 0 HcmV?d00001