Skip to content

Commit cf64287

Browse files
deepak-soni1svera
authored andcommitted
LYNX-781:Return only free payment method when the order total is 0
1 parent 56b1f55 commit cf64287

File tree

4 files changed

+263
-1
lines changed

4 files changed

+263
-1
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Plugin\Model;
9+
10+
use Magento\Payment\Model\MethodList;
11+
use Magento\Quote\Api\Data\CartInterface;
12+
13+
class RestrictPaymentMethods
14+
{
15+
/**
16+
* Show only the "free" payment method if the order total is 0
17+
*
18+
* @param MethodList $subject
19+
* @param array $result
20+
* @param CartInterface|null $quote
21+
* @return array
22+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
23+
*/
24+
public function afterGetAvailableMethods(
25+
MethodList $subject,
26+
array $result,
27+
CartInterface $quote = null
28+
): array {
29+
if (!$quote || $quote->getGrandTotal() != 0) {
30+
return $result;
31+
}
32+
33+
return array_filter($result, fn ($method) => $method->getCode() === 'free') ?: [];
34+
}
35+
}

app/code/Magento/QuoteGraphQl/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"magento/module-catalog-inventory": "*",
2121
"magento/module-eav-graph-ql": "*",
2222
"magento/module-downloadable": "*",
23-
"magento/module-catalog-graph-ql": "*"
23+
"magento/module-catalog-graph-ql": "*",
24+
"magento/module-payment": "*"
2425
},
2526
"suggest": {
2627
"magento/module-graph-ql-cache": "*",

app/code/Magento/QuoteGraphQl/etc/graphql/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,4 +96,7 @@
9696
<plugin name="billing_address_save_same_as_shipping"
9797
type="Magento\QuoteGraphQl\Plugin\CustomerManagementPlugin"/>
9898
</type>
99+
<type name="Magento\Payment\Model\MethodList">
100+
<plugin name="restrict_payment_methods_graphql" type="Magento\QuoteGraphQl\Plugin\Model\RestrictPaymentMethods"/>
101+
</type>
99102
</config>
Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Quote;
9+
10+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
11+
use Magento\Checkout\Test\Fixture\SetBillingAddress as SetBillingAddressFixture;
12+
use Magento\Checkout\Test\Fixture\SetDeliveryMethod as SetDeliveryMethodFixture;
13+
use Magento\Checkout\Test\Fixture\SetShippingAddress as SetShippingAddressFixture;
14+
use Magento\Customer\Test\Fixture\Customer as CustomerFixture;
15+
use Magento\Framework\Exception\AuthenticationException;
16+
use Magento\Integration\Api\CustomerTokenServiceInterface;
17+
use Magento\Quote\Test\Fixture\AddProductToCart as AddProductToCartFixture;
18+
use Magento\Quote\Test\Fixture\CustomerCart as CustomerCartFixture;
19+
use Magento\Quote\Test\Fixture\QuoteIdMask;
20+
use Magento\SalesRule\Model\Rule as SalesRule;
21+
use Magento\SalesRule\Test\Fixture\AddressCondition as AddressConditionFixture;
22+
use Magento\SalesRule\Test\Fixture\Rule as SalesRuleFixture;
23+
use Magento\Quote\Test\Fixture\ApplyCoupon as ApplyCouponFixture;
24+
use Magento\TestFramework\Fixture\DataFixture;
25+
use Magento\TestFramework\Fixture\DataFixtureStorage;
26+
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
27+
use Magento\TestFramework\Helper\Bootstrap;
28+
use Magento\TestFramework\TestCase\GraphQlAbstract;
29+
30+
class AvailablePaymentMethodsTest extends GraphQlAbstract
31+
{
32+
/**
33+
* @var CustomerTokenServiceInterface
34+
*/
35+
private $customerTokenService;
36+
37+
/**
38+
* @var DataFixtureStorage
39+
*/
40+
private $fixtures;
41+
42+
/**
43+
* @inheridoc
44+
*/
45+
protected function setUp(): void
46+
{
47+
$this->customerTokenService = Bootstrap::getObjectManager()->get(CustomerTokenServiceInterface::class);
48+
$this->fixtures = Bootstrap::getObjectManager()->get(DataFixtureStorageManager::class)->getStorage();
49+
}
50+
51+
#[
52+
DataFixture(
53+
AddressConditionFixture::class,
54+
[
55+
'attribute' => 'total_qty',
56+
'operator' => '>=',
57+
'value' => 1
58+
],
59+
'condition'
60+
),
61+
DataFixture(
62+
SalesRuleFixture::class,
63+
[
64+
'store_labels' => [1 => 'Flat 100 percent off'],
65+
'coupon_type' => SalesRule::COUPON_TYPE_SPECIFIC,
66+
'simple_action' => SalesRule::BY_PERCENT_ACTION,
67+
'discount_amount' => 100,
68+
'coupon_code' => "SALE100",
69+
'conditions' => ['$condition$'],
70+
'uses_per_customer' => 1,
71+
'stop_rules_processing' => true,
72+
'simple_free_shipping' => 1
73+
],
74+
as: 'rule'
75+
),
76+
DataFixture(ProductFixture::class, ['price' => 100], as: 'product'),
77+
DataFixture(CustomerFixture::class, as: 'customer'),
78+
DataFixture(CustomerCartFixture::class, ['customer_id' => '$customer.id$'], as: 'quote'),
79+
DataFixture(
80+
AddProductToCartFixture::class,
81+
[
82+
'cart_id' => '$quote.id$',
83+
'product_id' => '$product.id$',
84+
'qty' => 1
85+
]
86+
),
87+
DataFixture(
88+
ApplyCouponFixture::class,
89+
[
90+
'cart_id' => '$quote.id$',
91+
'coupon_codes' => ["SALE100"]
92+
]
93+
),
94+
DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$quote.id$']),
95+
DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$quote.id$']),
96+
DataFixture(SetDeliveryMethodFixture::class, ['cart_id' => '$quote.id$']),
97+
DataFixture(QuoteIdMask::class, ['cart_id' => '$quote.id$'], 'quoteIdMask')
98+
]
99+
public function testAvailablePaymentMethodsWhenOrderTotalZero(): void
100+
{
101+
self::assertEquals(
102+
[
103+
'cart' => [
104+
'available_payment_methods' => [
105+
0 => [
106+
'code' => 'free',
107+
'title' => 'No Payment Information Required'
108+
]
109+
]
110+
]
111+
],
112+
$this->graphQlQuery(
113+
$this->getCartQuery($this->fixtures->get('quoteIdMask')->getMaskedId()),
114+
[],
115+
'',
116+
$this->getCustomerAuthHeaders($this->fixtures->get('customer')->getEmail())
117+
)
118+
);
119+
}
120+
121+
#[
122+
DataFixture(
123+
AddressConditionFixture::class,
124+
[
125+
'attribute' => 'total_qty',
126+
'operator' => '>=',
127+
'value' => 1
128+
],
129+
'condition'
130+
),
131+
DataFixture(
132+
SalesRuleFixture::class,
133+
[
134+
'store_labels' => [1 => 'Flat 50 percent off'],
135+
'coupon_type' => SalesRule::COUPON_TYPE_SPECIFIC,
136+
'simple_action' => SalesRule::BY_PERCENT_ACTION,
137+
'discount_amount' => 50,
138+
'coupon_code' => "SALE50",
139+
'conditions' => ['$condition$'],
140+
'uses_per_customer' => 1,
141+
'stop_rules_processing' => true,
142+
'simple_free_shipping' => 1
143+
],
144+
as: 'rule'
145+
),
146+
DataFixture(ProductFixture::class, ['price' => 110], as: 'product'),
147+
DataFixture(CustomerFixture::class, as: 'customer'),
148+
DataFixture(CustomerCartFixture::class, ['customer_id' => '$customer.id$'], as: 'quote'),
149+
DataFixture(
150+
AddProductToCartFixture::class,
151+
[
152+
'cart_id' => '$quote.id$',
153+
'product_id' => '$product.id$',
154+
'qty' => 1
155+
]
156+
),
157+
DataFixture(
158+
ApplyCouponFixture::class,
159+
[
160+
'cart_id' => '$quote.id$',
161+
'coupon_codes' => ["SALE50"]
162+
]
163+
),
164+
DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$quote.id$']),
165+
DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$quote.id$']),
166+
DataFixture(SetDeliveryMethodFixture::class, ['cart_id' => '$quote.id$']),
167+
DataFixture(QuoteIdMask::class, ['cart_id' => '$quote.id$'], 'quoteIdMask')
168+
]
169+
public function testAvailablePaymentMethodsWhenOrderTotalNonZero(): void
170+
{
171+
self::assertEquals(
172+
[
173+
'cart' => [
174+
'available_payment_methods' => [
175+
0 => [
176+
'code' => 'checkmo',
177+
'title' => 'Check / Money order',
178+
]
179+
]
180+
]
181+
],
182+
$this->graphQlQuery(
183+
$this->getCartQuery($this->fixtures->get('quoteIdMask')->getMaskedId()),
184+
[],
185+
'',
186+
$this->getCustomerAuthHeaders($this->fixtures->get('customer')->getEmail())
187+
)
188+
);
189+
}
190+
191+
/**
192+
* Get customer cart query with available_payment_methods fields
193+
*
194+
* @param string $maskedQuoteId
195+
* @return string
196+
*/
197+
private function getCartQuery(string $maskedQuoteId): string
198+
{
199+
return <<<QUERY
200+
{
201+
cart(cart_id: "{$maskedQuoteId}") {
202+
available_payment_methods{
203+
code
204+
title
205+
}
206+
}
207+
}
208+
QUERY;
209+
}
210+
211+
/**
212+
* Returns the header with customer token for GQL Mutation
213+
*
214+
* @param string $email
215+
* @return array
216+
* @throws AuthenticationException
217+
*/
218+
private function getCustomerAuthHeaders(string $email): array
219+
{
220+
$customerToken = $this->customerTokenService->createCustomerAccessToken($email, 'password');
221+
return ['Authorization' => 'Bearer ' . $customerToken];
222+
}
223+
}

0 commit comments

Comments
 (0)