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
Related
// 1
let urlWhats = "https://wa.me/\(mobile)/?text=\(text)"
// 2
if let urlString = urlWhats.addingPercentEncoding(withAllowedCharacters: NSCharacterSet.urlQueryAllowed) {
// 3
if let whatsappURL = NSURL(string: urlString) {
// 4
if UIApplication.shared.canOpenURL(whatsappURL as URL) {
// 5
UIApplication.shared.open(whatsappURL as URL, options: [:], completionHandler: nil)
// UIApplication.shared.\
} else {
// 6
print("Cannot Open Whatsapp")
}
}
}
I'm able to launch whatsapp from my app from the above mentioned code, it is composing prefix text to the contact I wish to send and I need to click the send button in whatsapp manually . But I'm looking for a code which automatically sends whatsapp text to number from my app. Can anyone share your thoughts on this?
You can only compose the message for a particular contact using the Deep Linking method that you have used for it. For sending the message user has to click on the send button manually. You could provide the user with an alert that says so. But, it's not possible to do it for the user from your side. If you were able to send a message on Whatsapp by writing code without the user's confirmation it would be a break of user's privacy. Don't you think?
in my app I have ovpn profile (for example, in Document directory). I'd like to send (share) this file to official client openVPN.
I've implemented this:
let app = UIApplication.shared
var installed: Bool? = nil
if let url = URL(string: "openvpn://") {
installed = app.canOpenURL(url)
}
guard installed ?? false, let url = URL(string: "openvpn://") else {
if let url = URL(string: "https://itunes.apple.com/app/id590379981?mt=8") {
app.open(url)
}
return
}
app.open(url)
And this works great, but I don't know how to improve url scheme and, accordingly, I don't know how to send my file to "Import Profile" screen. Could you share your experience?
Yes, I know about UIActivityViewController
let activityViewController = UIActivityViewController(activityItems: [ovpnUrlPath], applicationActivities: nil)
self.present(activityViewController, animated: true, completion: nil)
but there are additional user's actions, but it's again works great: profile file is opened on "Import Profile" screen as expected:
Question is: how to share my ovpn with url scheme for openVPN?
I've received comment from official openVPN account:
unfortunately, OpenVPN Connect client application doesn't have functionality for sharing connection profiles.
so, right now it's impossible.
I am trying to help my boss and co-workers out with an iOS 12 Swift App to help us all better manage inventory when out on the shop floor.
The all works by taking advantage of the barcode/QR-code reading technology that comes bundled with iOS 12.
The webpage used to log into the inventory service uses plain-old http technology and so the iOS (appears) not to be offering me a means of letting me save/retrieve the password to/from the Keychain. I CAN however save the login information when I access the website via my Mac. I have verified that the login information been saved on the Mac's keychain (which is shared with the iPhone via iCloud).
The webpage warns that the password (on either platform) will be sent unencrypted.
I have adapted some of the code already at https://www.appcoda.com/barcode-reader-swift/.
I don't have a full Apple developer account, so at present this is not a production app.
The main difference between the code supplied by www.appcoda.com/barcode-reader-swift and mine nearly all lies in the 'QRSwiftController.swift' file's func launchApp function. Slight modifications to help improve readability and usability. A Safari View Controller is used make everything more cohesive inside of one app etc.
func launchApp(decoded_barcode: String) {
if presentedViewController != nil {
return
}
AudioServicesPlayAlertSound(SystemSoundID(kSystemSoundID_Vibrate))
let result = decoded_barcode.replacingOccurrences( of:"[^0-9]", with: "", options: .regularExpression)
let startOfURL: String = "http://xxx.webname.com/deploy/artikel.php?nummer="
let fullURL = startOfURL + result
let alertPrompt = UIAlertController(title: "Open App", message: "You're going to open \(fullURL)", preferredStyle: .actionSheet)
let confirmAction = UIAlertAction(title: "Confirm", style: UIAlertActionStyle.default, handler: { (action) -> Void in
if let url = URL(string: fullURL){
let safariVC = SFSafariViewController(url: url)
self.present(safariVC, animated: true, completion: nil)
}
})
let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)
alertPrompt.addAction(confirmAction)
alertPrompt.addAction(cancelAction)
present(alertPrompt, animated: true, completion: nil)
}
Even when I visit the inventory management website via normal Safari on my iPhone I am prompted for a username/password every time.
Alt URL for login screen https://imgur.com/a/S2EMYcE
Is there any way I possibly circumvent this problem by automating the tapping of the text fields for the username/password (following by pasting the info) and then tapping 'Log in'??
I've looked already for solutions on Stackoverflow but they seem overwhelmingly complicated and/or no longer valid for Swift 4.
Thanks!
Assume generic username and passwords such as 'user' and 'password'.
In the end (as a workaround) I just got Google Chrome (on iOS) to do all the donkey-work (it appears willing to save the password for this website for future retrieval).
if URL(string: fullURL) != nil {
//let safariVC = SFSafariViewController(url: url)
//self.present(safariVC, animated: true, completion: nil)
UIApplication.shared.openURL(NSURL(string: fullURL)! as URL)
}
I have an app and I wanna add messages extension feature.
I thought the feature is if the user selects a message, it switches my host app directly like google map.
I made a MSMessage and set URL and the message has template layout which had caption and sub-caption.
let message = MSMessage()
message.url = "http://blahblah?customScheme=myHostAppLaunchScheme"
let template = MSMessageTemplateLayout()
template.image = sampleImage
template.caption = "this is a caption"
template.subCaption = "this is a sub caption"
message.layout = template
guard let conversation = activeConversation else {
print("blahblah")
return
}
conversation.insert(message) { (error) in
print("finish. error = \(error == nil ? "nil" : error!.localizedDescription)")
}
and i wrote a code extensionContext.open(url, completionHandler) in
willBecomeActive(with conversation: MSConversation)
didReceive(_ message: MSMessage, conversation: MSConversation)
of course, i parsed selectedMessage's URL.
but it didn't work I expected.
the messages extension switches expand mode automatically.
it works if I used
conversation.insertText("myHostAppLaunchScheme", nil)
but I don't want it because it can't add template :(
is there any idea to switch iMessage to host app directly?
thanks for any ideas.
i think i found the answer.
there is no way with using
conversation.insert(message, completionHandler)
i think apple music and google maps are using
conversation.insertText("some url", completionHandler)
because i copied an URL after long press a message which is shared by apple music or google map
then i use the URL in my code
conversation.insertText("the URL", completionHandler)
it's working they did!!
I might be a little slow here, but is is possible to send push notifications with firebase programatically?
Let's say I have an iOS app and a button event. When I press that button I want to send a push notification to certain users via firebase that says 'Hello World!'.
The only way I see now to accomplish that is to use the notification console, but I want to do it programatically. Do I actually have to have my own server to do this?
What do you recommend as the easiest way nowadays to send remote push notifications programatically besides having my own server?
Currently, no. There's no recommended way of doing this through Firebase Cloud Messaging without having your own server to perform the logic. (I wouldn't make calls to the service from the client like Dupinder recommended, as it will leak your server key to the world, which is a Bad Thing Indeed)
That said, it's certainly a feature request the team hears about quite frequently so it's something they're certainly aware about and looking into.
Please make sure do NOT include the server-key into your client. There are ways "for not so great people" to find it and do stuff... The Proper way to achieve that is for your client to instruct your app-server to send the notification.
You have to send a HTTP-Post to the Google-API-Endpoint.
You need the following headers:
Content-Type: application/json
Authorization: key={your_server_key}
You can obtain your server key within in the Firebase-Project.
HTTP-Post-Content: Sample
{
"notification": {
"title": "Notification Title",
"text": "The Text of the notification."
},
"project_id": "<your firebase-project-id",
"to":"the specific client-device-id"
}
Yes, we can send push notification with firebase programatically.I have try this by getting the device token of both the users and hitting one api at the send button .Just have a look..
let url = NSURL(string: "https://fcm.googleapis.com/fcm/send")
let request = NSMutableURLRequest(URL: url!)
request.setValue("your server key ", forHTTPHeaderField:"Authorization") // your legacy server key
request.setValue("ebl0RxL94Ss:APA91bGXn_i6TLcXC1rZZSO1pKXCnqKjg-SxOHsjdahoJ4qIjVxX6dwal3YNeCvpHltEnwHibEuldWzfTiQewgD_J_4HIg31VE_vyvONdHN9v6VQGRcY6PaXY1xZmJ9t_cKfs7sQ9K1q", forHTTPHeaderField:"Authentification") // sender refreshedToken
request.setValue("application/json", forHTTPHeaderField:"Content-Type")
request.HTTPMethod = "POST"
let sessionConfig = NSURLSessionConfiguration.defaultSessionConfiguration()
// dictionary containing sender refreshedToken and other notification detail including text
let json = ["to":"c6HixiMte3A:APA91bFfNvQev2qcZqdsnJ9qoho_GlXRj1PWx6FWleScgExBi95WAkRqmp2jilCbZYoifs9bfHPyGpofjTAM239SYEiAwMRzgAONFv_KH-u49pG9C6f6UEVY4WEctjFzek9WZ7pBv31t",
"priority":"high",
"content_available":true,
"notification":["body":"new messages","title":text,"score":"5x1","time": "15:10"]]
do {
let jsonData = try NSJSONSerialization.dataWithJSONObject(json, options: NSJSONWritingOptions.PrettyPrinted)
request.HTTPBody = jsonData
} catch let error as NSError {
print(error)
}
// insert json data to the request
let urlSession = NSURLSession(configuration: sessionConfig, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let dataTask = urlSession.dataTaskWithRequest(request) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
print("Body: \(strData)")
print(response,data)
print(error)
}
dataTask.resume()