feat(ios): fix bugs in ios; complete implementation

pull/2/merge
codinronan 5 years ago
parent e6522e4154
commit 37e9065ad6

@ -54,22 +54,25 @@
</feature> </feature>
</config-file> </config-file>
<!-- <framework src="Stripe" type="podspec" spec="~> 15.0.0" /> <framework src="Stripe" type="podspec" spec="~> 15.0.0" />
<framework src="Alamofire" type="podspec" spec="~> 4.8.1" /> <framework src="Alamofire" type="podspec" spec="~> 4.8.1" />
<framework src="CardIO" type="podspec" spec="~> 5.4.1" /> --> <framework src="CardIO" type="podspec" spec="~> 5.4.1" />
<!-- https://github.com/cordova-develop/cordova-plugin-pods3/blob/master/plugin.xml --> <!-- https://github.com/cordova-develop/cordova-plugin-pods3/blob/master/plugin.xml -->
<pods use-frameworks="true"> <!-- <podspec>
<pod name="Stripe" spec="~> 15.0.0" /> <config>
<pod name="CardIO" spec="~> 5.4.1" /> <source url="https://github.com/CocoaPods/Specs.git"/>
<pod name="Alamofire" spec="~> 4.8.1" /> </config>
</pods> <pods use-frameworks="true">
<pod name="Stripe" spec="~> 15.0.0" />
<pod name="CardIO" spec="~> 5.4.1" />
<pod name="Alamofire" spec="~> 4.8.1" swift-version="4.2" />
</pods>
</podspec> -->
<source-file src="src/ios/StripeAPIClient.swift" /> <source-file src="src/ios/StripeAPIClient.swift" />
<source-file src="src/ios/StripePaymentOptions.swift" /> <source-file src="src/ios/StripePaymentOptions.swift" />
<source-file src="src/ios/StripePaymentsPluginConfig.swift" /> <source-file src="src/ios/StripePaymentsPluginConfig.swift" />
<source-file src="src/ios/StripePaymentsPlugin.swift" /> <source-file src="src/ios/StripePaymentsPlugin.swift" />
<!-- <framework src="Foundation.framework" /> -->
</platform> </platform>
</plugin> </plugin>

@ -22,20 +22,26 @@ class StripeAPIClient: NSObject, STPCustomerEphemeralKeyProvider {
} }
let parameters: [String: Any] = ["api_version": apiVersion] let parameters: [String: Any] = ["api_version": apiVersion]
let headers: HTTPHeaders = [ var headers: HTTPHeaders = [
// "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", // "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==",
"Accept": "application/json" "Accept": "application/json"
] ]
// TODO need xcode for this. // Assign any extra headers we've been provided. We COULD use Alamofire's custom auth header types,
// but that would require tracking & strongly typing the headers we pass from the app. Too much
// work that is not really necessary.
if PluginConfig.extraHTTPHeaders.count > 0 { if PluginConfig.extraHTTPHeaders.count > 0 {
// for each HTTPHeader in extraHTTPHeaders for key: String in PluginConfig.extraHTTPHeaders.keys {
// headers.add(header) headers[key] = PluginConfig.extraHTTPHeaders[key]
}
} }
print("[StripePaymentsPlugin](StripeAPIClient).createCustomerKey: requesting key from \(url) with headers: \(headers)")
Alamofire.request(url, method: .post, parameters: parameters, headers: headers) Alamofire.request(url, method: .post, parameters: parameters, headers: headers)
.validate(statusCode: 200..<300) .validate(statusCode: 200..<300)
.responseJSON { responseJSON in .responseJSON { responseJSON in
print("[StripePaymentsPlugin](StripeAPIClient).createCustomerKey: got server result: \(responseJSON)")
switch responseJSON.result { switch responseJSON.result {
case .success(let json): case .success(let json):
guard let data = json as? [String: AnyObject] else { guard let data = json as? [String: AnyObject] else {
@ -54,5 +60,4 @@ class StripeAPIClient: NSObject, STPCustomerEphemeralKeyProvider {
// completion(json, nil) // completion(json, nil)
} }
} }
} }

@ -15,6 +15,7 @@ import Stripe
private var paymentStatusCallback: String = "" private var paymentStatusCallback: String = ""
private var customerContext: STPCustomerContext! private var customerContext: STPCustomerContext!
private var paymentContext: STPPaymentContext! private var paymentContext: STPPaymentContext!
private var keyRetries: Int = 0
override func pluginInitialize() { override func pluginInitialize() {
super.pluginInitialize() super.pluginInitialize()
@ -23,6 +24,11 @@ import Stripe
@objc(addPaymentStatusObserver:) @objc(addPaymentStatusObserver:)
func addPaymentStatusObserver(command: CDVInvokedUrlCommand) { func addPaymentStatusObserver(command: CDVInvokedUrlCommand) {
paymentStatusCallback = command.callbackId paymentStatusCallback = command.callbackId
let resultMsg = [
"status": "LISTENER_ADDED"
]
successCallback(paymentStatusCallback, resultMsg, keepCallback: true)
} }
// MARK: Init Method // MARK: Init Method
@ -43,10 +49,10 @@ import Stripe
PluginConfig.ephemeralKeyUrl = dict["ephemeralKeyUrl"] as? String ?? "" PluginConfig.ephemeralKeyUrl = dict["ephemeralKeyUrl"] as? String ?? ""
PluginConfig.appleMerchantId = dict["appleMerchantId"] as? String ?? "" PluginConfig.appleMerchantId = dict["appleMerchantId"] as? String ?? ""
PluginConfig.companyName = dict["companyName"] as? String ?? "" PluginConfig.companyName = dict["companyName"] as? String ?? ""
PluginConfig.requestPaymentImmediately = dict["requestPaymentImmediately"] as? Bool ?? true PluginConfig.maximumKeyRetries = dict["maximumKeyRetries"] as? Int ?? 0
if let headersDict = dict["extraHTTPHeaders"] as? [String:String] { if let headersDict = dict["extraHTTPHeaders"] as? [String:String] {
PluginConfig.parseExtraHeaders(dict: headersDict) PluginConfig.extraHTTPHeaders = headersDict
} }
if !self.verifyConfig() { if !self.verifyConfig() {
@ -62,13 +68,19 @@ import Stripe
STPPaymentConfiguration.shared().appleMerchantIdentifier = PluginConfig.appleMerchantId STPPaymentConfiguration.shared().appleMerchantIdentifier = PluginConfig.appleMerchantId
} }
customerContext = STPCustomerContext(keyProvider: StripeAPIClient.shared) successCallback(command.callbackId, [ "status": "INIT_SUCCESS" ])
paymentContext = STPPaymentContext(customerContext: customerContext) }
paymentContext.delegate = self func createPaymentContext() {
paymentContext.hostViewController = self.viewController if (customerContext == nil || paymentContext == nil) {
customerContext = STPCustomerContext(keyProvider: StripeAPIClient.shared)
paymentContext = STPPaymentContext(customerContext: customerContext)
successCallback(command.callbackId, [ "status": "INIT_SUCCESS" ]) paymentContext.delegate = self
paymentContext.hostViewController = self.viewController
}
customerContext.clearCachedCustomer()
} }
@ -90,17 +102,18 @@ import Stripe
return return
} }
let paymentOptions = PaymentOptions(dict: options)
paymentContext.paymentAmount = paymentOptions.price
paymentContext.paymentCurrency = paymentOptions.currency
paymentContext.paymentCountry = paymentOptions.country
// Allow these to be overridden // Allow these to be overridden
PluginConfig.requestPaymentImmediately = options["requestPaymentImmediately"] as? Bool ?? PluginConfig.requestPaymentImmediately
if let headersDict = options["extraHTTPHeaders"] as? [String:String] { if let headersDict = options["extraHTTPHeaders"] as? [String:String] {
PluginConfig.parseExtraHeaders(dict: headersDict) PluginConfig.extraHTTPHeaders = headersDict
} }
createPaymentContext()
let paymentOptions = StripePaymentOptions(dict: options)
paymentContext.paymentAmount = paymentOptions.price
paymentContext.paymentCurrency = paymentOptions.currency
paymentContext.paymentCountry = paymentOptions.country
// This dialog collects a payment method from the user. When they close it, you get a context // This dialog collects a payment method from the user. When they close it, you get a context
// change event with the payment info. NO charge has been created at that point, NO source // change event with the payment info. NO charge has been created at that point, NO source
// has been created from the payment method. All that has happened is the user entered // has been created from the payment method. All that has happened is the user entered
@ -120,12 +133,19 @@ import Stripe
return return
} }
if (paymentContext == nil || customerContext == nil) {
let error = "[CONFIG]: Config is not set, init() must be called before using plugin"
errorCallback(command.callbackId, [ "status": "REQUEST_PAYMENT_ERROR", "error": error ])
return
}
doRequestPayment(command.callbackId) doRequestPayment(command.callbackId)
} }
func doRequestPayment(_ callbackId: String) { func doRequestPayment(_ callbackId: String) {
keyRetries = 0
successCallback(callbackId, [ "status": "REQUEST_PAYMENT_STARTED" ], keepCallback: true)
paymentContext.requestPayment() paymentContext.requestPayment()
successCallback(callbackId, [ "status": "REQUEST_PAYMENT_STARTED" ])
} }
@ -153,19 +173,24 @@ import Stripe
} }
print(callbackMessage) print(callbackMessage)
errorCallback(paymentStatusCallback, ["error": callbackMessage], keepCallback: true)
let alertController = UIAlertController( if (keyRetries < PluginConfig.maximumKeyRetries) {
title: "", keyRetries += 1
message: message,
preferredStyle: .alert let alertController = UIAlertController(
) title: "",
let retry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in message: message,
// Retry payment context loading preferredStyle: .alert
self.paymentContext.retryLoading() )
}) let retry = UIAlertAction(title: "Retry", style: .default, handler: { (action) in
alertController.addAction(retry) // Retry payment context loading
self.viewController.present(alertController, animated: true, completion: nil) self.paymentContext.retryLoading()
})
alertController.addAction(retry)
self.viewController.present(alertController, animated: true, completion: nil)
} else {
errorCallback(paymentStatusCallback, ["error": callbackMessage], keepCallback: true)
}
} }
func paymentContextDidChange(_ paymentContext: STPPaymentContext) { func paymentContextDidChange(_ paymentContext: STPPaymentContext) {
@ -197,11 +222,8 @@ import Stripe
"image": image "image": image
] ]
print("[StripePaymentsPlugin].paymentContextDidChange: \(resultMsg)")
successCallback(paymentStatusCallback, resultMsg, keepCallback: true) successCallback(paymentStatusCallback, resultMsg, keepCallback: true)
if isPaymentReady && PluginConfig.requestPaymentImmediately {
doRequestPayment(paymentStatusCallback)
}
} }
// This callback is triggered when requestPayment() completes successfully to create a Source. // This callback is triggered when requestPayment() completes successfully to create a Source.
@ -213,6 +235,7 @@ import Stripe
"source": paymentResult.source.stripeID "source": paymentResult.source.stripeID
] ]
print("[StripePaymentsPlugin].paymentContext.didCreatePaymentResult: \(resultMsg)")
successCallback(paymentStatusCallback, resultMsg, keepCallback: true) successCallback(paymentStatusCallback, resultMsg, keepCallback: true)
completion(nil) completion(nil)
} }
@ -242,12 +265,14 @@ import Stripe
"error": "[ERROR]: Unrecognized error while finishing payment: \(String(describing: error))" "error": "[ERROR]: Unrecognized error while finishing payment: \(String(describing: error))"
] ]
print("[StripePaymentsPlugin].didFinishWith: \(resultMsg)")
errorCallback(paymentStatusCallback, resultMsg, keepCallback: true) errorCallback(paymentStatusCallback, resultMsg, keepCallback: true)
return return
case .userCancellation: case .userCancellation:
resultMsg = [ "status": "PAYMENT_CANCELED" ] resultMsg = [ "status": "PAYMENT_CANCELED" ]
} }
print("[StripePaymentsPlugin].didFinishWith: \(resultMsg)")
successCallback(paymentStatusCallback, resultMsg, keepCallback: true) successCallback(paymentStatusCallback, resultMsg, keepCallback: true)
} }
@ -257,6 +282,8 @@ import Stripe
messageAs: data as [AnyHashable : Any] messageAs: data as [AnyHashable : Any]
) )
pluginResult?.setKeepCallbackAs(keepCallback) pluginResult?.setKeepCallbackAs(keepCallback)
print("[StripePaymentsPlugin](successCallback) sending result to \(callbackId), result: \(String(describing: pluginResult))")
self.commandDelegate!.send(pluginResult, callbackId: callbackId) self.commandDelegate!.send(pluginResult, callbackId: callbackId)
} }
@ -266,6 +293,8 @@ import Stripe
messageAs: data as [AnyHashable : Any] messageAs: data as [AnyHashable : Any]
) )
pluginResult?.setKeepCallbackAs(keepCallback) pluginResult?.setKeepCallbackAs(keepCallback)
print("[StripePaymentsPlugin](errorCallback) sending result to \(callbackId), result: \(data)")
self.commandDelegate!.send(pluginResult, callbackId: callbackId) self.commandDelegate!.send(pluginResult, callbackId: callbackId)
} }

@ -1,5 +1,3 @@
import Alamofire
// TODO: // TODO:
// We can add an option to execute the charge API-side, in which case // We can add an option to execute the charge API-side, in which case
// the developer would also need to provide their 'charge' endpoint, // the developer would also need to provide their 'charge' endpoint,
@ -11,17 +9,8 @@ public class StripePaymentsPluginConfig {
public var ephemeralKeyUrl: String = "" public var ephemeralKeyUrl: String = ""
public var appleMerchantId: String = "" public var appleMerchantId: String = ""
public var companyName: String = "" public var companyName: String = ""
public var requestPaymentImmediately: Bool = true public var maximumKeyRetries: Int = 0
public var extraHTTPHeaders: HTTPHeaders = [:] public var extraHTTPHeaders: [String:String] = [:]
// TODO need xcode for this
func parseExtraHeaders(dict: [String:String]) {
// extraHTTPHeaders.push(new HTTPHeader(dict[something]))
// this actually needs to replace them..dunno. I mean they'll just have
// duplicates and HTTPHeaders should be able to resolve them by updating the header
// if they're already there, using the latest value (later index in array).
// must confirm that works.
}
} }
let PluginConfig = StripePaymentsPluginConfig() let PluginConfig = StripePaymentsPluginConfig()

@ -5,8 +5,9 @@ var StripePaymentsPlugin = function () { };
StripePaymentsPlugin._paymentStatusObserverList = []; StripePaymentsPlugin._paymentStatusObserverList = [];
StripePaymentsPlugin._processFunctionList = function (array, param) { StripePaymentsPlugin._processFunctionList = function (array, param) {
for (var i = 0; i < array.length; i++) for (var i = 0; i < array.length; i++) {
array[i](param); array[i](param);
}
}; };
var paymentStatusCallbackProcessor = function (state) { var paymentStatusCallbackProcessor = function (state) {
@ -60,15 +61,16 @@ StripePaymentsPlugin.prototype.requestPayment = function (successCallback, error
//------------------------------------------------------------------- //-------------------------------------------------------------------
var instance = new StripePaymentsPlugin();
if (!window.plugins) { if (!window.plugins) {
window.plugins = {}; window.plugins = {};
} }
if (!window.plugins.StripePaymentsPlugin) { if (!window.plugins.StripePaymentsPlugin) {
window.plugins.StripePaymentsPlugin = new StripePaymentsPlugin(); window.plugins.StripePaymentsPlugin = instance;
} }
if (typeof module != 'undefined' && module.exports) { if (typeof module != 'undefined' && module.exports) {
module.exports = StripePaymentsPlugin; module.exports = instance;
} }

Loading…
Cancel
Save