mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-01-29 18:52:22 +01:00
payzen keys configuration form
This commit is contained in:
parent
1d42fa8781
commit
54c1a3cfd9
@ -2,6 +2,7 @@
|
||||
|
||||
## Next release
|
||||
- [TODO DEPLOY] `rails fablab:stripe:set_gateway`
|
||||
- [TODO DEPLOY] `rails fablab:maintenance:rebuild_stylesheet`
|
||||
|
||||
## v4.7.7 (pending)
|
||||
- Enforced validation on required input fields
|
||||
|
@ -27,7 +27,9 @@ export const FabInput: React.FC<FabInputProps> = ({ id, onChange, value, icon, c
|
||||
|
||||
useEffect(() => {
|
||||
setInputValue(value);
|
||||
onChange(value);
|
||||
if (value) {
|
||||
onChange(value);
|
||||
}
|
||||
}, [value]);
|
||||
|
||||
/**
|
||||
|
159
app/frontend/src/javascript/components/payzen-keys-form.tsx
Normal file
159
app/frontend/src/javascript/components/payzen-keys-form.tsx
Normal file
@ -0,0 +1,159 @@
|
||||
/**
|
||||
* Form to set the PayZen's username, password and public key
|
||||
*/
|
||||
|
||||
import React, { ReactNode, useEffect, useState } from 'react';
|
||||
import { Loader } from './loader';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SettingAPI from '../api/setting';
|
||||
import { SettingName } from '../models/setting';
|
||||
import { FabInput } from './fab-input';
|
||||
|
||||
|
||||
interface PayZenKeysFormProps {
|
||||
onValidKeys: (payZenSettings: Map<SettingName, string>) => void
|
||||
}
|
||||
|
||||
const payZenSettings = [SettingName.PayZenUsername, SettingName.PayZenPassword, SettingName.PayZenEndpoint, SettingName.PayZenHmacKey, SettingName.PayZenPublicKey];
|
||||
const payZenKeys = SettingAPI.query(payZenSettings);
|
||||
|
||||
const PayZenKeysFormComponent: React.FC<PayZenKeysFormProps> = ({ onValidKeys }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const defaultSettings: [SettingName, string][] = payZenSettings.map(name => [name, '']);
|
||||
const [settings, setSettings] = useState<Map<SettingName, string>>(new Map(defaultSettings));
|
||||
const [restApiAddOn, setRestApiAddOn] = useState<ReactNode>(null);
|
||||
const [restApiAddOnClassName, setRestApiAddOnClassName] = useState<string>('');
|
||||
const [publicKeyAddOn, setPublicKeyAddOn] = useState<ReactNode>(null);
|
||||
const [publicKeyAddOnClassName, setPublicKeyAddOnClassName] = useState<string>('');
|
||||
|
||||
useEffect(() => {
|
||||
setSettings(payZenKeys.read());
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const validClassName = 'key-valid';
|
||||
if (publicKeyAddOnClassName === validClassName && restApiAddOnClassName === validClassName) {
|
||||
onValidKeys(settings);
|
||||
}
|
||||
}, [publicKeyAddOnClassName, restApiAddOnClassName]);
|
||||
|
||||
|
||||
/**
|
||||
* Check if the inputted public key is valid and assign it to the settings if the key is valid
|
||||
*/
|
||||
const testPublicKey = (key: string) => {
|
||||
if (!key.match(/^[0-9]+:/)) {
|
||||
setPublicKeyAddOn(<i className="fa fa-times" />);
|
||||
setPublicKeyAddOnClassName('key-invalid');
|
||||
return;
|
||||
}
|
||||
setSettings(new Map(settings).set(SettingName.PayZenPublicKey, key));
|
||||
setPublicKeyAddOn(<i className="fa fa-check" />);
|
||||
setPublicKeyAddOnClassName('key-valid');
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a test call to the payZen REST API to check if the inputted settings key are valid
|
||||
*/
|
||||
const testRestApi = (setting: SettingName.PayZenUsername | SettingName.PayZenPassword | SettingName.PayZenEndpoint | SettingName.PayZenHmacKey) => {
|
||||
return (key: string) => {
|
||||
// if (!key.match(/^sk_/)) {
|
||||
setRestApiAddOn(<i className="fa fa-times" />);
|
||||
setRestApiAddOnClassName('key-invalid');
|
||||
return;
|
||||
// }
|
||||
// StripeAPI.listAllCharges(key).then(() => {
|
||||
// setSecretKey(key);
|
||||
// setSecretKeyAddOn(<i className="fa fa-check" />);
|
||||
// setSecretKeyAddOnClassName('key-valid');
|
||||
// }, reason => {
|
||||
// if (reason.response.status === 401) {
|
||||
// setSecretKeyAddOn(<i className="fa fa-times" />);
|
||||
// setSecretKeyAddOnClassName('key-invalid');
|
||||
// }
|
||||
// });
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an add-on icon must be shown for the API settings
|
||||
*/
|
||||
const hasApiAddOn = () => {
|
||||
return restApiAddOn !== null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="payzen-keys-form">
|
||||
<div className="payzen-keys-info" dangerouslySetInnerHTML={{__html: t('app.admin.invoices.payment.payzen_keys_info_html')}} />
|
||||
<form name="payzenKeysForm">
|
||||
<fieldset>
|
||||
<legend>{t('app.admin.invoices.payment.client_keys')}</legend>
|
||||
<div className="payzen-public-input">
|
||||
<label htmlFor="payzen_public_key">{ t('app.admin.invoices.payment.public_key') } *</label>
|
||||
<FabInput id="payzen_public_key"
|
||||
icon={<i className="fas fa-info" />}
|
||||
value={settings.get(SettingName.PayZenPublicKey)}
|
||||
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">
|
||||
<label htmlFor="payzen_username">{ t('app.admin.invoices.payment.username') } *</label>
|
||||
<FabInput id="payzen_username"
|
||||
type="number"
|
||||
icon={<i className="fas fa-user-alt" />}
|
||||
value={settings.get(SettingName.PayZenUsername)}
|
||||
onChange={testRestApi(SettingName.PayZenUsername)}
|
||||
debounce={200}
|
||||
required />
|
||||
</div>
|
||||
<div className="payzen-api-password-input">
|
||||
<label htmlFor="payzen_password">{ t('app.admin.invoices.payment.password') } *</label>
|
||||
<FabInput id="payzen_password"
|
||||
icon={<i className="fas fa-key" />}
|
||||
value={settings.get(SettingName.PayZenPassword)}
|
||||
onChange={testRestApi(SettingName.PayZenPassword)}
|
||||
debounce={200}
|
||||
required />
|
||||
</div>
|
||||
<div className="payzen-api-endpoint-input">
|
||||
<label htmlFor="payzen_endpoint">{ t('app.admin.invoices.payment.endpoint') } *</label>
|
||||
<FabInput id="payzen_endpoint"
|
||||
type="url"
|
||||
icon={<i className="fas fa-anchor" />}
|
||||
value={settings.get(SettingName.PayZenEndpoint)}
|
||||
onChange={testRestApi(SettingName.PayZenEndpoint)}
|
||||
debounce={200}
|
||||
required />
|
||||
</div>
|
||||
<div className="payzen-api-hmac-input">
|
||||
<label htmlFor="payzen_hmac">{ t('app.admin.invoices.payment.hmac') } *</label>
|
||||
<FabInput id="payzen_hmac"
|
||||
icon={<i className="fas fa-subscript" />}
|
||||
value={settings.get(SettingName.PayZenHmacKey)}
|
||||
onChange={testRestApi(SettingName.PayZenHmacKey)}
|
||||
debounce={200}
|
||||
required />
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export const PayZenKeysForm: React.FC<PayZenKeysFormProps> = ({ onValidKeys }) => {
|
||||
return (
|
||||
<Loader>
|
||||
<PayZenKeysFormComponent onValidKeys={onValidKeys} />
|
||||
</Loader>
|
||||
);
|
||||
}
|
@ -14,6 +14,7 @@ import { Gateway } from '../models/gateway';
|
||||
import { StripeKeysForm } from './stripe-keys-form';
|
||||
import { SettingBulkResult, SettingName } from '../models/setting';
|
||||
import SettingAPI from '../api/setting';
|
||||
import { PayZenKeysForm } from './payzen-keys-form';
|
||||
|
||||
|
||||
declare var Application: IApplication;
|
||||
@ -116,6 +117,7 @@ const SelectGatewayModal: React.FC<SelectGatewayModalModalProps> = ({ isOpen, to
|
||||
<option value={Gateway.PayZen}>{t('app.admin.invoices.payment.gateway_modal.payzen')}</option>
|
||||
</select>
|
||||
{selectedGateway === Gateway.Stripe && <StripeKeysForm onValidKeys={handleValidStripeKeys} />}
|
||||
{selectedGateway === Gateway.PayZen && <PayZenKeysForm onValidKeys={handleValidStripeKeys} />}
|
||||
</FabModal>
|
||||
);
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Form to set the stripe's public and private keys
|
||||
*/
|
||||
|
||||
import React, { BaseSyntheticEvent, ReactNode, useEffect, useState } from 'react';
|
||||
import React, { ReactNode, useEffect, useState } from 'react';
|
||||
import { Loader } from './loader';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import SettingAPI from '../api/setting';
|
||||
|
@ -102,7 +102,12 @@ export enum SettingName {
|
||||
PaymentSchedulePrefix = 'payment_schedule_prefix',
|
||||
TrainingsModule = 'trainings_module',
|
||||
AddressRequired = 'address_required',
|
||||
PaymentGateway = 'payment_gateway'
|
||||
PaymentGateway = 'payment_gateway',
|
||||
PayZenUsername = 'payzen_username',
|
||||
PayZenPassword = 'payzen_password',
|
||||
PayZenEndpoint = 'payzen_endpoint',
|
||||
PayZenPublicKey = 'payzen_public_key',
|
||||
PayZenHmacKey = 'payzen_hmac'
|
||||
}
|
||||
|
||||
export interface Setting {
|
||||
|
@ -36,5 +36,6 @@
|
||||
@import "modules/plan-card";
|
||||
@import "modules/select-gateway-modal";
|
||||
@import "modules/stripe-keys-form";
|
||||
@import "modules/payzen-keys-form";
|
||||
|
||||
@import "app.responsive";
|
||||
|
55
app/frontend/src/stylesheets/modules/payzen-keys-form.scss
Normal file
55
app/frontend/src/stylesheets/modules/payzen-keys-form.scss
Normal file
@ -0,0 +1,55 @@
|
||||
.payzen-keys-form {
|
||||
& {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.payzen-keys-info {
|
||||
border: 1px solid #bce8f1;
|
||||
border-radius: 4px;
|
||||
color: #31708f;
|
||||
background-color: #d9edf7;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c4c4c4;
|
||||
border-radius: 4px;
|
||||
margin-top: 1em;
|
||||
padding: 7px;
|
||||
|
||||
& > legend {
|
||||
padding: 3px 6px;
|
||||
width: fit-content;
|
||||
font-size: 1em;
|
||||
border-radius: 4px;
|
||||
margin-left: 1em;
|
||||
margin-bottom: 0;
|
||||
position: relative;
|
||||
|
||||
&.with-addon {
|
||||
border-radius: 4px 0 0 4px;;
|
||||
}
|
||||
}
|
||||
.fieldset-legend--addon {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: -35px;
|
||||
font-size: 1em;
|
||||
padding: 3px 12px;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
border-radius: 0 4px 4px 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
.key-valid {
|
||||
background-color: #7bca38;
|
||||
}
|
||||
|
||||
.key-invalid {
|
||||
background-color: #d92227;
|
||||
color: white;
|
||||
}
|
||||
}
|
@ -110,7 +110,12 @@ class Setting < ApplicationRecord
|
||||
payment_schedule_prefix
|
||||
trainings_module
|
||||
address_required
|
||||
payment_gateway] }
|
||||
payment_gateway
|
||||
payzen_username
|
||||
payzen_password
|
||||
payzen_endpoint
|
||||
payzen_public_key
|
||||
payzen_hmac] }
|
||||
# WARNING: when adding a new key, you may also want to add it in app/policies/setting_policy.rb#public_whitelist
|
||||
|
||||
def value
|
||||
|
@ -349,3 +349,10 @@ section#cookies-modal div.cookies-consent .cookies-actions button.accept {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.payzen-keys-form {
|
||||
fieldset > legend {
|
||||
background-color: $secondary;
|
||||
color: $secondary-text-color;
|
||||
}
|
||||
}
|
||||
|
@ -638,6 +638,13 @@ en:
|
||||
error_check_keys: "Error: please check your Stripe keys."
|
||||
stripe_keys_saved: "Stripe keys successfully saved."
|
||||
error_saving_stripe_keys: "Unable to save the Stripe keys. Please try again later."
|
||||
payzen_keys_info_html: "<p>To be able to collect online payments, you must configure the <a href='https://payzen.eu' target='_blank'>PayZen</a> identifiers and keys.</p><p>Retrieve them from <a href='https://secure.payzen.eu/vads-merchant/' target='_blank'>your merchant back office</a>.</p>"
|
||||
client_keys: "Client keys"
|
||||
api_keys: "API keys"
|
||||
username: "User"
|
||||
password: "Password"
|
||||
endpoint: "REST API server name"
|
||||
hmac: "HMAC-SHA-256 key"
|
||||
edit_keys: "Edit keys"
|
||||
currency: "Currency"
|
||||
currency_info_html: "Please specify below the currency used for online payment. You should provide a three-letter ISO code, from the list of <a href='https://stripe.com/docs/currencies' target='_blank'>Stripe supported currencies</a>."
|
||||
|
@ -638,6 +638,13 @@ fr:
|
||||
error_check_keys: "Erreur : veuillez vérifier vos clefs Stripe."
|
||||
stripe_keys_saved: "Les clefs Stripe ont bien été enregistrées."
|
||||
error_saving_stripe_keys: "Impossible d’enregistrer les clefs Stripe. Veuillez réessayer ultérieurement."
|
||||
payzen_keys_info_html: "<p>Pour pouvoir encaisser des paiements en ligne, vous devez configurer les identifiants et les clefs <a href='https://payzen.eu' target='_blank'>PayZen</a>.</p><p>Retrouvez les dans <a href='https://secure.payzen.eu/vads-merchant/' target='_blank'>votre back office marchant</a>.</p>"
|
||||
client_keys: "Clefs client"
|
||||
api_keys: "Clefs d'API"
|
||||
username: "Utilisateur"
|
||||
password: "Mot de passe"
|
||||
endpoint: "Nom du serveur de l'API REST"
|
||||
hmac: "Clef HMAC-SHA-256"
|
||||
edit_keys: "Modifier les clefs"
|
||||
currency: "Devise"
|
||||
currency_info_html: "Veuillez indiquer la devise à utiliser lors des paiements en ligne. Vous devez fournir un code ISO à trois lettres, issu de la liste des <a href='https://stripe.com/docs/currencies' target='_blank'>devises supportées par Stripe</a>."
|
||||
|
Loading…
x
Reference in New Issue
Block a user