I have successfully generated a .pkpass file, but it gives following error when trying to open the file:
"The pass “Sample.pkpass” could not be opened."
If I open a prepackaged pkpass from here, it opens successfully. Furthermore, if I use the signpass tool to repackage one of the example folders, it will open successfully.
If I alter my pass.json file to declare:
"barcode" : {
"message" : "123456789",
"format" : "PKBarcodeFormatPDF417",
"messageEncoding" : "iso-8859-1"
}
instead of:
"nfc" : {
"message" : "04:9B:95:D1:70:00:00",
}
Then the pass will open successfully and I can add it to Wallet.
Alternatively, I can remove the "nfc" and "barcode" portions altogether and the resulting pkpass will open successfully. It seems to be something about the "nfc" declaration in particular that is not right.
According to here and here, I am using the correct key names for an nfc card.
I've also tried including "encryptionPublicKey," which is listed as optional.
The whole concept of an NFC Pass in Wallet is elusive, even though it's been in use for years by companies like Hilton for use as a Digital Room Key.
I've requested an "NFC Certificate" from Apple using this form, but who knows how much time that will take, whether it will be approved, or what I am supposed to do with the cert if I did receive it. Also, the goal does not involve ApplePay at all; I just want a pass to present as an NFC card for Door Access with an NFC reader, which should be 100% doable.
Any support or guidance is greatly appreciated.
Additional Reference:
https://tranzer.com/blogs/how-to-create-your-own-wallet-passes-pkpass/
Related
I'm trying to register a custom protocol with electron. I want it to be a redirect location that a website can use to provide an api key (like myprotocol://example/payload=api-key). I have been using electron's registerHttpProtocol and also tried electron's interceptHttpProtocol.
But, when the website tries to redirect to my protocol my electron app doesn't do anything. The website goes to myprotocol://example/payload=api-key, and registers a "page doesn't exist error"--while nothing happens in my app.
This is in a development environment. I've seen some discussion about custom protocols that assume a production environment.
Can you register a custom protocol with electron in development?
Why am I not able to intercept the website's going to the protocol I've set out?
Here's my code:
main.js:
app.whenReady().then(() => {
protocol.registerHttpProtocol('examplep', (request, callback) => {
console.log("examplep", request);
callback('it-worked');
}, (error) => {
if (error) console.error('Failed to register protocol = ' + error)
})
protocol.interceptHttpProtocol("examplep", function (request, callback) { //I've tried both registerHttp... and interceptHttp... methods, so including both here; though I think in practice only one should be required
console.log('intercepted!' + request)
callback(request);
});
})
redirect url provided to website:
'http://examplep'
And I've whitelisted this url on the website itself.
I've also tried related methods registerStringProtocol, interceptStringProtocol, registerFileProtocol, and interceptFileProtocol, without success.
What am I missing?
Sounds like you need to support deep linking fora desktop app, which is done via a Custom URI Scheme and is registered with setAsDefaultProtocolClient.
When your Electron app starts up write this code to register the scheme, on the main side of your app:
const customScheme = 'x-mycompany-myapp';
app.setAsDefaultProtocolClient(customScheme);
The custom scheme can be tested from the command line like this, depending whether you are running macOS or Windows:
open x-mycompany-myapp:/some/location
start x-mycompany-myapp:/some/location
A web client will just invoke a URL as in this Javascript code of mine;
The notification will be received within the main side of your app and on Windows will attempt to create a new instance of the app, in which case you need to detect this condition, process the notification then cancel the new app instance.
On MacOS it will be received within the open-url event, so you register it like this:
app.on('open-url', this._onOpenUrl);
Once the main side of the Electron app has the notification, it needs to get the URL information and forward it to the renderer process. You can use ipcMain events for this.
Finally the code for receiving the notification in running instances and starting the app from a deep link are different.
EXAMPLE APP
Since the code is a little tricky, here is some example code that may be useful, to give you something to compare against. If it helps you can also run the app by following the instructions in the blog post:
Code
Blog Post
My use case is around receiving OAuth responses after signing in from the system browser. Hopefully you can borrow some ideas from it related to deep linking though.
INFO.PLIST
My understand is that in a development environment (on macOS) deep links work when the app is running, but if you stop the app and attempt a deep link it will not start the app.
You can only resolve this for a packaged app, which requires an info.plist. In my code sample the info.plist is generated from build protocol entries in the package.json file.
My code sample is packaged in a basic way by the Electron Packager, so when I run npm run pack, the app is built to a dist folder. I can then run the packaged version of the app and it gets registered with the system - as can be seen in the Default Apps tool. See screenshots in the blog post.
SECRETS
Secrets for a desktop app should be stored using operating system secure storage. There are screenshots of credential storage in the blog post.
On Electron, have a look at the keytar component - and this wrapper class of mine. I am storing tokens (strings) so you should be able to adapt the code for your API keys.
I'm working on building my first App Clip and am hoping to get thoughts on an issue I'm facing. The App Clip is meant to allow me to sell items from my own little personal shop without people having to download my full app first.
When I try to upload my App Clip to the App Store, I'm getting a Domain URL Status error of "Unexpected Error"
My App has what I believe to be an appropriate Apple App Site Association file at the domain I've provided (I've checked it a number of times and the invocation works correctly in my developer local experience) so I don't see where that problem is coming from. This is what the JSON looks like on the website and also code below (with the identifying information changed to their generalized labels):
{
"appclips": {
"apps": [
"TeamIDNumber.com.AppName.AppBundleID.Clip"
]
},
"applinks": {
"apps": [],
"details": [
{
"appID": "TeamIDNumber.com.AppName.AppBundleID.MarqetAppTest",
"paths": [
"*"
]
}
]
}
}
In addition, when I try to create an Advanced App Clip Experience so that I can use QR code and NFC invocations, I get an error that "This URL is not contained in your app's associated domains".
However, when I go into the build metadata, it clearly shows my website as an associated domain so I don't know whats causing that error.
The consequence of all this is that when I use an NFC tag (or scan the QR code using the iPhone QR reader) with my phone, I get taken to my website on Safari rather than the App Clip invocation coming up.
I submitted a ticket to Apple nearly 3 weeks ago and am being told they have no updates so checking if anyone here has thoughts. Any input appreciated, thank you!
This has been resolved with the help of Apple! A bit embarrassing to say, but the error was that in the associated domains I had included an unnecessary space after the colon. So the associated domain was written as "appclips: marqetapp.com" when it should have been "appclips:marqetapp.com". Apple informed me that they are working to update their error messaging to make these kinds of issues clearer in the future.
I want to use Firebase email link authentication in my iOS (Flutter) app with a custom domain:
The app requests Firebase Auth backend to send an email to the user. -- works
The user clicks a link in the email and is taken back to the app. -- works
The app processes the payload of that link to perform the sign in. -- does not work
Firebase Dynamic Links do work in general but the link from that particular Firebase auto-generated email is not. Technically the app is brought to foreground but the Firebase Dynamic Link onLink callback is not fired. I tracked it down to one tiny trailing slash that is missing in the email's link URL:
https://link.mydomain.com?link=https://app.mydomain.com/__/auth/action?apiKey=... (not working)
https://link.mydomain.com/?link=https://app.mydomain.com/__/auth/action?apiKey=... (works)
-------------------------^
To work around this I tried to add a path suffix to my domain but this gave the same results:
https://link.mydomain.com/app?link=https://app.mydomain.com/__/auth/action?apiKey=... (not working)
https://link.mydomain.com/app/?link=https://app.mydomain.com/__/auth/action?apiKey=... (works)
-----------------------------^
The worst part of this difference that made it so hard to find is that if you copy the link on iOS or long press it to see a preview, the slash is just silently added in the right place! You can paste the link to the notes app, click it, and it works!
Only when viewing the email's source code you can see that it is actually not there:
When requesting the link, I call FirebaseAuth.instance.sendSignInWithEmailLink with these params set:
url: 'https://app.mydomain.com',
dynamicLinkDomain: 'link.mydomain.com',
The dynamicLinkDomain param does not accept a protocol or path.
Does anybody know how to...
make Firebase add this slash to the link when sending the mail?
or
make Firebase Dynamic Link's onLink callback react to clicked links that do not have a trailing slash?
For reference
My Info.plist contains this key:
<key>FirebaseDynamicLinksCustomDomains</key>
<array>
<string>https://link.mydomain.com</string>
</array>
My entitlements file contains this key:
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:link.mydomain.com</string>
</array>
apple-app-site-association (https://link.mydomain.com/apple-app-site-association):
{
"applinks": {
"apps": [],
"details": [{
"appID": "XYZ.com.mydomain.app",
"paths": [
"NOT /_/*",
"/*"
]
}]
}
}
The links with a custom domain worked fine in Apple Mail but no other email client.
As a temporary solution, you can use a Google-provided domain (e.g. projectname.page.link) to generate sign-in links.
You can track it here.
After debugging the iOS implementation of Firebase Dynamic Links it turns out that the missing slash is explicitly required in code (though I am not sure why). Its absence in the email link seems to be a bug and should probably be fixed in the Firebase backend; I filed a bug report on that. The Firebase console has no option to configure a dynamic link domain to be used for automatically generated sign-in links (instead takes any first from the list of configured domains but somehow without path) so I hope this will be made configurable in the future.
Workaround
I simply changed that code (in my Flutter project it's in Pods/FirebaseDynamicLinks/FIRDynamicLinks.m) and removed the check for the trailing slash. But I have to repeat it when the dependency is updated and I don't know why the check is explicitly there so it might cause other problems.
Two more hints on debugging your dynamic links
Check the link itself
Copy the link into the address line of your browser and add &d=1 to get the debug view. It shows errors in a big red box above of the diagram - if there are any.
Check your iOS configuration
Add these two lines temporarily to your didFinishLaunchingWithOptions in AppDelegate.m:
[FIRApp configure];
[FIRDynamicLinks performDiagnosticsWithCompletion:nil];
(you may have to #import Firebase;)
Run the project in Xcode to see a report like this in the debug console:
---- Firebase Dynamic Links diagnostic output start ----
Firebase Dynamic Links framework version 4.0.8
System information: OS iOS, OS version 14.0.1, model iPhone
Current date 2020-10-02 05:02:39 +0000
Device locale en-US (raw en_US), timezone Europe/Berlin
Specified custom URL scheme is com.domain and Info.plist contains such scheme in CFBundleURLTypes key.
AppID Prefix: XXXXXXXX, Team ID: XXXXXXXX, AppId Prefix equal to Team ID: YES
performDiagnostic completed successfully! No errors found.
---- Firebase Dynamic Links diagnostic output end ----
This seems to have been fix in later firebase sdks, if you look at the PR linked in this github issue (I haven't tested, but I have an older sdk version with the issue)
If you don't want to update your SDK right away, an alternative solution is to not use firebase auto-generated email, and instead provide your own email where you insert the firebase link.
In that case, you can tweak the link before inserting it in the email, and make sure it has a trailing slash.
dont forget to add dynamicLinkDomain: 'link.mydomain.com',
url: 'https://app.mydomain.com',
dynamicLinkDomain: 'link.mydomain.com'
I got it working after adding dynamicLinkDomain: 'link.mydomain.com'
P.S Flutter project
Our organization uses an enterprise account and the itms-services protocol to internally deploy apps over-the-air.
Our plists and ipas are hosted on Amazon S3 and everything works as expected - you click a link and an alert pops up asking if you'd like to install the app.
We are now trying to store our files on Firebase storage and send out links in the following format:
itms-services://?action=download-manifest&url=https://firebasestorage.googleapis.com/v0/b/my-app.appspot.com/o/MyApp.plist?alt=media&token=my-token
Pasting this link in Safari opens a dialog asking: 'Open this page in "iTunes"?' Clicking on open does nothing.
It's worth mentioning that if I upload the same plist/ipa combo to S3 it works fine. Also, if I paste the url itself (without the itms-services part) I am able to download both plist and ipa.
Why don't I get the dialog asking if I'd like to install the app? I have a feeling that it's somehow related to an issue with permissions to Firebase but as I am able to download the file directly I'm not really sure.
Your url should be encoded.
For example:
Normal url: https://firebasestorage.googleapis.com/v0/b/my-app.appspot.com/o/MyApp.plist?alt=media&token=my-token
Encoded url: https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fmy-app.appspot.com%2Fo%2FMyApp.plist%3Falt%3Dmedia%26token%3Dmy-token
Finally: itms-services://?action=download-manifest&url=https%3A%2F%2Ffirebasestorage.googleapis.com%2Fv0%2Fb%2Fmy-app.appspot.com%2Fo%2FMyApp.plist%3Falt%3Dmedia%26token%3Dmy-token
gfvilela's solution worked in 2017 and if you have spaces you still need to do that but there is a new issue where firebase removes the // after itms-services: in redirects.
I used https://www.redirect-checker.org/index.php to check what my redirect actually redirects to and it shows that it's leaving out the //:
itms-services:?action=download-manifest&url=...
Somehow this still opens the popup "Open this page in Itunes" but it will not open the next popup "<domain> would like to install <app>" probably because the Itunes process that is opened parses the URL different from how iOS handles deeplinks.
I can only speculate but I think the problem with firebase removing the // lies with how they handle : since they use it with their "glob" pattern matching: https://firebase.google.com/docs/hosting/full-config.
Attempts
I tried encoding the entire URL, just the // part and even only the : but all of these redirect to mydomain.com/itms-services....
I tried using the Dynamic Links module but that doesn't support this either:
Please enter a valid URL starting with http:// or https://
Solution
I think the only way to do this using firebase is to redirect using functions similar to this question: Cloud function for firebase to redirect to a URL
This is definitely more work and is not included in the free firebase package but here is how I solved it:
run firebase init functions
Write the redirect in functions/index.js
exports.downloadApp = functions.https.onRequest((req, res) => {
res.redirect(302, 'itms-services://?action=download-manifest&url=<YOURMANIFEST>');
});
Run firebase deploy --only functions
In your firebase.json add a rewrite (not redirect) to the function:
"rewrites": [
{
"source": "/app",
"function": "downloadApp"
}
]
Run firebase deploy --only hosting
Note
This is an awful lot of workaround just because firebase doesn't have an escape character for : for when you don't want to use it for "glob" pattern matching.
How to Open an iOS App using Firebase Dynamic Links and Pass or get Parameters To an App Via Custom URL Scheme in iOS(swift)?
for eg :- https://q3tyj.app.goo.gl/abcd
My URL Scheme is ‘q3tyj.app.goo.gl’ in iOS app in Url Types.
If I type q3tyj.app.goo.gl in safari, I am able to open the application. But if I type q3tyj.app.goo.gl with some extra parameter like https://q3tyj.app.goo.gl/abcd in safari, , I am not able to open the application.
please also explain me how to get “link” parameter (which associated with dynamic link) from dynamic link in iOS app ( Swift ) .
I followed steps which were mentioned in Firebase.google.com for iOS ( Swift ).but its not working.
Thanks,
Nirav Virpara
It's hard to know exactly where your error is, but a few things to help you debug:
If you go to https://q3tyj.app.goo.gl/apple-app-site-association, you should see some JSON that points to your app. If you don't see this, make sure you've entered your team ID and your App Store ID in the project settings in the Firebase console
Make sure you're using your Bundle ID, not the shortlink domain, as your custom URL scheme in Xcode
Make sure you've enabled Associated Domains in the Capabilities tab of your Xcode project, and your domain looks like applinks:q3tyj.app.goo.gl
Universal Links (and, therefore, Dynamic Links) generally don't work if you type them directly into the Safari address bar. Instead, try typing the URL into an app like Notes and then clicking on them from there.
Good luck!
If you type https://q3tyj.app.goo.gl/apple-app-site-association this link in your browser and check, you will end up seeing a json, meaning your apple-app-site-association is correctly configured on your google website. However, you need to make sure that teamid in your google console or appid is correct.