Skip to content

Commit

Permalink
feat: support Concardis Direct Debit payment method (#165)
Browse files Browse the repository at this point in the history
- requires CONCARDIS 1.7.2 release and an ICM release 7.10.16.6+
  • Loading branch information
skoch-intershop authored and shauke committed Mar 31, 2020
1 parent 41d9d2e commit a3b3e74
Show file tree
Hide file tree
Showing 17 changed files with 824 additions and 217 deletions.
28 changes: 26 additions & 2 deletions src/app/core/models/payment-method/payment-method.mapper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export class PaymentMethodMapper {
if (!body.data.length) {
return [];
}

return body.data
.filter(data => PaymentMethodMapper.isPaymentMethodValid(data))
.map(data => ({
Expand All @@ -41,7 +40,10 @@ export class PaymentMethodMapper {
? data.paymentInstruments.map(id => included.paymentInstruments[id])
: undefined,
parameters: data.parameterDefinitions ? PaymentMethodMapper.mapParameter(data.parameterDefinitions) : undefined,
hostedPaymentPageParameters: data.hostedPaymentPageParameters,
hostedPaymentPageParameters:
data.id === 'Concardis_DirectDebit'
? PaymentMethodMapper.mapSEPAMandateInformation(data.hostedPaymentPageParameters)
: data.hostedPaymentPageParameters,
}));
}

Expand Down Expand Up @@ -190,4 +192,26 @@ export class PaymentMethodMapper {
return param;
});
}

/**
* convenience method to restructure concardis sepa mandate hosted payment page parameter
*/
private static mapSEPAMandateInformation(
hostedPaymentPageParameters: { name: string; value: string }[]
): { name: string; value: string }[] {
const mandateEntry = hostedPaymentPageParameters.find(hppp => hppp.name === 'Concardis_SEPA_Mandate');

if (typeof mandateEntry.value !== 'string') {
const sepaMandateArray = mandateEntry.value as {
mandateId: string;
mandateText: string;
directDebitType: string;
};
hostedPaymentPageParameters.push({ name: 'mandateId', value: sepaMandateArray.mandateId });
hostedPaymentPageParameters.push({ name: 'mandateText', value: sepaMandateArray.mandateText });
hostedPaymentPageParameters.push({ name: 'directDebitType', value: sepaMandateArray.directDebitType });
}

return hostedPaymentPageParameters;
}
}
10 changes: 9 additions & 1 deletion src/app/pages/checkout-payment/checkout-payment-page.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,18 @@ import { SharedModule } from 'ish-shared/shared.module';
import { CheckoutPaymentPageComponent } from './checkout-payment-page.component';
import { CheckoutPaymentComponent } from './checkout-payment/checkout-payment.component';
import { PaymentConcardisCreditcardComponent } from './payment-concardis-creditcard/payment-concardis-creditcard.component';
import { PaymentConcardisDirectdebitComponent } from './payment-concardis-directdebit/payment-concardis-directdebit.component';
import { PaymentConcardisComponent } from './payment-concardis/payment-concardis.component';

@NgModule({
imports: [SharedModule],
declarations: [CheckoutPaymentComponent, CheckoutPaymentPageComponent, PaymentConcardisCreditcardComponent],
declarations: [
CheckoutPaymentComponent,
CheckoutPaymentPageComponent,
PaymentConcardisComponent,
PaymentConcardisCreditcardComponent,
PaymentConcardisDirectdebitComponent,
],
})
export class CheckoutPaymentPageModule {
static component = CheckoutPaymentPageComponent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,39 +107,52 @@ <h3>{{ 'checkout.payment.method.select.heading' | translate }}</h3>
<p class="indicates-required">
<span class="required">*</span>{{ 'account.required_field.message' | translate }}
</p>
<ng-container *ngIf="paymentMethod.serviceId !== 'Concardis_CreditCard'; else ConcardisCreditCard">
<formly-form
[form]="parameterForm"
[options]="options"
[model]="model"
[fields]="paymentMethod.parameters"
>
<div class="offset-md-4 col-md-8">
<ng-container *ngIf="paymentMethod.saveAllowed">
<ng-container *ngTemplateOutlet="saveForLaterTemplate"></ng-container>
</ng-container>
<div class="form-group">
<button type="submit" class="btn btn-primary" [disabled]="submitDisabled">
{{ 'checkout.account.submit.button.label' | translate }}
</button>
<button type="button" class="btn btn-secondary" (click)="cancelNewPaymentInstrument()">
{{ 'checkout.cancel.button.label' | translate }}
</button>
<ng-container [ngSwitch]="paymentMethod.serviceId">
<ng-template [ngSwitchCase]="'Concardis_CreditCard'">
<ish-payment-concardis-creditcard
[paymentMethod]="paymentMethod"
[activated]="formIsOpen(i)"
(submit)="createNewPaymentInstrument($event)"
(cancel)="cancelNewPaymentInstrument()"
></ish-payment-concardis-creditcard>
</ng-template>

<ng-template [ngSwitchCase]="'Concardis_DirectDebit'">
<ish-payment-concardis-directdebit
[paymentMethod]="paymentMethod"
[activated]="formIsOpen(i)"
(submit)="createNewPaymentInstrument($event)"
(cancel)="cancelNewPaymentInstrument()"
></ish-payment-concardis-directdebit>
</ng-template>

<ng-template ngSwitchDefault>
<formly-form
[form]="parameterForm"
[options]="options"
[model]="model"
[fields]="paymentMethod.parameters"
>
<div class="offset-md-4 col-md-8">
<ng-container *ngIf="paymentMethod.saveAllowed">
<ng-container *ngTemplateOutlet="saveForLaterTemplate"></ng-container>
</ng-container>
<div class="form-group">
<button type="submit" class="btn btn-primary" [disabled]="submitDisabled">
{{ 'checkout.account.submit.button.label' | translate }}
</button>
<button type="button" class="btn btn-secondary" (click)="cancelNewPaymentInstrument()">
{{ 'checkout.cancel.button.label' | translate }}
</button>
</div>
</div>
</div>
</formly-form>
</formly-form>
</ng-template>
</ng-container>
<ng-template #ConcardisCreditCard>
<ish-payment-concardis-creditcard
[paymentMethod]="paymentMethod"
[activated]="formIsOpen(i)"
(submit)="createNewPaymentInstrument($event)"
(cancel)="cancelNewPaymentInstrument()"
></ish-payment-concardis-creditcard>
</ng-template>
</div>
</div></li
></ng-container>
</div>
</li>
</ng-container>
</ul>
<!-- saveForLater checkbox - outlet template -->
<ng-template #saveForLaterTemplate>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { ModalDialogLinkComponent } from 'ish-shared/components/common/modal-dia
import { CheckboxComponent } from 'ish-shared/forms/components/checkbox/checkbox.component';

import { PaymentConcardisCreditcardComponent } from '../payment-concardis-creditcard/payment-concardis-creditcard.component';
import { PaymentConcardisDirectdebitComponent } from '../payment-concardis-directdebit/payment-concardis-directdebit.component';

import { CheckoutPaymentComponent } from './checkout-payment.component';

Expand Down Expand Up @@ -51,6 +52,7 @@ describe('Checkout Payment Component', () => {
MockComponent(ModalDialogLinkComponent),
MockComponent(NgbCollapse),
MockComponent(PaymentConcardisCreditcardComponent),
MockComponent(PaymentConcardisDirectdebitComponent),
MockDirective(ServerHtmlDirective),
MockPipe(PricePipe),
],
Expand Down Expand Up @@ -152,33 +154,33 @@ describe('Checkout Payment Component', () => {

describe('next button', () => {
it('should set submitted if next button is clicked', () => {
expect(component.nextSubmitted).toBeFalse();
expect(component.nextSubmitted).toBeFalsy();
component.goToNextStep();
expect(component.nextSubmitted).toBeTrue();
expect(component.nextSubmitted).toBeTruthy();
});

it('should not disable next button if basket payment method is set and next button is clicked', () => {
expect(component.nextDisabled).toBeFalse();
expect(component.nextDisabled).toBeFalsy();
component.goToNextStep();
expect(component.nextDisabled).toBeFalse();
expect(component.nextDisabled).toBeFalsy();
});

it('should disable next button if basket payment method is missing and next button is clicked', () => {
component.basket.payment = undefined;

component.goToNextStep();
expect(component.nextDisabled).toBeTrue();
expect(component.nextDisabled).toBeTruthy();
});
});

describe('parameter forms', () => {
it('should open and close payment form if open/cancel form is triggered', () => {
expect(component.formIsOpen(-1)).toBeTrue();
expect(component.formIsOpen(-1)).toBeTruthy();
component.openPaymentParameterForm(2);
expect(component.formIsOpen(2)).toBeTrue();
expect(component.formIsOpen(2)).toBeTruthy();

component.cancelNewPaymentInstrument();
expect(component.formIsOpen(-1)).toBeTrue();
expect(component.formIsOpen(-1)).toBeTruthy();
});

it('should throw createPaymentInstrument event when the user submits a valid parameter form and saving is not allowed', done => {
Expand All @@ -190,7 +192,7 @@ describe('Checkout Payment Component', () => {
paymentMethod: 'Concardis_CreditCard',
parameters: [{ name: 'creditCardNumber', value: '123' }],
});
expect(formValue.saveForLater).toBeFalse();
expect(formValue.saveForLater).toBeFalsy();
done();
});

Expand All @@ -200,14 +202,14 @@ describe('Checkout Payment Component', () => {

it('should throw createUserPaymentInstrument event when the user submits a valid parameter form and saving is allowed', done => {
component.ngOnChanges(paymentMethodChange);
component.openPaymentParameterForm(2);
component.openPaymentParameterForm(3);

component.createPaymentInstrument.subscribe(formValue => {
expect(formValue.paymentInstrument).toEqual({
paymentMethod: 'ISH_CreditCard',
parameters: [{ name: 'creditCardNumber', value: '456' }],
});
expect(formValue.saveForLater).toBeTrue();
expect(formValue.saveForLater).toBeTruthy();
done();
});

Expand All @@ -219,10 +221,10 @@ describe('Checkout Payment Component', () => {
component.openPaymentParameterForm(1);
fixture.detectChanges();

expect(component.formSubmitted).toBeFalse();
expect(component.formSubmitted).toBeFalsy();
component.parameterForm.addControl('IBAN', new FormControl('', Validators.required));
component.submitParameterForm();
expect(component.formSubmitted).toBeTrue();
expect(component.formSubmitted).toBeTruthy();
});

it('should render standard parameter form for standard parametrized form', () => {
Expand Down
Loading

0 comments on commit a3b3e74

Please sign in to comment.