Skip to content

Commit d853171

Browse files
authored
Merge pull request #135 from unzerdev/CC-177/add_exemption_type
Cc 177/add exemption type
2 parents c7f606f + 4c62034 commit d853171

14 files changed

+273
-94
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,20 @@ to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
1111

1212
* Enable PHP version 8.2 in composer.json.
1313
* Add paypage property to `Payment` class.
14+
* Add class `\UnzerSDK\Resources\EmbeddedResources\CardTransactionData`.
15+
Set as "card" field of additionalTransactionData
1416
* Add constants `\UnzerSDK\Constants\LiabilityShiftIndicator` for valid liability shift indicator values, relevant for card payment.
15-
* Charge and authorize transactions with card can contain that indicator in Api Response. (Accesed like:`$transaction->getAdditionalTransactionData()->card->liability`)
17+
* Charge and authorize transactions with card can contain that indicator in Api Response. (`CardTransactionData::$liability`)
1618

1719
### Changed
1820

1921
* Switch SDK to 3-digit versioning. First digit, formerly representing API version gets omitted (1.3.0.0 -> 3.0.0).
2022
* Add Type declaration to methods where applicable.
2123
* Enable `Unzer::fetchPaymentRefund` and `Unzer::fetchPaymentReversal` to use resource ID as parameter.
2224
* Raise minimum PHP version to 7.4 in composer.json
25+
* Handling of additionalTransactionData:
26+
* `additionalTransactionData.card` from API responses will be mapped on `\UnzerSDK\Resources\EmbeddedResources\CardTransactionData` now.
27+
* Remove `paymentType` parameter of `\UnzerSDK\Traits\HasRecurrenceType::setRecurrenceType`, it will always be set for `card` field of `additionalTransactionData`.
2328

2429
## [1.2.3.0](https://github.com/unzerdev/php-sdk/compare/1.2.2.0..1.2.3.0)
2530

src/Constants/AdditionalTransactionDataKeys.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ class AdditionalTransactionDataKeys
3030

3131
// Checkout types
3232
public const CHECKOUTTYPE = 'checkoutType';
33+
34+
public const CARD = 'card';
3335
}

src/Constants/ExemptionType.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* This file contains valid exemption type values
4+
*
5+
* Copyright (C) 2020 - today Unzer E-Com GmbH
6+
*
7+
* Licensed under the Apache License, Version 2.0 (the "License");
8+
* you may not use this file except in compliance with the License.
9+
* You may obtain a copy of the License at
10+
*
11+
* http://www.apache.org/licenses/LICENSE-2.0
12+
*
13+
* Unless required by applicable law or agreed to in writing, software
14+
* distributed under the License is distributed on an "AS IS" BASIS,
15+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* See the License for the specific language governing permissions and
17+
* limitations under the License.
18+
*
19+
* @link https://dev.unzer.com/
20+
*
21+
* @package UnzerSDK\Constants
22+
*/
23+
namespace UnzerSDK\Constants;
24+
25+
class ExemptionType
26+
{
27+
public const LOW_VALUE_PAYMENT = 'lvp';
28+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
/*
4+
* Represents `card` object of `additionalTransactionData'.
5+
*
6+
* Copyright (C) 2023 - today Unzer E-Com GmbH
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*
20+
* @link https://docs.unzer.com/
21+
*
22+
* @package UnzerSDK
23+
*
24+
*/
25+
namespace UnzerSDK\Resources\EmbeddedResources;
26+
27+
use UnzerSDK\Resources\AbstractUnzerResource;
28+
29+
class CardTransactionData extends AbstractUnzerResource
30+
{
31+
/** @var string|null $recurrenceType */
32+
protected $recurrenceType;
33+
/** @var string|null $exemptionType */
34+
protected $exemptionType;
35+
/** @var string|null $liability */
36+
private $liability;
37+
38+
/**
39+
* @return string|null
40+
*/
41+
public function getRecurrenceType(): ?string
42+
{
43+
return $this->recurrenceType;
44+
}
45+
46+
/**
47+
* @param string|null $recurrenceType
48+
*
49+
* @return CardTransactionData
50+
*/
51+
public function setRecurrenceType(?string $recurrenceType): CardTransactionData
52+
{
53+
$this->recurrenceType = $recurrenceType;
54+
55+
return $this;
56+
}
57+
58+
/**
59+
* @return string|null
60+
*/
61+
public function getLiability(): ?string
62+
{
63+
return $this->liability;
64+
}
65+
66+
/**
67+
* @param string|null $liability
68+
*
69+
* @return CardTransactionData
70+
*/
71+
public function setLiability(?string $liability): CardTransactionData
72+
{
73+
$this->liability = $liability;
74+
return $this;
75+
}
76+
77+
/**
78+
* @return string|null
79+
*/
80+
public function getExemptionType(): ?string
81+
{
82+
return $this->exemptionType;
83+
}
84+
85+
/**
86+
* @param string|null $exemptionType
87+
*
88+
* @return CardTransactionData
89+
*/
90+
public function setExemptionType(?string $exemptionType): CardTransactionData
91+
{
92+
$this->exemptionType = $exemptionType;
93+
return $this;
94+
}
95+
}

src/Resources/TransactionTypes/AbstractTransactionType.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
use UnzerSDK\Adapter\HttpAdapterInterface;
2626
use UnzerSDK\Exceptions\UnzerApiException;
2727
use UnzerSDK\Resources\AbstractUnzerResource;
28+
use UnzerSDK\Resources\EmbeddedResources\CardTransactionData;
2829
use UnzerSDK\Resources\EmbeddedResources\RiskData;
2930
use UnzerSDK\Resources\EmbeddedResources\ShippingData;
3031
use UnzerSDK\Resources\Payment;
@@ -192,6 +193,7 @@ protected function handleAdditionalTransactionData(stdClass $response): void
192193

193194
$this->handleRiskData($additionalTransactionData);
194195
$this->handleShipping($additionalTransactionData);
196+
$this->handleCardTransactionData($additionalTransactionData);
195197
}
196198
}
197199

@@ -228,4 +230,21 @@ protected function handleShipping(stdClass $additionalTransactionData): void
228230
$this->setShipping($shippingObject);
229231
}
230232
}
233+
234+
/**
235+
* Handle CardTransactionData object contained in additional transaction data from API response.
236+
*
237+
* @param stdClass $additionalTransactionData
238+
*
239+
* @return void
240+
*/
241+
protected function handleCardTransactionData(stdClass $additionalTransactionData): void
242+
{
243+
$card = $additionalTransactionData->card ?? null;
244+
if ($card !== null) {
245+
$cardTransactionData = $this->getCardTransactionData() ?? new CardTransactionData();
246+
$cardTransactionData->handleResponse($card);
247+
$this->setCardTransactionData($cardTransactionData);
248+
}
249+
}
231250
}

src/Traits/HasAdditionalTransactionData.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<?php
2+
23
/**
34
* This trait allows a transaction type to have additional transaction Data.
45
*
@@ -25,6 +26,7 @@
2526

2627
use stdClass;
2728
use UnzerSDK\Constants\AdditionalTransactionDataKeys;
29+
use UnzerSDK\Resources\EmbeddedResources\CardTransactionData;
2830
use UnzerSDK\Resources\EmbeddedResources\RiskData;
2931
use UnzerSDK\Resources\EmbeddedResources\ShippingData;
3032
use UnzerSDK\Resources\PaymentTypes\BasePaymentType;
@@ -209,4 +211,29 @@ public function getCheckoutType(): ?string
209211

210212
return null;
211213
}
214+
215+
/**
216+
* Get the card field from additional transaction Data.
217+
*
218+
* @return CardTransactionData|null "card" object of additionalTransaction data.
219+
*/
220+
public function getCardTransactionData(): ?CardTransactionData
221+
{
222+
$key = AdditionalTransactionDataKeys::CARD;
223+
$card = $this->getAdditionalTransactionData()->$key ?? null;
224+
return $card instanceof CardTransactionData ? $card : null;
225+
}
226+
227+
/**
228+
* Sets CardTransactionData object as "card" field of additionalTransactionData.
229+
*
230+
* @param CardTransactionData|null $cardTransactionData
231+
*
232+
* @return self
233+
*/
234+
public function setCardTransactionData(?CardTransactionData $cardTransactionData): self
235+
{
236+
$this->addAdditionalTransactionData(AdditionalTransactionDataKeys::CARD, $cardTransactionData);
237+
return $this;
238+
}
212239
}

src/Traits/HasRecurrenceType.php

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424

2525
namespace UnzerSDK\Traits;
2626

27-
use RuntimeException;
28-
use UnzerSDK\Resources\PaymentTypes\BasePaymentType;
29-
use UnzerSDK\Resources\TransactionTypes\AbstractTransactionType;
27+
use UnzerSDK\Resources\EmbeddedResources\CardTransactionData;
3028

3129
trait HasRecurrenceType
3230
{
@@ -37,38 +35,24 @@ trait HasRecurrenceType
3735
*/
3836
public function getRecurrenceType(): ?string
3937
{
40-
$additionalTransactionData = $this->getAdditionalTransactionData();
41-
if ($additionalTransactionData !== null) {
42-
foreach ($additionalTransactionData as $data) {
43-
if (property_exists($data, 'recurrenceType')) {
44-
return $data->recurrenceType ?? null;
45-
}
46-
}
38+
$cardTransactionData = $this->getCardTransactionData();
39+
if ($cardTransactionData instanceof CardTransactionData) {
40+
return $cardTransactionData->getRecurrenceType();
4741
}
4842

49-
return null;
43+
return $this->getAdditionalTransactionData()->card['recurrenceType'] ?? null;
5044
}
5145

5246
/**
53-
* @param string $recurrenceType Recurrence type used for recurring payment.
54-
* @param BasePaymentType|null $paymentType If provided recurrenceType is set based on this payment type.
55-
* This is required for recurring transaction, since the type can not be
56-
* determined automatically.
47+
* @param string $recurrenceType Recurrence type used for recurring payment.
5748
*
5849
* @return $this
5950
*/
60-
public function setRecurrenceType(string $recurrenceType, BasePaymentType $paymentType = null): self
51+
public function setRecurrenceType(string $recurrenceType): self
6152
{
62-
if ($paymentType === null && $this instanceof AbstractTransactionType) {
63-
$payment = $this->getPayment();
64-
$paymentType = $payment ? $payment->getPaymentType() : null;
65-
}
66-
67-
if ($paymentType === null) {
68-
throw new RuntimeException('Payment type can not be determined. Set it first or provide it via parameter $paymentType.');
69-
}
70-
$recurrenceTypeObject = (object)['recurrenceType' => $recurrenceType];
71-
$this->addAdditionalTransactionData($paymentType::getResourceName(), $recurrenceTypeObject);
53+
$card = $this->getCardTransactionData() ?? new CardTransactionData();
54+
$card->setRecurrenceType($recurrenceType);
55+
$this->addAdditionalTransactionData('card', $card);
7256

7357
return $this;
7458
}

test/integration/PaymentTypes/CardTest.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,13 @@
2626
namespace UnzerSDK\test\integration\PaymentTypes;
2727

2828
use UnzerSDK\Constants\ApiResponseCodes;
29+
use UnzerSDK\Constants\ExemptionType;
2930
use UnzerSDK\Exceptions\UnzerApiException;
31+
use UnzerSDK\Resources\EmbeddedResources\CardTransactionData;
3032
use UnzerSDK\Resources\EmbeddedResources\CardDetails;
3133
use UnzerSDK\Resources\PaymentTypes\BasePaymentType;
3234
use UnzerSDK\Resources\PaymentTypes\Card;
35+
use UnzerSDK\Resources\TransactionTypes\Charge;
3336
use UnzerSDK\Services\ValueService;
3437
use UnzerSDK\test\BaseIntegrationTest;
3538

@@ -265,11 +268,36 @@ public function cardWith3dsFlagShouldSetItAlsoInTransactions(): void
265268
$this->assertFalse($charge->isCard3ds());
266269
}
267270

271+
/**
272+
* Verfify card transaction can be used with exemptionType
273+
*
274+
* @test
275+
*/
276+
public function cardTransactionAcceptsExemptionType(): void
277+
{
278+
$card = $this->createCardObject();
279+
/** @var Card $card */
280+
$card = $this->unzer->createPaymentType($card);
281+
$charge = new Charge(12.34, 'EUR', 'https://docs.unzer.com');
282+
$cardTransactionData = (new CardTransactionData())
283+
->setExemptionType(ExemptionType::LOW_VALUE_PAYMENT);
284+
285+
$charge->setCardTransactionData($cardTransactionData);
286+
$this->getUnzerObject()->performCharge($charge, $card);
287+
288+
// Verify lvp value gets mapped from response
289+
$fetchedCharge = $this->unzer->fetchChargeById($charge->getPaymentId(), $charge->getId());
290+
$this->assertEquals(ExemptionType::LOW_VALUE_PAYMENT, $fetchedCharge->getCardTransactionData()->getExemptionType());
291+
}
292+
268293
/**
269294
* Verify card transaction returns Liability Shift Indicator.
270295
*
271296
* @test
297+
*
272298
* @dataProvider cardTransactionReturnsLiabilityIndicatorDP()
299+
*
300+
* @param mixed $pan
273301
*/
274302
public function cardTransactionReturnsLiabilityIndicator($pan): void
275303
{

test/integration/RecurringPaymentTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public function sepaDirectDebitSecuredShouldBeAbleToActivateRecurringPayments():
155155

156156
$this->expectException(UnzerApiException::class);
157157
$this->expectExceptionCode(ApiResponseCodes::API_ERROR_RECURRING_ALREADY_ACTIVE);
158-
$this->unzer->activateRecurringPayment($ddg, self::RETURN_URL, RecurrenceTypes::ONE_CLICK);
158+
$this->unzer->activateRecurringPayment($ddg, self::RETURN_URL);
159159
}
160160

161161
/**

test/unit/Resources/TransactionTypes/AbstractTransactionTypeTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,11 +280,11 @@ public function liabilityResponseShouldBeStroedInTransaction()
280280

281281
$transaction = new DummyTransactionType();
282282
$transaction->handleResponse(json_decode($jsonRespone, false));
283-
$this->assertEquals($transaction->getAdditionalTransactionData()->card->liability, LiabilityShiftIndicator::MERCHANT);
283+
$this->assertEquals($transaction->getCardTransactionData()->getLiability(), LiabilityShiftIndicator::MERCHANT);
284284

285285
$jsonRespone = '{"additionalTransactionData":{"card":{"liability":"ISSUER"}}}';
286286
$transaction->handleResponse(json_decode($jsonRespone, false));
287-
$this->assertEquals($transaction->getAdditionalTransactionData()->card->liability, LiabilityShiftIndicator::ISSUER);
287+
$this->assertEquals($transaction->getCardTransactionData()->getLiability(), LiabilityShiftIndicator::ISSUER);
288288
}
289289

290290
//<editor-fold desc="Data Providers">

0 commit comments

Comments
 (0)