feat(ios): fix bugs in ios; complete implementation
This commit is contained in:
parent
e6522e4154
commit
37e9065ad6
21
plugin.xml
21
plugin.xml
@ -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,15 +68,21 @@ import Stripe
|
|||||||
STPPaymentConfiguration.shared().appleMerchantIdentifier = PluginConfig.appleMerchantId
|
STPPaymentConfiguration.shared().appleMerchantIdentifier = PluginConfig.appleMerchantId
|
||||||
}
|
}
|
||||||
|
|
||||||
customerContext = STPCustomerContext(keyProvider: StripeAPIClient.shared)
|
|
||||||
paymentContext = STPPaymentContext(customerContext: customerContext)
|
|
||||||
|
|
||||||
paymentContext.delegate = self
|
|
||||||
paymentContext.hostViewController = self.viewController
|
|
||||||
|
|
||||||
successCallback(command.callbackId, [ "status": "INIT_SUCCESS" ])
|
successCallback(command.callbackId, [ "status": "INIT_SUCCESS" ])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func createPaymentContext() {
|
||||||
|
if (customerContext == nil || paymentContext == nil) {
|
||||||
|
customerContext = STPCustomerContext(keyProvider: StripeAPIClient.shared)
|
||||||
|
paymentContext = STPPaymentContext(customerContext: customerContext)
|
||||||
|
|
||||||
|
paymentContext.delegate = self
|
||||||
|
paymentContext.hostViewController = self.viewController
|
||||||
|
}
|
||||||
|
|
||||||
|
customerContext.clearCachedCustomer()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MARK: Public plugin API
|
// MARK: Public plugin API
|
||||||
|
|
||||||
@ -90,17 +102,18 @@ import Stripe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let paymentOptions = PaymentOptions(dict: options)
|
// Allow these to be overridden
|
||||||
|
if let headersDict = options["extraHTTPHeaders"] as? [String:String] {
|
||||||
|
PluginConfig.extraHTTPHeaders = headersDict
|
||||||
|
}
|
||||||
|
|
||||||
|
createPaymentContext()
|
||||||
|
|
||||||
|
let paymentOptions = StripePaymentOptions(dict: options)
|
||||||
paymentContext.paymentAmount = paymentOptions.price
|
paymentContext.paymentAmount = paymentOptions.price
|
||||||
paymentContext.paymentCurrency = paymentOptions.currency
|
paymentContext.paymentCurrency = paymentOptions.currency
|
||||||
paymentContext.paymentCountry = paymentOptions.country
|
paymentContext.paymentCountry = paymentOptions.country
|
||||||
|
|
||||||
// Allow these to be overridden
|
|
||||||
PluginConfig.requestPaymentImmediately = options["requestPaymentImmediately"] as? Bool ?? PluginConfig.requestPaymentImmediately
|
|
||||||
if let headersDict = options["extraHTTPHeaders"] as? [String:String] {
|
|
||||||
PluginConfig.parseExtraHeaders(dict: headersDict)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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…
x
Reference in New Issue
Block a user