Skip to content

Commit

Permalink
Release 6.0.3.
Browse files Browse the repository at this point in the history
  • Loading branch information
WorldlineConnect committed Aug 30, 2024
1 parent 2551804 commit 07412f0
Show file tree
Hide file tree
Showing 11 changed files with 327 additions and 201 deletions.
397 changes: 231 additions & 166 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "connect-sdk-client-js",
"version": "6.0.2",
"version": "6.0.3",
"description": "The JavaScript based client SDK that can be used for client to server communication between you and the Worldline Global Collect platform",
"source": "./src/index.ts",
"module": "./dist/connect-sdk-client-js.js",
Expand Down Expand Up @@ -53,7 +53,7 @@
"eslint-config-prettier": "^9.0.0",
"happy-dom": "^10.9.0",
"husky": "^8.0.0",
"lint-staged": "^14.0.1",
"lint-staged": "^15.2.9",
"microbundle": "^0.15.1",
"node-forge": "^1.3.1",
"prettier": "^3.0.1",
Expand Down
100 changes: 69 additions & 31 deletions src/ApplePay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {

import { PaymentProductId } from './constants';
import * as utils from './utils';
import { ApplePayError, ApplePayErrorStatus, ResponseError } from './error';

// This interface is used to break the circular import dependency between ApplePay and C2SCommunicator.
// C2SCommunicator automatically implements it.
Expand All @@ -18,18 +19,31 @@ interface ApplePayC2SCommunicator {
): Promise<CreatePaymentProductSessionResponseJSON>;
}

export class ApplePay {
isApplePayAvailable(): boolean {
const isAvailable =
/**
* Return `true` if Apple Pay can make payments in the browser
* Ignore errors being thrown by `ApplePaySession.canMakePayments()`
*/
function canMakePayments(): boolean {
try {
return (
Object.hasOwn(window, 'ApplePaySession') &&
ApplePaySession.canMakePayments();
ApplePaySession.canMakePayments()
);
} catch (err) {
return false;
}
}

export class ApplePay {
private _isCancelled: boolean = false;

isApplePayAvailable(): boolean {
const isAvailable = canMakePayments();
if (!isAvailable) {
utils.client.unsupportedPaymentProductsInBrowser.add(
PaymentProductId.APPLE_PAY,
);
}

return isAvailable;
}

Expand All @@ -38,6 +52,7 @@ export class ApplePay {
c2SCommunicator: ApplePayC2SCommunicator,
): Promise<ApplePayInitResult> {
return new Promise<ApplePayInitResult>((resolve, reject) => {
this._isCancelled = false;
const countryCode = context.acquirerCountry
? context.acquirerCountry
: context.countryCode;
Expand All @@ -56,33 +71,51 @@ export class ApplePay {
const applePaySession = new ApplePaySession(1, payment);
applePaySession.begin();

const onError = (error: unknown) => {
reject(error);
applePaySession.abort();
applePaySession.oncancel = () => {
this._isCancelled = true;
reject(
new ApplePayError('Payment cancelled', ApplePayErrorStatus.Cancelled),
);
};

applePaySession.onvalidatemerchant = (event) => {
const sessionContext = {
displayName: context.displayName,
validationUrl: event.validationURL,
domainName: window.location.hostname,
};
c2SCommunicator
.createPaymentProductSession(
PaymentProductId.APPLE_PAY,
sessionContext,
)
.then(({ paymentProductSession302SpecificOutput }) => {
try {
const merchantSession = JSON.parse(
paymentProductSession302SpecificOutput?.sessionObject as string,
);
applePaySession.completeMerchantValidation(merchantSession);
} catch (e) {
onError(e);
}
})
.catch(onError);
applePaySession.onvalidatemerchant = async (event) => {
try {
const sessionContext = {
displayName: context.displayName,
validationUrl: event.validationURL,
domainName: window.location.hostname,
};

const { paymentProductSession302SpecificOutput } =
await c2SCommunicator.createPaymentProductSession(
PaymentProductId.APPLE_PAY,
sessionContext,
);

const merchantSession = JSON.parse(
paymentProductSession302SpecificOutput?.sessionObject as string,
);

applePaySession.completeMerchantValidation(merchantSession);
} catch (error) {
// Prevent throwing an error when the session is cancelled (`oncancel` event).
// The error is already thrown and the `applePaySession.abort()` is
// called internally by Apple Pay JS API.
if (this._isCancelled) return;

applePaySession.abort();

if (error instanceof ResponseError) return reject(error);
if (error instanceof Error) {
return reject(
new ApplePayError(
error.message,
ApplePayErrorStatus.ValidateMerchant,
),
);
}
reject(error);
}
};

applePaySession.onpaymentauthorized = (event) => {
Expand All @@ -98,7 +131,12 @@ export class ApplePay {
resolve({ message: 'Payment authorized', data: token });
break;
case ApplePaySession.STATUS_FAILURE:
reject(new Error('Error payment authorization'));
reject(
new ApplePayError(
'Error payment authorization',
ApplePayErrorStatus.PaymentAuthorized,
),
);
break;
}
};
Expand Down
4 changes: 2 additions & 2 deletions src/Session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,12 +298,12 @@ export class Session {
*/
async createApplePayPayment(
context: PaymentDetails,
paymentProductSpecificInput: ApplePaySpecificInput,
applePaySpecificInput: ApplePaySpecificInput,
networks: string[],
): Promise<ApplePayInitResult> {
return this._c2sCommunicator.initApplePayPayment(
context,
paymentProductSpecificInput,
applePaySpecificInput,
networks,
);
}
Expand Down
17 changes: 17 additions & 0 deletions src/error/ApplePayError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const ApplePayErrorStatus = {
Cancelled: 'cancelled',
ValidateMerchant: 'validateMerchant',
PaymentAuthorized: 'paymentAuthorized',
} as const;
export type ApplePayErrorStatus =
(typeof ApplePayErrorStatus)[keyof typeof ApplePayErrorStatus];

export class ApplePayError extends Error {
constructor(
readonly message: string,
readonly status: ApplePayErrorStatus,
) {
super(message);
Error.captureStackTrace(this, ApplePayError);
}
}
1 change: 1 addition & 0 deletions src/error/EncryptError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export class EncryptError extends Error {
readonly validationErrors: ValidationError[] = [],
) {
super(message);
Error.captureStackTrace(this, EncryptError);
}
}
1 change: 1 addition & 0 deletions src/error/IinDetailsResponseError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ export class IinDetailsResponseError extends Error {
readonly json?: GetIINDetailsResponseJSON,
) {
super(status);
Error.captureStackTrace(this, IinDetailsResponseError);
}
}
1 change: 1 addition & 0 deletions src/error/PaymentProductError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ export class PaymentProductError extends Error {
readonly json: PaymentProductJSON,
) {
super(message);
Error.captureStackTrace(this, PaymentProductError);
}
}
1 change: 1 addition & 0 deletions src/error/ResponseError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ export class ResponseError<Response extends SdkResponse> extends Error {
this.status = response.status;
this.success = response.success;
this.data = response.data;
Error.captureStackTrace(this, ResponseError);
}
}
1 change: 1 addition & 0 deletions src/error/ResponseJsonError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@ export class ResponseJsonError extends Error {
super(message);
this.errorId = errorId;
this.errors = errors;
Error.captureStackTrace(this, ResponseJsonError);
}
}
1 change: 1 addition & 0 deletions src/error/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './ApplePayError';
export * from './IinDetailsResponseError';
export * from './ResponseError';
export * from './EncryptError';
Expand Down

0 comments on commit 07412f0

Please sign in to comment.