Skip to content

Commit 9ff2cda

Browse files
authored
feat: support multiple payment gateway (#21374)
1 parent c73c228 commit 9ff2cda

10 files changed

Lines changed: 282 additions & 98 deletions

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/apple-pay/apple-pay.component.spec.ts

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import { ComponentFixture, TestBed } from '@angular/core/testing';
88
import { Cart } from '@spartacus/cart/base/root';
99
import { Product } from '@spartacus/core';
10-
import { OpfActiveConfiguration } from '@spartacus/opf/base/root';
1110
import { OpfPaymentErrorHandlerService } from '@spartacus/opf/payment/core';
1211
import { OpfQuickBuyTransactionService } from '@spartacus/opf/quick-buy/core';
1312
import {
@@ -33,17 +32,6 @@ const mockCart: Cart = {
3332
code: '123',
3433
};
3534

36-
const mockActiveConfiguration: OpfActiveConfiguration = {
37-
digitalWalletQuickBuy: [
38-
{
39-
merchantId: 'merchant.com.adyen.upscale.test',
40-
provider: OpfQuickBuyProviderType.APPLE_PAY,
41-
countryCode: 'US',
42-
},
43-
{ merchantId: 'merchant.test.example' },
44-
],
45-
};
46-
4735
describe('ApplePayComponent', () => {
4836
let component: ApplePayComponent;
4937
let fixture: ComponentFixture<ApplePayComponent>;
@@ -110,50 +98,54 @@ describe('ApplePayComponent', () => {
11098
provider: OpfQuickBuyProviderType.APPLE_PAY,
11199
countryCode: mockCountryCode,
112100
merchantId: 'merchant.com.adyen.upscale.test',
101+
enabled: true,
102+
};
103+
component.activeConfiguration = {
104+
digitalWalletQuickBuy: [digitalWallet],
113105
};
114-
component.activeConfiguration = { digitalWalletQuickBuy: [digitalWallet] };
115106

116107
const mockObservable = of(true);
117108
mockApplePayService.isApplePaySupported.and.returnValue(mockObservable);
118109

119110
fixture.detectChanges();
120-
expect(component.isApplePaySupported$).toBe(mockObservable);
111+
expect(component.isApplePaySupported$).toEqual(mockObservable);
121112
});
122113

123114
it('should not initialize isApplePaySupported$ provider is not Apple pay', () => {
124115
const digitalWallet: OpfQuickBuyDigitalWallet = {
125116
provider: OpfQuickBuyProviderType.GOOGLE_PAY,
126117
countryCode: mockCountryCode,
127118
merchantId: 'merchant.com.adyen.upscale.test',
119+
enabled: true,
120+
};
121+
component.activeConfiguration = {
122+
digitalWalletQuickBuy: [digitalWallet],
128123
};
129-
component.activeConfiguration = { digitalWalletQuickBuy: [digitalWallet] };
130-
131-
const mockObservable = of(true);
132-
mockApplePayService.isApplePaySupported.and.returnValue(mockObservable);
133124

134125
fixture.detectChanges();
126+
expect(component.isApplePaySupported$).toBeUndefined();
135127
expect(mockApplePayService.isApplePaySupported).not.toHaveBeenCalled();
136128
});
137129

138130
it('should start applePayService', () => {
139131
mockApplePayService.start.and.returnValue(
140132
of(<ApplePayJS.ApplePayPaymentAuthorizationResult>{ status: 1 })
141133
);
134+
135+
const digitalWallet: OpfQuickBuyDigitalWallet = {
136+
provider: OpfQuickBuyProviderType.APPLE_PAY,
137+
countryCode: mockCountryCode,
138+
merchantId: 'merchant.com.adyen.upscale.test',
139+
enabled: true,
140+
};
141+
142142
component.activeConfiguration = {
143-
digitalWalletQuickBuy: [
144-
{
145-
provider: OpfQuickBuyProviderType.APPLE_PAY,
146-
countryCode: mockCountryCode,
147-
merchantId: 'merchant.com.adyen.upscale.test',
148-
},
149-
],
143+
digitalWalletQuickBuy: [digitalWallet],
150144
};
151-
component.activeConfiguration = mockActiveConfiguration;
145+
152146
fixture.detectChanges();
153147

154148
component.initTransaction();
155-
expect(
156-
mockOpfPaymentErrorHandlerService.handlePaymentError
157-
).not.toHaveBeenCalled();
149+
expect(mockApplePayService.start).toHaveBeenCalled();
158150
});
159151
});

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/apple-pay/apple-pay.component.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ import { ApplePayService } from './apple-pay.service';
3131
imports: [NgIf, AsyncPipe],
3232
})
3333
export class ApplePayComponent implements OnInit {
34-
@Input() activeConfiguration: OpfActiveConfiguration;
34+
@Input() activeConfiguration:
35+
| OpfActiveConfiguration
36+
| OpfActiveConfiguration[];
3537

3638
protected applePayService = inject(ApplePayService);
3739
protected currentProductService = inject(CurrentProductService);
@@ -43,10 +45,15 @@ export class ApplePayComponent implements OnInit {
4345
applePayDigitalWallet?: OpfQuickBuyDigitalWallet;
4446

4547
ngOnInit(): void {
46-
this.applePayDigitalWallet =
47-
this.activeConfiguration?.digitalWalletQuickBuy?.find(
48+
const activeConfigurations = Array.isArray(this.activeConfiguration)
49+
? this.activeConfiguration
50+
: [this.activeConfiguration];
51+
this.applePayDigitalWallet = activeConfigurations
52+
?.flatMap((config) => config.digitalWalletQuickBuy || [])
53+
.find(
4854
(digitalWallet) =>
49-
digitalWallet.provider === OpfQuickBuyProviderType.APPLE_PAY
55+
digitalWallet.provider === OpfQuickBuyProviderType.APPLE_PAY &&
56+
digitalWallet.enabled
5057
);
5158
if (
5259
!this.applePayDigitalWallet?.merchantId ||

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/google-pay/google-pay.component.spec.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
ElementRef,
1111
} from '@angular/core';
1212
import { ComponentFixture, TestBed } from '@angular/core/testing';
13+
1314
import { OpfGooglePayComponent } from './google-pay.component';
1415
import { OpfGooglePayService } from './google-pay.service';
1516

@@ -64,9 +65,9 @@ describe('OpfGooglePayComponent', () => {
6465
await detectChanges();
6566

6667
expect(mockOpfGooglePayService.loadResources).toHaveBeenCalled();
67-
expect(mockOpfGooglePayService.initClient).toHaveBeenCalledWith(
68-
component.activeConfiguration
69-
);
68+
expect(mockOpfGooglePayService.initClient).toHaveBeenCalledWith([
69+
component.activeConfiguration,
70+
]);
7071
});
7172

7273
it('should update ready to pay state when Google Pay is ready', async () => {

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/google-pay/google-pay.component.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,20 @@ export class OpfGooglePayComponent implements OnInit {
2929
protected opfGooglePayService = inject(OpfGooglePayService);
3030
protected changeDetectionRef = inject(ChangeDetectorRef);
3131

32-
@Input() activeConfiguration: OpfActiveConfiguration;
32+
@Input() activeConfiguration:
33+
| OpfActiveConfiguration
34+
| OpfActiveConfiguration[];
3335

3436
@ViewChild('googlePayButtonContainer') googlePayButtonContainer: ElementRef;
3537

3638
isReadyToPayState$: BehaviorSubject<boolean> = new BehaviorSubject(false);
3739

3840
ngOnInit(): void {
41+
const activeConfigurations = Array.isArray(this.activeConfiguration)
42+
? this.activeConfiguration
43+
: [this.activeConfiguration];
3944
this.opfGooglePayService.loadResources().then(() => {
40-
this.opfGooglePayService.initClient(this.activeConfiguration);
45+
this.opfGooglePayService.initClient(activeConfigurations);
4146
this.opfGooglePayService.isReadyToPay().then((response: any) => {
4247
this.isReadyToPayState$.next(!!response?.result);
4348
this.changeDetectionRef.detectChanges();

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/google-pay/google-pay.service.spec.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7+
/// <reference types="@types/googlepay" />
78
import { ElementRef } from '@angular/core';
89
import { TestBed } from '@angular/core/testing';
910
import { Cart } from '@spartacus/cart/base/root';
1011
import { Address, PriceType } from '@spartacus/core';
11-
import { OpfResourceLoaderService } from '@spartacus/opf/base/root';
12+
import {
13+
OpfActiveConfiguration,
14+
OpfResourceLoaderService,
15+
} from '@spartacus/opf/base/root';
1216
import { OpfPaymentFacade } from '@spartacus/opf/payment/root';
1317
import { OpfQuickBuyTransactionService } from '@spartacus/opf/quick-buy/core';
1418
import {
@@ -86,7 +90,7 @@ describe('OpfGooglePayService', () => {
8690
]);
8791
mockQuickBuyButtonsService = jasmine.createSpyObj(
8892
'OpfQuickBuyButtonsService',
89-
['getQuickBuyProviderConfig']
93+
['getQuickBuyProviderConfig', 'getActiveConfigurationForProvider']
9094
);
9195

9296
mockOpfQuickBuyConfig = {
@@ -145,7 +149,7 @@ describe('OpfGooglePayService', () => {
145149

146150
describe('getClient', () => {
147151
it('should return the Google Payment client instance', () => {
148-
const activeConfiguration = {};
152+
const activeConfiguration: OpfActiveConfiguration[] = [];
149153
service.initClient(activeConfiguration);
150154

151155
const client = service['getClient']();
@@ -225,7 +229,7 @@ describe('OpfGooglePayService', () => {
225229

226230
describe('isReadyToPay', () => {
227231
it('should return info about readiness to pay from the Google Pay API', async () => {
228-
const activeConfiguration = {};
232+
const activeConfiguration: OpfActiveConfiguration[] = [];
229233

230234
service.initClient(activeConfiguration);
231235

@@ -246,8 +250,20 @@ describe('OpfGooglePayService', () => {
246250
});
247251

248252
describe('initClient', () => {
249-
it('should initialize the Google Payment client with configurations', () => {
250-
const activeConfiguration = {};
253+
it('should initialize the Google Payment client with configurations (array)', () => {
254+
const activeConfiguration: any[] = [];
255+
service.initClient(activeConfiguration);
256+
257+
const client = service['googlePaymentClient'];
258+
259+
expect(client).toBeDefined();
260+
});
261+
262+
it('should initialize the Google Payment client with single configuration', () => {
263+
const activeConfiguration: OpfActiveConfiguration = {
264+
merchantId: 'test-merchant',
265+
providerType: 'PAYMENT_GATEWAY',
266+
} as any;
251267
service.initClient(activeConfiguration);
252268

253269
const client = service['googlePaymentClient'];

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/google-pay/google-pay.service.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,20 @@ export class OpfGooglePayService {
169169
]);
170170
}
171171

172-
initClient(activeConfiguration: OpfActiveConfiguration): void {
173-
this.setAllowedPaymentMethodsConfig(activeConfiguration);
172+
initClient(
173+
activeConfiguration: OpfActiveConfiguration | OpfActiveConfiguration[]
174+
): void {
175+
const activeConfigurations = Array.isArray(activeConfiguration)
176+
? activeConfiguration
177+
: [activeConfiguration];
178+
const googlePayGateway =
179+
this.opfQuickBuyButtonsService.getActiveConfigurationForProvider(
180+
OpfQuickBuyProviderType.GOOGLE_PAY,
181+
activeConfigurations
182+
);
183+
if (googlePayGateway) {
184+
this.setAllowedPaymentMethodsConfig(googlePayGateway);
185+
}
174186
this.updateGooglePaymentClient();
175187
}
176188

@@ -498,9 +510,8 @@ export class OpfGooglePayService {
498510
const googlePayConfig =
499511
this.opfQuickBuyButtonsService.getQuickBuyProviderConfig(
500512
OpfQuickBuyProviderType.GOOGLE_PAY,
501-
activeConfiguration
513+
[activeConfiguration]
502514
);
503-
504515
this.googlePaymentRequest.allowedPaymentMethods = [
505516
{
506517
parameters: {

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/opf-quick-buy-buttons.component.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { OpfQuickBuyProviderType } from '../../root/model';
1111
import { OpfQuickBuyButtonsComponent } from './opf-quick-buy-buttons.component';
1212
import { OpfQuickBuyButtonsService } from './opf-quick-buy-buttons.service';
1313
import createSpy = jasmine.createSpy;
14+
import { OpfActiveConfiguration } from '@spartacus/opf/base/root';
1415

1516
const routerStateSubject = new BehaviorSubject<RouterState>({
1617
state: {
@@ -33,6 +34,8 @@ describe('OpfQuickBuyButtonsComponent', () => {
3334
opfQuickBuyButtonsServiceMock = jasmine.createSpyObj('OpfQuickBuyService', [
3435
'getPaymentGatewayConfiguration',
3536
'isQuickBuyProviderEnabled',
37+
'getQuickBuyProviderConfig',
38+
'getActiveConfigurationForProvider',
3639
]);
3740

3841
await TestBed.configureTestingModule({
@@ -70,7 +73,7 @@ describe('OpfQuickBuyButtonsComponent', () => {
7073

7174
it('should determine if a payment method is enabled', () => {
7275
const provider = OpfQuickBuyProviderType.APPLE_PAY;
73-
const activeConfiguration = {};
76+
const activeConfiguration: OpfActiveConfiguration[] = [];
7477
opfQuickBuyButtonsServiceMock.isQuickBuyProviderEnabled.and.returnValue(
7578
true
7679
);

integration-libs/opf/quick-buy/components/opf-quick-buy-buttons/opf-quick-buy-buttons.component.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ import { OpfQuickBuyButtonsService } from './opf-quick-buy-buttons.service';
2626
})
2727
export class OpfQuickBuyButtonsComponent implements OnInit {
2828
protected opfQuickBuyButtonsService = inject(OpfQuickBuyButtonsService);
29-
protected paymentGatewayConfig$: Observable<OpfActiveConfiguration>;
29+
protected paymentGatewayConfig$: Observable<
30+
OpfActiveConfiguration | OpfActiveConfiguration[]
31+
>;
3032

3133
PAYMENT_METHODS = OpfQuickBuyProviderType;
3234

@@ -37,7 +39,7 @@ export class OpfQuickBuyButtonsComponent implements OnInit {
3739

3840
isPaymentMethodEnabled(
3941
provider: OpfQuickBuyProviderType,
40-
activeConfiguration: OpfActiveConfiguration
42+
activeConfiguration: OpfActiveConfiguration | OpfActiveConfiguration[]
4143
): boolean {
4244
return this.opfQuickBuyButtonsService.isQuickBuyProviderEnabled(
4345
provider,

0 commit comments

Comments
 (0)