It is considered that Wallet is not the most popular service in the CIS. But already in the second project in a row, the customer sets the task “To make integration with the Wallet”. Therefore, I decided to write this article in order to tell about the service as a whole and show how to integrate my product into it.
What is a wallet? It allows you to keep in your phone various types of cards (tickets, discount cards, etc.), making life easier for users of the product. Moreover, it is possible to update the card information via push notifications, but this is a topic for a separate article. But if you have a card / ticket / subscription that can be integrated into the phone, then there is a solution for this! How to do this - read below.
As a rule, your server is responsible for creating the map. The application receives the card in the form of a .pkpass file and already through the application the user can add the card to the Wallet.
What is the map from the point of view of the developer? The map is an archive with the .pkpass extension. It contains all the data necessary for the display and operation of the map. The contents of the archive are in the table below.
File | Purpose |
---|---|
background.png | Background picture for the map. |
footer.png | Picture next to the barcode |
icon.png | Icon for notifications and letters |
logo.png | Logo card. Displayed on the upper left |
manifest.json | Registry of all included files |
signature | PKCS7 signature |
pass.json | Appearance and information on the map |
strip.png | Picture behind the main card description |
thumbnail.png | Additional picture (specify) |
There are the following types of cards:
Consider schematically the appearance of different cards. Pictures should be called as indicated in the table above.
Required fields. Contain Pass Type ID, Team ID, organization name, etc.
Keys for related applications. Needed to display applications that need to be "associated" with the map.
Keys "expiration date" cards.
Keys of relevance. For example, the coordinates of the area where the map can be used, or the beginning of the event for which it is intended.
The key is style. At the beginning of the article were listed 5 types of maps for Wallet. Each of them has its own style. Such a key must be strictly one.
Keys visual card design. In addition to the obvious, they contain information about the barcode displayed on the map.
Web service keys. You can use web services to interact with the map, for example, automatically update it.
NFC keys. Contain additional information for Apple Pay transactions.
Now everything is more detailed.
description | String. Localizable | Brief map description. Localizable |
formatVersion | Int | File format version. The value must be 1. |
String. Localizable | The name of the organization that issues the cards. | |
String | Pass Type ID and developer cabinet. | |
String | The serial number of the individual card | |
String | Team ID Developer Team |
[Int] | Optional. Application ID associated with the card. Always take the first, compatible with the current device. | |
String | URL that is passed to the application when opened |
[Json] | Basic information about the map. | |
[Json] | Background Information. | |
[Json] | Fields for additional information. Optional | |
[Json] | The title of the card. It is displayed even when the cards are visible in the list. | |
[Json] | Basic information about the map. | |
String | Type of transport for card tickets. It can take the following values: PKTransitTypeAir, PKTransitTypeBoat, PKTransitTypeBu`, PKTransitTypeGeneric, `PKTransitTypeTrain`. | |
[Json] | Array of fields responsible for the back side of the card |
JSON in this case has the following form:
"key" : "value1", "label" : "value2", "value" : "value3"
The value of the key value can be either numeric or string. However, currencyCode together with a string value will not work. As for auxiliaryFields and secondaryFields, there may be several of them, and it is worth monitoring the length of the lines that they use.
[Json] | Information for the barcode (see below). | |
color as string | Background color. (# Fa32e4) | |
color as string | Color labels with values | |
String | Optional for event tickets and transport tickets. Cards with the same style - passTypeIdentifier and groupingIdentifier - will be grouped | |
color as string | Label text with field names | |
Localizable string | Text displayed next to the logo |
The most important part of the map. The identification number of the card is sewn into it (for example, the physical card number or the ticket number). It is important that a scanner or any other tool be able to read codes in the proper encoding.
String | Optional text displayed next to the barcode if the barcode is not readable. | |
String | Barcode format. May take values: PKBarcodeFormatQR, PKBarcodeFormatPDF417, PKBarcodeFormatAztec, PKBarcodeFormatCode128 | |
String | Code or card number encrypted in barcode. | |
String | Message encoding Usually iso-8859-1 |
These keys are responsible for the location within which the map can be used.
String | Optional text displayed next to the barcode if the barcode is not readable. | |
Longitude | Latitude | |
Double | Latitude | |
String | Optional text that is displayed on the lock screen when the user enters the range of the card. |
Additional information can be placed on the reverse information part: terms of use, auto-update policy, contact details and a link to the application to which the card belongs. The figure shows the correspondence of the fields in pass.json and the appearance of the back side of the map. If the value-field has links, phone numbers, etc., they will be highlighted automatically.
So, the pictures are ready, pass.json is formed, it remains to put all this together. To do this, fill in manifest.json (see table 1), where you need to include all the pictures and pass.json. It turns out like this:
. . . . . . "pass.json" = 303c753abc39aa732ec74643d6db28348fe8a823; "strip.png" = 736d01f84cb73d06e8a9932e43076d68f19461ff; "strip@2x.png" = 468fa7bc93e6b55342b56fda09bdce7c829d7d46; . . . . . .
From this point on it is not necessary to change anything, since SHA will be incorrect, in case of changes, it is necessary to generate SHA again.
Next you need to create a Pass Type ID in the developer’s office and make a certificate for it. The procedure should be more or less familiar if you have previously created, for example, Provisioning profiles.
Then we go to the key-keeper (Keychain) and export the Apple Worldwide Developer Relation Certificate (WWDR) from there as .pem.
From there, we export the created Pass Type ID as .p12. At this stage, the key card asks you to enter the password for the certificate. In this case, the password is optional.
Please note that all further actions should be performed in one folder where manifest.json, pass.json and pictures should already be located.
Now you need to generate a signature, which we will sign the archive. To begin with, export the Pass Type ID and the key to it as .pem.
openssl pkcs12 -in certificate.p12 -clcerts -nokeys -out passcertificate.pem -passin pass: your_password
and
openssl pkcs12 -in certificates.p12 -nocerts -out passkey.pem -passin pass: -passout pass:new_password
Now we are ready to generate a signature. Make this a command:
openssl smime -binary -sign -certfile WWDR.pem -signer passcertificate.pem -inkey passkey.pem -in manifest.json -out signature -outform DER -passin pass:___
So, everything is ready with us, it remains only to collect the archive, we do it with the command:
zip -r nameOfPass.pkpass manifest.json pass.json signature logo.png logo@2x.png logo@3x.png icon.png icon@2x.png icon@3x.png
I draw your attention to the fact that all the files to which you want to include the data archive for the card (.pkpass) should be listed here.
As a result, we get a .pkpass file that can be opened on the computer. We will see a preview of the map, the appearance of which may differ from the appearance on the phone.
All this can be done a little easier. Apple provides the signpass
utility ( Apple Wallet sample meterials ), which takes all the SHA calculations (the manifest.json
file can be left alone) and the work of creating signatures. To use it, you need to collect the project and place the signpass
file in a folder with all the necessary resources.
In general, the structure should look like this:
Next, execute the command:
./signpass -p wallet
Wallet is the name of the folder in which all resources lie. At the output we get the file wallet.pkpass. Its contents can be viewed by unarchiving wallet.pkpass.
unzip wallet.pkpass
It is possible that the creation of pkpass will be put on the backend, in this case it will be necessary to transfer to the developers of WWDR, a certificate for the Pass Type ID in the form of .p12 and a password for it.
In order for the app to have the ability to add maps to the Wallet, you must enable this feature in the App ID and also enable this feature in the Capabilities in the project.
This is necessary for full-fledged correct work with Wallet. Otherwise, it will not be possible to read cards from the Wallet and, for example, it will not be possible to understand whether our card has been added or not. It is also important to note that the team id in pass.json must match the c team id, or you will have to add them manually to the entitlements and this may correct the situation, but I did not check it.
Adding cards is very simple:
guard let passPath = Bundle.main.path(forResource: "wallet", ofType: "pkpass") else { return } let error: ErrorPointer = ErrorPointer(nilLiteral: ()) guard let passData = NSData(contentsOfFile: passPath) else { return } let pass = PKPass(data: passData as Data, error: error) let passLibrary = PKPassLibrary() passLibrary.addPasses([pass]) { (status) in print(passLibrary.containsPass(pass)) }
However, again, more often .pkpass file will need to be downloaded from your server.
It is worth noting that PassKit gives quite readable errors, so you can easily understand what exactly was done wrong.
To get information about the maps available in the Wallet and related to your application, you need to refer to the PKPassLibrary object.
let passLibrary = PKPassLibrary() let passes = passLibrary.passes()
Thus, it is possible to understand whether a map has been added or not, as well as to update the interface. In addition, through the PKPassLibrary maps can be updated and deleted. You can update maps via web services, but in this article we will not consider this option.
Since in your service, as a rule, the card is tied to an account, the application will most likely have to somehow determine whether the card belongs to the current user. I suggest doing this through serialNumber
. For example, set the user ID or card number as the serialNumber
.
Apple provides examples of pkpass for different types, you can focus on them.
Apple Wallet samples
To see how the map looks, you can add pkpass to the project (see “Adding a Map”). The process of adding / deleting has already been discussed above, it remains only to remind that the application will not see already added cards, if the card for Wallet was created on one developer account, and the development itself was carried out from another account (relevant for outsourcing companies). In this case, you can add cards without problems.
You can check whether the information in the barcode is correctly encoded using any QR code scanner. And just need to check the correctness of the work with this scanner.
The article reviewed the process of creating and designing the card, as well as the process of integration with the application and the problems that may arise. I deliberately did not address the issues of integration with web services and map updates, and I hope to do this in the next article.
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/PassKit_PG/Creating.html
https://developer.apple.com/library/archive/documentation/UserExperience/Reference/PassKit_Bundle/Chapters/TopLevel.html#//apple_ref/doc/uid/TP40012026-CH2-SW3
https://itechroof.wordpress.com/2015/11/30/apple-wallet-part-13/
https://developer.apple.com/library/archive/documentation/UserExperience/Conceptual/PassKit_PG/Updating.html
Special thanks to mehdzor for the developer account for tests.
Source: https://habr.com/ru/post/428437/
All Articles