I am trying to implement the SetUp Apple Pay button on my iOS Xamarin application. I have added button and click handler for it. Then I Use PKPassLibrary.OpenPaymentSetup() to open Wallet. Then if user has successfully added Card into Wallet I need to handle this event via changing "SetUp ApplePay button" to "Pay with Apple Pay". But I can't find working any event handler or something like that.
What I have tried:
private PKPassLibrary _library;
private NSObject _walletNotificationSubscription;
private void OnSetuApplePayClicked(object button, EventArgs args)
{
_library = new PKPassLibrary();
_library.OpenPaymentSetup();
_walletNotificationSubscription = PKPassLibrary.Notifications.ObserveDidChange(_library, HandleEventHandler);
}
void HandleEventHandler(object sender, NSNotificationEventArgs e)
{
_walletNotificationSubscription.Dispose();
ViewModel.UpdateApplePay();
SetButtonVisibility();
}
but it does not work.
P.S.: I guess I maybe observe incorrect events.
Try to use the following code :
if(PKPaymentAuthorizationViewController.CanMakePayments)
{
//the device supports Apple Pay
//check whether the user can make a payment with a bank card ,such as Amex ,MasterCard,Visa,ChinaUnion and so on
NSString[] paymentString = { PKPaymentNetwork.Amex, PKPaymentNetwork.ChinaUnionPay, PKPaymentNetwork.MasterCard, PKPaymentNetwork.Visa };
if(PKPaymentAuthorizationViewController.CanMakePaymentsUsingNetworks(paymentString))
{
//user has added bank card ,do something you want
}
else
{
//user has not added bank card
}
}
else
{
//the device doesn't support Apple Pay
}
There are also some other way of payment ,you can check them in
public static class PKPaymentNetwork
It seems that there is no callbacks or events (at least at Xamarin). So, I had to switch a boolean property of controller when user is sent to the Wallet, and then, when user goes back to app I track "WillEnterForeground" App event where I check whether boolean property is true (if true then user returns from Wallet).
Please note that "ViewWillAppear" does not work in this case, it is not an analogue to the Android's "OnResume".
Also please note that card is activated after 15-20 seconds after adding it to wallet, so I am using "listening cycle" to track card activation.
When card is finally activated I am switching the button from Setup Apple Pay to Pay with Apple Pay.
Related
Public key and AGC configurations are correct, but when a user tries subscribing to a product, error code -1 is returned, and the payment page fails to be displayed.
In this case, check whether the log contains
"errorCode:6". The error code returned to the SDK layer is -1, indicating that the order fails to be created.
public class OrderStatusCode {
public static final int ORDER_STATE_SUCCESS = 0;
public static final int ORDER_STATE_FAILED = -1;
}
Check whether the order creation failure is caused by the server. If not, check whether the product created in the PMS contains invalid fields and whether the product is valid.
Its because you didn't set IAP function yet, you might have missed this step.
In this you can see "IAP function has not been set yet!" and a settings button. Click the settings button to set IAP function for your app.
If you finished it your page will be like this
Now all you have to do is wait for some time around 5 or 10 minutes and IAP can purchased in you app in mobile.
I am implementing braintree on IOS Client in order to receive payments through credit cards and PayPal
But whenever I tap on PayPal it takes times to open it on browser, so in this mean time I want to show Loader so user can't feel any thing weird.
I am unable to find any delegate methods of BTDropInController which allow me to show loader when user press PayPal option.
Thanks in advance.
Happy Coding :)
You need to start your activity indicator when you call paypal request from braintree. Below is the code for your reference:
SVProgressHUD .show(withStatus: "Proccessing")
let payPalRequest = BTPayPalRequest(amount: "1.20")
payPalRequest.currencyCode = "USD"
payPalRequest.landingPageType = .default
payPalRequest.intent = .authorize
payPalDriver.requestOneTimePayment(payPalRequest) { (tokenizedPayPalAccount, error) -> Void in
if let tokenizedResult = tokenizedPayPalAccount{
print("Get a nonce: \(tokenizedResult)")
SVProgressHUD .dismiss()
}
}
I've implement Firebase Authorization to login on my iOS app via Facebook and Google. I'm coding Swift.
When the app starts up I need to check whether a user is already signed-in in order to present the proper ViewController (e.g., if nobody is signed in I present the Login View Controller, otherwise I present the Home View Controller).
If I use the "easy" solution offered by Firebase, meaning
if FIRAuth.auth()?.currentUser != nil {
// User is signed in.
// ...
} else {
// No user is signed in.
// ...
}
So checking if the current user is not nil, it happens exactly what the Firebase guide (https://firebase.google.com/docs/auth/ios/manage-users) alerts might happen meaning
"Note: currentUser might also be nil because the auth object has not finished initializing. If you use a listener to keep track of the user's sign-in status, you don't need to handle this case."
So I would like to implement the listener as suggested in the guide:
handle = FIRAuth.auth()?.addStateDidChangeListener() { (auth, user) in
// ...
}
The listener will handle also intermediate status so that it is triggered when the Auth object is created. Point is I really cannot make it to work properly. Anybody can help me to use this listener in order to check if a user is logged in?
Thanks
I've implemented it like this:
FIRAuth.auth()?.addStateDidChangeListener { auth, user in
if let user = user {
// User is signed in. Show home screen
} else {
// No User is signed in. Show user the login screen
}
}
If you don't need the User object after checking, you can replace if let user = user with a boolean test, like this:
FIRAuth.auth()?.addStateDidChangeListener { auth, user in
if user != nil {
// User is signed in. Show home screen
} else {
// No User is signed in. Show user the login screen
}
}
Where to put the listener (from the comments):
For the cases I used to check if a user is signed in, it was enough to put it at the beginning of viewDidLoad in the specific view controller. But if you have any cases where you need to check every time you enter the specific view controller then it would be better to put it at the beginning of viewDidAppear. But I think in most cases you need to check only once, if the user enters the view
If you're setting up the StateDidChangeListener in application:didFinishLaunchingWithOptions, you'll notice that it fires once when the listener is attached (to set the initial state, which is nil when initialising) and then again once it's finished initialising (potentially not nil). This is intended behaviour, but really impractical if you're setting it up early.
An alternative to using the listener is using NotificationCenter. This will fire once initialisation has finished:
NotificationCenter.default.addObserver(forName: NSNotification.Name.AuthStateDidChange, object: Auth.auth(), queue: nil) { _ in
let user = Auth.auth().currentUser
}
This is what I used to register the phone number with Account Kit
- (void)viewDidLoad{
[super viewDidLoad];
// initialize Account Kit
if (_accountKit == nil) {
// may also specify AKFResponseTypeAccessToken
_accountKit = [[AKFAccountKit alloc] initWithResponseType:AKFResponseTypeAuthorizationCode];
}
// view controller for resuming login
_pendingLoginViewController = [_accountKit viewControllerForLoginResume];
}
I have implemented Account kit using Swift. I have implemented to register the phone number, but I was wondering if I could detect if the phone is already registered within this the app.
You can check if somebody is already logged in like this:
https://developers.facebook.com/docs/accountkit/ios#loginview
You can store the phone numbers and accountIDs in your own user tables to also verify if somebody has already created an account with that information. You can call the GraphAPI (https://developers.facebook.com/docs/accountkit/graphapi) from your server to check if there have been any updates to those accounts.
I define a Challenge Handler,
var AuthRealmChallengeHandler = WL.Client.createChallengeHandler("AuthRealm");
AuthRealmChallengeHandler.isCustomResponse = function(response) {
//returns true or false
};
once I click the login button i send a request to the adapter:
var resourceRequest = new WLResourceRequest(
"/adapters/AuthAdapter/getSecretData", WLResourceRequest.GET,
30000);
resourceRequest.send().then(getSecretData_CallbackOK,
getSecretData_CallbackFail);
However, after closing the app, re-launching and the login button is pressed again, the isCustomResponse is not called again. Why is it so?
I've checked that the isUserAuthenticated returns true, however it still doesn't call isCustomResponse:
WL.Client.updateUserInfo();
if (WL.Client.isUserAuthenticated("AuthRealm")) {
}else{
}
In addition to changing the project settings as was mentioned in the comments, to answer the remaining questions:
There is no relation between the application session "state" to JSONStore. JSONStore is local to your app itself in the device and not to the network.
You can invoke the logout function on application initialization, as a way to ensure that the client will be logged out once you have re-started the app in order to simulate the expected behavior by you. You will likely also want to extend the splash screen duration while this action is done so the user experience will be better... the logout function needs to simply call WL.Client.logout (refer to the documentation for this).