Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
16 / 16
CRAP
100.00% covered (success)
100.00%
55 / 55
InApp
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
16 / 16
24
100.00% covered (success)
100.00%
55 / 55
 __construct
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getQuantity
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getProductIdentifier
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getTransactionIdentifier
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getPurchaseDate
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
3 / 3
 getPurchaseDateTimestamp
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getOriginalTransactionIdentifier
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getOriginalPurchaseDate
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
4 / 4
 getOriginalPurchaseDateTimestamp
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getSubscriptionExpirationDate
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getSubscriptionExpirationDateTimestamp
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getWebOrderLineItemID
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getCancellationDate
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 getCancellationDateTimestamp
100.00% covered (success)
100.00%
1 / 1
1
100.00% covered (success)
100.00%
1 / 1
 getSubscriptionIntroductoryPricePeriod
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
2 / 2
 jsonSerialize
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
20 / 20
1<?php
2
3namespace Proton\IosReceiptParser;
4
5use Proton\IosReceiptParser\ASN1\SimpleDecoder;
6use Proton\IosReceiptParser\Attribute\AttributeSet;
7use Proton\IosReceiptParser\Attribute\AttributeType;
8use phpseclib3\File\ASN1;
9
10/**
11 * @psalm-import-type AttributeSequence from AttributeSet
12 */
13final class InApp implements \JsonSerializable
14{
15    /** @var AttributeSet */
16    private $attributes;
17
18    /** @var SimpleDecoder */
19    private $decoder;
20
21    /**
22     * @psalm-param list<AttributeSet> $data
23     */
24    public function __construct(array $data, SimpleDecoder $decoder)
25    {
26        $this->attributes = new AttributeSet($data, 'in_app');
27        $this->decoder = $decoder;
28    }
29
30    /**
31     * @throws Exception\AttributeMissingException
32     */
33    public function getQuantity(): string
34    {
35        return (string) $this->decoder->decode(
36            $this->attributes->getRequired(AttributeType::IN_APP_QUANTITY),
37            ASN1::TYPE_INTEGER
38        );
39    }
40
41    /**
42     * @throws Exception\AttributeMissingException
43     */
44    public function getProductIdentifier(): string
45    {
46        return $this->decoder->decode(
47            $this->attributes->getRequired(AttributeType::IN_APP_PRODUCT_IDENTIFIER),
48            ASN1::TYPE_UTF8_STRING,
49        );
50    }
51
52    /**
53     * @throws Exception\AttributeMissingException
54     */
55    public function getTransactionIdentifier(): string
56    {
57        return $this->decoder->decode(
58            $this->attributes->getRequired(AttributeType::IN_APP_TRANSACTION_IDENTIFIER),
59            ASN1::TYPE_UTF8_STRING,
60        );
61    }
62
63    /**
64     * @throws Exception\AttributeMissingException
65     */
66    public function getPurchaseDate(): string
67    {
68        return $this->decoder->decode(
69            $this->attributes->getRequired(AttributeType::IN_APP_PURCHASE_DATE),
70            ASN1::TYPE_IA5_STRING,
71        );
72    }
73
74    /**
75     * @throws Exception\AttributeMissingException
76     */
77    public function getPurchaseDateTimestamp(): string
78    {
79        return Parser::convertTimestampMs($this->getPurchaseDate());
80    }
81
82    /**
83     * @throws Exception\AttributeMissingException
84     */
85    public function getOriginalTransactionIdentifier(): string
86    {
87        $raw = $this->attributes->get(AttributeType::IN_APP_ORIGINAL_TRANSACTION_IDENTIFIER);
88
89        return $raw === null
90            ? $this->getTransactionIdentifier()
91            : $this->decoder->decode($raw, ASN1::TYPE_UTF8_STRING);
92    }
93
94    /**
95     * @throws Exception\AttributeMissingException
96     */
97    public function getOriginalPurchaseDate(): string
98    {
99        $raw = $this->attributes->get(AttributeType::IN_APP_ORIGINAL_PURCHASE_DATE);
100
101        return $raw === null
102            ? $this->getPurchaseDate()
103            : $this->decoder->decode($raw, ASN1::TYPE_IA5_STRING);
104    }
105
106    /**
107     * @throws Exception\AttributeMissingException
108     */
109    public function getOriginalPurchaseDateTimestamp(): string
110    {
111        return Parser::convertTimestampMs($this->getOriginalPurchaseDate());
112    }
113
114    public function getSubscriptionExpirationDate(): ?string
115    {
116        $raw = $this->attributes->get(AttributeType::IN_APP_SUBSCRIPTION_EXPIRATION_DATE);
117
118        return $raw === null ? null : $this->decoder->decode($raw, ASN1::TYPE_IA5_STRING);
119    }
120
121    public function getSubscriptionExpirationDateTimestamp(): ?string
122    {
123        return Parser::convertTimestampMs($this->getSubscriptionExpirationDate());
124    }
125
126    public function getWebOrderLineItemID(): ?string
127    {
128        $raw = $this->attributes->get(AttributeType::IN_APP_WEB_ORDER_LINE_ITEM_ID);
129
130        return $raw === null ? null : (string) $this->decoder->decode($raw, ASN1::TYPE_INTEGER);
131    }
132
133    public function getCancellationDate(): ?string
134    {
135        $raw = $this->attributes->get(AttributeType::IN_APP_CANCELLATION_DATE);
136
137        return $raw === null ? null : $this->decoder->decode($raw, ASN1::TYPE_IA5_STRING);
138    }
139
140    public function getCancellationDateTimestamp(): ?string
141    {
142        return Parser::convertTimestampMs($this->getCancellationDate());
143    }
144
145    public function getSubscriptionIntroductoryPricePeriod(): ?string
146    {
147        $raw = $this->attributes->get(AttributeType::IN_APP_SUBSCRIPTION_INTRODUCTORY_PRICE_PERIOD);
148
149        return $raw === null ? null : $this->decoder->decode($raw, ASN1::TYPE_IA5_STRING);
150    }
151
152    /**
153     * @throws Exception\AttributeMissingException
154     */
155    public function jsonSerialize(): array
156    {
157        $return = [];
158
159        foreach ([
160            AttributeType::IN_APP_QUANTITY => $this->getQuantity(),
161            AttributeType::IN_APP_PRODUCT_IDENTIFIER => $this->getProductIdentifier(),
162            AttributeType::IN_APP_TRANSACTION_IDENTIFIER => $this->getTransactionIdentifier(),
163            AttributeType::IN_APP_PURCHASE_DATE => $this->getPurchaseDate(),
164            AttributeType::IN_APP_PURCHASE_DATE_MS => $this->getPurchaseDateTimestamp(),
165            AttributeType::IN_APP_ORIGINAL_TRANSACTION_IDENTIFIER => $this->getOriginalTransactionIdentifier(),
166            AttributeType::IN_APP_ORIGINAL_PURCHASE_DATE => $this->getOriginalPurchaseDate(),
167            AttributeType::IN_APP_ORIGINAL_PURCHASE_DATE_MS => $this->getOriginalPurchaseDateTimestamp(),
168            AttributeType::IN_APP_SUBSCRIPTION_EXPIRATION_DATE => $this->getSubscriptionExpirationDate(),
169            AttributeType::IN_APP_SUBSCRIPTION_EXPIRATION_DATE_MS => $this->getSubscriptionExpirationDateTimestamp(),
170            AttributeType::IN_APP_WEB_ORDER_LINE_ITEM_ID => $this->getWebOrderLineItemID(),
171            AttributeType::IN_APP_CANCELLATION_DATE => $this->getCancellationDate(),
172            AttributeType::IN_APP_CANCELLATION_DATE_MS => $this->getCancellationDateTimestamp(),
173            AttributeType::IN_APP_SUBSCRIPTION_INTRODUCTORY_PRICE_PERIOD => $this
174                ->getSubscriptionIntroductoryPricePeriod(),
175        ] as $type => $value) {
176            if ($value === null) {
177                continue;
178            }
179
180            $return[AttributeType::getJsonFieldName($type)] = $value;
181        }
182
183        return $return;
184    }
185}