#Svenson
1 messages ยท Page 1 of 1 (latest)
What specific issue are you encountering? Are there errors? Are you following a guide/doc?
hey man
func beginPushProvisioning() {
let config = STPPushProvisioningContext.requestConfiguration(
withName: "Jenny Rosen", // the cardholder's name
description: "RocketRides Card", // optional; a description of your card
last4: "4242", // optional; the last 4 digits of the card
brand: .visa // optional; the brand of the card
)
let controller = STPFakeAddPaymentPassViewController(requestConfiguration: config, delegate: self)
self.present(controller!, animated: true, completion: nil)
}
this is the code I am using
and this is the error I get
and swift is not my expertise, so I do not know if I am missing something
from what I see, I am putting invalid delegate type
Are you following a specific guide? Its not clear to me what you're actually trying to do
I am following this guie
this is my first interaction with swift, and i have no idea how to continue
I made this step successfuly
https://stripe.com/docs/issuing/cards/digital-wallets?platform=iOS#check-eligibility
but other steps are bugging me
hmm, using our Issuing SDKs and the native Apple provisioning SDKs to add cards to Apple Pay is one of the most complicated things you could do really and not something for a junior mobile developer
what's the error there exactly when you click on the red section to the right of the line?
to take a step back too, are you sure you need to use Issuing and this integration at all? What are you actually trying to do at a higher level/what's your task?
"Thread 11: Assertion failed: Invalid parameter not satisfying: delegate != nil"
this is the error I get
yeah, I am 100% sure I need this
can you share the complete code of the entire ViewController in text form?
can I dm you with that?
just want to be sure. You definitely need to issue credit cards to users of your marketplace and let them add those cards to their Apple Pay wallets through a flow in your company's iOS app? You are not just trying to accept payments using Apple Pay from end-customers?
no. You can post it here.
yup, user will need to add this card to their wallet
just a min, will share you files now
import Foundation
import PassKit
import Capacitor
import Stripe
import StripeApplePay
import Alamofire
@available(iOS 13.4, *)
@objc(WalletPlugin)
public class WalletPlugin: CAPPlugin {
@objc public func checkEligible(_ call: CAPPluginCall) {
var showButton = false
let value = call.getObject("value", JSObject())
let accountIdentifier = value["primaryAccountIdentifier"] ?? ""
if (value["eligible"] != nil) &&
PKPassLibrary().canAddSecureElementPass(primaryAccountIdentifier: accountIdentifier as! String) {
showButton = true
} else {
showButton = false
}
var hideButton: [String: Bool] = ["showButton": showButton]
call.resolve(hideButton);
}
@objc public func testingCard(_ call: CAPPluginCall) {
let implementation = Wallet()
implementation.beginPushProvisioning()
var hideButton: [String: Bool] = ["showButton": true]
call.resolve(hideButton);
}
}
this is one part of it
and this is different file in which I have uicontroller
import Stripe
import PassKit
import Alamofire
public class Wallet: UIViewController {
var pushProvisioningContext: STPPushProvisioningContext? = nil
@IBOutlet weak var addPassButton: PKAddPassButton!
public weak var delegate: PKAddPaymentPassViewControllerDelegate? = nil
func beginPushProvisioning() {
let config = STPPushProvisioningContext.requestConfiguration(
withName: "Jenny Rosen", // the cardholder's name
description: "RocketRides Card", // optional; a description of your card
last4: "4242", // optional; the last 4 digits of the card
brand: .visa // optional; the brand of the card
)
print(config)
let controller = STPFakeAddPaymentPassViewController(requestConfiguration: config, delegate: delegate)
self.present(controller!, animated: true, completion: nil)
}
}
plus extensions
extension Wallet {
public func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, generateRequestWithCertificateChain certificates: [Data], nonce: Data, nonceSignature: Data, completionHandler handler: @escaping (PKAddPaymentPassRequest) -> Void) {
self.pushProvisioningContext = STPPushProvisioningContext(keyProvider: self)
// STPPushProvisioningContext implements this delegate method for you, by retrieving encrypted card details from the Stripe API.
self.pushProvisioningContext?.addPaymentPassViewController(controller, generateRequestWithCertificateChain: certificates, nonce: nonce, nonceSignature: nonceSignature, completionHandler: handler);
}
}
extension Wallet: STPIssuingCardEphemeralKeyProvider {
public func createIssuingCardKey(withAPIVersion apiVersion: String, completion: @escaping STPJSONResponseCompletionBlock) {
// This example uses Alamofire for brevity, but you can make the request however you want
AF.request("",
method: .post,
parameters: ["api_version": apiVersion])
.responseJSON { response in
switch response.result {
case .failure(let error):
completion(nil, error)
case .success:
if let data = response.data {
do {
let obj = try JSONSerialization.jsonObject(with: data, options: []) as! [AnyHashable: Any]
completion(obj, nil)
} catch {
completion(nil, error)
}
}
}
}
}
}
don't you need an extension Wallet: PKAddPaymentPassViewControllerDelegate { ... } as well? Second code snippet at https://stripe.com/docs/issuing/cards/digital-wallets?platform=iOS#provision-a-card .
i..e you need your VC to implement that interface so that when you pass the instance of your VC as self to STPFakeAddPaymentPassViewController it is a valid delegate
of what exactly? The docs have an example of the extension
self
that fails for me
I know yes. For that to work though, self needs to implement the extension
extensions are like abstract interface in Java if you know that. You have a like a Class Wallet (in your case) and then you can do extension Wallet:SomeInterface {...} to provide the implementation
press the Fix button.
then it creates 4 or 5 functions
it does yes
it will add stubs that you need to add the implementation for, the second code snippet at https://stripe.com/docs/issuing/cards/digital-wallets?platform=iOS#provision-a-card has some examples of the implementations
now it runs without any errors
that's nice
that's not possible to test on actual device in EU right?
I don't know I'm afraid, I'm not familiar with this feature
could this error be becasue of simulator?
Attempt to present <Stripe.STPFakeAddPaymentPassViewController: 0x7ff1ade33f10> on <App.Wallet: 0x7ff1ade33b70> (from <App.Wallet: 0x7ff1ade33b70>) whose view is not in the window hierarchy.
โก๏ธ TO JS {"showButton":true}
I don't think so, it's more a general iOS thing
where is testingCard called from in your code?
I am calling it from javascript file, this is just a plugin I made with swift
since that function is what leads to the attempt to present the STPFakeAddPaymentPassViewController and if it's called in the wrong place/time you can get errors like that. (https://stackoverflow.com/questions/11862883/attempt-to-present-uiviewcontroller-on-uiviewcontroller-whose-view-is-not-in-the)
I don't really know what that means, are we talking about React Native now?
angular
I didn't even know you can call iOS code from Angular
I can not go into too much details unfortunately
it's actually ionic with angular
and capacitor
yeah unfortunately all of those technologies are unsupported by Stripe and nobody internally uses them(we only really have internal knowledge of React, React Native, and native iOS/Android) so I'm extremely limited in what I can help you with there
all good, I appreciate the time and will to help
in any case that type of error is usually caused by calling a function that tries to present a view(in this case self.present(controller!, animated: true, completion: nil)) from the wrong context, like before the enclosing View(Wallet in your case) has fully appeared
I would say so yes, the idea is your Wallet should already exist and then you have a button in that view that when pressed, triggers the provisioning stuff
okay, I think I got it
I am only doing the triggering provisionoing stuff now
thought that's gonna trigger the wallet to open also
you can look at https://github.com/stripe/stripe-react-native/blob/f4d9ab0f/ios/pushprovisioning/AddToWalletButtonView.swift as an implementation for our React Native library (related to https://github.com/stripe/stripe-react-native/pull/889)
thank you
let vc = findViewControllerPresenter(from: UIApplication.shared.delegate?.window??.rootViewController ?? UIViewController())
vc.present(controller!, animated: true, completion: nil)
this looks helpful
yeah, getting the root view controller and presenting on to that might make sense.
findViewControllerPresenter this would be the root controller?
sorry for stupid questions
first time doing Swift
and I am aware that it's not the best place to start
but need that for the app so
Hello ๐
Taking over as karllekko needs to step away
hey
thank you
I can not figure out how to use this
let vc = findViewControllerPresenter(from: UIApplication.shared.delegate?.window??.rootViewController ?? UIViewController())
vc.present(controller!, animated: true, completion: nil)
Are you seeing any specific errors?
"Cannot find 'findViewControllerPresenter' in scope"
"'nil' requires a contextual type"
Umm can you try defining that function in scope of the class?
// Note: creating a UIViewController inside here results in a nil window
// This is a bit of a hack: We traverse the view hierarchy looking for the most reasonable VC to present from.
// A VC hosted within a SwiftUI cell, for example, doesn't have a parent, so we need to find the UIWindow.
var presentingViewController: UIViewController =
uiViewController.view.window?.rootViewController ?? uiViewController
// Find the most-presented UIViewController
while let presented = presentingViewController.presentedViewController {
presentingViewController = presented
}
return presentingViewController
}```
okay, thanks
now I am getting a different error
- Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Call must be made on main thread'
Hmm that's quite generic ๐
Does it occur when you call .present or before that?
when I call .present
I think in order to call the function from main thread, you'd want to put the code in-between
// your code here
}```
๐
I am missing something here right?
Not sure, what's going on?
Any errors or anything?
can you try logging error before calling dismiss?
if you look my last image
that's the error
something with exceding the limit and make sure to call completionHandler
that's probably this
the first part in extension
OH ok ok
yeah looks like the completion handler isn't getting called
I need to step away soon so checking if there were any updates @tender hawk
I am good
thank you
very much
if I can provide a beer
i will be happy do it
you helped a lot
Ah awesome ๐ Glad we were able to help