#Svenson

1 messages · Page 1 of 1 (latest)

limber hawkBOT
alpine shadow
#

Hi there,
I invite you test it, but I think when using Apple Simulators you have already a test card added

mystic jungle
#

this is the error I get

#

when trying to use it without that completion

alpine shadow
#

So here you are not using Stripe SDK ?

mystic jungle
#

this is after that fake class you provide

#

addPaymentPassViewController trying to use this, this is also from your doc

#

second section

alpine shadow
#

Ah ok so your are trying to use issuing cards, sorry I didn't get the information at the beginning

mystic jungle
#

yeah

#

addPaymentPassViewController from what I see expects the real controller, not the fake one

#

and I can not replace it

alpine shadow
#

The error message shows that you exceed the 10sec timeout, in your test scenario are you having a delay ?

mystic jungle
#

yeah, I am trying that

#

the error I get is after this step

#

after I click next

#

it waits for around 10sec and gives me the error

alpine shadow
#

OK I'll ask for another feedback from one of my colleague

mystic jungle
#

thank you!

red lagoon
#

hi again @mystic jungle can you share the full code of your ViewController in text form?

mystic jungle
#

hi

#

yeah sure

#
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
      )
        
        let controller = STPFakeAddPaymentPassViewController(requestConfiguration: config, delegate: self)
        
        print(11111)
        
        let a = Data.init()
        
        DispatchQueue.main.async {
            let vc = self.findViewControllerPresenter(from: UIApplication.shared.delegate?.window??.rootViewController ?? UIViewController())
            print(22222222)
                    vc.present(controller!, animated: true, completion: nil)
            print(33333333)
            
       
            
            
        }
        
    }
```
#

first part

#
    
    func findViewControllerPresenter(from uiViewController: UIViewController) -> UIViewController {
        // 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
    }

#
extension Wallet: PKAddPaymentPassViewControllerDelegate {
    public func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, generateRequestWithCertificateChain certificates: [Data], nonce: Data, nonceSignature: Data, completionHandler handler: @escaping (PKAddPaymentPassRequest) -> Void) {
        self.pushProvisioningContext = STPPushProvisioningContext(keyProvider: self)

        self.pushProvisioningContext?.addPaymentPassViewController(controller, generateRequestWithCertificateChain: certificates, nonce: nonce, nonceSignature: nonceSignature, completionHandler: handler);
    }
    
    public func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, didFinishAdding pass: PKPaymentPass?, error: Error?) {
        self.dismiss(animated: true, completion: nil)
        print(error)
    }
}
#
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)
                    }
            }
            }

        }
    }
}

#

sorry I could not place it all one one message

red lagoon
#

seems correct enough to me but I've never built this integration so aren't too familiar with debugging it

#

to confirm, is your backend call working?

#

i.e. in createIssuingCardKey are you contacting your backend, confirmed your backend received the request and responded promptly with valid data, and if you add some logs after the let obj = <get json> line, is that logging something sensible?

mystic jungle
#

my understanding was that I do not need ephKeys for a testing env

red lagoon
#

hmm, is that understanding based on something? I don't see that mentioned in the docs

mystic jungle
#

just base on this
"To make testing easier, we provide a mock version of PKAddPaymentPassViewController called STPFakeAddPaymentPassViewController that can be used interchangeably during testing"

#

I could be wrong however

#

maybe thats just for that fake class

#

should I call createIssuingCardKey() after vc.present

red lagoon
#

I would suspect you are wrong yes, the test implementation is probably just to mock out the Apple library. But the basics of using our product and SDK(creating an IssuingCard object ic_xxx for the customer user and using that in conjunction with your app(via the eph key)) are the actual integration that you're building

red lagoon
mystic jungle
#

oh, okay. did not know that

#

that's cool

#

let me try that

red lagoon
#

i.e when you create STPPushProvisioningContext and pass self, that context object knows to call your implemented createIssuingKey method when it needs to(when addPaymentPassViewController is called)

mystic jungle
#

yeah, seems like i am not getting into that createIssuingCardKeys

red lagoon
#

as in it's never called when you do the full flow in your app?

mystic jungle
#

correct

#

at least full flow until I get the error

#

I understand the error, I am missing something in my completionHandler

#

but

#

when try to call addPaymentPassViewController

#

it seems that it expects real class and not STPFakeAddPaymentPassViewController

#

and I can not edit that, even if I change the type I get some other error for delegate

#

maybe I do not need to call that addPaymentPassViewController

#

same as you said for ephKeys

red lagoon
mystic jungle
#

Cannot convert value of type 'STPFakeAddPaymentPassViewController' to expected argument type 'PKAddPaymentPassViewController'

red lagoon
#

on which line, can you share the full context?

mystic jungle
#
self.addPaymentPassViewController(
                controller!,
                generateRequestWithCertificateChain: [a],
                nonce: a,
                nonceSignature: a,
                completionHandler: { request in
                    var contents: String?
                    if request.encryptedPassData != nil {
                        if let encryptedPassData1 = request.encryptedPassData {
                            contents = String(data: encryptedPassData1, encoding: .utf8)
                        }
                    }
                    if false {
                        var error =
                            "123"
                            as? String
                        if error == nil {
                            error = "123"
                        }

                    } else if contents == "TESTMODE_CONTENTS" {

                    } else {

                    }
                })

#

on controller

#

this 123 are just there for a testing purposes

#

not sure if I need certificates for testing too

#

or if my app wont allow paying with apple pay

#

just adding to apple pay

#

not sure if I need those if I wont allow payments

#

just adding to wallet

red lagoon
#

how does the code snippet above relate to the VC you posted earlier? I'm a bit lost

mystic jungle
#

i am calling that after vc.present

#

from the error message in screenshot, from exceeding the timout I think that this is needed

#

that completionHandler

red lagoon
#

I don't know why you call that, there's no code like that in our example React Native implementation or in the docs

#

the timeout is likely because of a missing/broken implementation of createEphemeralKey not calling your backend. Revisiting that, what's the status there?

mystic jungle
#

so you think it's not needed?

red lagoon
#

did you update createIssuingKey to use a real backend URL instead of "" and test the backend/confirm the app is contacting it and getting the ephemeral key back?

mystic jungle
#

still not getting my logs in the function

#

can I use localhost?

red lagoon
#

I don't think so, since if you use localhost the simulator will probably try to connect to a service on the simulated device, not your Mac

mystic jungle
#

gotcha, will need to release then to test it

red lagoon
#

not necessarily, I contact backend servers from my local testing/sandbox iOS apps all the time, by using services like ngrok.com or glitch.com or heroku to throw some HTTP servers online

#

you can also probably hard code an ephemeral key if you manually write some script to call the API and get the key. createIssuingCardKey just has to call completion(<an object that is an ephemeral key object>) , naturally that is calling a backend server and passing the object that way but it is possible to hard code it too. Probably easier for you to build the normal backend flow though.

mystic jungle
#

even with actual URL it does not get called

red lagoon
#
  func addPaymentPassViewController(_ controller: PKAddPaymentPassViewController, generateRequestWithCertificateChain certificates, ...........){
.....
}

does that function get called?

mystic jungle
#

no

#

both of my extensions do not get called

red lagoon
#

and you do present the controller? i.e. your print(33333333) gets called?

mystic jungle
#

correct

red lagoon
#

ok at this point I'd suggest writing in to https://support.stripe.com/?contact=true so you can talk to someone familiar with this integration over email as we're at this point deep into this integration which no one on my team is really deeply familiar with. Or if you're working with our sales team(most users using something this advanced are) then perhaps there's someone there can help.
When you write in please write a detailed email with complete context, all of your code, a screen recording of the flow you're seeing, links to all the docs you're using, and so on. Feel free to mention you were talking to me.

mystic jungle
#

okay, I understand