projectsaturn/appypass

A Laravel 包,用于创建兼容 Apple Wallet 的通行证。

0.3.0 2019-09-25 05:06 UTC

This package is auto-updated.

Last update: 2024-09-29 05:22:07 UTC


README

AppyPass 是一个 Laravel6+ 包,可以轻松创建与 Apple Wallet 兼容的通行证。

(thenextweb/passgenerator 分支出来)

👉 目录 👈

👮 要求

所需的是 Laravel 6+ 和已安装并启用的 PHP Zip 扩展

💾 安装

安装此包的最佳和最简单方法是使用 Composer 包管理器。要在项目根目录中运行此命令。

composer require projectsaturnstudios/appypass

然后,将 ProjectSaturn\AppyPassServiceProvider 提供者添加到 config/app.php 中的 providers 数组中。

'providers' => [
// ...
    ProjectSaturn\AppyPassServiceProvider::class,
],

就这样!

🍎 Apple 文档

从现在起,一些内容在 Apple 文档中有更详细的解释,所以如果有疑问,请查看以下文档(如果您尚未这样做)

📝 配置

要开始使用此包,需要一些 Apple 文件以及一些操作来将它们转换为更友好的格式。

  1. 访问Apple Developer 页面 ➵ Identifiers ➵ Pass Type IDs

  2. 接下来,您需要创建一个通行证类型 ID。这与应用的包 ID 类似。它将唯一标识一种特定的通行证。它应该是反向域名样式字符串的形式(例如,pass.com.example.appname)。

  3. 创建通行证类型 ID 后,单击 编辑 并按照说明创建新的证书。

  4. 过程完成后,可以下载通行证证书。但这还不是全部,证书以 .cer 文件的形式下载,需要将其转换为 .p12 才能工作。如果您使用的是 Mac,可以将其导入到 Keychain Access 并从那里导出。请确保记住您为导出文件设置的密码,因为您以后需要使用它。您也可以使用其他工具来转换证书,但请确保导出的 PKCS12 文件中包含私钥。

  5. 如果您已经进行过 iOS 开发,您可能已经在 Mac 的密钥链中有了 Apple Worldwide Developer Relations Intermediate Certificate。如果没有,可以从Apple 网站(格式为 .cer)下载。这个需要以 .pem 格式导出,您也可以从 Keychain Access(或您用于管理 OS 上的证书的任何工具)中导出。

完成所有这些繁琐的过程后,一切准备就绪,可以开始使用此包了。现在最简单的是将以下键添加到您的 .env 文件中

  • CERTIFICATE_PATH ➪ 通行证证书的路径。
  • CERTIFICATE_PASS ➪ 导出证书时设置的密码。
  • WWDR_CERTIFICATE ➪ Apple Worldwide Developer Relations Intermediate Certificate 的路径(格式为 .pem)。

如果必须修改配置文件(冲突的env键、需要动态证书等),可以使用以下命令进行发布

// file will be at config/appypass.php
php artisan vendor:publish --provider="ProjectSaturn\AppyPassServiceProvider"

🚀 使用

要首次创建通行证,您首先需要创建通行证定义,可以是JSON文件或数组。强烈建议您已经阅读了Apple文档以及PassKit包格式参考

use ProjectSaturn\AppyPass;

//...

$pass_identifier = 'somekindofid';  // This, if set, it would allow for retrieval later on of the created Pass

$pass = new AppyPass($pass_identifier);

$pass_definition = [
    "description"       => "description",
    "formatVersion"     => 1,
    "organizationName"  => "organization",
    "passTypeIdentifier"=> "pass.com.example.appname",
    "serialNumber"      => "123456",
    "teamIdentifier"    => "teamid",
    "foregroundColor"   => "rgb(99, 99, 99)",
    "backgroundColor"   => "rgb(212, 212, 212)",
    "barcode" => [
        "message"   => "encodedmessageonQR",
        "format"    => "PKBarcodeFormatQR",
        "altText"   => "altextfortheQR",
        "messageEncoding"=> "utf-8",
    ],
    "boardingPass" => [
        "headerFields" => [
            [
                "key" => "destinationDate",
                "label" => "Trip to: BCN-SANTS",
                "value" => "15/09/2015"
            ]
        ],
        "primaryFields" => [
            [
                "key" => "boardingTime",
                "label" => "MURCIA",
                "value" => "13:54",
                "changeMessage" => "Boarding time has changed to %@"
            ],
            [
                "key" => "destination",
                "label" => "BCN-SANTS",
                "value" => "21:09"
            ]

        ],
        "secondaryFields" => [
            [
                "key" => "passenger",
                "label" => "Passenger",
                "value" => "J.DOE"
            ],
            [
                "key" => "bookingref",
                "label" => "Booking Reference",
                "value" => "4ZK6FG"
            ]
        ],
        "auxiliaryFields" => [
            [
                "key" => "train",
                "label" => "Train TALGO",
                "value" => "00264"
            ],
            [
                "key" => "car",
                "label" => "Car",
                "value" => "009"
            ],
            [
                "key" => "seat",
                "label" => "Seat",
                "value" => "04A"
            ],
            [
                "key" => "classfront",
                "label" => "Class",
                "value" => "Tourist"
            ]
        ],
        "backFields" => [
            [
                "key" => "ticketNumber",
                "label" => "Ticket Number",
                "value" => "7612800569875"
            ], [
                "key" => "passenger-name",
                "label" => "Passenger",
                "value" => "John Doe"
            ], [
                "key" => "classback",
                "label" => "Class",
                "value" => "Tourist"
            ]
        ],
        "locations" => [
            [
                "latitude" => 37.97479,
                "longitude" => -1.131522,
                "relevantText" => "Departure station"
            ]
        ],
        "transitType" => "PKTransitTypeTrain"
    ],
];

$pass->setPassDefinition($pass_definition);

// Definitions can also be set from a JSON string
// $pass->setPassDefinition(file_get_contents('/path/to/pass.json));

// Add assets to the PKPass package
$pass->addAsset(base_path('resources/assets/wallet/background.png'));
$pass->addAsset(base_path('resources/assets/wallet/thumbnail.png'));
$pass->addAsset(base_path('resources/assets/wallet/icon.png'));
$pass->addAsset(base_path('resources/assets/wallet/logo.png'));

$pkpass = $pass->create();

现在,有效票证已经设置好。苹果推荐使用MIME类型将其提供给其设备,以下类似内容应该可以做到

$headers = [
   'Content-Transfer-Encoding' => 'binary',
   'Content-Description' => 'File Transfer',
   'Content-Disposition' => 'attachment; filename="pass.pkpass"',
   'Content-length' => strlen($pkpass),
   'Content-Type' => AppyPass::getPassMimeType(),
   'Pragma' => 'no-cache',
];

return response($pkpass, 200, $headers);

稍后,如果您的用户需要再次下载通行证,您无需再次创建(浪费所有那些在加密方面的CPU周期),您只需做类似以下操作

// If the pass for that ID does not exist, you can then proceed to generate it as done above.
$pkpass = AppyPass::getPass($pass_identifier);
if (!$pkpass) {
    $pkpass = $this->createWalletPass();
}
// ...

还可以检索文件系统中通行证的实际路径。默认情况下,AppyPass会复制您的默认文件系统配置(通常基于storage_path('app'),但您始终可以使用getPassFilePath($pass_identifier)来检索实际路径(如果存在的话)。

定义

还可以使用定义对象编程创建/修改通行证。例如:

$coupon = ProjectSaturn\Definitions\Coupon();
$coupon->setDescription('Coupon description');
$coupon->setSerialNumber('123456');

$coupon->setUserInfo([
    'email' => 'user@domain.com',
]);
$coupon->setExpirationDate(Carbon::now()->addMonths(6));

$location = new Location();
$location->setLatitude(40.4378698);
$location->setLongitude(-3.819619);
$coupon->addLocation($location);

$coupon->setMaxDistance(50);
$coupon->setRelevantDate(Carbon::now()->addDays(10));

$coupon->addAuxiliaryField(new Field('key', 'value'));

$coupon->addBackField(new Number('price', 13, [
    'currencyCode' => 'EUR',
    'numberStyle' => Number::STYLE_DECIMAL
]));

$coupon->addPrimaryField(new Date('created_at', Carbon::now(), [
    'dateStyle' => Date::STYLE_FULL,
]));

$barcode = new Barcode('7898466321', Barcode::FORMAT_CODE128);
$coupon->addBarcode($barcode);

$appypass->setPassDefinition($coupon);