Skip to content

Commit

Permalink
Update initiate payment to take additional parameters
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesmcroft committed Sep 26, 2023
1 parent fe83d52 commit 1291ecc
Show file tree
Hide file tree
Showing 7 changed files with 98 additions and 11 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ The FuturePay (Worldpay) Form Integration Library for JavaScript is a library th
## Install

```sh
npm install futurepay-form-integration-for-js
npm install futurepay-form-integration-js
```

## Usage

### Initiating a recurring payment agreement

```js
import { FuturePayService, FuturePayType, CurrencyCode, DelayUnit, RegularAgreement, RegularAgreementOption } from 'futurepay-form-integration-for-js';
import { FuturePayService, FuturePayType, CurrencyCode, DelayUnit, RegularAgreement, RegularAgreementOption } from 'futurepay-form-integration-js';

var service = new FuturePayService();

Expand Down
6 changes: 5 additions & 1 deletion src/Agreement.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { CurrencyCode } from "./CurrencyCode";
import { FuturePayType } from "./FuturePayType";
import { AgreementMap } from "./AgreementMap";
import { TestMode } from "./TestMode";

export interface Agreement extends AgreementMap {
/**
Expand Down Expand Up @@ -33,5 +34,8 @@ export interface Agreement extends AgreementMap {
**/
desc: string;

testMode: number;
/**
* Determines whether to initiate the payment in test or live modes.
**/
testMode: TestMode;
}
29 changes: 26 additions & 3 deletions src/FuturePayService.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,28 @@
import { Agreement } from "./Agreement";
import { AgreementMap } from "./AgreementMap";

/**
* Defines a class used to initiate recurring payments in FuturePay.
*/
export class FuturePayService {
url: string;

/**
* Creates a new instance of the FuturePayService class.
* @param isTestEnvironment Indicates whether the service should use the test environment or the production environment.
*/
constructor(isTestEnvironment: boolean = false) {
this.url = isTestEnvironment ? "https://secure-test.worldpay.com/wcc/purchase" : "https://secure.worldpay.com/wcc/purchase";
}

initiateAgreement(agreement: Agreement, callbackUrl: string | null = null): Promise<void> {
/**
* Initiates a payment in FuturePay.
* @param agreement The agreement object to construct the form inputs used to initiate the payment in FuturePay.
* @param callbackUrl The optional callback URL to be used by FuturePay to notify the payment status.
* @param additionalProperties The optional additional properties to be used to construct the form inputs used to initiate the payment in FuturePay.
* @returns A promise that resolves to the HTML form inputs used to initiate the payment in FuturePay.
*/
initiateAgreement(agreement: Agreement, callbackUrl: string | null = null, additionalProperties: AgreementMap | null = null): Promise<string> {
var formInputsHtml = "";

for (var key in agreement) {
Expand All @@ -16,6 +31,14 @@ export class FuturePayService {
}
}

if (additionalProperties) {
for (var key in additionalProperties) {
if (additionalProperties.hasOwnProperty(key) && (key.startsWith("C_") || key.startsWith("M_") || key.startsWith("MC_") || key.startsWith("CM_"))) {
formInputsHtml += `<input type='hidden' name='${key}' value='${additionalProperties[key]}'></input>`;
}
}
}

if (callbackUrl) {
formInputsHtml += `<input type='hidden' name='MC_callback' value='${callbackUrl}'></input>`;
}
Expand All @@ -28,12 +51,12 @@ export class FuturePayService {
document.body.appendChild(form);

try {
form?.submit();
form.submit();
} catch (error) {
console.log(error);
}
}

return Promise.resolve();
return Promise.resolve(formInputsHtml);
}
}
4 changes: 4 additions & 0 deletions src/TestMode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum TestMode {
Test = 100,
Live = 0
}
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export * from './FuturePayType';
export * from './LimitedAgreement';
export * from './LimitedAgreementOption';
export * from './RegularAgreement';
export * from './RegularAgreementOption';
export * from './RegularAgreementOption';
export * from './TestMode';
61 changes: 57 additions & 4 deletions tests/FuturePayService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ describe("when initiating an agreement", () => {

var agreement = regularAgreement();

// Act & Assert
expect(async () => await futurePayService.initiateAgreement(agreement)).not.toThrow();
// Act
var formInputsHtml = await futurePayService.initiateAgreement(agreement);

// Assert
expect(formInputsHtml).not.toBeNull();
expect(formInputsHtml).not.toContain("MC_callback");
});

it("should generate limited agreement", async () => {
Expand All @@ -18,7 +22,56 @@ describe("when initiating an agreement", () => {

var agreement = limitedAgreement();

// Act & Assert
expect(async () => await futurePayService.initiateAgreement(agreement)).not.toThrow();
// Act
var formInputsHtml = await futurePayService.initiateAgreement(agreement);

// Assert
expect(formInputsHtml).not.toBeNull();
expect(formInputsHtml).not.toContain("MC_callback");
});

it("should include callback URL", async () => {
// Arrange
const futurePayService = new FuturePayService(true);

var agreement = regularAgreement();

// Act
var formInputsHtml = await futurePayService.initiateAgreement(agreement, "https://www.example.com");

// Assert
expect(formInputsHtml).not.toBeNull();
expect(formInputsHtml).toContain("MC_callback");
});

it("should include additional FuturePay properties", async () => {
// Arrange
const futurePayService = new FuturePayService(true);

var agreement = regularAgreement();

// Act
var formInputsHtml = await futurePayService.initiateAgreement(agreement, null, { C_test: "C", M_test: "M", MC_test: "MC", CM_test: "CM" });

// Assert
expect(formInputsHtml).not.toBeNull();
expect(formInputsHtml).toContain("C_test");
expect(formInputsHtml).toContain("M_test");
expect(formInputsHtml).toContain("MC_test");
expect(formInputsHtml).toContain("CM_test");
});

it("should ignore invalid additional properties", async () => {
// Arrange
const futurePayService = new FuturePayService(true);

var agreement = regularAgreement();

// Act
var formInputsHtml = await futurePayService.initiateAgreement(agreement, null, { VAR_test: "test" });

// Assert
expect(formInputsHtml).not.toBeNull();
expect(formInputsHtml).not.toContain("VAR_test");
});
});
2 changes: 2 additions & 0 deletions tests/fakers/AgreementFaker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const regularAgreement = (): RegularAgreement => {
option: RegularAgreementOption.Default,
cartId: faker.finance.accountNumber(),
desc: faker.lorem.sentence(),
testMode: 100,
} as RegularAgreement;
};

Expand All @@ -37,5 +38,6 @@ export const limitedAgreement = (): LimitedAgreement => {
currency: CurrencyCode.GBP,
cartId: faker.finance.accountNumber(),
desc: faker.lorem.sentence(),
testMode: 100,
} as LimitedAgreement;
}

0 comments on commit 1291ecc

Please sign in to comment.