How to get the card number from braintree payments? - ios

I am using braintree pod for my project and it is working nicely after getting nonce. But I want to retrieve the card icon and digits of the card number.
How can I get both card icon in an imageView and card number in UILabel?
I used two pod files.
pod 'BraintreeDropIn'
pod 'BraintreeDropIn/UIKit'
and I am using this function provided from braintree documentation.
func showDropIn(clientTokenOrTokenizationKey: String) {
let request = BTDropInRequest()
//BTUIKAppearance.darkTheme()
//BTUIKAppearance.sharedInstance().primaryTextColor = UIColor.green
let dropIn = BTDropInController(authorization: clientTokenOrTokenizationKey, request: request)
{ (controller, result, error) in
if (error != nil) {
print("ERROR : \(error.debugDescription)")
} else if (result?.isCancelled == true) {
print("CANCELLED")
} else if let result = result {
// Use the BTDropInResult properties to update your UI
//result.paymentOptionType
//result.paymentMethod
//result.paymentIcon
//result.paymentDescription
if let outPut = result.paymentMethod {
print("\nNonce : \(outPut.nonce)")
self.paymentNonce = outPut.nonce
self.paymentCardType = result.paymentDescription.description
}
}
controller.dismiss(animated: true, completion: nil)
}
self.present(dropIn!, animated: true, completion: nil)
}

Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.
Right now, Braintree's iOS SDK does not return the card brand icon in the result. However, an image URL is returned in a transaction response object that contains the card brand icon within the imageUrl attribute. You can check out this gist on how to display image URLs in Swift. Alternatively, the type is available on the client when the nonce is returned.
For PCI compliance reasons, the full card number is not ever exposed to a merchant if you are using the Drop-in UI. Instead, the iOS SDK will provide the lastTwo digits if you cast the payment method to BTCardNonce. Swift's documentation has a lot of good info on casting. Though Objective-C, an example would be:
BTCardNonce *cardNonce = (BTCardNonce*)result.paymentMethod;
Alternatively, you can get a maskedNumber from the transaction response object, similarly to the image URL.
Edited: updated link for adding image URL to Swift 4

Related

Programmatically add a credit/bank card to a user's apple wallet

I work for a bank and I am working on a project that programmatically add a user’s credit/bank card to their apple wallet. The card has been issued by our bank.
Our app already has the entitlement com.apple.developer.payment-pass-provisioning. I am able to populate the config and call PKAddPaymentPassViewController. The modal loads correctly and once the user clicks next I get a response with the certificates, nonce, and nonceSignature.
I am now trying to call the PKAddPaymentPassRequest which requires the fields activationData, encryptedPassData, wrappedKey, ephemeralPublicKey
I’m reading the documentation here
https://developer.apple.com/documentation/passkit/pkaddpaymentpassrequest?language=objc
My understanding is the app will need to pass the certificates, nonce, and nonceSignature to our api which then uses those certificates to encrypt the credit card info etc. Our api will respond with activationData, encryptedPassData, wrappedKey, ephemeralPublicKey and then the app can call PKAddPaymentPassRequest with that data to complete the process.
I am not sure where to start with the api side. How can I use the certificates to properly produce the required encrypted strings? What is the json format for a payment pass? There's lots of examples of different passes but no a payment pass.
Is there any example code that takes the certificates and produces the encryptedPassData and the other fields? I see there’s some pass example code on developer.apple.com but there is not any example code for a payment pass.
This question is the closest I could find to what I am asking. There's some comments asking about server side implementation but the answers are not clear
PKAddPassPaymentRequest not able to send a Request
You can add a credit card into apple wallet by creating .pkpass on the server-side
and download that file on the ios side it will add to the ios wallet
Here is the code to download the .pkpass (passbook file) from server with completion handler and show pkpassviewcontroller for further adding into the apple wallet.
import PassKit
let url : NSURL! = NSURL(string: "YOUR .pkpass URL GOES HERE")
let request: NSURLRequest = NSURLRequest(url:
url as URL)
let config = URLSessionConfiguration.default
let session = URLSession(configuration: config)
let task : URLSessionDataTask = session.dataTask(with: request as URLRequest, completionHandler: {(data, response, error) in
var error: NSError?
let pass = try? PKPass(data: data!, error: &error)
if error != nil {
DispatchQueue.main.async {
let alertView = UIAlertView(title: "Error", message: (error?.localizedDescription)!, delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "Cancel")
alertView.show()
}
}
else {
let passLibrary = PKPassLibrary()
if passLibrary.containsPass(pass!) {
DispatchQueue.main.async {
let alertView = UIAlertView(title: "Already Exist", message: "This pass already added in wallet. Thanks!", delegate: nil, cancelButtonTitle: "OK", otherButtonTitles: "Cancel")
alertView.show()
self.hideLoading()
}
} else {
let pkvc = PKAddPassesViewController(pass: pass!)
pkvc.delegate = self
self.present(pkvc, animated: true, completion: {() -> Void in
// Do any cleanup here
self.hideLoading()
})
}
}
})
task.resume()
PHP library to create passes for iOS wallet app
https://github.com/flexible-agency/php-pkpass
The implementation details are considered confidential and you must contact apple for the proper documentation

Action Extensions - how do I know when a host app support modification in place?

I'm following a tutorial to create a simple Action Extension for text. Action extension is triggered as a modal overlay from the “Share…” button in the systemwide text selection context menu (or using the Action button in apps that handle simple text and support it).
The modified are made on a modal overlay handle in a target of your app and at the end of the editing you send back the edited content to the host app (if you want to) and the text is replaced with the edited content. If you send it to an hosted app that don't support modification in place the action don't have effect. My question is: how do I know when an host app supports modification in place?
Here is the code I'm using (derived from this online tutorial).
Get the items from extension:
let textItem = self.extensionContext!.inputItems[0]
as! NSExtensionItem
let textItemProvider = textItem.attachments![0] // the extension supports text based content so the kUTTypeText UTI is used to perform this test
if textItemProvider.hasItemConformingToTypeIdentifier(kUTTypeText as String) {
textItemProvider.loadItem(forTypeIdentifier: // if the host app has data of the required type, it can be loaded into the extension
kUTTypeText as String,
options: nil,
completionHandler: { (result, error) in
self.receivedText = result as? String // string containing the text loaded from the host app
if self.receivedText != nil {
DispatchQueue.main.async {
self.processedText = self.receivedText!
}
}
})
}
Returning edited content to the host app:
func returnEditedContent() {
let returnProvider =
NSItemProvider(item: processedText as NSSecureCoding?,
typeIdentifier: kUTTypeText as String) // create a new NSItemProvider instance
let returnItem = NSExtensionItem() // a new NSExtensionItem instance is created
returnItem.attachments = [returnProvider]
self.extensionContext!.completeRequest(returningItems: [returnItem], completionHandler: nil)
}
Cancel button:
#IBAction func cancelButtonPressed(_ sender: Any) {
self.extensionContext!.cancelRequest(withError: DismissExtension.cancelByUser)
}
I searched for a solution in various resources without finding it. Here are some documents:
Apple - Understand Action Extensions, Apple Human Interface Guidelines - Sharing and Actions, Medium - Simple Text Action Extension Swift 3

How to use my view controllers and other class in the Share Extension ? iOS | Swift 4

I am creating a chatting application. User can share the images from other application to my application. I have added Share Extension to show my app in the native share app list. I'm also getting the selected data in didSelectPost Method. From here I want to show the list of the users to whom the image can be forwarded. For this, I'm using an already created view controller in the main app target.
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
if let content = self.extensionContext!.inputItems[0] as? NSExtensionItem {
let contentType = kUTTypeImage as String
// Verify the provider is valid
if let contents = content.attachments as? [NSItemProvider] {
for attachment in contents {
if attachment.hasItemConformingToTypeIdentifier(contentType) {
attachment.loadItem(forTypeIdentifier: contentType, options: nil) { (data, error) in
let url = data as! URL
let imageData = try! Data(contentsOf: url)
// Here I'm navigating to my viewcontroller, let's say: ForwardVC
}
}
}
}
}
I don't want to recreate the same screen in Share Extension. Apart from this view controllers, I have many more classes and wrappers that I want to use within the share extension. Like, SocketManager, Webservices, etc. Please suggest me your approach to achieve the same.
P.S.: I've tried setting multiple targets to required viewControllers and using same pods for Share Extention. In this approach, I'm facing a lot of issues as many of the methods and pods are not extention compliant. Also, is it the right way to do this.

Problems with structs in Swift and making a UIImage from url?

Alright, I am not familiar with structs or the ordeal I am dealing with in Swift, but what I need to do is create an iMessage in my iMessage app extension with a sticker in it, meaning the image part of the iMessage is set to the sticker.
I have pored over Apple's docs and https://www.captechconsulting.com/blogs/ios-10-imessages-sdk-creating-an-imessages-extension but I do not understand how to do this or really how structs work. I read up on structs but that has not helped me accomplishing what Apple does in their sample code (downloadable at Apple)
What Apple does is they first compose a message, which I understood, taking their struct as a property, but I take sticker instead
guard let conversation = activeConversation else { fatalError("Expected a conversation") }
//Create a new message with the same session as any currently selected message.
let message = composeMessage(with: MSSticker, caption: "sup", session: conversation.selectedMessage?.session)
// Add the message to the conversation.
conversation.insert(message) { error in
if let error = error {
print(error)
}
}
They then do this (this is directly from sample code) to compose the message:
fileprivate func composeMessage(with iceCream: IceCream, caption: String, session: MSSession? = nil) -> MSMessage {
var components = URLComponents()
components.queryItems = iceCream.queryItems
let layout = MSMessageTemplateLayout()
layout.image = iceCream.renderSticker(opaque: true)
layout.caption = caption
let message = MSMessage(session: session ?? MSSession())
message.url = components.url!
message.layout = layout
return message
}
}
Basically this line is what Im having the problem with as I need to set my sticker as the image:
layout.image = iceCream.renderSticker(opaque: true)
Apple does a whole complicated function thing that I don't understand in renderSticker to pull the image part out of their stickers, and I have tried their way but I think this is better:
let img = UIImage(contentsOfURL: square.imageFileURL)
layout.image = ing
layout.image needs a UIImage, and I can get the imageFileURL from the sticker, I just cant get this into a UIImage. I get an error it does not match available overloads.
What can I do here? How can I insert the image from my sticker into a message? How can I get an image from its imageFileURL?
I'm not sure what exactly the question is, but I'll try to address as much as I can --
As rmaddy mentioned, if you want to create an image given a file location, simply use the UIImage constructor he specified.
As far as sending just a sticker (which you asked about in the comments on rmaddy's answer), you can insert just a sticker into an iMessage conversation. This functionality is available as part of an MSConversation. Here is a link to the documentation:
https://developer.apple.com/reference/messages/msconversation/1648187-insert
The active conversation can be accessed from your MSMessagesAppViewController.
There is no init(contentsOfURL:) initializer for UIImage. The closest one is init(contentsOfFile:).
To use that one with your file URL you can do:
let img = UIImage(contentsOfFile: square.imageFileURL.path)

Creating Architecture for Sharing Photos with Apple Watch OS2

I'm trying to figure out the proper approach for sharing 10+ photos from an iOS app to an Apple Watch app using watchOS 2.
I want to transfer these images in the background so that the user doesn't have to open the iOS app in order to view the photos.
I've tried querying photos from Facebook and sending them to the watch via transferUserInfo() but the payload is too large:
FBSDKGraphRequest(graphPath: "me/photos?limit=2", parameters:["fields": "name, source"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error != nil){
print(error.description)
}
else {
var arr = [NSData]()
for res in result["data"] as! NSArray {
if let string = res["source"] as? String {
if let url = NSURL(string: string) {
if let data = NSData(contentsOfURL: url){
arr.append(data)
}
}
}
}
print(arr)
if arr.count > 0 {
self.session.transferUserInfo(["image" : arr])
}
}
})
Any ideas how I should go about doing this?
The proper method is mentioned in the WCSession documentation:
Use the transferFile:metadata: method to transfer files in the background. Use this method in cases where you want to send more than a dictionary of values. For example, use this method to send images or file-based documents.
The images will be asynchronously delivered to the watch on a background thread. session:didReceiveFile: will be called when the watch successfully receives an image.
Make sure to include (date) metadata with the image, and remove any existing images from the watch which are no longer a part of the ten most recent Facebook uploads.

Resources