Skip to content

Commit

Permalink
Merge pull request #2 from michielgerritsen/release
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
Marvin-Magmodules authored Feb 23, 2023
2 parents ae9edf3 + a71a5ab commit 094ee3a
Show file tree
Hide file tree
Showing 10 changed files with 235 additions and 4 deletions.
5 changes: 4 additions & 1 deletion renderers.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { applePayType } from './src/utility/config';
import DefaultRenderer from './src/components/DefaultRenderer';
import ApplePayRenderer from './src/components/ApplePayRenderer';
import CreditCardComponentsRenderer from './src/components/CreditCardComponentsRenderer';

export default {
mollie_methods_applepay: DefaultRenderer,
mollie_methods_applepay:
applePayType === 'direct' ? ApplePayRenderer : DefaultRenderer,
mollie_methods_bancontact: DefaultRenderer,
mollie_methods_banktransfer: DefaultRenderer,
mollie_methods_belfius: DefaultRenderer,
Expand Down
18 changes: 18 additions & 0 deletions src/api/applePayValidationRequest/applePayValidationRequest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import sendRequest from '../../../../../api/sendRequest';
import modifier from './modifier';
import { MOLLIE_APPLE_PAY_VALIDATION } from './mutation';

export default async function applePayValidationRequest(
appDispatch,
validationURL
) {
return modifier(
await sendRequest(appDispatch, {
query: MOLLIE_APPLE_PAY_VALIDATION,
variables: {
domain: window.location.hostname,
validationURL,
},
})
);
}
3 changes: 3 additions & 0 deletions src/api/applePayValidationRequest/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import applePayValidationRequest from './applePayValidationRequest';

export default applePayValidationRequest;
5 changes: 5 additions & 0 deletions src/api/applePayValidationRequest/modifier.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { get as _get } from 'lodash-es';

export default function applePayValidationRequestModifier(response) {
return _get(response, 'data.mollieApplePayValidation.response', {});
}
13 changes: 13 additions & 0 deletions src/api/applePayValidationRequest/mutation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const MOLLIE_APPLE_PAY_VALIDATION = `
mutation mollieApplePayValidation(
$domain: String!
$validationURL: String!
) {
mollieApplePayValidation(
domain: $domain
validationUrl: $validationURL
) {
response
}
}
`;
4 changes: 3 additions & 1 deletion src/api/setPaymentMethodOnCartRequest/mutation.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@ export const SET_PAYMENT_METHOD_ON_CART = `
$paymentCode: String!
$issuer: String,
$cardToken: String
$applePayToken: String
) {
setPaymentMethodOnCart(
input: {
cart_id: $cartId,
payment_method: {
code: $paymentCode
mollie_selected_issuer: $issuer,
mollie_card_token: $cardToken
mollie_card_token: $cardToken,
mollie_applepay_payment_token: $applePayToken
}
}
) {
Expand Down
76 changes: 76 additions & 0 deletions src/components/ApplePayRenderer.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useEffect, useCallback } from 'react';
import { shape, func } from 'prop-types';
import { paymentMethodShape } from '../../../../utils/payment';
import RadioInput from '../../../../components/common/Form/RadioInput';
import useCheckoutFormContext from '../../../../hook/useCheckoutFormContext';
import useApplePayToPlaceOrder from '../hooks/useApplePayToPlaceOrder';
import usePaymentMethodFormContext from '../../../../components/paymentMethod/hooks/usePaymentMethodFormContext';

function ApplePayRenderer({ method, selected, actions }) {
const isSelected = method.code === selected.code;

const { registerPaymentAction } = useCheckoutFormContext();
const { applePayPlaceOrder } = useApplePayToPlaceOrder();
const { submitHandler } = usePaymentMethodFormContext();
const submitHandlerCallback = useCallback(submitHandler, [submitHandler]);

useEffect(() => {
if (!isSelected) {
return;
}

registerPaymentAction(method.code, applePayPlaceOrder);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isSelected, method.code]);

useEffect(() => {
if (!isSelected) {
return;
}

// Mark this method as selected
submitHandlerCallback(method.code);
}, [method.code, isSelected]); // eslint-disable-line react-hooks/exhaustive-deps

try {
if (!window.ApplePaySession || !window.ApplePaySession.canMakePayments()) {
return null;
}
} catch (error) {
return null;
}

if (!isSelected) {
return (
<RadioInput
value={method.code}
label={method.title}
name="paymentMethod"
checked={isSelected}
onChange={actions.change}
/>
);
}

return (
<div>
<div>
<RadioInput
value={method.code}
label={method.title}
name="paymentMethod"
checked={isSelected}
onChange={actions.change}
/>
</div>
</div>
);
}

ApplePayRenderer.propTypes = {
method: paymentMethodShape.isRequired,
selected: paymentMethodShape.isRequired,
actions: shape({ change: func }).isRequired,
};

export default ApplePayRenderer;
76 changes: 76 additions & 0 deletions src/hooks/useApplePayToPlaceOrder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { useCallback, useContext } from 'react';
import { get as _get } from 'lodash-es';
import CartContext from '../../../../context/Cart/CartContext';
import useMollieAppContext from './useMollieAppContext';
import applePayValidationRequest from '../api/applePayValidationRequest';
import useMolliePlaceOrder from './useMolliePlaceOrder';
import { currencyCode, defaultCountry, storeName } from '../utility/config';

export default function useApplePayToPlaceOrder() {
const { appDispatch } = useMollieAppContext();
const [cartData] = useContext(CartContext);
const cart = _get(cartData, 'cart');
const prices = _get(cart, 'prices') || {};
const { placeOrder } = useMolliePlaceOrder({
methodCode: 'mollie_methods_applepay',
});

return {
applePayPlaceOrder: useCallback(() => {
let session;

const request = {
countryCode: defaultCountry,
currencyCode,

supportedNetworks: ['amex', 'maestro', 'masterCard', 'visa', 'vPay'],
merchantCapabilities: ['supports3DS'],
total: {
// TODO: Make this configurable
label: storeName,
amount: prices.grandTotalAmount,
},
};

if (!session) {
// eslint-disable-next-line no-undef
session = new ApplePaySession(3, request);
}

session.onpaymentmethodselected = () => {
session.completePaymentMethodSelection(
{
label: 'Total',
type: 'final',
amount: prices.grandTotalAmount,
},
[]
);
};

session.onvalidatemerchant = async (event) => {
const response = await applePayValidationRequest(
appDispatch,
event.validationURL
);

session.completeMerchantValidation(JSON.parse(response));
};

session.onpaymentauthorized = (event) => {
try {
placeOrder({ applePayToken: JSON.stringify(event.payment.token) });
} catch {
// eslint-disable-next-line no-undef
session.completePayment(ApplePaySession.STATUS_ERROR);
}
};

session.oncancel = () => {
session = null;
};

session.begin();
}, [prices.grandTotalAmount, appDispatch, placeOrder]),
};
}
14 changes: 13 additions & 1 deletion src/hooks/useMolliePlaceOrder.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import useMollieCartContext from './useMollieCartContext';
import placeOrderRequest from '../api/placeOrderRequest';
import restoreCartRequest from '../api/restoreCartRequest';
import useMollieComponentsApi from './useMollieComponentsApi';
import LocalStorage from '../../../../utils/localStorage';
import { config } from '../../../../config';

export default function useMolliePlaceOrder({ methodCode, selectedIssuer }) {
const { cartId, setCartInfo } = useMollieCartContext();
Expand All @@ -14,14 +16,15 @@ export default function useMolliePlaceOrder({ methodCode, selectedIssuer }) {
useMollieComponentsApi(methodCode, setMollie);

const placeOrder = useCallback(
async ({ token = null }) => {
async ({ token = null, applePayToken = null }) => {
try {
setPageLoader(true);
await setPaymentMethodOnCartRequest(appDispatch, {
cartId,
paymentCode: methodCode,
issuer: selectedIssuer,
cardToken: token,
applePayToken,
});
} catch (error) {
setPageLoader(false);
Expand All @@ -36,6 +39,15 @@ export default function useMolliePlaceOrder({ methodCode, selectedIssuer }) {
const { mollie_redirect_url: mollieRedirectUrl } =
await placeOrderRequest(appDispatch);

if (
!mollieRedirectUrl &&
(methodCode === 'mollie_methods_applepay' ||
methodCode === 'mollie_methods_creditcard')
) {
LocalStorage.clearCheckoutStorage();
window.location.replace(config.successPageRedirectUrl);
}

if (!mollieRedirectUrl) {
throw Error('No redirect url found');
}
Expand Down
25 changes: 24 additions & 1 deletion src/utility/config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,37 @@
import RootElement from '../../../../utils/rootElement';
import env from '../../../../utils/env';
import { config } from '../../../../config';

const paymentConfig = RootElement.getPaymentConfig();

const mollieConfig = paymentConfig.mollie || {};
const useComponents = mollieConfig?.creditcard?.use_components;
const applePayType = mollieConfig?.applepay?.integration_type;
const storeName = mollieConfig?.store?.name || 'Your Store Name';

const { code: rootCurrencyCode } = RootElement.getCurrency();
const envCurrencyCode = env.currencyCode;

const currencyCode = envCurrencyCode || rootCurrencyCode;

const defaultCountry =
env.defaultCountry ||
RootElement.getDefaultCountryId() ||
config.defaultCountry;

const {
profile_id, // eslint-disable-line camelcase
locale,
testmode,
} = mollieConfig;

export { profile_id as profileId, useComponents, locale, testmode }; // eslint-disable-line camelcase
export {
profile_id as profileId, // eslint-disable-line camelcase
useComponents,
locale,
testmode,
applePayType,
currencyCode,
defaultCountry,
storeName,
};

0 comments on commit 094ee3a

Please sign in to comment.