2021-03-31 16:03:51 +02:00
|
|
|
import React, { ReactNode, useEffect, useState } from 'react';
|
|
|
|
import { useTranslation } from 'react-i18next';
|
2021-03-31 17:58:09 +02:00
|
|
|
import { enableMapSet } from 'immer';
|
|
|
|
import { useImmer } from 'use-immer';
|
2021-04-09 08:47:34 +02:00
|
|
|
import { HtmlTranslate } from '../../base/html-translate';
|
|
|
|
import { FabInput } from '../../base/fab-input';
|
|
|
|
import { Loader } from '../../base/loader';
|
|
|
|
import { SettingName } from '../../../models/setting';
|
|
|
|
import SettingAPI from '../../../api/setting';
|
|
|
|
import PayzenAPI from '../../../api/payzen';
|
2021-03-31 16:03:51 +02:00
|
|
|
|
2021-03-31 17:58:09 +02:00
|
|
|
enableMapSet();
|
2021-03-31 16:03:51 +02:00
|
|
|
|
|
|
|
interface PayZenKeysFormProps {
|
|
|
|
onValidKeys: (payZenSettings: Map<SettingName, string>) => void
|
|
|
|
}
|
|
|
|
|
2021-04-07 16:21:12 +02:00
|
|
|
// all settings related to PayZen that are requested by this form
|
2021-03-31 17:58:09 +02:00
|
|
|
const payZenSettings: Array<SettingName> = [SettingName.PayZenUsername, SettingName.PayZenPassword, SettingName.PayZenEndpoint, SettingName.PayZenHmacKey, SettingName.PayZenPublicKey];
|
2021-04-07 16:21:12 +02:00
|
|
|
// settings related the to PayZen REST API (server side)
|
2021-04-02 16:02:50 +02:00
|
|
|
const restApiSettings: Array<SettingName> = [SettingName.PayZenUsername, SettingName.PayZenPassword, SettingName.PayZenEndpoint, SettingName.PayZenHmacKey];
|
2021-04-07 16:21:12 +02:00
|
|
|
|
2021-04-02 16:02:50 +02:00
|
|
|
// Prevent multiples call to the payzen keys validation endpoint.
|
|
|
|
// this cannot be handled by a React state because of their asynchronous nature
|
|
|
|
let pendingKeysValidation = false;
|
|
|
|
|
2021-04-08 09:35:09 +02:00
|
|
|
/**
|
|
|
|
* Form to set the PayZen's username, password and public key
|
|
|
|
*/
|
2021-03-31 16:03:51 +02:00
|
|
|
const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys }) => {
|
|
|
|
const { t } = useTranslation('admin');
|
|
|
|
|
2021-04-08 09:35:09 +02:00
|
|
|
// values of the PayZen settings
|
2021-03-31 17:58:09 +02:00
|
|
|
const [settings, updateSettings] = useImmer<Map<SettingName, string>>(new Map(payZenSettings.map(name => [name, ''])));
|
2021-04-08 09:35:09 +02:00
|
|
|
// Icon of the fieldset for the PayZen's keys concerning the REST API. Used to display if the key is valid.
|
2021-03-31 16:03:51 +02:00
|
|
|
const [restApiAddOn, setRestApiAddOn] = useState<ReactNode>(null);
|
2021-04-08 09:35:09 +02:00
|
|
|
// Style class for the add-on icon, for the REST API
|
|
|
|
const [restApiAddOnClassName, setRestApiAddOnClassName] = useState<'key-invalid' | 'key-valid' | ''>('');
|
|
|
|
// Icon of the input field for the PayZen's public key. Used to display if the key is valid.
|
2021-03-31 16:03:51 +02:00
|
|
|
const [publicKeyAddOn, setPublicKeyAddOn] = useState<ReactNode>(null);
|
2021-04-08 09:35:09 +02:00
|
|
|
// Style class for the add-on icon, for the public key
|
|
|
|
const [publicKeyAddOnClassName, setPublicKeyAddOnClassName] = useState<'key-invalid' | 'key-valid' | ''>('');
|
2021-03-31 16:03:51 +02:00
|
|
|
|
2021-04-08 09:35:09 +02:00
|
|
|
/**
|
|
|
|
* When the component loads for the first time, initialize the keys with the values fetched from the API (if any)
|
|
|
|
*/
|
2021-03-31 16:03:51 +02:00
|
|
|
useEffect(() => {
|
2021-04-09 12:09:54 +02:00
|
|
|
const api = new SettingAPI();
|
|
|
|
api.query(payZenSettings).then(payZenKeys => {
|
|
|
|
updateSettings(new Map(payZenKeys));
|
|
|
|
}).catch(error => console.error(error));
|
2021-03-31 16:03:51 +02:00
|
|
|
}, []);
|
|
|
|
|
2021-04-08 09:35:09 +02:00
|
|
|
/**
|
|
|
|
* When the style class for the public key, and the REST API are updated, check if they indicate valid keys.
|
|
|
|
* If both are valid, run the 'onValidKeys' callback
|
|
|
|
*/
|
2021-03-31 16:03:51 +02:00
|
|
|
useEffect(() => {
|
|
|
|
const validClassName = 'key-valid';
|
|
|
|
if (publicKeyAddOnClassName === validClassName && restApiAddOnClassName === validClassName) {
|
|
|
|
onValidKeys(settings);
|
|
|
|
}
|
2021-04-01 18:20:26 +02:00
|
|
|
}, [publicKeyAddOnClassName, restApiAddOnClassName, settings]);
|
2021-03-31 16:03:51 +02:00
|
|
|
|
2021-04-02 16:02:50 +02:00
|
|
|
useEffect(() => {
|
|
|
|
testRestApi();
|
|
|
|
}, [settings])
|
|
|
|
|
2021-03-31 16:03:51 +02:00
|
|
|
/**
|
2021-04-02 16:02:50 +02:00
|
|
|
* Assign the inputted key to the settings and check if it is valid.
|
|
|
|
* Depending on the test result, assign an add-on icon and a style to notify the user.
|
2021-03-31 16:03:51 +02:00
|
|
|
*/
|
|
|
|
const testPublicKey = (key: string) => {
|
|
|
|
if (!key.match(/^[0-9]+:/)) {
|
|
|
|
setPublicKeyAddOn(<i className="fa fa-times" />);
|
|
|
|
setPublicKeyAddOnClassName('key-invalid');
|
|
|
|
return;
|
|
|
|
}
|
2021-03-31 17:58:09 +02:00
|
|
|
updateSettings(draft => draft.set(SettingName.PayZenPublicKey, key));
|
2021-03-31 16:03:51 +02:00
|
|
|
setPublicKeyAddOn(<i className="fa fa-check" />);
|
|
|
|
setPublicKeyAddOnClassName('key-valid');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2021-04-02 16:02:50 +02:00
|
|
|
* Send a test call to the payZen REST API to check if the inputted settings key are valid.
|
|
|
|
* Depending on the test result, assign an add-on icon and a style to notify the user.
|
2021-03-31 16:03:51 +02:00
|
|
|
*/
|
2021-04-02 16:02:50 +02:00
|
|
|
const testRestApi = () => {
|
|
|
|
let valid: boolean = restApiSettings.map(s => !!settings.get(s))
|
|
|
|
.reduce((acc, val) => acc && val, true);
|
|
|
|
|
|
|
|
if (valid && !pendingKeysValidation) {
|
|
|
|
pendingKeysValidation = true;
|
|
|
|
PayzenAPI.chargeSDKTest(
|
|
|
|
settings.get(SettingName.PayZenEndpoint),
|
|
|
|
settings.get(SettingName.PayZenUsername),
|
|
|
|
settings.get(SettingName.PayZenPassword)
|
|
|
|
).then(result => {
|
|
|
|
pendingKeysValidation = false;
|
|
|
|
|
|
|
|
if (result.success) {
|
|
|
|
setRestApiAddOn(<i className="fa fa-check" />);
|
|
|
|
setRestApiAddOnClassName('key-valid');
|
|
|
|
} else {
|
2021-04-01 18:20:26 +02:00
|
|
|
setRestApiAddOn(<i className="fa fa-times" />);
|
|
|
|
setRestApiAddOnClassName('key-invalid');
|
2021-04-02 16:02:50 +02:00
|
|
|
}
|
|
|
|
}, () => {
|
|
|
|
pendingKeysValidation = false;
|
|
|
|
|
|
|
|
setRestApiAddOn(<i className="fa fa-times" />);
|
|
|
|
setRestApiAddOnClassName('key-invalid');
|
|
|
|
});
|
|
|
|
}
|
2021-04-02 17:16:27 +02:00
|
|
|
if (!valid) {
|
|
|
|
setRestApiAddOn(<i className="fa fa-times" />);
|
|
|
|
setRestApiAddOnClassName('key-invalid');
|
|
|
|
}
|
2021-04-02 16:02:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Assign the inputted key to the given settings
|
|
|
|
*/
|
|
|
|
const setApiKey = (setting: SettingName.PayZenUsername | SettingName.PayZenPassword | SettingName.PayZenEndpoint | SettingName.PayZenHmacKey) => {
|
|
|
|
return (key: string) => {
|
|
|
|
updateSettings(draft => draft.set(setting, key));
|
|
|
|
}
|
2021-03-31 16:03:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if an add-on icon must be shown for the API settings
|
|
|
|
*/
|
|
|
|
const hasApiAddOn = () => {
|
|
|
|
return restApiAddOn !== null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (
|
|
|
|
<div className="payzen-keys-form">
|
2021-04-07 16:25:14 +02:00
|
|
|
<div className="payzen-keys-info">
|
|
|
|
<HtmlTranslate trKey="app.admin.invoices.payment.payzen_keys_info_html" />
|
|
|
|
</div>
|
2021-03-31 16:03:51 +02:00
|
|
|
<form name="payzenKeysForm">
|
|
|
|
<fieldset>
|
|
|
|
<legend>{t('app.admin.invoices.payment.client_keys')}</legend>
|
|
|
|
<div className="payzen-public-input">
|
2021-04-06 17:47:47 +02:00
|
|
|
<label htmlFor="payzen_public_key">{ t('app.admin.invoices.payment.payzen.payzen_public_key') } *</label>
|
2021-03-31 16:03:51 +02:00
|
|
|
<FabInput id="payzen_public_key"
|
|
|
|
icon={<i className="fas fa-info" />}
|
2021-04-02 17:16:27 +02:00
|
|
|
defaultValue={settings.get(SettingName.PayZenPublicKey)}
|
2021-03-31 16:03:51 +02:00
|
|
|
onChange={testPublicKey}
|
|
|
|
addOn={publicKeyAddOn}
|
|
|
|
addOnClassName={publicKeyAddOnClassName}
|
|
|
|
debounce={200}
|
|
|
|
required />
|
|
|
|
</div>
|
|
|
|
</fieldset>
|
|
|
|
<fieldset>
|
|
|
|
<legend className={hasApiAddOn() ? 'with-addon' : ''}>
|
|
|
|
<span>{t('app.admin.invoices.payment.api_keys')}</span>
|
|
|
|
{hasApiAddOn() && <span className={`fieldset-legend--addon ${restApiAddOnClassName ? restApiAddOnClassName : ''}`}>{restApiAddOn}</span>}
|
|
|
|
</legend>
|
|
|
|
<div className="payzen-api-user-input">
|
2021-04-06 17:47:47 +02:00
|
|
|
<label htmlFor="payzen_username">{ t('app.admin.invoices.payment.payzen.payzen_username') } *</label>
|
2021-03-31 16:03:51 +02:00
|
|
|
<FabInput id="payzen_username"
|
|
|
|
type="number"
|
|
|
|
icon={<i className="fas fa-user-alt" />}
|
2021-04-02 17:16:27 +02:00
|
|
|
defaultValue={settings.get(SettingName.PayZenUsername)}
|
2021-04-02 16:02:50 +02:00
|
|
|
onChange={setApiKey(SettingName.PayZenUsername)}
|
2021-03-31 16:03:51 +02:00
|
|
|
debounce={200}
|
|
|
|
required />
|
|
|
|
</div>
|
|
|
|
<div className="payzen-api-password-input">
|
2021-04-06 17:47:47 +02:00
|
|
|
<label htmlFor="payzen_password">{ t('app.admin.invoices.payment.payzen.payzen_password') } *</label>
|
2021-03-31 16:03:51 +02:00
|
|
|
<FabInput id="payzen_password"
|
|
|
|
icon={<i className="fas fa-key" />}
|
2021-04-02 17:16:27 +02:00
|
|
|
defaultValue={settings.get(SettingName.PayZenPassword)}
|
2021-04-02 16:02:50 +02:00
|
|
|
onChange={setApiKey(SettingName.PayZenPassword)}
|
2021-03-31 16:03:51 +02:00
|
|
|
debounce={200}
|
|
|
|
required />
|
|
|
|
</div>
|
|
|
|
<div className="payzen-api-endpoint-input">
|
2021-04-06 17:47:47 +02:00
|
|
|
<label htmlFor="payzen_endpoint">{ t('app.admin.invoices.payment.payzen.payzen_endpoint') } *</label>
|
2021-03-31 16:03:51 +02:00
|
|
|
<FabInput id="payzen_endpoint"
|
|
|
|
type="url"
|
2021-04-01 18:20:26 +02:00
|
|
|
icon={<i className="fas fa-link" />}
|
2021-04-02 17:16:27 +02:00
|
|
|
defaultValue={settings.get(SettingName.PayZenEndpoint)}
|
2021-04-02 16:02:50 +02:00
|
|
|
onChange={setApiKey(SettingName.PayZenEndpoint)}
|
2021-03-31 16:03:51 +02:00
|
|
|
debounce={200}
|
|
|
|
required />
|
|
|
|
</div>
|
|
|
|
<div className="payzen-api-hmac-input">
|
2021-04-06 17:47:47 +02:00
|
|
|
<label htmlFor="payzen_hmac">{ t('app.admin.invoices.payment.payzen.payzen_hmac') } *</label>
|
2021-03-31 16:03:51 +02:00
|
|
|
<FabInput id="payzen_hmac"
|
|
|
|
icon={<i className="fas fa-subscript" />}
|
2021-04-02 17:16:27 +02:00
|
|
|
defaultValue={settings.get(SettingName.PayZenHmacKey)}
|
2021-04-02 16:02:50 +02:00
|
|
|
onChange={setApiKey(SettingName.PayZenHmacKey)}
|
2021-03-31 16:03:51 +02:00
|
|
|
debounce={200}
|
|
|
|
required />
|
|
|
|
</div>
|
|
|
|
</fieldset>
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export const PayZenKeysForm: React.FC<PayZenKeysFormProps> = ({ onValidKeys }) => {
|
|
|
|
return (
|
|
|
|
<Loader>
|
|
|
|
<PayZenKeysFormComponent onValidKeys={onValidKeys} />
|
|
|
|
</Loader>
|
|
|
|
);
|
|
|
|
}
|