Skip to content

Commit

Permalink
Apple pay integration
Browse files Browse the repository at this point in the history
  • Loading branch information
Petrisor Frincu committed Aug 13, 2024
1 parent 75800e2 commit 87c1d64
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 1 deletion.
87 changes: 87 additions & 0 deletions apps/web/components/PayPal/ApplePayButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<template>
<div class="apple-pay-button"></div>
</template>

<script lang="ts" setup>
import { ApplepayType } from '~/components/PayPal/types';
const { loadScript } = usePayPal();
// const loadApplePay = async () => {
// const scriptElement = document.createElement('script');
// scriptElement.setAttribute('src', 'https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js');
// scriptElement.setAttribute('type', 'text/javascript');
// document.head.append(scriptElement);
// };
const canMakePayments = ref(false);
const initiateApplePay = async () => {
try {
const paypal = await loadScript('EUR');
if (!paypal) {
console.error('Paypal sdk failed');
return;
}
const applePay = (paypal as any).Applepay() as ApplepayType;
const paymentRequest = applePay.paymentRequest({
countryCode: 'DE',
currencyCode: 'EUR',
total: {
label: 'Store',
amount: 100,
},
});
const paymentSession = applePay.createPaymentSession(paymentRequest);
paymentSession.begin();
paymentSession.onvalidatemerchant = async (event: any) => {
try {
const validationData = await applePay.validateMerchant({
validationUrl: event.validationUrl,
});
paymentSession.completeMerchantValidation(validationData);
} catch (error) {
console.error('Merchant validation failed:', error);
paymentSession.abort();
}
};
paymentSession.onpaymentauthorized = async (event: any) => {
try {
const authorization = event.payment;
const paymentResult = await applePay.tokenizePayment(authorization);
if (paymentResult.error) {
throw new Error(paymentResult.error.message);
}
// await props.onPaymentSuccess(paymentResult);
// paymentSession.completePayment(ApplePaySession.STATUS_SUCCESS);
} catch (error) {
console.error('Payment authorization failed:', error);
// props.onPaymentError(error);
// paymentSession.completePayment(ApplePaySession.STATUS_FAILURE);
}
};
paymentSession.addEventListener('cancel', () => {
console.error('Apple pay cancel');
});
} catch (error) {
console.error('Apple pay initiation failed:', error);
}
};
if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
canMakePayments.value = true;
}
onMounted(() => {
initiateApplePay();
});
</script>
1 change: 1 addition & 0 deletions apps/web/components/PayPal/PayPalExpressButton.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<div v-if="paypalUuid" ref="paypalButton" :id="'paypal-' + paypalUuid" class="z-0 relative paypal-button" />
<PayPalApplePayButton />
</template>

<script setup lang="ts">
Expand Down
122 changes: 122 additions & 0 deletions apps/web/components/PayPal/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,125 @@ export type PaypalButtonPropsType = {
};

export type PayPalAddToCartCallback = (successfully: boolean) => void;

export type OrderPayload = {
intent: string;
purchase_units: {
amount: { currency_code: string; value: string };
payee: { merchant_id: string };
}[];
};

export type PayPalApplePayErrorType = {
name: string;
message: string;
paypalDebugId: null | string;
};

export type ConfigResponse = {
isEligible: boolean;
countryCode: string;
merchantCountry: string;
currencyCode: string;
merchantCapabilities: string[];
supportedNetworks: string[];
};

export type GQLConfigResponse = {
isEligible: boolean;
merchantCountry: string;
merchantCapabilities: string[];
supportedNetworks: string[];
};

export type ApplePaySession = {
displayName: string;
domainName: string;
epochTimestamp: number;
expiresAt: number;
merchantIdentifier: string;
merchantSessionIdentifier: string;
nonce: string;
operationalAnalyticsIdentifier: string;
pspId: string;
retries: number;
signature: string;
};

export type ApplePayPaymentContact = {
phoneNumber?: string;
emailAddress?: string;
givenName?: string;
familyName?: string;
phoneticGivenName?: string;
phoneticFamilyName?: string;
addressLines?: string[];
subLocality?: string;
locality?: string;
postalCode?: string;
subAdministrativeArea?: string;
administrativeArea?: string;
country?: string;
countryCode?: string;
};

export type ApplePayPaymentMethodType = 'debit' | 'credit' | 'prepaid' | 'store';

export type ApplePayPaymentPassActivationState =
| 'activated'
| 'requiresActivation'
| 'activating'
| 'suspended'
| 'deactivated';

export type ApplePayPaymentPass = {
primaryAccountIdentifier: string;
primaryAccountNumberSuffix: string;
deviceAccountIdentifier?: string;
deviceAccountNumberSuffic?: string;
activationState: ApplePayPaymentPassActivationState;
};

// https://developer.apple.com/documentation/apple_pay_on_the_web/applepaypaymentmethod
export type ApplePayPaymentMethod = {
displayName?: string;
network?: string;
type?: ApplePayPaymentMethodType;
paymentPass?: ApplePayPaymentPass;
billingContact?: ApplePayPaymentContact;
};

export type ApplePayPaymentToken = {
paymentMethod: ApplePayPaymentMethod;
transactionIdentifier?: string;
paymentData?: object;
};

export type ApplePayPayment = {
token: ApplePayPaymentToken;
billingContact?: ApplePayPaymentContact;
shippingContact?: ApplePayPaymentContact;
};

export type ConfirmOrderParams = {
orderId: string;
token: ApplePayPaymentToken;
billingContact?: ApplePayPaymentContact;
shippingContact?: ApplePayPaymentContact;
};

export type ValidateMerchantParams = {
validationUrl: string;
displayName?: string;
};

export type ValidateMerchantResponse = {
merchantSession: ApplePaySession;
paypalDebugId: null | string;
};

export type ApplepayType = {
config(): Promise<ConfigResponse>;
validateMerchant(argument0: ValidateMerchantParams): Promise<ValidateMerchantResponse>;
confirmOrder(argument0: ConfirmOrderParams): Promise<void>;
};
3 changes: 2 additions & 1 deletion apps/web/composables/usePayPal/usePayPal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ export const usePayPal: UsePayPalMethodsReturn = () => {
dataClientToken: paypalGetters.getClientToken(state.value.config),
currency: currency,
dataPartnerAttributionId: 'Plenty_Cart_PWA_PPCP',
components: 'messages,buttons,funding-eligibility,hosted-fields,payment-fields,marks&enable-funding=paylater',
components:
'applepay,messages,buttons,funding-eligibility,hosted-fields,payment-fields,marks&enable-funding=paylater',
locale: localePayPal,
commit: commit,
});
Expand Down
1 change: 1 addition & 0 deletions apps/web/configuration/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ export const appConfiguration = {
{ rel: 'icon', href: '/favicon.ico' },
{ rel: 'apple-touch-icon', href: '/favicon.ico' },
],
script: [{ src: 'https://applepay.cdn-apple.com/jsapi/v1/apple-pay-sdk.js' }],
},
};

0 comments on commit 87c1d64

Please sign in to comment.