laulamanapps / apple-passbook-bundle

从您的Symfony应用程序生成Apple Passbooks

v1.1 2020-07-18 09:55 UTC

This package is auto-updated.

Last update: 2024-09-10 03:09:02 UTC


README

此软件包为LauLamanApps Apple Passbook Package提供Symfony配置

GithubCi Build Status Code Coverage Scrutinizer Code Quality Latest Stable Version License

安装

使用composer,添加

$ composer require laulamanapps/apple-passbook-bundle

运行测试

为了确保一切正常工作,您可以运行测试

$ make tests-unit 
$ make tests-integration 
$ make tests-infection 

获取证书

前往Apple Developer Portal以获取证书,用于签署您的passbooks。

转换证书和密钥到.p12文件,使用的是密钥链访问

配置Bundle

#config/packages/laulamanapps_apple_passbook.yml

laulamanapps_apple_passbook:
  certificate: '%env(APPLE_PASSBOOK_CERTIFICATE)%'
  password: '%env(APPLE_PASSBOOK_CERTIFICATE_PASSWORD)%'
  team_identifier: '%env(APPLE_PASSBOOK_TEAM_IDENTIFIER)%'
  pass_type_identifier: '%env(APPLE_PASSBOOK_PASS_TYPE_IDENTIFIER)%'

将环境变量添加到.env文件中

##> laulamanapps/apple-passbook-bundle
APPLE_PASSBOOK_CERTIFICATE=path/to/certificate.p12
APPLE_PASSBOOK_CERTIFICATE_PASSWORD=password
APPLE_PASSBOOK_PASS_TYPE_IDENTIFIER=pass.com.your.pass.identifiers
APPLE_PASSBOOK_TEAM_IDENTIFIER=identifier
APPLE_PASSBOOK_WEB_SERVICE_URL='http://example.com/'
##< laulamanapps/apple-passbook-bundle

创建 & 编译Passbook

namespace App\Controller;

use LauLamanApps\ApplePassbook\Build\Compiler;
use LauLamanApps\ApplePassbook\GenericPassbook;
use LauLamanApps\ApplePassbook\MetaData\Barcode;
use LauLamanApps\ApplePassbook\Style\BarcodeFormat;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;

final class PassbookController extends AbstractController
{
    /**
     * @var Compiler
     */
    private $passbookCompiler;

    public function __construct(Compiler $passbookCompiler) {
        $this->passbookCompiler = $passbookCompiler;
    }

    /**
     * @Route("/download/passbook/", name="download_passbook")
     */
    public function download(): Response
    {
        $passbook = new GenericPassbook('8j23fm3');
        $passbook->setTeamIdentifier('<TeamId>');
        $passbook->setPassTypeIdentifier('<PassTypeId>');
        $passbook->setOrganizationName('Toy Town');
        $passbook->setDescription('Toy Town Membership');
        
        $barcode = new Barcode();
        $barcode->setFormat(BarcodeFormat::pdf417());
        $barcode->setMessage('123456789');
        $passbook->setBarcode($barcode);

        $data = $this->passbookCompiler->compile($passbook);

        $response = new Response($data);
        $response->headers->set('Content-Description', 'File Transfer');
        $response->headers->set('Content-Type', 'application/vnd.apple.pkpass');
        $response->headers->set('Content-Disposition', 'filename="passbook.pkpass"');

        return $response;
    }
}

配置Web服务中的构建

此软件包包含所有Apple passbooks webservice URL的内置控制器。它使用Symfonys内置的EventDispatcher

通过向config/routes/routes.yaml添加以下配置来启用它

passbook_routes:
    resource: '@ApplePassbookBundle/Controller/'
    type:     annotation

控制器将触发以下事件,以下信息可用

/* Available on All events */
$event->getPassTypeIdentifier();
$event->getStatus();

/* Available on DeviceRegisteredEvent */
$event->getAuthenticationToken();
$event->getDeviceLibraryIdentifier();
$event->getSerialNumber();

/* Available on DeviceRequestUpdatedPassesEvent */
$event->getAuthenticationToken();
$event->getDeviceLibraryIdentifier();
$event->getPassesUpdatedSince();

/* Available on DeviceUnregisteredEvent */
$event->getAuthenticationToken();
$event->getDeviceLibraryIdentifier();
$event->getSerialNumber();

/* Available on RetrieveUpdatedPassbookEvent */
$event->getAuthenticationToken();
$event->getSerialNumber();
$event->getPassTypeIdentifier();
$event->getUpdatedSince();

现在订阅事件

这里的想法是处理事件,并通过在事件本身上调用setter来标记事件已被处理。默认情况下,事件的状态是Status::unhandled()

namespace App\Integration\Symfony\EventSubscriber;

use DateTimeImmutable;
use LauLamanApps\ApplePassbook\GenericPassbook;
use LauLamanApps\ApplePassbookBundle\Event\DeviceRegisteredEvent;
use LauLamanApps\ApplePassbookBundle\Event\DeviceRequestUpdatedPassesEvent;
use LauLamanApps\ApplePassbookBundle\Event\DeviceUnregisteredEvent;
use LauLamanApps\ApplePassbookBundle\Event\RetrieveUpdatedPassbookEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

final class ApplePassbookSubscriber implements EventSubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return [
            DeviceRegisteredEvent::class => 'onDeviceRegistered',
            DeviceRequestUpdatedPassesEvent::class => 'onDeviceRequestUpdatedPasses',
            RetrieveUpdatedPassbookEvent::class => 'onRetrieveUpdatedPassbook',
            DeviceUnregisteredEvent::class => 'onDeviceUnregistered',
        ];
    }

    public function onDeviceRegistered(DeviceRegisteredEvent $event): void
    {
        $passbook = $this->passbookRepository->getBySerial($event->getSerialNumber());

        if ($event->getAuthenticationToken() <> $passbook->getAuthToken()) {
            $event->notAuthorized();

            return;
        }

        /**
         * Save in Database 
         */

        $event->deviceRegistered();
    }

    public function onDeviceRequestUpdatedPasses(DeviceRequestUpdatedPassesEvent $event): void
    {
        $passbooks = $this->passbookRepository->getSerialsSince(
            $event->getPassTypeIdentifier(),
            $event->getDeviceLibraryIdentifier(),
            $event->getPassesUpdatedSince()
        );

        if ($passbooks) {
            $serials = [];
            foreach ($passbooks as $passbook) {
                $serials[] = $passbook->getSerialNumber();
            }

            $event->setSerialNumbers($serials, new DateTimeImmutable());

            return;
        }

        $event->notFound();
    }

    public function onRetrieveUpdatedPassbook(RetrieveUpdatedPassbookEvent $event): void
    {
        try {
            $entity = $this->passbookRepository->getBySerial($event->getSerialNumber());
            if ($entity->getAuthToken() !== $event->getAuthenticationToken()) {
                $event->notAuthorized();

                return;
            }

            if ($event->getUpdatedSince() && $entity->getUpdatedAt() < $event->getUpdatedSince()) {
                $event->notModified();

                return;
            }

            $passbook = new GenericPassbook($event->getSerialNumber());
            /* Generate Passbook */

            $event->setPassbook($passbook);
        } catch (NoResultException $e) {
            $event->notFound();
        }
    }

    public function onDeviceUnregistered(DeviceUnregisteredEvent $event): void
    {
        $passbook = $this->passbookRepository->getBySerial($event->getSerialNumber());

        if ($event->getAuthenticationToken() <> $passbook->getAuthToken()) {
            $event->notAuthorized();

            return;
        }

        /**
         * Remove from Database 
         */

        $event->deviceUnregistered();
    }
}

鸣谢

此软件包由LauLaman开发。