From e0532aef465b13bfe9b47f1dc64cd35bde5eeac7 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Wed, 19 Feb 2025 15:37:47 +0100 Subject: [PATCH 01/19] AD-375 Select delivery method during Apple Express Pay --- .../apple-express-payment.component.ts | 123 ++++++++++++++++-- .../src/express/base/express-payment-base.ts | 99 ++++++++++++++ .../google-express-payment.component.ts | 97 ++------------ 3 files changed, 223 insertions(+), 96 deletions(-) create mode 100644 projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index 2c64b71..07053d8 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -4,10 +4,12 @@ import {ApplePay, SubmitData, UIElement} from "@adyen/adyen-web"; import {AdyenCheckout, AdyenCheckoutError} from '@adyen/adyen-web/auto'; import {AdyenExpressConfigData} from "../../core/models/occ.config.models"; import {AdyenExpressOrderService} from "../../service/adyen-express-order.service"; -import {Product, RoutingService,} from '@spartacus/core'; -import {Subscription} from 'rxjs'; -import {ActiveCartFacade} from '@spartacus/cart/base/root'; +import {Address, Product, RoutingService, UserIdService,} from '@spartacus/core'; +import {Subscription, switchMap} from 'rxjs'; +import {ActiveCartFacade, MultiCartFacade} from '@spartacus/cart/base/root'; import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; +import {ExpressPaymentBase} from "../base/express-payment-base"; +import {AdyenCartService} from "../../service/adyen-cart-service"; @Component({ selector: 'cx-apple-express-payment', @@ -16,7 +18,7 @@ import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; templateUrl: './apple-express-payment.component.html', styleUrls: ['./apple-express-payment.component.css'] }) -export class AppleExpressPaymentComponent implements OnInit, OnDestroy{ +export class AppleExpressPaymentComponent extends ExpressPaymentBase implements OnInit, OnDestroy { protected subscriptions = new Subscription(); @@ -34,16 +36,17 @@ export class AppleExpressPaymentComponent implements OnInit, OnDestroy{ protected adyenOrderService: AdyenExpressOrderService, protected routingService: RoutingService, protected activeCartFacade: ActiveCartFacade, - ) {} + protected override multiCartService: MultiCartFacade, + protected override userIdService: UserIdService, + protected override adyenCartService: AdyenCartService, + ) { + super(multiCartService, userIdService, activeCartFacade, adyenCartService) + } ngOnInit(): void { this.setupAdyenCheckout(this.configuration) } - ngOnDestroy(): void { - this.subscriptions.unsubscribe(); - if(this.applePay) this.applePay.unmount(); - } private async setupAdyenCheckout(config: AdyenExpressConfigData) { const adyenCheckout = await AdyenCheckout(getAdyenExpressCheckoutConfig(config)); @@ -57,6 +60,7 @@ export class AppleExpressPaymentComponent implements OnInit, OnDestroy{ merchantId: config.applePayMerchantId, merchantName: config.applePayMerchantName }, + isExpress: true, // Button config buttonType: "check-out", buttonColor: "black", @@ -65,6 +69,8 @@ export class AppleExpressPaymentComponent implements OnInit, OnDestroy{ "name", "email" ], + onShippingContactSelected: (resolve, reject, event) => this.handleShippingContactSelected(resolve,reject,event, config.applePayMerchantName), + onShippingMethodSelected: (resolve, reject, event) =>this.handleShippingMethodSelected(resolve,reject,event, config.applePayMerchantName), onSubmit: (state, element: UIElement, actions) => this.handleOnSubmit(state, actions), onAuthorized: (paymentData, actions) => { this.authorizedPaymentData = paymentData; @@ -90,7 +96,7 @@ export class AppleExpressPaymentComponent implements OnInit, OnDestroy{ console.error(result?.error); actions.reject(); } - actions.resolve({ resultCode: 'Authorised' }); + actions.resolve({resultCode: 'Authorised'}); }, error => { console.error(error); @@ -98,9 +104,102 @@ export class AppleExpressPaymentComponent implements OnInit, OnDestroy{ } ); } - handleError(error: AdyenCheckoutError) {} + + async handleShippingContactSelected(resolve: any, reject: any, event: any, label: string): Promise { + await this.initializeCart(this.product); + if (event.shippingContact) { + const shippingAddress: Address = { + postalCode: event.shippingContact.postalCode, + country: {isocode: event.shippingContact.countryCode}, + firstName: "placeholder", + lastName: "placeholder", + town: "placeholder", + line1: "placeholder" + } + this.subscriptions.add(this.adyenCartService.createAndSetAddress(this.cartId, shippingAddress).subscribe(() => { + this.subscriptions.add(this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { + const validDeliveryModes = deliveryModes.filter(mode => mode.code); + + if (validDeliveryModes.length > 0) { + this.subscriptions.add(this.adyenCartService + .setDeliveryMode(validDeliveryModes[0].code!, this.cartId) + .pipe( + switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + ).subscribe({ + next: cart => { + try { + const shippingContactUpdate = { + newTotal: { + label: label, + type: 'final', + amount: cart.totalPriceWithTax!.value!.toString() + }, + newShippingMethods: deliveryModes.map((mode) => ({ + identifier: mode.code!, + label: mode.name || "", + detail: mode.description || "", + amount: mode.deliveryCost!.value!.toString() + })) + } + + resolve(shippingContactUpdate); + } catch (e) { + console.error("Delivery mode mapping issue") + reject(); + } + }, + error: err => { + console.error('Error updating delivery mode:', err); + reject() + }, + })); + } else { + console.error("No delivery modes") + reject('Error updating delivery mode') + } + })) + })) + + } + } + + handleShippingMethodSelected(resolve: any, reject: any, event: any, label: string): void { + this.subscriptions.add(this.adyenCartService.setDeliveryMode(event.shippingMethod.identifier, this.cartId) + .pipe( + switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + ).subscribe({ + next: cart => { + try { + const shippingMethodUpdate = { + newTotal: { + label: label, + type: 'final', + amount: cart.totalPriceWithTax!.value!.toString() + } + } + resolve(shippingMethodUpdate) + } catch (e) { + console.error("Delivery mode selection issue") + reject(); + } + }, + error: err => { + console.error('Error updating delivery mode:', err); + reject() + }, + })); + } + + handleError(error: AdyenCheckoutError) { + } onSuccess(): void { - this.routingService.go({ cxRoute: 'orderConfirmation' }); + this.routingService.go({cxRoute: 'orderConfirmation'}); + } + + override ngOnDestroy(): void { + super.ngOnDestroy() + this.subscriptions.unsubscribe(); + if (this.applePay) this.applePay.unmount(); } } diff --git a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts new file mode 100644 index 0000000..dc11ee3 --- /dev/null +++ b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts @@ -0,0 +1,99 @@ +import {Injectable, OnDestroy} from "@angular/core"; +import {Product, UserIdService} from '@spartacus/core'; +import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; +import {firstValueFrom, Observable, of, Subject} from 'rxjs'; +import {catchError, filter, map, switchMap, take, takeUntil, tap} from 'rxjs/operators'; +import {AdyenCartService} from "../../service/adyen-cart-service"; + + +@Injectable() +export class ExpressPaymentBase implements OnDestroy { + + constructor(protected multiCartService: MultiCartFacade, + protected userIdService: UserIdService, + protected activeCartService: ActiveCartFacade, + protected adyenCartService: AdyenCartService) { + + } + + private unsubscribe$ = new Subject(); + + productAdded = false; + cartId: string; + cart$!: Observable; + + + async initializeCart(product: Product): Promise { + try { + const activeCart = await firstValueFrom( + this.activeCartService.getActive().pipe( + take(1), + catchError((error) => { + console.error("Error fetching the active cart:", error); + return of(null); // Ensure chain does not terminate + }) + ) + ); + + if (!activeCart) { + console.warn("No active cart found, emitting null."); + return; // Gracefully handle missing active cart + } + + const cart = product + ? await firstValueFrom(this.createAndAddProductToCart(product)) + : activeCart; + + if (!this.cartId) { + if (cart && cart.code) { + this.cart$ = this.multiCartService.getCart(cart.code); + this.cartId = cart.code; + + } else { + console.warn("Cart not available or invalid."); + } + } + } catch (error) { + console.error("Error in async cart initialization:", error); + } + } + + private createAndAddProductToCart(product: Product): Observable { + return this.userIdService.takeUserId().pipe( + filter(userId => !!userId), // Ensure we have a valid user ID + take(1), + takeUntil(this.unsubscribe$), + switchMap((userId) => + this.multiCartService.createCart({ + userId, + extraData: {active: false}, + }).pipe( + tap((cart) => { + if (!this.productAdded) { + if (cart && cart.code && product?.code) { + // Call addEntry here, as it does not return an Observable + this.multiCartService.addEntry(userId, cart.code, product.code, 1); + this.productAdded = true; + } else { + console.error("Unable to add product or cart is invalid."); + } + } + }), + map((cart) => cart) // Forward the cart in the pipeline + ) + ) + ) + } + + getSupportedDeliveryModesState(cartId: string): Observable { + return this.adyenCartService.getSupportedDeliveryModesStateForCart(cartId).pipe( + map((state) => state.data || []), + catchError(() => of([])) + ); + } + + ngOnDestroy(): void { + this.unsubscribe$.next(); + this.unsubscribe$.complete(); + } +} diff --git a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts index 9231ebc..d1de2fd 100644 --- a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts @@ -11,6 +11,7 @@ import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; import {Observable, of,Subject, firstValueFrom, last} from 'rxjs'; import { filter, map,tap, switchMap, take, takeUntil, catchError } from 'rxjs/operators'; import {AdyenCartService} from "../../service/adyen-cart-service"; +import {ExpressPaymentBase} from "../base/express-payment-base"; @Component({ @@ -20,110 +21,39 @@ import {AdyenCartService} from "../../service/adyen-cart-service"; templateUrl: './google-express-payment.component.html', styleUrls: ['./google-express-payment.component.css'] }) -export class GoogleExpressPaymentComponent implements OnInit, OnDestroy{ - - private unsubscribe$ = new Subject(); +export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements OnInit, OnDestroy{ @Input() product: Product; @Input() configuration: AdyenExpressConfigData; - cart$!: Observable; - deliveryModes$: Observable = of([]); - productAdded = false; + googlePay!: GooglePay; - cartId: string; private authorizedPaymentData: any; constructor( protected adyenOrderService: AdyenExpressOrderService, protected routingService: RoutingService, - protected activeCartService: ActiveCartFacade, - protected multiCartService: MultiCartFacade, - private userIdService: UserIdService, - protected adyenCartService: AdyenCartService, - ) {} + protected override activeCartService: ActiveCartFacade, + protected override multiCartService: MultiCartFacade, + protected override userIdService: UserIdService, + protected override adyenCartService: AdyenCartService, + ) { + super(multiCartService, userIdService, activeCartService, adyenCartService) + } ngOnInit(): void { this.initializeGooglePay(); } - private async initializeCart(): Promise { - try { - const activeCart = await firstValueFrom( - this.activeCartService.getActive().pipe( - take(1), - catchError((error) => { - console.error("Error fetching the active cart:", error); - return of(null); // Ensure chain does not terminate - }) - ) - ); - - if (!activeCart) { - console.warn("No active cart found, emitting null."); - return; // Gracefully handle missing active cart - } - - const cart = this.product - ? await firstValueFrom(this.createAndAddProductToCart()) - : activeCart; - - if (!this.cartId) { - if (cart && cart.code) { - this.cart$ = this.multiCartService.getCart(cart.code); - this.cartId = cart.code; - - } else { - console.warn("Cart not available or invalid."); - } - } - } catch (error) { - console.error("Error in async cart initialization:", error); - } - } - - private createAndAddProductToCart(): Observable { - return this.userIdService.takeUserId().pipe( - filter(userId => !!userId), // Ensure we have a valid user ID - take(1), - takeUntil(this.unsubscribe$), - switchMap((userId) => - this.multiCartService.createCart({ - userId, - extraData: { active: false }, - }).pipe( - tap((cart) => { - if(!this.productAdded) { - if (cart && cart.code && this.product?.code) { - // Call addEntry here, as it does not return an Observable - this.multiCartService.addEntry(userId, cart.code, this.product.code, 1); - this.productAdded = true; - } else { - console.error("Unable to add product or cart is invalid."); - } - } - }), - map((cart) => cart) // Forward the cart in the pipeline - ) - ) - ) - } private initializeGooglePay(): void { if (this.configuration) { this.setupAdyenCheckout(this.configuration); // Existing logic encapsulated into functions. } } - deliveryModes: DeliveryMode[] = []; - getSupportedDeliveryModesState(cartId: string): Observable { - return this.adyenCartService.getSupportedDeliveryModesStateForCart(cartId).pipe( - map((state) => state.data || []), - catchError(() => of([])) - ); - } private async setupAdyenCheckout(config: AdyenExpressConfigData) { @@ -158,7 +88,7 @@ export class GoogleExpressPaymentComponent implements OnInit, OnDestroy{ const paymentDataRequestUpdate: google.payments.api.PaymentDataRequestUpdate = {}; if(callbackTrigger === 'INITIALIZE'){ - await this.initializeCart(); + await this.initializeCart(this.product); } if (callbackTrigger === 'INITIALIZE' || callbackTrigger === 'SHIPPING_ADDRESS') { @@ -272,9 +202,8 @@ export class GoogleExpressPaymentComponent implements OnInit, OnDestroy{ this.routingService.go({ cxRoute: 'orderConfirmation' }); } - ngOnDestroy(): void { - this.unsubscribe$.next(); - this.unsubscribe$.complete(); + override ngOnDestroy(): void { + super.ngOnDestroy(); if (this.googlePay) { this.googlePay.unmount(); } From cf54c7d1035b387119b32a6c0cafdce920c3b101 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Wed, 19 Feb 2025 15:41:53 +0100 Subject: [PATCH 02/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index cdc76a4..79058d5 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2", + "version": "1.1.2-AD-375a", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From 0785ea4ab09f8dec610e9451ebfba648279c90a6 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:15:46 +0100 Subject: [PATCH 03/19] AD-375 Select delivery method during Apple Express Pay - Update apple-express-payment.component.ts --- .../apple-express-payment/apple-express-payment.component.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index 07053d8..517cd6b 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -153,10 +153,7 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements reject() }, })); - } else { - console.error("No delivery modes") - reject('Error updating delivery mode') - } + } })) })) From 6866424e121ca45b5a21724206729a9112cfb59e Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Thu, 20 Feb 2025 09:16:03 +0100 Subject: [PATCH 04/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index 79058d5..165b499 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375a", + "version": "1.1.2-AD-375b", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From 8e41927117ff0edd4dd8689471953c259cb0b520 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 20 Feb 2025 12:29:59 +0100 Subject: [PATCH 05/19] AD-375 Select delivery method during Apple Express Pay - change to cartId flow --- .../adyen-order-connector.service.ts | 4 ++-- .../src/core/models/occ.order.models.ts | 3 ++- .../occ/adapters/occ-adyen-order.adapter.ts | 4 ++-- .../service/adyen-express-order.service.ts | 23 +++++++++---------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts b/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts index c65aa51..3adc726 100644 --- a/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts +++ b/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { ApplePayExpressRequest, - GooglePayExpressCartRequest, + GooglePayExpressRequest, PlaceOrderRequest, PlaceOrderResponse } from "../models/occ.order.models"; @@ -20,7 +20,7 @@ export class AdyenOrderConnector { return this.adapter.cancelPayment(userId, cartId, orderCode); } - placeGoogleExpressOrderCart(userId: string, cartId: string, request: GooglePayExpressCartRequest): Observable { + placeGoogleExpressOrderCart(userId: string, cartId: string, request: GooglePayExpressRequest): Observable { return this.adapter.placeGoogleExpressOrderCart(userId, cartId, request); } diff --git a/projects/adyen/adyen-spartacus/src/core/models/occ.order.models.ts b/projects/adyen/adyen-spartacus/src/core/models/occ.order.models.ts index 0dab1d0..8a4030e 100644 --- a/projects/adyen/adyen-spartacus/src/core/models/occ.order.models.ts +++ b/projects/adyen/adyen-spartacus/src/core/models/occ.order.models.ts @@ -2,12 +2,13 @@ import { PaymentAction,PaymentResponseData } from "@adyen/adyen-web"; import { Order } from '@spartacus/order/root'; export interface ApplePayExpressRequest { + cartId?: string; applePayDetails: any; addressData: any; productCode?: string; } -export interface GooglePayExpressCartRequest { +export interface GooglePayExpressRequest { googlePayDetails: any; addressData: any; productCode?: string; diff --git a/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts b/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts index 7ebb6fb..8fe4821 100644 --- a/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts +++ b/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts @@ -4,7 +4,7 @@ import {OccEndpointsService} from '@spartacus/core'; import {Observable} from 'rxjs'; import { ApplePayExpressRequest, - GooglePayExpressCartRequest, + GooglePayExpressRequest, PlaceOrderRequest, PlaceOrderResponse } from "../../models/occ.order.models"; @@ -45,7 +45,7 @@ export class OccAdyenOrderAdapter { }); } - public placeGoogleExpressOrderCart(userId: string, cartId: string, orderData: GooglePayExpressCartRequest): Observable { + public placeGoogleExpressOrderCart(userId: string, cartId: string, orderData: GooglePayExpressRequest): Observable { return this.http.post(orderData.cartId ? this.getPlaceGoogleExpressOrderEndpointProduct(userId, cartId) : this.getPlaceGoogleExpressOrderEndpointCart(userId, cartId), orderData); } diff --git a/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts b/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts index 5829132..7ad5b70 100644 --- a/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts +++ b/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts @@ -15,13 +15,13 @@ import {catchError, map, Observable, of, switchMap, tap} from "rxjs"; import {OrderPlacedEvent} from '@spartacus/order/root'; import {AdyenOrderConnector} from "../core/connectors/adyen-order-connector.service"; import {ActiveCartFacade} from '@spartacus/cart/base/root'; -import {ApplePayExpressRequest, GooglePayExpressCartRequest, PlaceOrderResponse} from "../core/models/occ.order.models"; +import {ApplePayExpressRequest, GooglePayExpressRequest, PlaceOrderResponse} from "../core/models/occ.order.models"; import {HttpErrorResponse} from "@angular/common/http"; import {AdyenOrderService} from "./adyen-order.service"; import {AdditionalDetailsConnector} from "../core/connectors/additional-details.connector"; import {PaymentData} from "@adyen/adyen-web"; -type ExpressPaymentDataRequest = GooglePayExpressCartRequest | ApplePayExpressRequest; +type ExpressPaymentDataRequest = GooglePayExpressRequest | ApplePayExpressRequest; type ExpressCommand = { paymentData: ExpressPaymentDataRequest, @@ -84,11 +84,11 @@ export class AdyenExpressOrderService extends AdyenOrderService { } protected placeExpressGoogleOrderWrapper = (userId: string, cartId: string, request: ExpressPaymentDataRequest) => { - return this.placeOrderConnector.placeGoogleExpressOrderCart(userId, cartId, request as GooglePayExpressCartRequest) + return this.placeOrderConnector.placeGoogleExpressOrderCart(userId, cartId, request as GooglePayExpressRequest) } - adyenPlaceAppleExpressOrder(paymentData: PaymentData, authorizedPaymentData: any, product: Product): Observable { - return this.adyenPlaceExpressOrderCommand.execute({paymentData: this.prepareDataApple(paymentData, authorizedPaymentData, product), connectorFunction: this.placeExpressAppleOrderWrapper, isPDP: !!product}); + adyenPlaceAppleExpressOrder(paymentData: PaymentData, authorizedPaymentData: any, product: Product, cartId: string): Observable { + return this.adyenPlaceExpressOrderCommand.execute({paymentData: this.prepareDataApple(paymentData, authorizedPaymentData, cartId), connectorFunction: this.placeExpressAppleOrderWrapper, isPDP: !!product}); } protected placeExpressAppleOrderWrapper = (userId: string, cartId: string, request: ExpressPaymentDataRequest) => { @@ -107,8 +107,9 @@ export class AdyenExpressOrderService extends AdyenOrderService { }); } - prepareDataGoogle(paymentData: any, authorizedPaymentData: any, cartId: string): GooglePayExpressCartRequest { - const baseData = { + prepareDataGoogle(paymentData: any, authorizedPaymentData: any, cartId: string): GooglePayExpressRequest { + return { + cartId: cartId, googlePayDetails: paymentData.paymentMethod, addressData: { email: authorizedPaymentData.authorizedEvent.email, @@ -125,14 +126,13 @@ export class AdyenExpressOrderService extends AdyenOrderService { } } }; - delete baseData.googlePayDetails.subtype; - return { cartId: cartId, ...baseData } } - prepareDataApple(paymentData: PaymentData, authorizedPaymentData: any, product: Product): ApplePayExpressRequest { + prepareDataApple(paymentData: PaymentData, authorizedPaymentData: any, cartId: string): ApplePayExpressRequest { let event = authorizedPaymentData.authorizedEvent; - const baseData = { + return { + cartId: cartId, applePayDetails: paymentData.paymentMethod, addressData: { email: event.payment.shippingContact?.emailAddress, @@ -150,6 +150,5 @@ export class AdyenExpressOrderService extends AdyenOrderService { } } }; - return product ? { productCode: product.code, ...baseData } : baseData; } } From 23f6c331902c68f54b49dd00a17263ce4d96b4ea Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Thu, 20 Feb 2025 12:30:43 +0100 Subject: [PATCH 06/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index 165b499..3bff316 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375b", + "version": "1.1.2-AD-375c", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From 050cf9849d32bd7bedbbc7d8ce97313ffebe66fc Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 20 Feb 2025 13:11:55 +0100 Subject: [PATCH 07/19] AD-375 Select delivery method during Apple Express Pay - change to cartId flow --- .../apple-express-payment/apple-express-payment.component.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index 517cd6b..b779b87 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -84,7 +84,7 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements } private handleOnSubmit(state: SubmitData, actions: any) { - this.adyenOrderService.adyenPlaceAppleExpressOrder(state.data, this.authorizedPaymentData, this.product).subscribe( + this.adyenOrderService.adyenPlaceAppleExpressOrder(state.data, this.authorizedPaymentData, this.product, this.cartId).subscribe( result => { if (result?.success) { if (result.executeAction && result.paymentsAction !== undefined) { @@ -153,7 +153,7 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements reject() }, })); - } + } })) })) From f042275c2936ffe4e5ba89775e70d44b485b046a Mon Sep 17 00:00:00 2001 From: PJaneta Date: Thu, 20 Feb 2025 14:47:04 +0100 Subject: [PATCH 08/19] AD-375 Select delivery method during Apple Express Pay - pdp url selection fix --- angular.json | 3 +++ .../core/connectors/adyen-order-connector.service.ts | 8 ++++---- .../src/core/occ/adapters/occ-adyen-order.adapter.ts | 8 ++++---- .../src/service/adyen-express-order.service.ts | 12 ++++++------ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/angular.json b/angular.json index fbe6620..91b8727 100644 --- a/angular.json +++ b/angular.json @@ -123,5 +123,8 @@ } } } + }, + "cli": { + "analytics": false } } diff --git a/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts b/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts index 3adc726..11526dc 100644 --- a/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts +++ b/projects/adyen/adyen-spartacus/src/core/connectors/adyen-order-connector.service.ts @@ -20,11 +20,11 @@ export class AdyenOrderConnector { return this.adapter.cancelPayment(userId, cartId, orderCode); } - placeGoogleExpressOrderCart(userId: string, cartId: string, request: GooglePayExpressRequest): Observable { - return this.adapter.placeGoogleExpressOrderCart(userId, cartId, request); + placeGoogleExpressOrderCart(userId: string, cartId: string, request: GooglePayExpressRequest, isPDP: boolean): Observable { + return this.adapter.placeGoogleExpressOrderCart(userId, cartId, request, isPDP); } - placeAppleExpressOrder(userId: string, cartId: string, request: ApplePayExpressRequest): Observable { - return this.adapter.placeAppleExpressOrder(userId, cartId, request); + placeAppleExpressOrder(userId: string, cartId: string, request: ApplePayExpressRequest, isPDP: boolean): Observable { + return this.adapter.placeAppleExpressOrder(userId, cartId, request, isPDP); } } diff --git a/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts b/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts index 8fe4821..a79c563 100644 --- a/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts +++ b/projects/adyen/adyen-spartacus/src/core/occ/adapters/occ-adyen-order.adapter.ts @@ -45,8 +45,8 @@ export class OccAdyenOrderAdapter { }); } - public placeGoogleExpressOrderCart(userId: string, cartId: string, orderData: GooglePayExpressRequest): Observable { - return this.http.post(orderData.cartId ? this.getPlaceGoogleExpressOrderEndpointProduct(userId, cartId) : this.getPlaceGoogleExpressOrderEndpointCart(userId, cartId), orderData); + public placeGoogleExpressOrderCart(userId: string, cartId: string, orderData: GooglePayExpressRequest, isPDP: boolean): Observable { + return this.http.post(isPDP ? this.getPlaceGoogleExpressOrderEndpointProduct(userId, cartId) : this.getPlaceGoogleExpressOrderEndpointCart(userId, cartId), orderData); } protected getPlaceGoogleExpressOrderEndpointCart(userId: string, cartId: string): string { @@ -67,8 +67,8 @@ export class OccAdyenOrderAdapter { }); } - public placeAppleExpressOrder(userId: string, cartId: string, orderData: ApplePayExpressRequest): Observable { - return this.http.post(orderData.productCode ? this.getPlaceAppleExpressOrderEndpointProduct(userId, cartId) : this.getPlaceAppleExpressOrderEndpointCart(userId, cartId), orderData); + public placeAppleExpressOrder(userId: string, cartId: string, orderData: ApplePayExpressRequest, isPDP: boolean): Observable { + return this.http.post(isPDP ? this.getPlaceAppleExpressOrderEndpointProduct(userId, cartId) : this.getPlaceAppleExpressOrderEndpointCart(userId, cartId), orderData); } protected getPlaceAppleExpressOrderEndpointCart(userId: string, cartId: string): string { diff --git a/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts b/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts index 7ad5b70..f4c9168 100644 --- a/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts +++ b/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts @@ -25,7 +25,7 @@ type ExpressPaymentDataRequest = GooglePayExpressRequest | ApplePayExpressReques type ExpressCommand = { paymentData: ExpressPaymentDataRequest, - connectorFunction: (userId: string, cartId: string, request: ExpressPaymentDataRequest) => Observable, + connectorFunction: (userId: string, cartId: string, request: ExpressPaymentDataRequest, isPDP: boolean) => Observable, isPDP: boolean, } @@ -53,7 +53,7 @@ export class AdyenExpressOrderService extends AdyenOrderService { (expressCommand) => this.checkoutPreconditions().pipe( switchMap(([userId, cartId]) => - expressCommand.connectorFunction(userId, cartId, expressCommand.paymentData).pipe( + expressCommand.connectorFunction(userId, cartId, expressCommand.paymentData, expressCommand.isPDP).pipe( tap((placeOrderResponse) => { this.placedOrder$.next(placeOrderResponse.orderData); this.placedOrderNumber$.next(placeOrderResponse.orderNumber); @@ -83,16 +83,16 @@ export class AdyenExpressOrderService extends AdyenOrderService { return this.adyenPlaceExpressOrderCommand.execute({paymentData: this.prepareDataGoogle(paymentData, authorizedPaymentData, cartId), connectorFunction: this.placeExpressGoogleOrderWrapper, isPDP: !!product}); } - protected placeExpressGoogleOrderWrapper = (userId: string, cartId: string, request: ExpressPaymentDataRequest) => { - return this.placeOrderConnector.placeGoogleExpressOrderCart(userId, cartId, request as GooglePayExpressRequest) + protected placeExpressGoogleOrderWrapper = (userId: string, cartId: string, request: ExpressPaymentDataRequest, isPDP: boolean) => { + return this.placeOrderConnector.placeGoogleExpressOrderCart(userId, cartId, request as GooglePayExpressRequest, isPDP) } adyenPlaceAppleExpressOrder(paymentData: PaymentData, authorizedPaymentData: any, product: Product, cartId: string): Observable { return this.adyenPlaceExpressOrderCommand.execute({paymentData: this.prepareDataApple(paymentData, authorizedPaymentData, cartId), connectorFunction: this.placeExpressAppleOrderWrapper, isPDP: !!product}); } - protected placeExpressAppleOrderWrapper = (userId: string, cartId: string, request: ExpressPaymentDataRequest) => { - return this.placeOrderConnector.placeAppleExpressOrder(userId, cartId, request as ApplePayExpressRequest) + protected placeExpressAppleOrderWrapper = (userId: string, cartId: string, request: ExpressPaymentDataRequest, isPDP: boolean) => { + return this.placeOrderConnector.placeAppleExpressOrder(userId, cartId, request as ApplePayExpressRequest, isPDP) } private handlePlaceOrderError(error: HttpErrorResponse): Observable { From a991f992db56f64e9d99b57891dfae82f8e555f5 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Thu, 20 Feb 2025 14:47:23 +0100 Subject: [PATCH 09/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index 3bff316..c7d2f55 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375c", + "version": "1.1.2-AD-375d", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From 78687d860d7653b6b1f604318d46f62768144966 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Fri, 21 Feb 2025 15:28:16 +0100 Subject: [PATCH 10/19] AD-375 Select delivery method during Apple Express Pay - cart init fix --- .../src/express/base/express-payment-base.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts index dc11ee3..05a4aa2 100644 --- a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts +++ b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts @@ -40,11 +40,16 @@ export class ExpressPaymentBase implements OnDestroy { return; // Gracefully handle missing active cart } - const cart = product - ? await firstValueFrom(this.createAndAddProductToCart(product)) - : activeCart; + console.log("init cart") if (!this.cartId) { + console.log("empty cart id, initializing with product: " + product.code) + + const cart = product + ? await firstValueFrom(this.createAndAddProductToCart(product)) + : activeCart; + + if (cart && cart.code) { this.cart$ = this.multiCartService.getCart(cart.code); this.cartId = cart.code; From abc4315088a129a048c5f065884e52c4e4295c24 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:28:56 +0100 Subject: [PATCH 11/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index c7d2f55..ddc201d 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375d", + "version": "1.1.2-AD-375e", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From ce73aba74e49a520e56f43aac1b931292673a37b Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 24 Feb 2025 12:00:58 +0100 Subject: [PATCH 12/19] AD-375 Select delivery method during Apple Express Pay - handlers refactor --- .../apple-express-payment.component.ts | 203 ++++++++++-------- .../src/express/base/express-payment-base.ts | 71 +++++- 2 files changed, 187 insertions(+), 87 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index b779b87..c59afc0 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -6,7 +6,7 @@ import {AdyenExpressConfigData} from "../../core/models/occ.config.models"; import {AdyenExpressOrderService} from "../../service/adyen-express-order.service"; import {Address, Product, RoutingService, UserIdService,} from '@spartacus/core'; import {Subscription, switchMap} from 'rxjs'; -import {ActiveCartFacade, MultiCartFacade} from '@spartacus/cart/base/root'; +import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; import {ExpressPaymentBase} from "../base/express-payment-base"; import {AdyenCartService} from "../../service/adyen-cart-service"; @@ -20,7 +20,7 @@ import {AdyenCartService} from "../../service/adyen-cart-service"; }) export class AppleExpressPaymentComponent extends ExpressPaymentBase implements OnInit, OnDestroy { - protected subscriptions = new Subscription(); + // protected subscriptions = new Subscription(); @Input() product: Product; @@ -69,8 +69,41 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements "name", "email" ], - onShippingContactSelected: (resolve, reject, event) => this.handleShippingContactSelected(resolve,reject,event, config.applePayMerchantName), - onShippingMethodSelected: (resolve, reject, event) =>this.handleShippingMethodSelected(resolve,reject,event, config.applePayMerchantName), + // onShippingContactSelected: (resolve, reject, event) => this.handleShippingContactSelected(resolve,reject,event, config.applePayMerchantName), + // onShippingMethodSelected: (resolve, reject, event) =>this.handleShippingMethodSelected(resolve,reject,event, config.applePayMerchantName), + onShippingContactSelected: (resolve, reject, event) => { + const mappingFunction = (cart: Cart, deliveryModes: DeliveryMode[]): any => { + return { + newTotal: { + label: config.applePayMerchantName, + type: 'final', + amount: cart.totalPriceWithTax!.value!.toString() + }, + newShippingMethods: deliveryModes.map((mode) => ({ + identifier: mode.code!, + label: mode.name || "", + detail: mode.description || "", + amount: mode.deliveryCost!.value!.toString() + })) + } + } + if (event.shippingContact) { + const address = {postalCode: event.shippingContact.postalCode!, countryCode: event.shippingContact.countryCode!} + this.handleShippingContactSelected(address, this.product, mappingFunction, resolve, reject) + } + }, + onShippingMethodSelected: (resolve, reject, event) => { + const mappingFunction = (cart: Cart): any => { + return { + newTotal: { + label: config.applePayMerchantName, + type: 'final', + amount: cart.totalPriceWithTax!.value!.toString() + } + } + } + this.setDeliveryMode(event.shippingMethod.identifier, this.product, mappingFunction, resolve, reject); + }, onSubmit: (state, element: UIElement, actions) => this.handleOnSubmit(state, actions), onAuthorized: (paymentData, actions) => { this.authorizedPaymentData = paymentData; @@ -105,87 +138,87 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements ); } - async handleShippingContactSelected(resolve: any, reject: any, event: any, label: string): Promise { - await this.initializeCart(this.product); - if (event.shippingContact) { - const shippingAddress: Address = { - postalCode: event.shippingContact.postalCode, - country: {isocode: event.shippingContact.countryCode}, - firstName: "placeholder", - lastName: "placeholder", - town: "placeholder", - line1: "placeholder" - } - this.subscriptions.add(this.adyenCartService.createAndSetAddress(this.cartId, shippingAddress).subscribe(() => { - this.subscriptions.add(this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { - const validDeliveryModes = deliveryModes.filter(mode => mode.code); - - if (validDeliveryModes.length > 0) { - this.subscriptions.add(this.adyenCartService - .setDeliveryMode(validDeliveryModes[0].code!, this.cartId) - .pipe( - switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - ).subscribe({ - next: cart => { - try { - const shippingContactUpdate = { - newTotal: { - label: label, - type: 'final', - amount: cart.totalPriceWithTax!.value!.toString() - }, - newShippingMethods: deliveryModes.map((mode) => ({ - identifier: mode.code!, - label: mode.name || "", - detail: mode.description || "", - amount: mode.deliveryCost!.value!.toString() - })) - } - - resolve(shippingContactUpdate); - } catch (e) { - console.error("Delivery mode mapping issue") - reject(); - } - }, - error: err => { - console.error('Error updating delivery mode:', err); - reject() - }, - })); - } - })) - })) - - } - } - - handleShippingMethodSelected(resolve: any, reject: any, event: any, label: string): void { - this.subscriptions.add(this.adyenCartService.setDeliveryMode(event.shippingMethod.identifier, this.cartId) - .pipe( - switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - ).subscribe({ - next: cart => { - try { - const shippingMethodUpdate = { - newTotal: { - label: label, - type: 'final', - amount: cart.totalPriceWithTax!.value!.toString() - } - } - resolve(shippingMethodUpdate) - } catch (e) { - console.error("Delivery mode selection issue") - reject(); - } - }, - error: err => { - console.error('Error updating delivery mode:', err); - reject() - }, - })); - } + // async handleShippingContactSelected(resolve: any, reject: any, event: any, label: string): Promise { + // await this.initializeCart(this.product); + // if (event.shippingContact) { + // const shippingAddress: Address = { + // postalCode: event.shippingContact.postalCode, + // country: {isocode: event.shippingContact.countryCode}, + // firstName: "placeholder", + // lastName: "placeholder", + // town: "placeholder", + // line1: "placeholder" + // } + // this.subscriptions.add(this.adyenCartService.createAndSetAddress(this.cartId, shippingAddress).subscribe(() => { + // this.subscriptions.add(this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { + // const validDeliveryModes = deliveryModes.filter(mode => mode.code); + // + // if (validDeliveryModes.length > 0) { + // this.subscriptions.add(this.adyenCartService + // .setDeliveryMode(validDeliveryModes[0].code!, this.cartId) + // .pipe( + // switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + // ).subscribe({ + // next: cart => { + // try { + // const shippingContactUpdate = { + // newTotal: { + // label: label, + // type: 'final', + // amount: cart.totalPriceWithTax!.value!.toString() + // }, + // newShippingMethods: deliveryModes.map((mode) => ({ + // identifier: mode.code!, + // label: mode.name || "", + // detail: mode.description || "", + // amount: mode.deliveryCost!.value!.toString() + // })) + // } + // + // resolve(shippingContactUpdate); + // } catch (e) { + // console.error("Delivery mode mapping issue") + // reject(); + // } + // }, + // error: err => { + // console.error('Error updating delivery mode:', err); + // reject() + // }, + // })); + // } + // })) + // })) + // + // } + // } + + // handleShippingMethodSelected(resolve: any, reject: any, event: any, label: string): void { + // this.subscriptions.add(this.adyenCartService.setDeliveryMode(event.shippingMethod.identifier, this.cartId) + // .pipe( + // switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + // ).subscribe({ + // next: cart => { + // try { + // const shippingMethodUpdate = { + // newTotal: { + // label: label, + // type: 'final', + // amount: cart.totalPriceWithTax!.value!.toString() + // } + // } + // resolve(shippingMethodUpdate) + // } catch (e) { + // console.error("Delivery mode selection issue") + // reject(); + // } + // }, + // error: err => { + // console.error('Error updating delivery mode:', err); + // reject() + // }, + // })); + // } handleError(error: AdyenCheckoutError) { } diff --git a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts index 05a4aa2..ff4cab2 100644 --- a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts +++ b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts @@ -1,7 +1,7 @@ import {Injectable, OnDestroy} from "@angular/core"; -import {Product, UserIdService} from '@spartacus/core'; +import {Address, Product, UserIdService} from '@spartacus/core'; import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; -import {firstValueFrom, Observable, of, Subject} from 'rxjs'; +import {firstValueFrom, Observable, of, Subject, Subscription} from 'rxjs'; import {catchError, filter, map, switchMap, take, takeUntil, tap} from 'rxjs/operators'; import {AdyenCartService} from "../../service/adyen-cart-service"; @@ -17,6 +17,7 @@ export class ExpressPaymentBase implements OnDestroy { } private unsubscribe$ = new Subject(); + protected subscriptions = new Subscription(); productAdded = false; cartId: string; @@ -97,7 +98,73 @@ export class ExpressPaymentBase implements OnDestroy { ); } + setDeliveryMode(deliveryModeId: string, product: Product, mappingFunction: (cart: Cart) => T, resolve: any, reject: any): void { + this.subscriptions.add(this.adyenCartService.setDeliveryMode(deliveryModeId, this.cartId) + .pipe( + switchMap(() => !!product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + ).subscribe({ + next: cart => { + try { + const update = mappingFunction(cart); + + resolve(update) + } catch (e) { + console.error("Delivery mode selection issue") + reject(); + } + }, + error: err => { + console.error('Error updating delivery mode:', err); + reject() + }, + })); + } + + async handleShippingContactSelected(address: { + postalCode: string, + countryCode: string + }, product: Product, mappingFunction: (cart: Cart, deliveryModes: DeliveryMode[]) => T, resolve: any, reject: any): Promise { + await this.initializeCart(product); + const shippingAddress: Address = { + postalCode: address.postalCode, + country: {isocode: address.countryCode}, + firstName: "placeholder", + lastName: "placeholder", + town: "placeholder", + line1: "placeholder" + } + this.subscriptions.add(this.adyenCartService.createAndSetAddress(this.cartId, shippingAddress).subscribe(() => { + this.subscriptions.add(this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { + const validDeliveryModes = deliveryModes.filter(mode => mode.code); + + if (validDeliveryModes.length > 0) { + this.subscriptions.add(this.adyenCartService + .setDeliveryMode(validDeliveryModes[0].code!, this.cartId) + .pipe( + switchMap(() => !!product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + ).subscribe({ + next: cart => { + try { + let update = mappingFunction(cart, validDeliveryModes); + + resolve(update); + } catch (e) { + console.error("Delivery mode mapping issue") + reject(); + } + }, + error: err => { + console.error('Error updating delivery mode:', err); + reject() + }, + })); + } + })) + })) + } + ngOnDestroy(): void { + this.subscriptions.unsubscribe(); this.unsubscribe$.next(); this.unsubscribe$.complete(); } From d0a8a21e26bf953fdf57ced9f81e11d35ae22b70 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Mon, 24 Feb 2025 12:01:32 +0100 Subject: [PATCH 13/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index ddc201d..d8c76d9 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375e", + "version": "1.1.2-AD-375f", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From 4ea4f62bc5e78fa00440b622a90e6b86a7cb5b23 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 24 Feb 2025 14:58:19 +0100 Subject: [PATCH 14/19] AD-375 Select delivery method during Apple Express Pay - cart page fix --- .../apple-express-payment.component.ts | 35 +++--- .../src/express/base/express-payment-base.ts | 105 ++++++++++-------- .../google-express-payment.component.ts | 51 +++++---- 3 files changed, 107 insertions(+), 84 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index c59afc0..3a526bc 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -117,25 +117,30 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements } private handleOnSubmit(state: SubmitData, actions: any) { - this.adyenOrderService.adyenPlaceAppleExpressOrder(state.data, this.authorizedPaymentData, this.product, this.cartId).subscribe( - result => { - if (result?.success) { - if (result.executeAction && result.paymentsAction !== undefined) { - this.applePay.handleAction(result.paymentsAction); + if(!!this.cartId){ + this.adyenOrderService.adyenPlaceAppleExpressOrder(state.data, this.authorizedPaymentData, this.product, this.cartId).subscribe( + result => { + if (result?.success) { + if (result.executeAction && result.paymentsAction !== undefined) { + this.applePay.handleAction(result.paymentsAction); + } else { + this.onSuccess(); + } } else { - this.onSuccess(); + console.error(result?.error); + actions.reject(); } - } else { - console.error(result?.error); + actions.resolve({resultCode: 'Authorised'}); + }, + error => { + console.error(error); actions.reject(); } - actions.resolve({resultCode: 'Authorised'}); - }, - error => { - console.error(error); - actions.reject(); - } - ); + ); + } else { + console.error("Undefined cart id") + } + } // async handleShippingContactSelected(resolve: any, reject: any, event: any, label: string): Promise { diff --git a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts index ff4cab2..b75f345 100644 --- a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts +++ b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts @@ -20,7 +20,7 @@ export class ExpressPaymentBase implements OnDestroy { protected subscriptions = new Subscription(); productAdded = false; - cartId: string; + cartId: string | undefined; cart$!: Observable; @@ -44,7 +44,7 @@ export class ExpressPaymentBase implements OnDestroy { console.log("init cart") if (!this.cartId) { - console.log("empty cart id, initializing with product: " + product.code) + console.log("empty cart id, initializing with product: " + product?.code) const cart = product ? await firstValueFrom(this.createAndAddProductToCart(product)) @@ -99,25 +99,29 @@ export class ExpressPaymentBase implements OnDestroy { } setDeliveryMode(deliveryModeId: string, product: Product, mappingFunction: (cart: Cart) => T, resolve: any, reject: any): void { - this.subscriptions.add(this.adyenCartService.setDeliveryMode(deliveryModeId, this.cartId) - .pipe( - switchMap(() => !!product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - ).subscribe({ - next: cart => { - try { - const update = mappingFunction(cart); - - resolve(update) - } catch (e) { - console.error("Delivery mode selection issue") - reject(); - } - }, - error: err => { - console.error('Error updating delivery mode:', err); - reject() - }, - })); + if(!!this.cartId) { + this.subscriptions.add(this.adyenCartService.setDeliveryMode(deliveryModeId, this.cartId) + .pipe( + switchMap(() => !!product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + ).subscribe({ + next: cart => { + try { + const update = mappingFunction(cart); + + resolve(update) + } catch (e) { + console.error("Delivery mode selection issue") + reject(); + } + }, + error: err => { + console.error('Error updating delivery mode:', err); + reject() + }, + })); + } else { + console.error("Undefined cart id") + } } async handleShippingContactSelected(address: { @@ -133,34 +137,39 @@ export class ExpressPaymentBase implements OnDestroy { town: "placeholder", line1: "placeholder" } - this.subscriptions.add(this.adyenCartService.createAndSetAddress(this.cartId, shippingAddress).subscribe(() => { - this.subscriptions.add(this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { - const validDeliveryModes = deliveryModes.filter(mode => mode.code); - - if (validDeliveryModes.length > 0) { - this.subscriptions.add(this.adyenCartService - .setDeliveryMode(validDeliveryModes[0].code!, this.cartId) - .pipe( - switchMap(() => !!product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - ).subscribe({ - next: cart => { - try { - let update = mappingFunction(cart, validDeliveryModes); - - resolve(update); - } catch (e) { - console.error("Delivery mode mapping issue") - reject(); - } - }, - error: err => { - console.error('Error updating delivery mode:', err); - reject() - }, - })); - } + if(!!this.cartId) { + const cartCode = this.cartId; + this.subscriptions.add(this.adyenCartService.createAndSetAddress(cartCode, shippingAddress).subscribe(() => { + this.subscriptions.add(this.getSupportedDeliveryModesState(cartCode).subscribe((deliveryModes) => { + const validDeliveryModes = deliveryModes.filter(mode => mode.code); + + if (validDeliveryModes.length > 0) { + this.subscriptions.add(this.adyenCartService + .setDeliveryMode(validDeliveryModes[0].code!, cartCode) + .pipe( + switchMap(() => !!product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) + ).subscribe({ + next: cart => { + try { + let update = mappingFunction(cart, validDeliveryModes); + + resolve(update); + } catch (e) { + console.error("Delivery mode mapping issue") + reject(); + } + }, + error: err => { + console.error('Error updating delivery mode:', err); + reject() + }, + })); + } + })) })) - })) + } else{ + console.error("Undefined cart id") + } } ngOnDestroy(): void { diff --git a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts index d1de2fd..b4c0860 100644 --- a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts @@ -92,8 +92,9 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements } if (callbackTrigger === 'INITIALIZE' || callbackTrigger === 'SHIPPING_ADDRESS') { - if (shippingAddress) { - this.adyenCartService.createAndSetAddress(this.cartId, { + if (shippingAddress && !!this.cartId) { + const cartCode = this.cartId; + this.adyenCartService.createAndSetAddress(cartCode, { postalCode: shippingAddress.postalCode, country: {isocode: shippingAddress.countryCode}, firstName: "placeholder", @@ -102,10 +103,10 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements line1: "placeholder" }).subscribe( (result) => { - this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { - if(deliveryModes.length > 0) { + this.getSupportedDeliveryModesState(cartCode).subscribe((deliveryModes) => { + if (deliveryModes.length > 0) { this.adyenCartService - .setDeliveryMode(deliveryModes[0]?.code || "", this.cartId) + .setDeliveryMode(deliveryModes[0]?.code || "", cartCode) .pipe( switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) ).subscribe({ @@ -123,10 +124,12 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements } ); } + } else { + console.error("Undefined cart id") } if (callbackTrigger === 'SHIPPING_OPTION') { - if (shippingOptionData) { + if (shippingOptionData && !!this.cartId) { this.adyenCartService .setDeliveryMode(shippingOptionData.id, this.cartId) .pipe( @@ -140,6 +143,8 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements console.error('Error updating delivery mode:', err); }, }); + } else { + console.error("Undefined cart id") } } }); @@ -175,25 +180,29 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements } private handleOnSubmit(state: any, actions: any) { - this.adyenOrderService.adyenPlaceGoogleExpressOrder(state.data, this.authorizedPaymentData, this.product, this.cartId).subscribe( - result => { - if (result?.success) { - if (result.executeAction && result.paymentsAction !== undefined) { - this.googlePay.handleAction(result.paymentsAction); + if(!!this.cartId) { + this.adyenOrderService.adyenPlaceGoogleExpressOrder(state.data, this.authorizedPaymentData, this.product, this.cartId).subscribe( + result => { + if (result?.success) { + if (result.executeAction && result.paymentsAction !== undefined) { + this.googlePay.handleAction(result.paymentsAction); + } else { + this.onSuccess(); + } } else { - this.onSuccess(); + console.error(result?.error); + actions.reject(); } - } else { - console.error(result?.error); + actions.resolve({resultCode: 'Authorised'}); + }, + error => { + console.error(error); actions.reject(); } - actions.resolve({ resultCode: 'Authorised' }); - }, - error => { - console.error(error); - actions.reject(); - } - ); + ); + } else { + console.error("Undefined cart id") + } } handleError(error: AdyenCheckoutError) {} From 728bc7f6815e37e726afcf7dc89f460a5a1309aa Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Mon, 24 Feb 2025 14:58:54 +0100 Subject: [PATCH 15/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index d8c76d9..b391dc8 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375f", + "version": "1.1.2-AD-375g", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From d41d6dc05847aee6bb06ceca3c5d0fc1131e42e1 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Mon, 24 Feb 2025 15:32:11 +0100 Subject: [PATCH 16/19] AD-375 Select delivery method during Apple Express Pay - refactor --- .../apple-express-payment.component.ts | 89 +------------- .../src/express/base/express-payment-base.ts | 3 - .../google-express-payment.component.ts | 111 +++++++----------- 3 files changed, 41 insertions(+), 162 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index 3a526bc..60cead3 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -4,8 +4,7 @@ import {ApplePay, SubmitData, UIElement} from "@adyen/adyen-web"; import {AdyenCheckout, AdyenCheckoutError} from '@adyen/adyen-web/auto'; import {AdyenExpressConfigData} from "../../core/models/occ.config.models"; import {AdyenExpressOrderService} from "../../service/adyen-express-order.service"; -import {Address, Product, RoutingService, UserIdService,} from '@spartacus/core'; -import {Subscription, switchMap} from 'rxjs'; +import {Product, RoutingService, UserIdService,} from '@spartacus/core'; import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; import {ExpressPaymentBase} from "../base/express-payment-base"; @@ -20,8 +19,6 @@ import {AdyenCartService} from "../../service/adyen-cart-service"; }) export class AppleExpressPaymentComponent extends ExpressPaymentBase implements OnInit, OnDestroy { - // protected subscriptions = new Subscription(); - @Input() product: Product; @@ -69,8 +66,6 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements "name", "email" ], - // onShippingContactSelected: (resolve, reject, event) => this.handleShippingContactSelected(resolve,reject,event, config.applePayMerchantName), - // onShippingMethodSelected: (resolve, reject, event) =>this.handleShippingMethodSelected(resolve,reject,event, config.applePayMerchantName), onShippingContactSelected: (resolve, reject, event) => { const mappingFunction = (cart: Cart, deliveryModes: DeliveryMode[]): any => { return { @@ -143,88 +138,6 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements } - // async handleShippingContactSelected(resolve: any, reject: any, event: any, label: string): Promise { - // await this.initializeCart(this.product); - // if (event.shippingContact) { - // const shippingAddress: Address = { - // postalCode: event.shippingContact.postalCode, - // country: {isocode: event.shippingContact.countryCode}, - // firstName: "placeholder", - // lastName: "placeholder", - // town: "placeholder", - // line1: "placeholder" - // } - // this.subscriptions.add(this.adyenCartService.createAndSetAddress(this.cartId, shippingAddress).subscribe(() => { - // this.subscriptions.add(this.getSupportedDeliveryModesState(this.cartId).subscribe((deliveryModes) => { - // const validDeliveryModes = deliveryModes.filter(mode => mode.code); - // - // if (validDeliveryModes.length > 0) { - // this.subscriptions.add(this.adyenCartService - // .setDeliveryMode(validDeliveryModes[0].code!, this.cartId) - // .pipe( - // switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - // ).subscribe({ - // next: cart => { - // try { - // const shippingContactUpdate = { - // newTotal: { - // label: label, - // type: 'final', - // amount: cart.totalPriceWithTax!.value!.toString() - // }, - // newShippingMethods: deliveryModes.map((mode) => ({ - // identifier: mode.code!, - // label: mode.name || "", - // detail: mode.description || "", - // amount: mode.deliveryCost!.value!.toString() - // })) - // } - // - // resolve(shippingContactUpdate); - // } catch (e) { - // console.error("Delivery mode mapping issue") - // reject(); - // } - // }, - // error: err => { - // console.error('Error updating delivery mode:', err); - // reject() - // }, - // })); - // } - // })) - // })) - // - // } - // } - - // handleShippingMethodSelected(resolve: any, reject: any, event: any, label: string): void { - // this.subscriptions.add(this.adyenCartService.setDeliveryMode(event.shippingMethod.identifier, this.cartId) - // .pipe( - // switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - // ).subscribe({ - // next: cart => { - // try { - // const shippingMethodUpdate = { - // newTotal: { - // label: label, - // type: 'final', - // amount: cart.totalPriceWithTax!.value!.toString() - // } - // } - // resolve(shippingMethodUpdate) - // } catch (e) { - // console.error("Delivery mode selection issue") - // reject(); - // } - // }, - // error: err => { - // console.error('Error updating delivery mode:', err); - // reject() - // }, - // })); - // } - handleError(error: AdyenCheckoutError) { } diff --git a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts index b75f345..ec00134 100644 --- a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts +++ b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts @@ -41,11 +41,8 @@ export class ExpressPaymentBase implements OnDestroy { return; // Gracefully handle missing active cart } - console.log("init cart") if (!this.cartId) { - console.log("empty cart id, initializing with product: " + product?.code) - const cart = product ? await firstValueFrom(this.createAndAddProductToCart(product)) : activeCart; diff --git a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts index b4c0860..6600e8e 100644 --- a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts @@ -5,11 +5,9 @@ import {UIElement} from "@adyen/adyen-web"; import {AdyenCheckout, AdyenCheckoutError, GooglePay} from '@adyen/adyen-web/auto'; import {AdyenExpressConfigData} from "../../core/models/occ.config.models"; import {AdyenExpressOrderService} from "../../service/adyen-express-order.service"; -import {Product, RoutingService,UserIdService} from '@spartacus/core'; -import {ActiveCartFacade, Cart, DeliveryMode,MultiCartFacade} from '@spartacus/cart/base/root'; +import {Product, RoutingService, UserIdService} from '@spartacus/core'; +import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; -import {Observable, of,Subject, firstValueFrom, last} from 'rxjs'; -import { filter, map,tap, switchMap, take, takeUntil, catchError } from 'rxjs/operators'; import {AdyenCartService} from "../../service/adyen-cart-service"; import {ExpressPaymentBase} from "../base/express-payment-base"; @@ -83,68 +81,35 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements onSubmit: (state: any, element: UIElement, actions) => this.handleOnSubmit(state, actions), paymentDataCallbacks: { onPaymentDataChanged: async (intermediatePaymentData) => { - return new Promise(async resolve => { + return new Promise(async (resolve, reject) => { const {callbackTrigger, shippingAddress, shippingOptionData} = intermediatePaymentData; - const paymentDataRequestUpdate: google.payments.api.PaymentDataRequestUpdate = {}; + // const paymentDataRequestUpdate: google.payments.api.PaymentDataRequestUpdate = {}; - if(callbackTrigger === 'INITIALIZE'){ + if (callbackTrigger === 'INITIALIZE') { await this.initializeCart(this.product); } if (callbackTrigger === 'INITIALIZE' || callbackTrigger === 'SHIPPING_ADDRESS') { - if (shippingAddress && !!this.cartId) { - const cartCode = this.cartId; - this.adyenCartService.createAndSetAddress(cartCode, { + if (shippingAddress) { + const mappingFunction = (cart: Cart, deliveryModes: DeliveryMode[]): google.payments.api.PaymentDataRequestUpdate => { + let shippingOptionsUpdate = this.updateShippingOptions(deliveryModes); + let cartUpdate = this.updateTransactionInfo(cart); + + return {...shippingOptionsUpdate, ...cartUpdate} + } + + const address = { postalCode: shippingAddress.postalCode, - country: {isocode: shippingAddress.countryCode}, - firstName: "placeholder", - lastName: "placeholder", - town: "placeholder", - line1: "placeholder" - }).subscribe( - (result) => { - this.getSupportedDeliveryModesState(cartCode).subscribe((deliveryModes) => { - if (deliveryModes.length > 0) { - this.adyenCartService - .setDeliveryMode(deliveryModes[0]?.code || "", cartCode) - .pipe( - switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - ).subscribe({ - next: cart => { - this.updateShippingOptions(paymentDataRequestUpdate, deliveryModes); - this.updateTransactionInfo(paymentDataRequestUpdate, cart); - resolve(paymentDataRequestUpdate); - }, - error: err => { - console.error('Error updating delivery mode:', err); - }, - }); - } - }); - } - ); + countryCode: shippingAddress.countryCode + } + + await this.handleShippingContactSelected(address, this.product, mappingFunction, resolve, reject) } - } else { - console.error("Undefined cart id") } if (callbackTrigger === 'SHIPPING_OPTION') { - if (shippingOptionData && !!this.cartId) { - this.adyenCartService - .setDeliveryMode(shippingOptionData.id, this.cartId) - .pipe( - switchMap(() => !!this.product ? this.adyenCartService.takeStable(this.cart$) : this.activeCartService.takeActive()) - ).subscribe({ - next: cart => { - this.updateTransactionInfo(paymentDataRequestUpdate, cart); - resolve(paymentDataRequestUpdate); - }, - error: err => { - console.error('Error updating delivery mode:', err); - }, - }); - } else { - console.error("Undefined cart id") + if (shippingOptionData) { + this.setDeliveryMode(shippingOptionData.id, this.product, this.updateTransactionInfo, resolve, reject); } } }); @@ -158,25 +123,29 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements }).mount("#google-pay-button"); } - private updateShippingOptions(paymentDataRequestUpdate: google.payments.api.PaymentDataRequestUpdate, deliveryModes: DeliveryMode[]) { - paymentDataRequestUpdate.newShippingOptionParameters = { - defaultSelectedOptionId: deliveryModes[0]?.code || "", - shippingOptions: deliveryModes.map(mode => ({ - id: mode.code || "", - label: mode.name || "", - description: mode.description || "" - })) + private updateShippingOptions(deliveryModes: DeliveryMode[]): google.payments.api.PaymentDataRequestUpdate { + return { + newShippingOptionParameters: { + defaultSelectedOptionId: deliveryModes[0]?.code || "", + shippingOptions: deliveryModes.map(mode => ({ + id: mode.code || "", + label: mode.name || "", + description: mode.description || "" + })) + } } } - private updateTransactionInfo(paymentDataRequestUpdate: google.payments.api.PaymentDataRequestUpdate, cart: Cart) { - paymentDataRequestUpdate.newTransactionInfo = { - countryCode: 'US', - currencyCode: cart.totalPriceWithTax?.currencyIso ?? '', - totalPriceStatus: 'FINAL', - totalPrice: (cart.totalPriceWithTax?.value ?? 0).toString(), - totalPriceLabel: 'Total' - }; + private updateTransactionInfo(cart: Cart): google.payments.api.PaymentDataRequestUpdate { + return { + newTransactionInfo: { + countryCode: 'US', + currencyCode: cart.totalPriceWithTax?.currencyIso ?? '', + totalPriceStatus: 'FINAL', + totalPrice: (cart.totalPriceWithTax?.value ?? 0).toString(), + totalPriceLabel: 'Total' + } + } } private handleOnSubmit(state: any, actions: any) { From a3872dafc2abc7fc60fbc1082be9a87204ce55f4 Mon Sep 17 00:00:00 2001 From: PJaneta Date: Tue, 25 Feb 2025 15:08:41 +0100 Subject: [PATCH 17/19] AD-375 Select delivery method during Apple Express Pay - add checkout success event --- .../src/events/checkout-adyen.events.ts | 6 ++++++ .../apple-express-payment.component.ts | 5 +++-- .../src/express/base/express-payment-base.ts | 13 ++++++++++--- .../google-express-payment.component.ts | 5 +++-- .../src/service/adyen-express-order.service.ts | 4 ++++ 5 files changed, 26 insertions(+), 7 deletions(-) diff --git a/projects/adyen/adyen-spartacus/src/events/checkout-adyen.events.ts b/projects/adyen/adyen-spartacus/src/events/checkout-adyen.events.ts index 18048ec..2cde162 100644 --- a/projects/adyen/adyen-spartacus/src/events/checkout-adyen.events.ts +++ b/projects/adyen/adyen-spartacus/src/events/checkout-adyen.events.ts @@ -9,4 +9,10 @@ export class CheckoutAdyenConfigurationReloadEvent extends CheckoutAdyenConfigur } } +export class ExpressCheckoutSuccessfulEvent extends CheckoutEvent { + readonly type = 'ExpressCheckoutSuccessfulEvent'; + constructor() { + super(); + } +} diff --git a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts index 60cead3..0103da5 100644 --- a/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/apple-express-payment/apple-express-payment.component.ts @@ -4,7 +4,7 @@ import {ApplePay, SubmitData, UIElement} from "@adyen/adyen-web"; import {AdyenCheckout, AdyenCheckoutError} from '@adyen/adyen-web/auto'; import {AdyenExpressConfigData} from "../../core/models/occ.config.models"; import {AdyenExpressOrderService} from "../../service/adyen-express-order.service"; -import {Product, RoutingService, UserIdService,} from '@spartacus/core'; +import {EventService, Product, RoutingService, UserIdService,} from '@spartacus/core'; import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; import {ExpressPaymentBase} from "../base/express-payment-base"; @@ -36,8 +36,9 @@ export class AppleExpressPaymentComponent extends ExpressPaymentBase implements protected override multiCartService: MultiCartFacade, protected override userIdService: UserIdService, protected override adyenCartService: AdyenCartService, + protected override eventService: EventService ) { - super(multiCartService, userIdService, activeCartFacade, adyenCartService) + super(multiCartService, userIdService, activeCartFacade, adyenCartService, eventService) } ngOnInit(): void { diff --git a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts index ec00134..e1b4ac2 100644 --- a/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts +++ b/projects/adyen/adyen-spartacus/src/express/base/express-payment-base.ts @@ -1,9 +1,10 @@ import {Injectable, OnDestroy} from "@angular/core"; -import {Address, Product, UserIdService} from '@spartacus/core'; +import {Address, EventService, Product, UserIdService} from '@spartacus/core'; import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; import {firstValueFrom, Observable, of, Subject, Subscription} from 'rxjs'; import {catchError, filter, map, switchMap, take, takeUntil, tap} from 'rxjs/operators'; import {AdyenCartService} from "../../service/adyen-cart-service"; +import {ExpressCheckoutSuccessfulEvent} from "../../events/checkout-adyen.events"; @Injectable() @@ -12,8 +13,14 @@ export class ExpressPaymentBase implements OnDestroy { constructor(protected multiCartService: MultiCartFacade, protected userIdService: UserIdService, protected activeCartService: ActiveCartFacade, - protected adyenCartService: AdyenCartService) { - + protected adyenCartService: AdyenCartService, + protected eventService: EventService) { + this.subscriptions.add(this.eventService.get(ExpressCheckoutSuccessfulEvent).subscribe(event => { + if (this.cartId) { + multiCartService.removeCart(this.cartId); + } + this.cartId = undefined; + })); } private unsubscribe$ = new Subject(); diff --git a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts index 6600e8e..f5427c4 100644 --- a/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts +++ b/projects/adyen/adyen-spartacus/src/express/google-express-payment/google-express-payment.component.ts @@ -5,7 +5,7 @@ import {UIElement} from "@adyen/adyen-web"; import {AdyenCheckout, AdyenCheckoutError, GooglePay} from '@adyen/adyen-web/auto'; import {AdyenExpressConfigData} from "../../core/models/occ.config.models"; import {AdyenExpressOrderService} from "../../service/adyen-express-order.service"; -import {Product, RoutingService, UserIdService} from '@spartacus/core'; +import {EventService, Product, RoutingService, UserIdService} from '@spartacus/core'; import {ActiveCartFacade, Cart, DeliveryMode, MultiCartFacade} from '@spartacus/cart/base/root'; import {getAdyenExpressCheckoutConfig} from "../adyenCheckoutConfig.util"; import {AdyenCartService} from "../../service/adyen-cart-service"; @@ -37,8 +37,9 @@ export class GoogleExpressPaymentComponent extends ExpressPaymentBase implements protected override multiCartService: MultiCartFacade, protected override userIdService: UserIdService, protected override adyenCartService: AdyenCartService, + protected override eventService: EventService ) { - super(multiCartService, userIdService, activeCartService, adyenCartService) + super(multiCartService, userIdService, activeCartService, adyenCartService, eventService) } ngOnInit(): void { diff --git a/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts b/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts index f4c9168..c145cdd 100644 --- a/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts +++ b/projects/adyen/adyen-spartacus/src/service/adyen-express-order.service.ts @@ -20,6 +20,7 @@ import {HttpErrorResponse} from "@angular/common/http"; import {AdyenOrderService} from "./adyen-order.service"; import {AdditionalDetailsConnector} from "../core/connectors/additional-details.connector"; import {PaymentData} from "@adyen/adyen-web"; +import {CheckoutAdyenConfigurationReloadEvent, ExpressCheckoutSuccessfulEvent} from "../events/checkout-adyen.events"; type ExpressPaymentDataRequest = GooglePayExpressRequest | ApplePayExpressRequest; @@ -68,6 +69,9 @@ export class AdyenExpressOrderService extends AdyenOrderService { OrderPlacedEvent ); } + this.eventService.dispatch( + new ExpressCheckoutSuccessfulEvent() + ); }), map((response) => ({ ...response, success: true })), catchError((error: HttpErrorResponse) => this.handlePlaceOrderError(error)) From 762806d00b7992b7dedd2be73e283e01182e0878 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Tue, 25 Feb 2025 15:09:14 +0100 Subject: [PATCH 18/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index b391dc8..a73c519 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375g", + "version": "1.1.2-AD-375h", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0", From 35801e15b47162b2d8aa4dd75c2172d6fda0f738 Mon Sep 17 00:00:00 2001 From: pjaneta <135803491+pjaneta@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:32:25 +0100 Subject: [PATCH 19/19] Update package.json --- projects/adyen/adyen-spartacus/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/adyen/adyen-spartacus/package.json b/projects/adyen/adyen-spartacus/package.json index a73c519..c9606b8 100644 --- a/projects/adyen/adyen-spartacus/package.json +++ b/projects/adyen/adyen-spartacus/package.json @@ -1,6 +1,6 @@ { "name": "@adyen/adyen-spartacus", - "version": "1.1.2-AD-375h", + "version": "1.1.4", "schematics": "./schematics/collection.json", "peerDependencies": { "@angular/common": "^17.3.0",