Braintree take time in opening PayPal - ios

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()
}
}

Related

Stripe SDK integration using swift and flutter

I am trying to integrate Apple Pay in iOS using flutter. I am using method channels to communicate with swift and get the payment process completed. I have followed the documentation which is in this link
However, I believe I have stuck in the very ending part which I don't understand how to continue the flow. Since I am using flutter UIs, I don't need iOS ViewControllers.
This is the code that I have tried so far in the AppDelegate.swift:
func handleApplePayButtonTapped(result: FlutterResult){
let merchantIdentifier = "my.apple.merchant.id"
let paymentRequest = Stripe.paymentRequest(withMerchantIdentifier:merchantIdentifier, country:"US", currency:"USD")
paymentRequest.paymentSummaryItems = [
PKPaymentSummaryItem(label:"Fancy Hat", amount:50.00),
PKPaymentSummaryItem(label:"iHats, Inc", amount:50.00),
]
if Stripe.canSubmitPaymentRequest(paymentRequest){
//next steps ???
result(String("Can submit payment request"))
}else{
result(String("Can't submit payment request"))
}
}
I am calling this code in flutter UI using this code:
Future<void> _doPayment() async {
String returnMsg;
try {
final bool result = await platform.invokeMethod('checkIfDeviceSupportsApplePay');
if(result){
final String status = await platform.invokeMethod('handleApplePayButtonTapped');
print(status);
}
returnMsg = '$result';
} on PlatformException catch (e) {
returnMsg = "Failed: '${e.message}'.";
}
print(returnMsg);}
I already have a Stripe publishable key as well as a Heroku deployed backend. If you checked my swift code, you will see where I am stuck at the moment.
As I have understood the flow, what is remaining to be done is
send the card details to the backend and get a token
using the token, send the payment details to the Stripe server
I am very new to swift language and code samples will be greatly helpful for me to continue with.
Thank you.
It looks like you're following the Stripe Custom iOS Integration, using the native PKPaymentAuthorizationViewController.
You should read through the integration steps here: https://stripe.com/docs/mobile/ios/custom#apple-pay
Basically, your next steps would be
instantiate a PKPaymentAuthorizationViewController with the paymentRequest
Set yourself to its delegate
present the PKPaymentAuthorizationViewController
implement the relevant delegate methods to get back an Apple Pay token (PKToken)
convert PKToken to STPToken (a Stripe token)
All these steps and more are detailed in the link above.

Handle credit card added to the Wallet Apple Pay

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.

How to test paypal payment using braintree sandbox

I am using braintree in my app for payment(Credit card & Paypal). I am using custom UI. When click on pay by Paypal button, i am using the following code.
braintreeClient = BTAPIClient(authorization: tokenizationKey)!
let payPalDriver = BTPayPalDriver(APIClient: braintreeClient)
payPalDriver.viewControllerPresentingDelegate = self
//payPalDriver.appSwitchDelegate = self // Optional
// Specify the transaction amount here. "2.32" is used in this example.
let request = BTPayPalRequest(amount: "2.32")
request.currencyCode = "USD" // Optional; see BTPayPalRequest.h for more options
payPalDriver.requestOneTimePayment(request) { (tokenizedPayPalAccount, error) in
if let tokenizedPayPalAccount = tokenizedPayPalAccount {
print("Got a nonce: \(tokenizedPayPalAccount.nonce)")
// Access additional information
// See BTPostalAddress.h for details
} else if error != nil {
// Handle error here...
} else {
// Buyer canceled payment approval
}
}
It opens this link https://checkout.paypal.com/one-touch-login-sandbox/index.html?action=setup_billing_agreement&ba_token=BA-HERMES-SANDBOX-TOKEN&cancel_url=com.pronto.btreeInteg.payments%3A%2F%2Fonetouch%2Fv1%2Fcancel&controller=client_api%2Fpaypal_hermes&experience_profile%5Baddress_override%5D=false&experience_profile%5Bno_shipping%5D=1&merchant_id=qkd2xjhc84nhd5b3&return_url=com.pronto.btreeInteg.payments%3A%2F%2Fonetouch%2Fv1%2Fsuccess&version=1 . It gives me dummy nonce. i want check with my Paypal a/c by login. Right now i am using Braintree sandbox a/c.
Full disclosure: I work at Braintree.
What you have described is the expected behavior for sandbox accounts. See the Braintree docs:
PayPal transactions initiated with sandbox API keys cannot be used for full end-to-end testing. The goal of sandbox testing is to ensure your client and server side configurations are correct and that you are receiving appropriate responses for your requests. If you wish to do end-to-end testing, you will need to do that in your production account.
However, if you have further questions about testing PayPal with your sandbox account, please contact Braintree support to see how your needs can be met.

iOS: How to detect if a user is subscribed to an auto-renewable subscription

Hopefully the title is self-explanatory. I'm trying to do something like this:
checkIfUserIsSubscribedToProduct(productID, transactionID: "some-unique-transaction-string", completion: { error, status in
if error == nil {
if status == .Subscribed {
// do something fun
}
}
}
does anything like the hypothetical code I've provided exist? I feel like I'm taking crazy pills
Edit
In similar questions I keep seeing a generic answer of "oh you gotta validate the receipt" but no explanation on how, or even what a receipt is. Could someone provide me with how to "validate the receipt"? I tried this tutorial but didn't seem to work.
Edit - For Bounty
Please address the following situation: A user subscribes to my auto-renewable subscription and gets more digital content because of it - cool, implemented. But how do I check whether that subscription is still valid (i.e. they did not cancel their subscription) each time they open the app? What is the simplest solution to check this? Is there something like the hypothetical code I provided in my question? Please walk me through this and provide any further details on the subject that may be helpful.
I know everyone was very concerned about me and how I was doing on this - fear not, solved my problem. Main problem was that I tried Apple's example code from the documentation, but it wasn't working so I gave up on it. Then I came back to it and implemented it with Alamofire and it works great. Here's the code solution:
Swift 3:
let receiptURL = Bundle.main.appStoreReceiptURL
let receipt = NSData(contentsOf: receiptURL!)
let requestContents: [String: Any] = [
"receipt-data": receipt!.base64EncodedString(options: []),
"password": "your iTunes Connect shared secret"
]
let appleServer = receiptURL?.lastPathComponent == "sandboxReceipt" ? "sandbox" : "buy"
let stringURL = "https://\(appleServer).itunes.apple.com/verifyReceipt"
print("Loading user receipt: \(stringURL)...")
Alamofire.request(stringURL, method: .post, parameters: requestContents, encoding: JSONEncoding.default)
.responseJSON { response in
if let value = response.result.value as? NSDictionary {
print(value)
} else {
print("Receiving receipt from App Store failed: \(response.result)")
}
}
As some comments pointed out there's a couple flaws with these answers.
Calling /verifyReceipt from the client isn't secure.
Comparing expiration dates against the device clock can be spoofed by changing the time (always a fun hack to try after cancelling a free trial :) )
There are some other tutorials of how to set up a server to handle the receipt verification, but this is only part of the problem. Making a network request to unpack and validate a receipt on every app launch can lead to issues, so there should be some caching too to keep things running smoothly.
The RevenueCat SDK provides a good out-of-the box solution for this.
A couple reasons why I like this approach:
Validates receipt server side (without requiring me to set up a server)
Checks for an "active" subscription with a server timestamp so can't be spoofed by changing the device clock
Caches the result so it's super fast and works offline
There's some more details in this question: https://stackoverflow.com/a/55404121/3166209
What it works down to is a simple function that you can call as often as needed and will return synchronously in most cases (since it's cached).
subscriptionStatus { (subscribed) in
if subscribed {
// Show that great pro content
}
}
What are you trying to achieve in particular? Do you want to check for a specific Apple ID?
I highly doubt that this is possible through the SDK. Referring to Is it possible to get the user's apple ID through the SDK? you can see that you can't even ask for the ID directly but rather services attached to it.
What would work is caching all transactions on your own server and search its database locally but that would require the app to ask for the user's Apple ID so the app could update the subscription state whenever it launches as it can check for IAP of the ID associated with the device.
However, the user could just type whatever he wanted - and it's unlikely to get this through Apple's app review process.
I am using MKSoreKit https://github.com/MugunthKumar/MKStoreKit for auto-renew subscriptions.but it is in objective c you can check the library code for solution.I am using it in my code and it is working fine.
using below method you can easily check subscription status..
if([MKStoreManager isProductPurchased:productIdentifier]) {
//unlock it
}
It gets the apple id from device and I think that is user specific

how to send verification code by sms in swift 2

i build a register form for my app and i need to send the user a verifiation code by sms in order to complete the registration proccess.
i tried to use MFMessageComposeViewController but its open the dialog sms on the device so the user can see the code.
i also checked the web for 3party of sending sms but there is a problem with the country code. i know its posible becuse whatsapp do it to confirm the user.
what it the right way to do it?
this is the topic the i tried:
Sending SMS in iOS with Swift
The best way to achieve this is by creating some views for allowing the user to enter the phone number with the country code which can be used by a server to send a request for initiating the OTP verification. To achieve this you need to:
Create View Controllers.
Upload Phone Number and Country code to the server.
Validate the requests by verifying the OTP.
As mentioned by Dan, you can use Digits in Fabric for that purpose, and create custom views for a great UX.
On the other hand, you can also use a service called as SendOTP from MSG91 - you can use it for internal testing and development ideas as they provide you with 5,000 free OTP SMS. The service has a complete set of APIs which you can implement on the backend as well on the app front. Also, they provide a framework so that you don't need to create the views, but only presentViewController and call delegate methods for knowing what happened during the verification process - such as Cancelled or Verified or Failed.
Swift implementation of the same looks like this:
class OTPFrame: UIViewController, sendOTPAuthenticationViewControllerDelegate {
func loadOTPFramework() {
SendOTP.sharedManager().startWithApiId("yourAppID")
let frameworkPath: NSString = NSBundle.mainBundle().privateFrameworksPath!
let frameworkBundlePath: NSString = frameworkPath.stringByAppendingPathComponent("SendOTPFramework.framework")
let frameworkBundle : NSBundle
= NSBundle(path: frameworkBundlePath as String)!
let authenticationViewController: AuthenticationViewController = AuthenticationViewController(nibName: "AuthenticationViewController", bundle: frameworkBundle)
authenticationViewController.delegate = self self.presentViewController(authenticationViewController, animated: true, completion: nil)
}
func authenticationisSuccessfulForMobileNumber(mobNo: String!, withCountryCode countryCode: String!) {
print("Success")
}
func canceledAuthentication() {
print("Cancelled")
}
func authenticationisFailedForMobileNumber(mobNo: String!, withCountryCode countryCode: String!) {
print("Failed")
}
}
Disclaimer: I, in no way, endorse the services mentioned above - you are free to choose whatever you like.
Thank You!
I would give digits a try! It's part of the Twitter Fabric package and it's very simple to use. The user enters their phone number and Fabric takes care of validating the number.

Resources