thenextweb/passgenerator

一个用于创建与 Apple Wallet (旧 Passbook) 兼容票据的 Laravel 包。

0.5.0 2024-03-13 12:48 UTC

This package is auto-updated.

Last update: 2024-09-13 13:48:14 UTC


README

Passgenerator 是一个 Laravel7+ 包,允许您轻松创建与 Apple Wallet (旧 Passbook) 兼容的通行证。

👉 目录 👈

👮 要求

只需要 Laravel 7+ 和安装并启用 PHP Zip 扩展

💾 安装

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

composer require thenextweb/passgenerator

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

'providers' => [
// ...
    Thenextweb\PassGeneratorServiceProvider::class,
],

就是这样!

🍎 Apple 文档

从现在起,一些内容在 Apple 文档中解释得更好,所以如果您不确定,请查看以下文档(如果您尚未查看)

📝 配置

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

  1. 访问 Apple 开发者页面 ➵ 标识 ➵ 通行证类型 ID

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

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

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

  5. 如果您已经进行过 iOS 开发,您可能已经在 Mac 的钥匙串中有了 Apple Worldwide Developer Relations 中间证书。如果没有,它可以从 Apple 网站(以 .cer 格式)下载。此证书需要以 .pem 格式导出,您也可以从 钥匙串访问(或您用于管理 OS 上证书的任何工具)中导出。

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

  • CERTIFICATE_PATH ➪ .p12 通行证证书的路径。
  • CERTIFICATE_PASS ➪ 在导出证书时设置的密码。
  • WWDR_CERTIFICATE ➪ .pem 格式 Apple Worldwide Developer Relations 中间证书 的路径。

如果出于某些原因必须修改配置文件(冲突的 env 键、需要动态证书等),可以使用以下命令发布它

// file will be at config/passgenerator.php
php artisan vendor:publish --provider="Thenextweb\PassGeneratorServiceProvider"

🚀 使用

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

use Thenextweb\PassGenerator;

//...

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

$pass = new PassGenerator($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类型来服务于其设备,以下类似的内容应该可以完成这个任务:

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

稍后,如果您的用户需要再次下载通行证,您无需重新创建(避免在加密操作上浪费CPU周期),只需进行类似以下操作:

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

也有可能检索您文件系统上通行证的实际路径。默认情况下,Passgenerator将复制您的默认文件系统配置(通常以storage_path('app')为根,但您始终可以使用getPassFilePath($pass_identifier)来获取实际路径,前提是它存在。

定义

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

$coupon = Thenextweb\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);

$passgenerator->setPassDefinition($coupon);