Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,8 @@ export default function createPaymentStrategyRegistry(
orderActionCreator,
paymentActionCreator,
storeCreditActionCreator,
new DigitalRiverScriptLoader(scriptLoader, getStylesheetLoader())
new DigitalRiverScriptLoader(scriptLoader, getStylesheetLoader()),
billingAddressActionCreator
)
);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { createClient as createPaymentClient } from '@bigcommerce/bigpay-client';
import { createAction, createErrorAction, Action } from '@bigcommerce/data-store';
import { createRequestSender } from '@bigcommerce/request-sender';
import { createRequestSender, RequestSender } from '@bigcommerce/request-sender';
import { createScriptLoader, createStylesheetLoader } from '@bigcommerce/script-loader';
import { merge } from 'lodash';
import { of, Observable } from 'rxjs';
Expand Down Expand Up @@ -31,6 +31,8 @@ import { AuthenticationSourceStatus, OnCancelOrErrorResponse, OnSuccessResponse
import DigitalRiverError from './digitalriver-error';
import DigitalRiverPaymentStrategy from './digitalriver-payment-strategy';
import DigitalRiverScriptLoader from './digitalriver-script-loader';
import { BillingAddressActionCreator, BillingAddressActionType, BillingAddressRequestSender } from '../../../billing';
import { SubscriptionsActionCreator, SubscriptionsRequestSender } from "../../../subscription";

describe('DigitalRiverPaymentStrategy', () => {
let paymentMethodActionCreator: PaymentMethodActionCreator;
Expand All @@ -48,12 +50,18 @@ describe('DigitalRiverPaymentStrategy', () => {
let submitPaymentAction: Observable<SubmitPaymentAction>;
let storeCreditActionCreator: StoreCreditActionCreator;
let applyStoreCreditAction: Observable<Action>;
let billingAddressActionCreator: BillingAddressActionCreator;
let requestSender: RequestSender;
let billingAddressRequestSender: BillingAddressRequestSender;
let updateAddressAction: Observable<Action>;

beforeEach(() => {
const scriptLoader = createScriptLoader();
const stylesheetLoader = createStylesheetLoader();
submitOrderAction = of(createAction(OrderActionType.SubmitOrderRequested));
submitPaymentAction = of(createAction(PaymentActionType.SubmitPaymentRequested));
requestSender = createRequestSender();
billingAddressRequestSender = new BillingAddressRequestSender(requestSender);
paymentActionCreator = new PaymentActionCreator(
new PaymentRequestSender(createPaymentClient()),
orderActionCreator,
Expand All @@ -72,6 +80,10 @@ describe('DigitalRiverPaymentStrategy', () => {
storeCreditActionCreator = new StoreCreditActionCreator(
new StoreCreditRequestSender(createRequestSender())
);
billingAddressActionCreator = new BillingAddressActionCreator(
billingAddressRequestSender,
new SubscriptionsActionCreator(new SubscriptionsRequestSender(requestSender))
);

paymentMethodMock = {...getDigitalRiverPaymentMethodMock(), clientToken: JSON.stringify(getClientMock())};
digitalRiverScriptLoader = new DigitalRiverScriptLoader(scriptLoader, stylesheetLoader);
Expand All @@ -81,6 +93,8 @@ describe('DigitalRiverPaymentStrategy', () => {
loadPaymentMethodAction = of(createAction(PaymentMethodActionType.LoadPaymentMethodSucceeded, paymentMethodMock, {methodId: paymentMethodMock.id}));
paymentMethodActionCreator = {} as PaymentMethodActionCreator;
paymentMethodActionCreator.loadPaymentMethod = jest.fn(() => loadPaymentMethodAction);
updateAddressAction = of(createAction(BillingAddressActionType.UpdateBillingAddressRequested));

jest.spyOn(store, 'dispatch');

jest.spyOn(store.getState().checkout, 'getCheckoutOrThrow')
Expand All @@ -94,9 +108,13 @@ describe('DigitalRiverPaymentStrategy', () => {

jest.spyOn(storeCreditActionCreator, 'applyStoreCredit')
.mockReturnValue(applyStoreCreditAction);

jest.spyOn(store.getState().paymentMethods, 'getPaymentMethodOrThrow')
.mockReturnValue(paymentMethodMock);

jest.spyOn(billingAddressActionCreator, 'updateAddress')
.mockReturnValue(updateAddressAction);

orderActionCreator = new OrderActionCreator(
new OrderRequestSender(createRequestSender()),
new CheckoutValidator(new CheckoutRequestSender(createRequestSender()))
Expand All @@ -108,7 +126,8 @@ describe('DigitalRiverPaymentStrategy', () => {
orderActionCreator,
paymentActionCreator,
storeCreditActionCreator,
digitalRiverScriptLoader
digitalRiverScriptLoader,
billingAddressActionCreator
);

});
Expand Down Expand Up @@ -398,6 +417,79 @@ describe('DigitalRiverPaymentStrategy', () => {
);
});

it('creates the order and should update the billing address', async () => {
const payPalOptions = {
...payload,
payment: {
...payload.payment,
methodId: 'paypal'
}
}

const owner = {
address: {
city: "Minnetonka",
country: "US",
line1: "10380 Bren Road W",
postalCode: "55343",
state: "MN"
},
email: "[email protected]",
firstName: "John",
lastName: "Doe",
phoneNumber: "000-000-0000"
};

jest.spyOn(digitalRiverLoadResponse, 'createDropin').mockImplementation(configuration => {
onSuccessCallback = configuration.onSuccess;

return digitalRiverComponent;
});

await strategy.initialize(options);
onSuccessCallback({
source: {
id: '1',
reusable: false,
owner: owner,
},
readyForStorage: true,
});

expect(digitalRiverLoadResponse.createDropin).toBeCalled();
expect(store.dispatch).toHaveBeenCalledWith(updateAddressAction);
expect(await strategy.execute(payPalOptions)).toEqual(store.getState());
expect(orderActionCreator.submitOrder).toHaveBeenCalled();
expect(paymentMethodActionCreator.loadPaymentMethod).toHaveBeenCalled();
expect(storeCreditActionCreator.applyStoreCredit).toHaveBeenCalledWith(false);
expect(await paymentActionCreator.submitPayment).toHaveBeenCalledWith(
{
methodId: 'paypal',
paymentData: {
formattedPayload: {
credit_card_token: {
token: JSON.stringify({
checkoutId: '12345676543',
source: {
source: {
id: '1',
reusable: false,
owner: owner,
},
readyForStorage: true,
},
sessionId: '1234',
}),
},
set_as_default_stored_instrument: false,
vault_payment_instrument: true,
},
},
}
);
});


it('executes the strategy successfully and applies the store credit', async () => {
jest.spyOn(digitalRiverLoadResponse, 'createDropin').mockImplementation(({onSuccess}) => {
onSuccessCallback = onSuccess;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { OrderFinalizationNotRequiredError } from '../../../order/errors';
import { StoreCreditActionCreator } from '../../../store-credit';
import { PaymentArgumentInvalidError } from '../../errors';
import { isVaultedInstrument, HostedInstrument } from '../../index';
import { BillingAddressActionCreator } from '../../../billing';
import PaymentActionCreator from '../../payment-action-creator';
import PaymentMethodActionCreator from '../../payment-method-action-creator';
import { PaymentInitializeOptions, PaymentRequestOptions } from '../../payment-request-options';
Expand All @@ -32,7 +33,8 @@ export default class DigitalRiverPaymentStrategy implements PaymentStrategy {
private _orderActionCreator: OrderActionCreator,
private _paymentActionCreator: PaymentActionCreator,
private _storeCreditActionCreator: StoreCreditActionCreator,
private _digitalRiverScriptLoader: DigitalRiverScriptLoader
private _digitalRiverScriptLoader: DigitalRiverScriptLoader,
private _billingAddressActionCreator: BillingAddressActionCreator
) {}

async initialize(options: PaymentInitializeOptions): Promise<InternalCheckoutSelectors> {
Expand Down Expand Up @@ -164,33 +166,51 @@ export default class DigitalRiverPaymentStrategy implements PaymentStrategy {
return errors.map(e => 'code: ' + e.code + ' message: ' + e.message).join('\n');
}

private _onSuccessResponse(data?: OnSuccessResponse): Promise<void> {
private async _onSuccessResponse(data?: OnSuccessResponse): Promise<void> {
const error = new InvalidArgumentError('Unable to initialize payment because success argument is not provided.');

return new Promise((resolve, reject) => {
if (data && this._submitFormEvent) {
const { browserInfo } = data.source;
this._loadSuccessResponse = browserInfo ? {
source: {
id: data.source.id,
reusable: data.source.reusable,
...browserInfo,
},
readyForStorage: data.readyForStorage,
} : {
source: {
id: data.source.id,
reusable: data.source.reusable,
},
readyForStorage: data.readyForStorage,
if (data && this._submitFormEvent) {
const { browserInfo, owner } = data.source;

this._loadSuccessResponse = browserInfo ? {
source: {
id: data.source.id,
reusable: data.source.reusable,
...browserInfo,
},
readyForStorage: data.readyForStorage,
} : {
source: {
id: data.source.id,
reusable: data.source.reusable,
},
readyForStorage: data.readyForStorage,
};

if (owner) {
const billingAddressPayPal = {
firstName: owner.firstName,
lastName: owner.lastName,
city: owner.address.city,
company: '',
address1: owner.address.line1,
address2: '',
postalCode: owner.address.postalCode,
countryCode: owner.address.country,
phone: owner.phoneNumber,
stateOrProvince: owner.address.state,
stateOrProvinceCode: owner.address.country,
customFields: [],
email: owner.email || owner.email,
};
resolve();
this._submitFormEvent();
} else {
reject(error);
this._getDigitalRiverInitializeOptions().onError?.(error);
this._loadSuccessResponse.source.owner = data.source.owner;
await this._store.dispatch(this._billingAddressActionCreator.updateAddress(billingAddressPayPal))
}
});

return this._submitFormEvent();
} else {
return this._getDigitalRiverInitializeOptions().onError?.(error);
}
}

private _onReadyResponse(data?: OnReadyResponse): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,20 @@ export interface OnSuccessResponse {
browserInfo?: {
browserIp?: string;
};
};
owner?: {
email: string;
firstName: string;
lastName: string;
phoneNumber: string;
address: {
city: string;
country: string;
line1: string;
postalCode: string;
state: string;
}
}
}

/**
* Indicates whether the source has been enabled for future use.
Expand Down