Il est généralement admis que Wallet n'est pas le service le plus populaire dans la CEI. Mais déjà dans le deuxième projet consécutif, le client définit la tâche "Faire l'intégration avec Wallet". J'ai donc décidé d'écrire cet article pour parler du service dans son ensemble et montrer comment y intégrer mon produit.
Qu'est-ce qu'un portefeuille? Il vous permet de conserver différents types de cartes dans votre téléphone (tickets, cartes de réduction, etc.), facilitant ainsi la vie des utilisateurs du produit. De plus, il est possible de mettre à jour les informations sur la carte via des notifications push, mais c'est un sujet pour un article séparé. Mais si vous avez une carte / ticket / abonnement qui peut être intégré au téléphone, alors il y a une solution! Comment le faire - lire ci-dessous.
En règle générale, votre serveur est responsable de la création de la carte. L'application reçoit la carte sous la forme d'un fichier .pkpass et via l'application, l'utilisateur peut ajouter la carte à Wallet.
Structure de la carte
Quelle est la carte du point de vue du développeur? Une carte est une archive avec l'extension .pkpass. Il contient toutes les données nécessaires à l'affichage et au fonctionnement de la carte. Le contenu de l'archive est dans le tableau ci-dessous.
Fichier | Rendez-vous |
---|
background.png | Image de fond pour la carte. |
footer.png | Image à côté du code-barres |
icon.png | Icône pour les notifications et les lettres |
logo.png | Logo de la carte. Affiché en haut à gauche |
manifest.json | Registre de tous les fichiers inclus |
signature | Signature PKCS7 |
pass.json | Apparence et informations cartographiques |
strip.png | Image située derrière la description principale de la carte |
thumbnail.png | Image supplémentaire (préciser) |
Les types de cartes suivants sont disponibles:
- Billet d'embarquement: en avion ou en train. Habituellement, le coupon fonctionne pour un voyage;
- Coupon: pour les coupons et les offres spéciales;
- Ticket d'événement: peut fonctionner à la fois pour un événement et pour toute une saison;
- Carte de réduction: cartes de fidélité, cartes de réduction ou cartes-cadeaux;
- Carte vue générale: si aucune des conditions ci-dessus ne s'applique à votre cas: par exemple, une carte pour voyager en métro ou un laissez-passer pour la salle de sport.
Considérez schématiquement l'apparence des différentes cartes. Les photos sont mieux nommées comme indiqué dans le tableau ci-dessus.
Carte d'embarquement

Coupon

Ticket d'événement

Carte communautaire

Carte de réduction

Structure Pass.json
Champs obligatoires. Contient l'ID de type de passe, l'ID d'équipe, le nom de l'organisation, etc.
Clés pour les applications connexes. Nécessaire pour afficher les applications qui doivent être "associées" à la carte.
Cartes clés "date d'expiration".
Clés de pertinence. Par exemple, les coordonnées de la zone où la carte peut être utilisée, ou le début de l'événement auquel elle est destinée.
La clé est le style. Au début de l'article, 5 types de cartes pour Wallet étaient répertoriés. Chacun d'eux a son propre style. Une telle clé doit être strictement une.
Clés pour la conception visuelle de la carte. En plus de l'évidence, ils contiennent des informations sur le code-barres affiché sur la carte.
Clés de service Web. Vous pouvez utiliser les services Web pour interagir avec la carte, par exemple, la mettre à jour automatiquement.
Clés NFC. Contiennent des informations supplémentaires pour les transactions Apple Pay.
Maintenant sur tout plus en détail.
Champs obligatoires
Clé dans JSON | Type de données | La description |
---|
description | String Localisé | Une brève description de la carte. Localisé. |
formatVersion | Int | Version du format de fichier. La valeur doit être 1. |
organizationName | String Localisé | Le nom de l'organisation qui délivre les cartes. |
passTypeIdentifier | String | Transmettez l'ID de type et le compte développeur. |
serialNumber | String | Numéro de série d'une seule carte |
teamIdentifier | String | ID d'équipe de l'équipe de développement |
Clés pour les applications connexes
Clé dans JSON | Type de données | La description |
---|
associatedStoreIdentifiers | [Int] | En option. L'ID des applications associées à la carte. Le premier qui est compatible avec l'appareil actuel est toujours pris. |
appLaunchURL | String | URL transmise à l'application à l'ouverture |
Touches de style
Clé dans JSON | Type de données | La description |
---|
primaryFields | [JSON] | Informations de base sur la carte. |
domaines secondaires | [JSON] | Informations générales. |
champs auxiliaires | [JSON] | Champs pour des informations supplémentaires. En option |
headerFields | [JSON] | Le titre de la carte. Il s'affiche même lorsque les cartes sont visibles dans la liste. |
champs auxiliaires | [JSON] | Informations de base sur la carte. |
transitType | String | Type de transport pour les cartes de ticket. Il peut prendre les valeurs suivantes: PKTransitTypeAir, PKTransitTypeBoat, PKTransitTypeBu`, PKTransitTypeGeneric, `PKTransitTypeTrain`. |
backFields | [JSON] | Tableau des champs responsables du verso de la carte |
JSON dans ce cas a la forme suivante:
"key" : "value1", "label" : "value2", "value" : "value3"
La valeur par la clé de valeur peut être numérique ou chaîne. Cependant, currencyCode et la valeur de chaîne ne peuvent pas être utilisés. Comme pour les champs auxiliaires et les champs secondaires, il peut y en avoir plusieurs, et vous devez surveiller la longueur des lignes qui y sont utilisées.
Clés pour la conception visuelle
Clé dans JSON | Type de données | La description |
---|
codes à barres | [JSON] | Informations sur le code-barres (voir ci-dessous). |
backgroundColor | couleur comme chaîne | Couleur d'arrière-plan. (# Fa32e4) |
foregroundColor | couleur comme chaîne | Couleur d'étiquette avec valeurs |
groupingIdentifier | String | Facultatif pour les billets d'événement et les billets de transport. Les cartes du même style - passTypeIdentifier et groupingIdentifier - seront regroupées |
labelColor | couleur comme chaîne | Étiqueter le texte avec les noms de champ |
logoText | Chaîne localisable | Texte affiché à côté du logo |
Code barre
La partie la plus importante de la carte. Un numéro d'identification de carte y est cousu (par exemple, un numéro de carte physique ou un numéro de ticket). Il est important que le scanner ou tout autre outil soit capable de lire les codes avec l'encodage correct.
Clé dans JSON | Type de données | La description |
---|
altText | String | Texte facultatif affiché à côté du code-barres si le code-barres n'est pas lu. |
format | String | Format de code-barres. Peut prendre des valeurs: PKBarcodeFormatQR, PKBarcodeFormatPDF417, PKBarcodeFormatAztec, PKBarcodeFormatCode128 |
message | String | Code ou numéro de carte crypté en code-barres. |
messageEncoding | String | Encodage des messages. Généralement iso-8859-1 |
Emplacement
Ces clés sont responsables de l'emplacement dans lequel la carte peut être utilisée.
Clé dans JSON | Type de données | La description |
---|
altiture | String | Texte facultatif affiché à côté du code-barres si le code-barres n'est pas lu. |
latitude | Longitude | Latitude |
longtitude | Double | Latitude |
relevantText | String | Texte facultatif qui apparaît sur l'écran de verrouillage au moment où l'utilisateur entre dans la portée de la carte. |
Face arrière
Des informations supplémentaires peuvent être placées sur la partie des informations inversées: conditions d'utilisation, politique de mise à jour automatique, coordonnées et un lien vers l'application à laquelle appartient la carte. La figure montre la correspondance des champs dans pass.json et l'apparence du verso de la carte. S'il y a des liens, des numéros de téléphone, etc. dans le champ de valeur, ils seront automatiquement mis en surbrillance.

Créez une carte. 2e partie
Alors, les photos sont prêtes, pass.json est formé, il reste à tout mettre ensemble. Pour ce faire, remplissez manifest.json (voir tableau 1), où vous devez inclure toutes les images et pass.json. Il s'avère quelque chose comme ceci:
. . . . . . "pass.json" = 303c753abc39aa732ec74643d6db28348fe8a823; "strip.png" = 736d01f84cb73d06e8a9932e43076d68f19461ff; "strip@2x.png" = 468fa7bc93e6b55342b56fda09bdce7c829d7d46; . . . . . .
A partir de ce moment, rien ne doit être changé, car le SHA sera incorrect; en cas de changement, il est nécessaire de régénérer le SHA.
Ensuite, vous devez créer un ID de type de passe dans le bureau du développeur et faire un certificat pour cela. La procédure doit être plus ou moins familière si vous avez créé précédemment, par exemple, des profils de provisioning.

Ensuite, accédez au trousseau et exportez à partir de là le certificat de relation de développeur Apple (WWDR) au format .pem.

À partir de là, nous exportons l'ID de type de passe créé au format .p12. À ce stade, la femme de ménage vous demandera de saisir le mot de passe du certificat. Dans ce cas, un mot de passe est facultatif.
Veuillez noter que toutes les autres actions doivent être effectuées dans un dossier, où manifest.json, pass.json et les images doivent déjà se trouver.
Vous devez maintenant générer une signature, que nous signerons l'archive. Tout d'abord, exportez l'ID de type de passe et la clé en tant que .pem.
openssl pkcs12 -in certificate.p12 -clcerts -nokeys -out passcertificate.pem -passin pass: your_password
et
openssl pkcs12 -in certificates.p12 -nocerts -out passkey.pem -passin pass: -passout pass:new_password
Nous sommes maintenant prêts à générer une signature. Faisons-en une commande:
openssl smime -binary -sign -certfile WWDR.pem -signer passcertificate.pem -inkey passkey.pem -in manifest.json -out signature -outform DER -passin pass:___
Donc, tout est prêt pour nous, il ne reste plus qu'à récupérer l'archive, nous le faisons avec la commande:
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
J'attire votre attention sur le fait que tous les fichiers dans lesquels vous souhaitez inclure l'archive de données pour la carte (.pkpass) doivent être répertoriés ici.
En conséquence, nous obtenons un fichier .pkpass qui peut être ouvert sur l'ordinateur. Nous verrons un aperçu de la carte, dont l'apparence peut différer de l'apparence sur le téléphone.
Tout cela peut être fait un peu plus facilement. Apple fournit l'utilitaire signpass
( exemples de métriques Apple Wallet ), qui prend en charge tous les calculs SHA (le fichier manifest.json
peut être laissé seul) et le travail de création de signatures. Pour l'utiliser, vous devez créer un projet et placer le fichier signpass
dans un dossier avec toutes les ressources nécessaires.

En général, la structure devrait ressembler à ceci:

Ensuite, exécutez la commande:
./signpass -p wallet
Wallet est le nom du dossier dans lequel se trouvent toutes les ressources. La sortie est wallet.pkpass. Son contenu peut être consulté en décompressant wallet.pkpass.
unzip wallet.pkpass
Il est possible que la création de pkpass soit soumise au backend, auquel cas il sera nécessaire de transférer aux développeurs WWDR un certificat pour ID de type de passe sous la forme .p12 et un mot de passe pour celui-ci.
Intégration d'applications
Pour que l'application puisse ajouter des cartes à Wallet, vous devez activer cette fonctionnalité dans l'ID d'application et également activer cette fonctionnalité dans les capacités du projet.


Ceci est nécessaire pour un travail correct et complet avec Wallet. Sinon, il ne sera pas possible de lire les cartes de Wallet et, par exemple, il ne sera pas possible de comprendre si notre carte est ajoutée ou non. Il est également important de noter que l'ID de l'équipe dans pass.json doit correspondre à l'ID de l'équipe, sinon vous devrez les ajouter manuellement aux droits d'accès, ce qui peut résoudre le problème, mais je n'ai pas vérifié cela.

Ajout d'une carte
L'ajout de cartes est très 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)) }
Cependant, encore une fois, le plus souvent, le fichier .pkpass devra être téléchargé à partir de votre serveur.
Il convient de noter que PassKit génère des erreurs assez lisibles, vous pouvez donc facilement comprendre ce qui a été mal fait.
Pour obtenir des informations sur les cartes disponibles dans Wallet et liées à votre application, vous devez vous tourner vers l'objet PKPassLibrary.
let passLibrary = PKPassLibrary() let passes = passLibrary.passes()
Ainsi, vous pouvez comprendre si la carte est ajoutée ou non, ainsi que mettre à jour l'interface. De plus, via PKPassLibrary, les cartes peuvent être mises à jour et supprimées. Les cartes peuvent également être mises à jour via des services Web, mais dans cet article, nous ne considérerons pas une telle option.
Contrôle d'unicité
Étant donné que dans votre service, en règle générale, la carte est liée à un compte, dans l'application, vous devrez probablement déterminer en quelque sorte si la carte appartient à l'utilisateur actuel. Je suggère de le faire via serialNumber
. Par exemple, définissez l'ID serialNumber
de l'utilisateur ou du numéro de carte.
Test
Apple fournit des exemples de pkpass pour différents types, vous pouvez vous concentrer sur eux.
Échantillons de portefeuille Apple
Pour voir à quoi ressemble la carte, vous pouvez ajouter pkpass au projet (voir «Ajouter une carte»). Le processus d'ajout / suppression est déjà discuté ci-dessus, il ne reste plus qu'à rappeler que l'application ne verra pas les cartes déjà ajoutées si la carte pour Wallet a été créée sur le compte d'un développeur et que le développement lui-même a été effectué à partir d'un autre compte (pertinent pour les sociétés d'externalisation). Dans ce cas, vous pouvez ajouter des cartes sans problème.
Vous pouvez vérifier si les informations du code-barres sont correctement encodées à l'aide d'un scanner de code QR. Et il est absolument nécessaire de vérifier l'exactitude du travail avec ce scanner.
Conclusion
L'article a examiné le processus de création et de conception d'une carte, ainsi que le processus d'intégration avec l'application et les problèmes qui peuvent survenir. Je n'ai intentionnellement pas abordé les problèmes d'intégration avec les services Web et les mises à jour de cartes, et j'espère le faire dans le prochain article.
Matériaux utilisés:
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
Un merci spécial à mehdzor pour le compte développeur pour les tests.