Skip to content

Commit 1a53502

Browse files
committed
Initial commit
0 parents  commit 1a53502

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1532
-0
lines changed

README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<p align="center">
2+
<img src="https://camo.githubusercontent.com/517483ae0eaba9884f397e9af1c4adc7bbc231575ac66cc54292e00400edcd10/68747470733a2f2f7777772e6d756c7469736166657061792e636f6d2f66696c6561646d696e2f74656d706c6174652f696d672f6d756c7469736166657061792d6c6f676f2d69636f6e2e737667" width="400px" position="center">
3+
</p>
4+
5+
# MultiSafepay module for the Hyva React Checkout
6+
7+
This is the module of our new Magento 2 Hyva React Checkout integration.
8+
9+
Before you get started with MultiSafepay and the Hyva React Checkout, please read and follow our [installation & configuration manual](https://docs.multisafepay.com/docs/magento-2) first.
10+
11+
## About MultiSafepay ##
12+
MultiSafepay is a collecting payment service provider which means we take care of the agreements, technical details and payment collection required for each payment method. You can start selling online today and manage all your transactions from one place.
13+
14+
## Supported Payment Methods ##
15+
The supported Payment Methods for this module can be found over here: [Payment Methods & Giftcards](https://docs.multisafepay.com/docs/magento-2#payment-methods)
16+
17+
## Requirements
18+
- To use the plugin you need a MultiSafepay account. You can create a test account on https://testmerchant.multisafepay.com/signup
19+
- Magento Open Source version 2.3.x & 2.4.x
20+
- PHP 7.1+
21+
22+
## Installation
23+
This package does not work yet with the MultiSafepay_Graphql module.
24+
Please disable the module first, if you have it installed.
25+
26+
Add our package to the PaymentMethodsRepo section in the reactapp package.json:
27+
28+
```
29+
"config": {
30+
"paymentMethodsRepo": {
31+
"multisafepay": "https://github.com/multisafepay/magento2-react-checkout-multisafepay"
32+
}
33+
},
34+
```
35+
36+
Install the MultiSafepay package:
37+
```
38+
npm install
39+
```
40+
41+
This module requires several third-party packages:
42+
43+
[react-datepicker](https://www.npmjs.com/package/react-datepicker) - Adds a datepicker component for Date of Birth fields.
44+
45+
[moment.js](https://momentjs.com/) - Parse the dates into a format that is supported by the MultiSafepay API.
46+
47+
[lodash](https://lodash.com/) - Manipulation of objects through different built in modular methods
48+
49+
To install these packages via npm, please run the following commands:
50+
```
51+
npm install --save react-datepicker moment lodash
52+
```
53+
54+
Make sure to rebuild the project with:
55+
```shell
56+
npm run build
57+
```
58+
59+
## Support
60+
You can create issues on our repository. If you need any additional help or support, please contact <a href="mailto:[email protected]">[email protected]</a>
61+
62+
We are also available on our Magento Slack channel [#multisafepay-payments](https://magentocommeng.slack.com/messages/multisafepay-payments/).
63+
Feel free to start a conversation or provide suggestions as to how we can refine our Hyva React Checkout integration.
64+
65+
## License
66+
[Open Software License (OSL 3.0)](https://github.com/MultiSafepay/Magento2Msp/blob/master/LICENSE.md)
67+
68+
## Want to be part of the team?
69+
Are you a developer interested in working at MultiSafepay? [View](https://www.multisafepay.com/careers/#jobopenings) our job openings and feel free to get in touch with us.

renderers.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import PaymentBaseComponent from './src/components/PaymentBaseComponent';
2+
import IdealComponent from './src/components/IdealComponent';
3+
import AfterPayComponent from './src/components/AfterPayComponent';
4+
import In3Component from './src/components/In3Component';
5+
import PayAfterDeliveryComponent from './src/components/PayAfterDeliveryComponent';
6+
import EinvoicingComponent from './src/components/EinvoicingComponent';
7+
import DirectDebitComponent from './src/components/DirectDebitComponent';
8+
import DirectBankTransferComponent from './src/components/DirectBankTransferComponent';
9+
import CreditCardComponent from './src/components/CreditCardComponent';
10+
11+
export default {
12+
multisafepay: PaymentBaseComponent,
13+
multisafepay_ideal: IdealComponent,
14+
multisafepay_afterpay: AfterPayComponent,
15+
multisafepay_alipay: PaymentBaseComponent,
16+
multisafepay_amex: PaymentBaseComponent,
17+
multisafepay_applepay: PaymentBaseComponent,
18+
multisafepay_bancontact: PaymentBaseComponent,
19+
multisafepay_banktransfer: PaymentBaseComponent,
20+
multisafepay_belfius: PaymentBaseComponent,
21+
multisafepay_cbc: PaymentBaseComponent,
22+
multisafepay_creditcard: CreditCardComponent,
23+
multisafepay_directbanktransfer: DirectBankTransferComponent,
24+
multisafepay_directdebit: DirectDebitComponent,
25+
multisafepay_dotpay: PaymentBaseComponent,
26+
multisafepay_einvoicing: EinvoicingComponent,
27+
multisafepay_eps: PaymentBaseComponent,
28+
multisafepay_giropay: PaymentBaseComponent,
29+
multisafepay_idealqr: PaymentBaseComponent,
30+
multisafepay_in3: In3Component,
31+
multisafepay_inghomepay: PaymentBaseComponent,
32+
multisafepay_kbc: PaymentBaseComponent,
33+
multisafepay_klarna: PaymentBaseComponent,
34+
multisafepay_maestro: PaymentBaseComponent,
35+
multisafepay_mastercard: PaymentBaseComponent,
36+
multisafepay_payafter: PayAfterDeliveryComponent,
37+
multisafepay_paypal: PaymentBaseComponent,
38+
multisafepay_paysafecard: PaymentBaseComponent,
39+
multisafepay_santander: PaymentBaseComponent,
40+
multisafepay_sofort: PaymentBaseComponent,
41+
multisafepay_trustly: PaymentBaseComponent,
42+
multisafepay_trustpay: PaymentBaseComponent,
43+
multisafepay_visa: PaymentBaseComponent,
44+
multisafepay_babygiftcard: PaymentBaseComponent,
45+
multisafepay_boekenbon: PaymentBaseComponent,
46+
multisafepay_fashioncheque: PaymentBaseComponent,
47+
multisafepay_fashiongiftcard: PaymentBaseComponent,
48+
multisafepay_fietsenbon: PaymentBaseComponent,
49+
multisafepay_gezondheidsbon: PaymentBaseComponent,
50+
multisafepay_givacard: PaymentBaseComponent,
51+
multisafepay_good4fun: PaymentBaseComponent,
52+
multisafepay_goodcard: PaymentBaseComponent,
53+
multisafepay_nationaletuinbon: PaymentBaseComponent,
54+
multisafepay_parfumcadeaukaart: PaymentBaseComponent,
55+
multisafepay_podiumcadeaukaart: PaymentBaseComponent,
56+
multisafepay_sportenfit: PaymentBaseComponent,
57+
multisafepay_vvvcadeaukaart: PaymentBaseComponent,
58+
multisafepay_webshopgiftcard: PaymentBaseComponent,
59+
multisafepay_wellnessgiftcard: PaymentBaseComponent,
60+
multisafepay_wijncadeau: PaymentBaseComponent,
61+
multisafepay_winkelcheque: PaymentBaseComponent,
62+
multisafepay_yourgift: PaymentBaseComponent,
63+
};
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import React, { useEffect, useContext, useState } from 'react';
2+
import { func, shape } from 'prop-types';
3+
import DatePicker from 'react-datepicker';
4+
import moment from 'moment';
5+
import { __ } from '@hyva/react-checkout/i18n';
6+
import RadioInput from '@hyva/react-checkout/components/common/Form/RadioInput';
7+
import TextInput from '@hyva/react-checkout/components/common/Form/TextInput';
8+
import SelectInput from '@hyva/react-checkout/components/common/Form/SelectInput';
9+
import Card from '@hyva/react-checkout/components/common/Card';
10+
import { PAYMENT_METHOD_FORM } from '@hyva/react-checkout/config';
11+
import CheckoutFormContext from '@hyva/react-checkout/context/Form/CheckoutFormContext';
12+
import useMultiSafepayPaymentMethodContext from '../../hooks/useMultiSafepayPaymentMethodContext';
13+
import useMultiSafepayAfterPay from './hooks/useMultiSafepayAfterPay';
14+
import afterPayConfig from './afterPayConfig';
15+
import { paymentMethodShape } from '../../utility';
16+
import useCSS from '../../hooks/useMultiSafepayStyles';
17+
18+
const dateOfBirthField = `${PAYMENT_METHOD_FORM}.multisafepay.afterpay.dateOfBirthField`;
19+
const genderField = `${PAYMENT_METHOD_FORM}.multisafepay.afterpay.genderField`;
20+
const phoneField = `${PAYMENT_METHOD_FORM}.multisafepay.afterpay.phoneField`;
21+
22+
function AfterPayComponent({ method, selected, actions }) {
23+
const { formikData, setFieldValue } = useMultiSafepayPaymentMethodContext();
24+
const [dateField, setDate] = useState(new Date());
25+
const { registerPaymentAction } = useContext(CheckoutFormContext);
26+
const { placeOrderWithAfterPay } = useMultiSafepayAfterPay(method.code);
27+
const isSelected = method.code === selected.code;
28+
29+
useEffect(() => {
30+
setFieldValue(genderField, '');
31+
setFieldValue(phoneField, '');
32+
}, [setFieldValue]);
33+
34+
useEffect(() => {
35+
setFieldValue(dateOfBirthField, moment(dateField).format('YYYY-MM-DD'));
36+
}, [dateField, setFieldValue]);
37+
38+
useEffect(() => {
39+
registerPaymentAction(method.code, placeOrderWithAfterPay);
40+
}, [method, registerPaymentAction, placeOrderWithAfterPay]);
41+
42+
const AfterPayRadioInput = (
43+
<RadioInput
44+
value={method.code}
45+
label={method.title}
46+
name="paymentMethod"
47+
checked={isSelected}
48+
onChange={actions.change}
49+
/>
50+
);
51+
52+
useCSS(
53+
'https://cdnjs.cloudflare.com/ajax/libs/react-datepicker/2.8.0/react-datepicker.min.css'
54+
);
55+
56+
if (!isSelected || afterPayConfig.transaction_type === 'redirect') {
57+
return AfterPayRadioInput;
58+
}
59+
60+
const genderOptions = [
61+
{ value: 'mr', label: __('Mr.') },
62+
{ value: 'mrs', label: __('Mrs.') },
63+
{ value: 'miss', label: __('Miss') },
64+
];
65+
66+
return (
67+
<div>
68+
<div>{AfterPayRadioInput}</div>
69+
<div className="mx-4 my-4">
70+
<Card bg="darker">
71+
<div className="container flex flex-col justify-center w-4/5">
72+
<DatePicker
73+
label={__('Date of Birth')}
74+
showYearDropdown
75+
showMonthDropdown
76+
dropdownMode="select"
77+
selected={dateField}
78+
className="w-full max-w-md form-input"
79+
onChange={(date) => setDate(date)}
80+
/>
81+
<SelectInput
82+
label={__('Gender')}
83+
name={genderField}
84+
formikData={formikData}
85+
options={genderOptions}
86+
/>
87+
<TextInput
88+
label={__('Telephone')}
89+
name={phoneField}
90+
formikData={formikData}
91+
/>
92+
</div>
93+
</Card>
94+
</div>
95+
</div>
96+
);
97+
}
98+
99+
AfterPayComponent.propTypes = {
100+
method: paymentMethodShape.isRequired,
101+
selected: paymentMethodShape.isRequired,
102+
actions: shape({ change: func }).isRequired,
103+
};
104+
105+
export default AfterPayComponent;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { get } from 'lodash';
2+
import RootElement from '@hyva/react-checkout/utils/rootElement';
3+
4+
const config = RootElement.getPaymentConfig();
5+
const afterpay = get(config, 'multisafepay_afterpay');
6+
const transactionType = get(afterpay, 'transaction_type', []);
7+
8+
const afterPayConfig = {
9+
transaction_type: transactionType,
10+
};
11+
12+
export default afterPayConfig;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useCallback } from 'react';
2+
import { get } from 'lodash';
3+
import { PAYMENT_METHOD_FORM } from '@hyva/react-checkout/config';
4+
import usePerformPlaceOrder from '../../../hooks/usePerformPlaceOrder';
5+
6+
const dateOfBirthField = `${PAYMENT_METHOD_FORM}.multisafepay.afterpay.dateOfBirthField`;
7+
const genderField = `${PAYMENT_METHOD_FORM}.multisafepay.afterpay.genderField`;
8+
const phoneField = `${PAYMENT_METHOD_FORM}.multisafepay.afterpay.phoneField`;
9+
10+
export default function useMultiSafepayAfterPay(paymentMethodCode) {
11+
const performPlaceOrder = usePerformPlaceOrder(paymentMethodCode);
12+
const placeOrderWithAfterPay = useCallback(
13+
async (values) => {
14+
const dateOfBirth = get(values, dateOfBirthField);
15+
const gender = get(values, genderField);
16+
const phone = get(values, phoneField);
17+
const additionalData = {
18+
date_of_birth: dateOfBirth,
19+
gender,
20+
phone_number: phone,
21+
};
22+
23+
await performPlaceOrder(values, additionalData);
24+
},
25+
[performPlaceOrder]
26+
);
27+
28+
return { placeOrderWithAfterPay };
29+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import AfterPayComponent from './AfterPayComponent';
2+
3+
export default AfterPayComponent;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { useEffect, useContext } from 'react';
2+
import { get } from 'lodash';
3+
import { func, shape } from 'prop-types';
4+
import Card from '@hyva/react-checkout/components/common/Card';
5+
import RadioInput from '@hyva/react-checkout/components/common/Form/RadioInput';
6+
import LocalStorage from '@hyva/react-checkout/utils/localStorage';
7+
import CartContext from '@hyva/react-checkout/context/Cart/CartContext';
8+
import useMultiSafepayCheckoutFormContext from '../../hooks/useMultiSafepayCheckoutFormContext';
9+
import useMultiSafepayCreditCard from './hooks/useMultiSafepayCreditCard';
10+
import creditCardConfig from './creditCardConfig';
11+
import { paymentMethodShape } from '../../utility';
12+
import {
13+
addComponent,
14+
loadComponent,
15+
initializeComponent,
16+
} from './utility/multisafepayComponent';
17+
18+
function CreditCardComponent({ method, selected, actions }) {
19+
const { registerPaymentAction } = useMultiSafepayCheckoutFormContext();
20+
const { placeOrderWithCreditCard } = useMultiSafepayCreditCard(method.code);
21+
const isSelected = method.code === selected.code;
22+
const paymentRequestData = get(
23+
LocalStorage.getMagentoLocalStorage(),
24+
'multisafepay-payment-request'
25+
);
26+
const [cartData] = useContext(CartContext);
27+
const cart = get(cartData, 'cart');
28+
29+
addComponent();
30+
31+
useEffect(() => {
32+
registerPaymentAction(method.code, placeOrderWithCreditCard);
33+
}, [method, registerPaymentAction, placeOrderWithCreditCard]);
34+
35+
useEffect(() => {
36+
if (isSelected) {
37+
initializeComponent();
38+
}
39+
}, [isSelected]);
40+
41+
const CreditCardRadioInput = (
42+
<RadioInput
43+
value={method.code}
44+
label={method.title}
45+
name="paymentMethod"
46+
checked={isSelected}
47+
onChange={actions.change}
48+
/>
49+
);
50+
51+
if (!isSelected || creditCardConfig.payment_type === 'redirect') {
52+
return CreditCardRadioInput;
53+
}
54+
55+
const orderData = {
56+
currency: paymentRequestData.currency,
57+
amount: paymentRequestData.cartTotal,
58+
customer: {
59+
locale: paymentRequestData.locale,
60+
country: cart.billing_address.country,
61+
},
62+
template: {
63+
settings: {
64+
embed_mode: true,
65+
},
66+
},
67+
};
68+
69+
loadComponent(paymentRequestData, orderData);
70+
71+
return (
72+
<div>
73+
<div>{CreditCardRadioInput}</div>
74+
<div className="mx-4 my-4">
75+
<Card bg="darker">
76+
<div id="MultiSafepayPayment" />
77+
</Card>
78+
</div>
79+
</div>
80+
);
81+
}
82+
83+
CreditCardComponent.propTypes = {
84+
method: paymentMethodShape.isRequired,
85+
selected: paymentMethodShape.isRequired,
86+
actions: shape({ change: func }).isRequired,
87+
};
88+
89+
export default CreditCardComponent;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { get } from 'lodash';
2+
import RootElement from '@hyva/react-checkout/utils/rootElement';
3+
4+
const config = RootElement.getPaymentConfig();
5+
6+
const creditcard = get(config, 'multisafepay_creditcard');
7+
const paymentType = get(creditcard, 'payment_type', []);
8+
9+
const creditCardConfig = {
10+
payment_type: paymentType,
11+
};
12+
13+
export default creditCardConfig;

0 commit comments

Comments
 (0)