APM-64: Add wallet provider (#55)

This commit is contained in:
Ildar Galeev 2022-03-10 16:17:31 +03:00 committed by GitHub
parent e00beadb06
commit 0674a75367
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 224 additions and 43 deletions

53
package-lock.json generated
View File

@ -20,6 +20,7 @@
"kjua": "^0.9.0",
"libphonenumber-js": "1.9.6",
"lodash-es": "~4.17.15",
"md5": "2.3.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-redux": "7.2.6",
@ -4031,6 +4032,14 @@
"node": ">=0.10.0"
}
},
"node_modules/charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=",
"engines": {
"node": "*"
}
},
"node_modules/check-types": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
@ -5189,6 +5198,14 @@
"node": ">=4.8"
}
},
"node_modules/crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=",
"engines": {
"node": "*"
}
},
"node_modules/crypto-browserify": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
@ -8480,8 +8497,7 @@
"node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"node_modules/is-builtin-module": {
"version": "1.0.0",
@ -10762,6 +10778,16 @@
"node": ">=0.10.0"
}
},
"node_modules/md5": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
"dependencies": {
"charenc": "0.0.2",
"crypt": "0.0.2",
"is-buffer": "~1.1.6"
}
},
"node_modules/md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@ -20089,6 +20115,11 @@
"supports-color": "^2.0.0"
}
},
"charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc="
},
"check-types": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
@ -20992,6 +21023,11 @@
"which": "^1.2.9"
}
},
"crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs="
},
"crypto-browserify": {
"version": "3.12.0",
"resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
@ -23715,8 +23751,7 @@
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
"dev": true
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"is-builtin-module": {
"version": "1.0.0",
@ -25529,6 +25564,16 @@
"object-visit": "^1.0.0"
}
},
"md5": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
"requires": {
"charenc": "0.0.2",
"crypt": "0.0.2",
"is-buffer": "~1.1.6"
}
},
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",

View File

@ -26,6 +26,7 @@
"kjua": "^0.9.0",
"libphonenumber-js": "1.9.6",
"lodash-es": "~4.17.15",
"md5": "2.3.0",
"react": "17.0.2",
"react-dom": "17.0.2",
"react-redux": "7.2.6",

View File

@ -0,0 +1,27 @@
import * as React from 'react';
import { WrappedFieldProps } from 'redux-form';
import { isError } from 'checkout/utils';
import { Input } from '../../input';
export interface CustomInputProps {
id: string;
placeholder: string;
type: React.HTMLInputTypeAttribute;
onInput?: React.FormEventHandler;
autocomplete?: string;
}
export const getCustomInput = (props: CustomInputProps, fieldProps: WrappedFieldProps) => (
<Input
{...fieldProps.input}
{...fieldProps.meta}
error={isError(fieldProps.meta)}
placeholder={props.placeholder}
mark={true}
type={props.type}
id={props.id}
onInput={props?.onInput}
autocomplete={props?.autocomplete}
/>
);

View File

@ -1 +1,3 @@
export * from './sticpay-account';
export * from './venus-point-account';
export * from './venus-point-password';

View File

@ -1,38 +1,21 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Field, WrappedFieldProps } from 'redux-form';
import { Field } from 'redux-form';
import { KnownDigitalWalletProviders, State } from 'checkout/state';
import { Locale } from 'checkout/locale';
import { Letter } from 'checkout/components';
import { formatEmail, isError, validateEmail } from 'checkout/utils';
import { Input } from '../../input';
import { formatEmail, validateEmail } from 'checkout/utils';
import { CustomInputProps, getCustomInput } from './get-custom-input';
export interface EmailDefProps {
locale: Locale;
}
const getCustomInput = (props: EmailDefProps, fieldProps: WrappedFieldProps) => (
<Input
{...fieldProps.input}
{...fieldProps.meta}
error={isError(fieldProps.meta)}
icon={<Letter />}
placeholder={props.locale['digital.wallet.providers'][KnownDigitalWalletProviders.Sticpay].fields.account}
mark={true}
type="email"
id="sticpay-account-input"
onInput={formatEmail}
autocomplete="email"
/>
);
export const SticpayAccountDef: React.FC<EmailDefProps> = (props) => (
const SticpayAccountDef: React.FC<CustomInputProps> = (props) => (
<Field name="sticpayAccount" component={getCustomInput.bind(null, props)} validate={validateEmail} />
);
const mapStateToProps = (state: State) => ({
locale: state.config.locale
id: 'sticpay-account-input',
placeholder: state.config.locale['digital.wallet.providers'][KnownDigitalWalletProviders.Sticpay].fields.account,
type: 'email',
onInput: formatEmail,
autocomplete: 'email'
});
export const SticpayAccount = connect(mapStateToProps)(SticpayAccountDef);

View File

@ -0,0 +1,21 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Field } from 'redux-form';
import { KnownDigitalWalletProviders, State } from 'checkout/state';
import { formatEmail, validateEmail } from 'checkout/utils';
import { CustomInputProps, getCustomInput } from './get-custom-input';
const VenusPointAccountDef: React.FC<CustomInputProps> = (props) => (
<Field name="venusPointAccount" component={getCustomInput.bind(null, props)} validate={validateEmail} />
);
const mapStateToProps = (state: State) => ({
id: 'venus-point-account-input',
placeholder: state.config.locale['digital.wallet.providers'][KnownDigitalWalletProviders.Venuspoint].fields.account,
type: 'email',
onInput: formatEmail,
autocomplete: 'email'
});
export const VenusPointAccount = connect(mapStateToProps)(VenusPointAccountDef);

View File

@ -0,0 +1,21 @@
import * as React from 'react';
import { connect } from 'react-redux';
import { Field } from 'redux-form';
import { KnownDigitalWalletProviders, State } from 'checkout/state';
import { CustomInputProps, getCustomInput } from './get-custom-input';
const validatePassword = (value: string): boolean => !value || !value.trim();
const VenusPointPasswordDef: React.FC<CustomInputProps> = (props) => (
<Field name="venusPointPassword" component={getCustomInput.bind(null, props)} validate={validatePassword} />
);
const mapStateToProps = (state: State) => ({
id: 'venus-point-password-input',
placeholder:
state.config.locale['digital.wallet.providers'][KnownDigitalWalletProviders.Venuspoint].fields.password,
type: 'password'
});
export const VenusPointPassword = connect(mapStateToProps)(VenusPointPasswordDef);

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import { KnownDigitalWalletProviders } from 'checkout/state';
import { assertUnreachable } from 'checkout/utils';
import { FormGroup } from '../form-group';
import { SticpayAccount } from './fields';
import { SticpayAccount, VenusPointAccount, VenusPointPassword } from './fields';
export const WalletProviderFormGroup: React.FC<{ provider: KnownDigitalWalletProviders }> = (props) => {
switch (props.provider) {
@ -12,6 +12,17 @@ export const WalletProviderFormGroup: React.FC<{ provider: KnownDigitalWalletPro
<SticpayAccount />
</FormGroup>
);
case KnownDigitalWalletProviders.Venuspoint:
return (
<>
<FormGroup>
<VenusPointAccount />
</FormGroup>
<FormGroup>
<VenusPointPassword />
</FormGroup>
</>
);
default:
assertUnreachable(props.provider);
}

View File

@ -1,13 +1,15 @@
import * as React from 'react';
import { ReactSVG } from 'react-svg';
import styled from 'styled-components';
import { KnownDigitalWalletProviders } from 'checkout/state';
import { assertUnreachable } from 'checkout/utils';
import { VenuspointLogo, SticpayLogo } from 'checkout/components/ui';
export const Logo: React.FC<{ provider: KnownDigitalWalletProviders }> = ({ provider }) => {
switch (provider) {
case KnownDigitalWalletProviders.Sticpay:
return <ReactSVG src="/assets/wallet-providers/logos/sticpay.svg" />;
return <SticpayLogo />;
case KnownDigitalWalletProviders.Venuspoint:
return <VenuspointLogo />;
default:
assertUnreachable(provider);
}

View File

@ -1,8 +1,8 @@
import * as React from 'react';
import { ReactSVG } from 'react-svg';
import { FormInfo, FormName, KnownDigitalWalletProviders, WalletFormInfo } from 'checkout/state';
import { PaymentMethodItemContainer } from './payment-method-item-container';
import { assertUnreachable } from 'checkout/utils';
import { VenuspointLogo, SticpayLogo } from 'checkout/components/ui';
export interface SticpayPaymentMethodItemProps {
previous?: FormName;
@ -16,7 +16,9 @@ const toWalletProvider = (props: SticpayPaymentMethodItemProps) =>
const Icon: React.FC<{ provider: KnownDigitalWalletProviders }> = ({ provider }) => {
switch (provider) {
case KnownDigitalWalletProviders.Sticpay:
return <ReactSVG src="/assets/wallet-providers/logos/sticpay.svg" />;
return <SticpayLogo />;
case KnownDigitalWalletProviders.Venuspoint:
return <VenuspointLogo />;
default:
assertUnreachable(provider);
}

View File

@ -42,14 +42,14 @@ class WalletProvidersDef extends React.Component<WalletProvidersProps> {
<form ref={this.formRef}>
<div>
<Header title={locale['form.header.payment.methods.label']} />
{providers.map((provider) => {
{providers.map((provider) => (
<WalletProviderPaymentMethodItem
key={provider}
previous={FormName.walletProviders}
setFormInfo={this.props.setFormInfo}
provider={provider}
/>;
})}
/>
))}
</div>
</form>
);

View File

@ -4,3 +4,4 @@ export * from './link';
export * from './loader';
export * from './icon';
export * from './round-icon';
export * from './logo';

View File

@ -0,0 +1,2 @@
export * from './venuspoint';
export * from './sticpay';

View File

@ -0,0 +1 @@
export * from './sticpay-logo';

View File

@ -0,0 +1,4 @@
import * as React from 'react';
import { ReactSVG } from 'react-svg';
export const SticpayLogo: React.FC = () => <ReactSVG src="/assets/wallet-providers/logos/sticpay.svg" />;

View File

@ -0,0 +1 @@
export * from './venuspoint-logo';

View File

@ -0,0 +1,15 @@
import * as React from 'react';
import styled from 'styled-components';
const Container = styled.div`
img {
height: 40px;
width: 194px;
}
`;
export const VenuspointLogo: React.FC = () => (
<Container>
<img src="/assets/wallet-providers/logos/venuspoint.png" />
</Container>
);

View File

@ -1,13 +1,28 @@
import { call, CallEffect } from 'redux-saga/effects';
import { KnownDigitalWalletProviders, SticpayWalletFormValues, WalletFormValues } from 'checkout/state';
import * as md5 from 'md5';
import {
KnownDigitalWalletProviders,
SticpayWalletFormValues,
VenusPointWalletFormValues,
WalletFormValues
} from 'checkout/state';
import { PaymentResource, PaymentToolType, createPaymentResource } from 'checkout/backend';
import { replaceSpaces } from './replace-spaces';
import { assertUnreachable } from 'checkout/utils';
const getID = (formValues: WalletFormValues): string => {
const getPaymentToolDetails = (formValues: WalletFormValues): { id: string; token?: string } => {
switch (formValues.provider) {
case KnownDigitalWalletProviders.Sticpay:
return (formValues as SticpayWalletFormValues).sticpayAccount;
return {
id: replaceSpaces((formValues as SticpayWalletFormValues).sticpayAccount)
};
case KnownDigitalWalletProviders.Venuspoint:
const venusPointFormValues = formValues as VenusPointWalletFormValues;
return {
id: replaceSpaces(venusPointFormValues.venusPointAccount),
token: md5(replaceSpaces(venusPointFormValues.venusPointPassword))
};
default:
assertUnreachable(formValues.provider);
}
@ -21,7 +36,7 @@ export function* createDigitalWallet(
const paymentTool = {
paymentToolType: PaymentToolType.DigitalWalletData,
provider: formValues.provider,
id: replaceSpaces(getID(formValues))
...getPaymentToolDetails(formValues)
};
return yield call(createPaymentResource, endpoint, token, paymentTool);
}

View File

@ -8,3 +8,8 @@ export interface WalletFormValues extends PayableFormValues {
export interface SticpayWalletFormValues extends WalletFormValues {
sticpayAccount: string;
}
export interface VenusPointWalletFormValues extends WalletFormValues {
venusPointAccount: string;
venusPointPassword: string;
}

View File

@ -6,7 +6,8 @@ export interface PaymentMethod {
}
export enum KnownDigitalWalletProviders {
Sticpay = 'Sticpay'
Sticpay = 'Sticpay',
Venuspoint = 'Venuspoint'
}
export interface DigitalWalletPaymentMethod extends PaymentMethod {

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -153,6 +153,13 @@
"fields": {
"account": "Sticpay account (email)"
}
},
"Venuspoint": {
"name": "Venus Point",
"fields": {
"account": "Venus Point account (email)",
"password": "Venus Point account password"
}
}
}
}

View File

@ -153,6 +153,13 @@
"fields": {
"account": "Stickpayアカウント (email)"
}
},
"Venuspoint": {
"name": "Venus Point",
"fields": {
"account": "Venus Pointアカウント (email)",
"password": "Venus Point account password"
}
}
}
}

View File

@ -153,6 +153,13 @@
"fields": {
"account": "Sticpay account (email)"
}
},
"Venuspoint": {
"name": "Venus Point",
"fields": {
"account": "Venus Point account (email)",
"password": "Venus Point account password"
}
}
}
}