Onboarding: Update payments task flow (https://github.com/woocommerce/woocommerce-admin/pull/3782)
* Add new payment method cards * Refactor payment methods * Track payment configuration and completion client-side * Record tasklist_payment_connect_method event in markConfigured * Record event on payment setup * Add recommended payment method ribbon * Return to payments task even when previously configured
This commit is contained in:
parent
7266042b79
commit
da6f113d18
|
@ -2,7 +2,7 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { Component, cloneElement, Fragment } from '@wordpress/element';
|
||||
import { get } from 'lodash';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import classNames from 'classnames';
|
||||
|
@ -334,7 +334,7 @@ class TaskDashboard extends Component {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { inline } = this.props;
|
||||
const { inline, query } = this.props;
|
||||
const { isCartModalOpen, isWelcomeModalOpen } = this.state;
|
||||
const currentTask = this.getCurrentTask();
|
||||
const listTasks = this.getTasks().map( ( task ) => {
|
||||
|
@ -362,7 +362,9 @@ class TaskDashboard extends Component {
|
|||
<Fragment>
|
||||
<div className="woocommerce-task-dashboard__container">
|
||||
{ currentTask ? (
|
||||
currentTask.container
|
||||
cloneElement( currentTask.container, {
|
||||
query,
|
||||
} )
|
||||
) : (
|
||||
<Fragment>
|
||||
<Card
|
||||
|
|
|
@ -295,98 +295,110 @@
|
|||
}
|
||||
}
|
||||
|
||||
.woocommerce-task-payments {
|
||||
.woocommerce-list__item .woocommerce-list__item-after {
|
||||
align-self: start;
|
||||
margin-left: $gap;
|
||||
margin-top: $gap-large;
|
||||
.woocommerce-task-payment {
|
||||
.woocommerce-card__body {
|
||||
display: flex;
|
||||
padding: $gap-large $gap-larger;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.woocommerce-list__item .woocommerce-list__item-before {
|
||||
max-width: 96px;
|
||||
background: $studio-gray-0;
|
||||
padding: $gap-small;
|
||||
align-self: start;
|
||||
margin-top: $gap;
|
||||
.woocommerce-task-payment__recommended-ribbon {
|
||||
position: absolute;
|
||||
transform: rotate(-45deg) translate(-50%, -50%);
|
||||
background: $studio-gray-80;
|
||||
color: $studio-white;
|
||||
font-size: 11px;
|
||||
line-height: 20px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
padding: 7px $gap-largest;
|
||||
transform-origin: top left;
|
||||
margin-top: 36px;
|
||||
margin-left: 36px;
|
||||
|
||||
span {
|
||||
max-width: 70px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-task-payment__before {
|
||||
margin-right: $gap-larger;
|
||||
|
||||
img {
|
||||
max-width: 72px;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-list__item-title {
|
||||
border-top: 1px solid $studio-gray-5;
|
||||
padding-top: $gap;
|
||||
.woocommerce-task-payment__title {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: $studio-gray-80;
|
||||
margin-top: 0;
|
||||
margin-bottom: $gap-smaller;
|
||||
}
|
||||
|
||||
.woocommerce-task-payments__woocommerce-services-options {
|
||||
border-top: 1px solid $studio-gray-5;
|
||||
margin-top: $gap;
|
||||
.woocommerce-task-payment__content {
|
||||
font-size: 14px;
|
||||
color: $studio-gray-60;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.woocommerce-task-payment__after {
|
||||
margin-left: $gap-larger;
|
||||
padding-top: $gap;
|
||||
|
||||
svg.dashicon.components-checkbox-control__checked {
|
||||
display: block;
|
||||
left: -38px;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.components-checkbox-control__input {
|
||||
margin-left: -$gap-larger;
|
||||
}
|
||||
|
||||
.components-checkbox-control__label {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
padding-left: 0;
|
||||
margin-left: -$gap-large;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.muriel-component {
|
||||
margin-left: $gap-smallest;
|
||||
.components-button.is-button {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@include breakpoint( '<600px' ) {
|
||||
.woocommerce-list__item > .woocommerce-list__item-inner {
|
||||
.woocommerce-card__body {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.woocommerce-list__item-title {
|
||||
border-top: 0;
|
||||
.woocommerce-task-payment__recommended-ribbon {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.woocommerce-list__item .woocommerce-list__item-before {
|
||||
margin-top: 0;
|
||||
.woocommerce-task-payment__before {
|
||||
order: 1;
|
||||
margin-right: auto;
|
||||
margin-bottom: $gap-large;
|
||||
}
|
||||
|
||||
.woocommerce-task-payments__woocommerce-services-options {
|
||||
margin-top: $gap-smaller;
|
||||
border-top: 0;
|
||||
.woocommerce-task-payment__after {
|
||||
position: absolute;
|
||||
right: $gap-larger;
|
||||
top: $gap-large;
|
||||
|
||||
.components-form-toggle {
|
||||
margin-top: $gap-smallest;
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-task-payments__woocommerce-services-options .muriel-component {
|
||||
margin-left: -$gap-larger;
|
||||
}
|
||||
|
||||
.woocommerce-list__item .woocommerce-list__item-after {
|
||||
margin-left: 0;
|
||||
order: 2;
|
||||
align-self: flex-end;
|
||||
margin-top: -$gap-larger;
|
||||
}
|
||||
|
||||
.woocommerce-list__item .woocommerce-list__item-text {
|
||||
.woocommerce-task-payment__text {
|
||||
order: 3;
|
||||
margin-top: $gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.woocommerce-task-payments__woocommerce-services-options .components-checkbox-control__label {
|
||||
margin-left: -$gap-larger;
|
||||
margin-top: -$gap-smaller;
|
||||
}
|
||||
.woocommerce-task-dashboard__container .woocommerce-task-payments .woocommerce-task-payments__actions {
|
||||
text-align: center;
|
||||
|
||||
button.components-button.is-primary {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
button.components-button.is-link {
|
||||
margin: 0;
|
||||
height: auto;
|
||||
color: $studio-gray-60;
|
||||
font-weight: normal;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +1,24 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Fragment, Component } from '@wordpress/element';
|
||||
import { __, sprintf } from '@wordpress/i18n';
|
||||
import { Fragment, cloneElement, Component } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import { get, filter, noop, keys, pickBy, difference } from 'lodash';
|
||||
import { Button, FormToggle, CheckboxControl } from '@wordpress/components';
|
||||
import { get, filter } from 'lodash';
|
||||
import { Button, FormToggle } from '@wordpress/components';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { Card, H } from '@woocommerce/components';
|
||||
import {
|
||||
Form,
|
||||
Card,
|
||||
Stepper,
|
||||
TextControl,
|
||||
List,
|
||||
} from '@woocommerce/components';
|
||||
import { getHistory, getNewPath } from '@woocommerce/navigation';
|
||||
getHistory,
|
||||
getNewPath,
|
||||
updateQueryString,
|
||||
} from '@woocommerce/navigation';
|
||||
import {
|
||||
WC_ASSET_URL as wcAssetUrl,
|
||||
getAdminLink,
|
||||
getSetting,
|
||||
} from '@woocommerce/wc-admin-settings';
|
||||
|
||||
|
@ -35,6 +32,7 @@ import Plugins from '../steps/plugins';
|
|||
import Stripe from './stripe';
|
||||
import Square from './square';
|
||||
import PayPal from './paypal';
|
||||
import { pluginNames } from 'wc-api/onboarding/constants';
|
||||
import Klarna from './klarna';
|
||||
import PayFast from './payfast';
|
||||
|
||||
|
@ -42,64 +40,25 @@ class Payments extends Component {
|
|||
constructor() {
|
||||
super( ...arguments );
|
||||
|
||||
this.chooseMethods = this.chooseMethods.bind( this );
|
||||
this.completeStep = this.completeStep.bind( this );
|
||||
this.recommendedMethod = 'stripe';
|
||||
this.completeTask = this.completeTask.bind( this );
|
||||
this.markConfigured = this.markConfigured.bind( this );
|
||||
this.setMethodRequestPending = this.setMethodRequestPending.bind(
|
||||
this
|
||||
);
|
||||
this.completePluginInstall = this.completePluginInstall.bind( this );
|
||||
|
||||
const { methods, installed, configured } = this.props;
|
||||
|
||||
let step = 'choose';
|
||||
let showIndividualConfigs = false;
|
||||
|
||||
// Figure out which step to show initially if there are still steps to be configured, or redirect back to the task list.
|
||||
if ( methods.length > 0 && configured.length > 0 ) {
|
||||
step = difference( methods, configured )[ 0 ] || '';
|
||||
showIndividualConfigs = true;
|
||||
const stepsLeft = difference( methods, configured ).length;
|
||||
if ( stepsLeft === 0 ) {
|
||||
this.state = {
|
||||
step: 'done',
|
||||
methodRequestPending: false,
|
||||
};
|
||||
this.completeTask();
|
||||
return;
|
||||
}
|
||||
} else if ( installed === 1 && methods.length > 0 ) {
|
||||
// Methods have been installed but not configured yet.
|
||||
step = methods[ 0 ];
|
||||
showIndividualConfigs = true;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
step,
|
||||
showIndividualConfigs,
|
||||
methodRequestPending: false,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
const { methods, configured } = this.props;
|
||||
if (
|
||||
prevProps.configured.length !== configured.length &&
|
||||
methods.length > 0 &&
|
||||
configured.length > 0
|
||||
) {
|
||||
const stepsLeft = difference( methods, configured );
|
||||
const nextStep = stepsLeft[ 0 ];
|
||||
/* eslint-disable react/no-did-update-set-state */
|
||||
this.setState( {
|
||||
step: nextStep,
|
||||
} );
|
||||
/* eslint-enable react/no-did-update-set-state */
|
||||
}
|
||||
this.skipTask = this.skipTask.bind( this );
|
||||
}
|
||||
|
||||
completeTask() {
|
||||
const { createNotice } = this.props;
|
||||
const { configured, createNotice, options, updateOptions } = this.props;
|
||||
|
||||
updateOptions( {
|
||||
woocommerce_task_list_payments: {
|
||||
...options.woocommerce_task_list_payments,
|
||||
completed: 1,
|
||||
},
|
||||
} );
|
||||
|
||||
recordEvent( 'tasklist_payment_done', {
|
||||
configured,
|
||||
} );
|
||||
|
||||
createNotice(
|
||||
'success',
|
||||
|
@ -112,6 +71,23 @@ class Payments extends Component {
|
|||
getHistory().push( getNewPath( {}, '/', {} ) );
|
||||
}
|
||||
|
||||
skipTask() {
|
||||
const { options, updateOptions } = this.props;
|
||||
|
||||
updateOptions( {
|
||||
woocommerce_task_list_payments: {
|
||||
...options.woocommerce_task_list_payments,
|
||||
completed: 1,
|
||||
},
|
||||
} );
|
||||
|
||||
recordEvent( 'tasklist_payment_skip_task', {
|
||||
options: this.getMethodOptions().map( ( method ) => method.key ),
|
||||
} );
|
||||
|
||||
getHistory().push( getNewPath( {}, '/', {} ) );
|
||||
}
|
||||
|
||||
isStripeEnabled() {
|
||||
const { countryCode } = this.props;
|
||||
const stripeCountries = getSetting( 'onboarding', {
|
||||
|
@ -120,116 +96,29 @@ class Payments extends Component {
|
|||
return stripeCountries.includes( countryCode );
|
||||
}
|
||||
|
||||
getInitialValues() {
|
||||
const stripeEmail = getSetting( 'onboarding', { userEmail: '' } )
|
||||
.userEmail;
|
||||
const values = {
|
||||
stripe: this.isStripeEnabled(),
|
||||
paypal: false,
|
||||
klarna_checkout: false,
|
||||
klarna_payments: false,
|
||||
square: false,
|
||||
create_stripe: this.isStripeEnabled(),
|
||||
stripe_email: ( this.isStripeEnabled() && stripeEmail ) || '',
|
||||
payfast: false,
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
validate() {
|
||||
const errors = {};
|
||||
return errors;
|
||||
}
|
||||
|
||||
completeStep() {
|
||||
const { step } = this.state;
|
||||
const steps = this.getSteps();
|
||||
const currentStepIndex = steps.findIndex( ( s ) => s.key === step );
|
||||
const nextStep = steps[ currentStepIndex + 1 ];
|
||||
|
||||
if ( nextStep ) {
|
||||
this.setState( { step: nextStep.key } );
|
||||
} else {
|
||||
getHistory().push( getNewPath( {}, '/', {} ) );
|
||||
}
|
||||
}
|
||||
|
||||
completePluginInstall() {
|
||||
const { completed } = this.props;
|
||||
this.props.updateOptions( {
|
||||
woocommerce_task_list_payments: {
|
||||
completed: completed || false,
|
||||
installed: 1,
|
||||
methods: this.getMethodsToConfigure(),
|
||||
},
|
||||
} );
|
||||
|
||||
this.setState( { showIndividualConfigs: true }, function() {
|
||||
this.completeStep();
|
||||
} );
|
||||
}
|
||||
|
||||
markConfigured( method ) {
|
||||
const { options, methods, configured } = this.props;
|
||||
configured.push( method );
|
||||
const stepsLeft = difference( methods, configured );
|
||||
const { options, configured, updateOptions } = this.props;
|
||||
|
||||
this.props.updateOptions( {
|
||||
getHistory().push( getNewPath( { task: 'payments' }, '/', {} ) );
|
||||
|
||||
if ( configured.includes( method ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: method,
|
||||
} );
|
||||
|
||||
configured.push( method );
|
||||
updateOptions( {
|
||||
woocommerce_task_list_payments: {
|
||||
...options.woocommerce_task_list_payments,
|
||||
configured,
|
||||
completed: stepsLeft.length === 0 ? 1 : 0,
|
||||
},
|
||||
} );
|
||||
|
||||
if ( stepsLeft.length === 0 ) {
|
||||
this.completeTask();
|
||||
}
|
||||
}
|
||||
|
||||
setMethodRequestPending( status ) {
|
||||
this.setState( {
|
||||
methodRequestPending: status,
|
||||
} );
|
||||
}
|
||||
|
||||
// If Jetpack is connected and WCS is enabled, we will offer a streamlined option.
|
||||
renderWooCommerceServicesStripeConnect() {
|
||||
const { getInputProps, values } = this.formData;
|
||||
if ( ! values.stripe ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { isJetpackConnected, activePlugins } = this.props;
|
||||
if (
|
||||
! isJetpackConnected ||
|
||||
! activePlugins.includes( 'woocommerce-services' )
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="woocommerce-task-payments__woocommerce-services-options">
|
||||
<CheckboxControl
|
||||
label={ __(
|
||||
'Create a Stripe account for me',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
{ ...getInputProps( 'create_stripe' ) }
|
||||
/>
|
||||
|
||||
{ values.create_stripe && (
|
||||
<TextControl
|
||||
label={ __( 'Email address', 'woocommerce-admin' ) }
|
||||
{ ...getInputProps( 'stripe_email' ) }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getMethodOptions() {
|
||||
const { getInputProps } = this.formData;
|
||||
const { countryCode, profileItems } = this.props;
|
||||
|
||||
const methods = [
|
||||
|
@ -246,12 +135,12 @@ class Payments extends Component {
|
|||
'and one-touch checkout with Apple Pay.',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
{ this.renderWooCommerceServicesStripeConnect() }
|
||||
</Fragment>
|
||||
),
|
||||
before: <img src={ wcAssetUrl + 'images/stripe.png' } alt="" />,
|
||||
after: <FormToggle { ...getInputProps( 'stripe' ) } />,
|
||||
visible: this.isStripeEnabled(),
|
||||
plugins: [ 'woocommerce-gateway-stripe' ],
|
||||
container: <Stripe markConfigured={ this.markConfigured } />,
|
||||
},
|
||||
{
|
||||
key: 'paypal',
|
||||
|
@ -265,8 +154,9 @@ class Payments extends Component {
|
|||
</Fragment>
|
||||
),
|
||||
before: <img src={ wcAssetUrl + 'images/paypal.png' } alt="" />,
|
||||
after: <FormToggle { ...getInputProps( 'paypal' ) } />,
|
||||
visible: true,
|
||||
plugins: [ 'woocommerce-gateway-paypal-express-checkout' ],
|
||||
container: <PayPal markConfigured={ this.markConfigured } />,
|
||||
},
|
||||
{
|
||||
key: 'klarna_checkout',
|
||||
|
@ -281,8 +171,14 @@ class Payments extends Component {
|
|||
alt=""
|
||||
/>
|
||||
),
|
||||
after: <FormToggle { ...getInputProps( 'klarna_checkout' ) } />,
|
||||
visible: [ 'SE', 'FI', 'NO', 'NL' ].includes( countryCode ),
|
||||
plugins: [ 'klarna-checkout-for-woocommerce' ],
|
||||
container: (
|
||||
<Klarna
|
||||
markConfigured={ this.markConfigured }
|
||||
plugin={ 'checkout' }
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'klarna_payments',
|
||||
|
@ -297,8 +193,14 @@ class Payments extends Component {
|
|||
alt=""
|
||||
/>
|
||||
),
|
||||
after: <FormToggle { ...getInputProps( 'klarna_payments' ) } />,
|
||||
visible: [ 'DK', 'DE', 'AT' ].includes( countryCode ),
|
||||
plugins: [ 'klarna-payments-for-woocommerce' ],
|
||||
container: (
|
||||
<Klarna
|
||||
markConfigured={ this.markConfigured }
|
||||
plugin={ 'payments' }
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: 'square',
|
||||
|
@ -314,12 +216,13 @@ class Payments extends Component {
|
|||
alt=""
|
||||
/>
|
||||
),
|
||||
after: <FormToggle { ...getInputProps( 'square' ) } />,
|
||||
visible:
|
||||
[ 'brick-mortar', 'brick-mortar-other' ].includes(
|
||||
profileItems.selling_venues
|
||||
) &&
|
||||
[ 'US', 'CA', 'JP', 'GB', 'AU' ].includes( countryCode ),
|
||||
plugins: [ 'woocommerce-square' ],
|
||||
container: <Square markConfigured={ this.markConfigured } />,
|
||||
},
|
||||
{
|
||||
key: 'payfast',
|
||||
|
@ -344,279 +247,180 @@ class Payments extends Component {
|
|||
alt="PayFast logo"
|
||||
/>
|
||||
),
|
||||
after: <FormToggle { ...getInputProps( 'payfast' ) } />,
|
||||
visible: [ 'ZA' ].includes( countryCode ),
|
||||
plugins: [ 'woocommerce-payfast-gateway' ],
|
||||
container: <PayFast markConfigured={ this.markConfigured } />,
|
||||
},
|
||||
];
|
||||
|
||||
return filter( methods, ( method ) => method.visible );
|
||||
}
|
||||
|
||||
getMethodsToConfigure() {
|
||||
const { options } = this.props;
|
||||
if (
|
||||
options &&
|
||||
options.woocommerce_task_list_payments &&
|
||||
options.woocommerce_task_list_payments.methods
|
||||
) {
|
||||
return options.woocommerce_task_list_payments.methods;
|
||||
getCurrentMethod() {
|
||||
const { query } = this.props;
|
||||
|
||||
if ( ! query.method ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { values } = this.formData;
|
||||
const methods = {
|
||||
stripe: values.stripe,
|
||||
paypal: values.paypal,
|
||||
'klarna-checkout': values.klarna_checkout,
|
||||
'klarna-payments': values.klarna_payments,
|
||||
square: values.square,
|
||||
payfast: values.payfast,
|
||||
};
|
||||
return keys( pickBy( methods ) );
|
||||
const methods = this.getMethodOptions();
|
||||
|
||||
return methods.find( ( method ) => method.key === query.method );
|
||||
}
|
||||
|
||||
getPluginsToInstall() {
|
||||
const { values } = this.formData;
|
||||
const pluginSlugs = {
|
||||
'woocommerce-gateway-stripe': values.stripe,
|
||||
'woocommerce-gateway-paypal-express-checkout': values.paypal,
|
||||
'klarna-checkout-for-woocommerce': values.klarna_checkout,
|
||||
'klarna-payments-for-woocommerce': values.klarna_payments,
|
||||
'woocommerce-square': values.square,
|
||||
'woocommerce-payfast-gateway': values.payfast,
|
||||
};
|
||||
return keys( pickBy( pluginSlugs ) );
|
||||
}
|
||||
getInstallStep() {
|
||||
const currentMethod = this.getCurrentMethod();
|
||||
|
||||
chooseMethods() {
|
||||
const methodsDisplayed = this.getMethodOptions().map(
|
||||
( method ) => method.key
|
||||
if ( ! currentMethod.plugins || ! currentMethod.plugins.length ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { activePlugins } = this.props;
|
||||
const pluginsToInstall = currentMethod.plugins.filter(
|
||||
( method ) => ! activePlugins.includes( method )
|
||||
);
|
||||
const methodsChosen = this.getMethodsToConfigure();
|
||||
const { values } = this.formData;
|
||||
const createAccount = values.create_stripe || false;
|
||||
const pluginNamesString = currentMethod.plugins
|
||||
.map( ( pluginSlug ) => pluginNames[ pluginSlug ] )
|
||||
.join( ' ' + __( 'and', 'woocommerce-admin' ) + ' ' );
|
||||
|
||||
recordEvent( 'wcadmin_tasklist_payment_choose_method', {
|
||||
payment_methods_displayed: methodsDisplayed,
|
||||
payment_methods_chosen: methodsChosen,
|
||||
create_stripe_account: createAccount,
|
||||
} );
|
||||
|
||||
this.completeStep();
|
||||
}
|
||||
|
||||
getSteps() {
|
||||
const { values } = this.formData;
|
||||
const isMethodSelected =
|
||||
values.stripe ||
|
||||
values.paypal ||
|
||||
values.klarna_checkout ||
|
||||
values.klarna_payments ||
|
||||
values.square ||
|
||||
values.payfast;
|
||||
|
||||
const { showIndividualConfigs } = this.state;
|
||||
const { activePlugins, countryCode, isJetpackConnected } = this.props;
|
||||
|
||||
const manualConfig =
|
||||
isJetpackConnected &&
|
||||
activePlugins.includes( 'woocommerce-services' )
|
||||
? false
|
||||
: true;
|
||||
|
||||
const methods = this.getMethodsToConfigure();
|
||||
|
||||
const steps = [
|
||||
{
|
||||
key: 'choose',
|
||||
label: __( 'Choose payment methods', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
"Select which payment methods you'd like to use",
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<Fragment>
|
||||
<List items={ this.getMethodOptions() } />
|
||||
<Button
|
||||
onClick={ this.chooseMethods }
|
||||
isPrimary
|
||||
disabled={ ! isMethodSelected }
|
||||
>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
),
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
key: 'install',
|
||||
label: __( 'Install selected methods', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
'Install plugins required to offer the selected payment methods',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: ! showIndividualConfigs && (
|
||||
<Plugins
|
||||
onComplete={ () => {
|
||||
this.completePluginInstall();
|
||||
recordEvent( 'tasklist_payment_install_method' );
|
||||
} }
|
||||
autoInstall
|
||||
pluginSlugs={ this.getPluginsToInstall() }
|
||||
/>
|
||||
),
|
||||
visible: true,
|
||||
},
|
||||
{
|
||||
key: 'configure',
|
||||
label: __( 'Configure payment methods', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
'Set up your chosen payment methods',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: <Fragment />,
|
||||
visible: ! showIndividualConfigs,
|
||||
},
|
||||
{
|
||||
key: 'stripe',
|
||||
label: __( 'Enable Stripe', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
'Connect your store to your Stripe account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<Stripe
|
||||
manualConfig={ manualConfig }
|
||||
markConfigured={ this.markConfigured }
|
||||
setRequestPending={ this.setMethodRequestPending }
|
||||
createAccount={ values.create_stripe && ! manualConfig }
|
||||
email={ values.stripe_email }
|
||||
countryCode={ countryCode }
|
||||
returnUrl={ getAdminLink(
|
||||
'admin.php?page=wc-admin&task=payments&stripe-connect=1'
|
||||
) }
|
||||
/>
|
||||
),
|
||||
visible: showIndividualConfigs && methods.includes( 'stripe' ),
|
||||
},
|
||||
{
|
||||
key: 'paypal',
|
||||
label: __( 'Enable PayPal Checkout', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
'Connect your store to your PayPal account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<PayPal
|
||||
markConfigured={ this.markConfigured }
|
||||
setRequestPending={ this.setMethodRequestPending }
|
||||
/>
|
||||
),
|
||||
visible: showIndividualConfigs && methods.includes( 'paypal' ),
|
||||
},
|
||||
{
|
||||
key: 'square',
|
||||
label: __( 'Enable Square', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
'Connect your store to your Square account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<Square
|
||||
markConfigured={ this.markConfigured }
|
||||
setRequestPending={ this.setMethodRequestPending }
|
||||
/>
|
||||
),
|
||||
visible: showIndividualConfigs && methods.includes( 'square' ),
|
||||
},
|
||||
{
|
||||
key: 'klarna-checkout',
|
||||
label: __( 'Klarna', 'woocommerce-admin' ),
|
||||
description: '',
|
||||
content: (
|
||||
<Klarna
|
||||
markConfigured={ this.markConfigured }
|
||||
setRequestPending={ this.setMethodRequestPending }
|
||||
plugin={ 'checkout' }
|
||||
/>
|
||||
),
|
||||
visible:
|
||||
showIndividualConfigs &&
|
||||
methods.includes( 'klarna-checkout' ),
|
||||
},
|
||||
{
|
||||
key: 'klarna-payments',
|
||||
label: __( 'Klarna', 'woocommerce-admin' ),
|
||||
description: '',
|
||||
content: (
|
||||
<Klarna
|
||||
markConfigured={ this.markConfigured }
|
||||
setRequestPending={ this.setMethodRequestPending }
|
||||
plugin={ 'payments' }
|
||||
/>
|
||||
),
|
||||
visible:
|
||||
showIndividualConfigs &&
|
||||
methods.includes( 'klarna-payments' ),
|
||||
},
|
||||
{
|
||||
key: 'payfast',
|
||||
label: __( 'Enable PayFast', 'woocommerce-admin' ),
|
||||
description: __(
|
||||
'Connect your store to your PayFast account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<PayFast
|
||||
markConfigured={ this.markConfigured }
|
||||
setRequestPending={ this.setMethodRequestPending }
|
||||
/>
|
||||
),
|
||||
visible: showIndividualConfigs && methods.includes( 'payfast' ),
|
||||
},
|
||||
];
|
||||
|
||||
return filter( steps, ( step ) => step.visible );
|
||||
return {
|
||||
key: 'install',
|
||||
label: sprintf(
|
||||
__( 'Install %s', 'woocommerce-admin' ),
|
||||
pluginNamesString
|
||||
),
|
||||
content: (
|
||||
<Plugins
|
||||
onComplete={ () => {
|
||||
recordEvent( 'tasklist_payment_install_method', {
|
||||
plugins: currentMethod.plugins,
|
||||
} );
|
||||
} }
|
||||
autoInstall
|
||||
pluginSlugs={ currentMethod.plugins }
|
||||
/>
|
||||
),
|
||||
isComplete: ! pluginsToInstall.length,
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { step, methodRequestPending } = this.state;
|
||||
const currentMethod = this.getCurrentMethod();
|
||||
const { configured, query } = this.props;
|
||||
|
||||
if ( currentMethod ) {
|
||||
return (
|
||||
<Card className="woocommerce-task-payment-method is-narrow">
|
||||
{ cloneElement( currentMethod.container, {
|
||||
query,
|
||||
installStep: this.getInstallStep(),
|
||||
} ) }
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
const methods = this.getMethodOptions();
|
||||
|
||||
return (
|
||||
<Form
|
||||
initialValues={ this.getInitialValues() }
|
||||
onSubmitCallback={ noop }
|
||||
validate={ this.validate }
|
||||
>
|
||||
{ ( formData ) => {
|
||||
this.formData = formData;
|
||||
<div className="woocommerce-task-payments">
|
||||
{ methods.map( ( method ) => {
|
||||
const {
|
||||
before,
|
||||
container,
|
||||
content,
|
||||
key,
|
||||
title,
|
||||
visible,
|
||||
} = method;
|
||||
|
||||
if ( ! visible ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="woocommerce-task-payments">
|
||||
<Card className="is-narrow">
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={
|
||||
methodRequestPending ||
|
||||
step === 'install'
|
||||
}
|
||||
currentStep={ step }
|
||||
steps={ this.getSteps() }
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
<Card
|
||||
key={ key }
|
||||
className="woocommerce-task-payment is-narrow"
|
||||
>
|
||||
<div className="woocommerce-task-payment__before">
|
||||
{ key === this.recommendedMethod &&
|
||||
! configured.includes( key ) && (
|
||||
<div className="woocommerce-task-payment__recommended-ribbon">
|
||||
<span>
|
||||
{ __(
|
||||
'Recommended',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
</span>
|
||||
</div>
|
||||
) }
|
||||
{ before }
|
||||
</div>
|
||||
<div className="woocommerce-task-payment__text">
|
||||
<H className="woocommerce-task-payment__title">
|
||||
{ title }
|
||||
</H>
|
||||
<p className="woocommerce-task-payment__content">
|
||||
{ content }
|
||||
</p>
|
||||
</div>
|
||||
<div className="woocommerce-task-payment__after">
|
||||
{ container ? (
|
||||
<Button
|
||||
isPrimary={
|
||||
key === this.recommendedMethod
|
||||
}
|
||||
isDefault={
|
||||
key !== this.recommendedMethod
|
||||
}
|
||||
onClick={ () => {
|
||||
recordEvent(
|
||||
'tasklist_payment_setup',
|
||||
{
|
||||
options: this.getMethodOptions().map(
|
||||
( option ) => option.key
|
||||
),
|
||||
selected: key,
|
||||
}
|
||||
);
|
||||
updateQueryString( {
|
||||
method: key,
|
||||
} );
|
||||
} }
|
||||
>
|
||||
{ __( 'Set up', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
) : (
|
||||
<FormToggle />
|
||||
) }
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
} }
|
||||
</Form>
|
||||
} ) }
|
||||
<div className="woocommerce-task-payments__actions">
|
||||
{ configured.length === 0 ? (
|
||||
<Button isLink onClick={ this.skipTask }>
|
||||
{ __(
|
||||
'My store doesn’t take payments',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
</Button>
|
||||
) : (
|
||||
<Button isPrimary onClick={ this.completeTask }>
|
||||
{ __( 'Done', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
) }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const {
|
||||
getProfileItems,
|
||||
isJetpackConnected,
|
||||
getActivePlugins,
|
||||
getOptions,
|
||||
} = select( 'wc-api' );
|
||||
const { getProfileItems, getActivePlugins, getOptions } = select(
|
||||
'wc-api'
|
||||
);
|
||||
|
||||
const options = getOptions( [
|
||||
'woocommerce_task_list_payments',
|
||||
|
@ -626,38 +430,18 @@ export default compose(
|
|||
options.woocommerce_default_country
|
||||
);
|
||||
|
||||
const methods = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_payments', 'methods' ],
|
||||
[]
|
||||
);
|
||||
const installed = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_payments', 'installed' ],
|
||||
false
|
||||
);
|
||||
const configured = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_payments', 'configured' ],
|
||||
[]
|
||||
);
|
||||
|
||||
const completed = get(
|
||||
options,
|
||||
[ 'woocommerce_task_list_payments', 'completed' ],
|
||||
false
|
||||
);
|
||||
|
||||
return {
|
||||
countryCode,
|
||||
profileItems: getProfileItems(),
|
||||
activePlugins: getActivePlugins(),
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
options,
|
||||
methods,
|
||||
installed,
|
||||
configured,
|
||||
completed,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
|
|
|
@ -10,12 +10,7 @@ import interpolateComponents from 'interpolate-components';
|
|||
* WooCommerce dependencies
|
||||
*/
|
||||
import { ADMIN_URL as adminUrl } from '@woocommerce/wc-admin-settings';
|
||||
import { Link } from '@woocommerce/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
import { Link, Stepper } from '@woocommerce/components';
|
||||
|
||||
class Klarna extends Component {
|
||||
constructor( props ) {
|
||||
|
@ -24,23 +19,20 @@ class Klarna extends Component {
|
|||
}
|
||||
|
||||
continue() {
|
||||
const { markConfigured, plugin } = this.props;
|
||||
|
||||
const slug =
|
||||
this.props.plugin === 'checkout'
|
||||
? 'klarna-checkout'
|
||||
: 'klarna-payments';
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: slug,
|
||||
} );
|
||||
this.props.markConfigured( slug );
|
||||
plugin === 'checkout' ? 'klarna-checkout' : 'klarna-payments';
|
||||
|
||||
markConfigured( slug );
|
||||
}
|
||||
|
||||
render() {
|
||||
renderConnectStep() {
|
||||
const { plugin } = this.props;
|
||||
|
||||
const slug =
|
||||
this.props.plugin === 'checkout'
|
||||
? 'klarna-checkout'
|
||||
: 'klarna-payments';
|
||||
const section =
|
||||
this.props.plugin === 'checkout' ? 'kco' : 'klarna_payments';
|
||||
plugin === 'checkout' ? 'klarna-checkout' : 'klarna-payments';
|
||||
const section = plugin === 'checkout' ? 'kco' : 'klarna_payments';
|
||||
|
||||
const link = (
|
||||
<Link
|
||||
|
@ -85,6 +77,29 @@ class Klarna extends Component {
|
|||
</Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { installStep } = this.props;
|
||||
|
||||
return (
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={ ! installStep.isComplete }
|
||||
currentStep={ installStep.isComplete ? 'connect' : 'install' }
|
||||
steps={ [
|
||||
installStep,
|
||||
{
|
||||
key: 'connect',
|
||||
label: __(
|
||||
'Connect your Klarna account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: this.renderConnectStep(),
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Klarna;
|
||||
|
|
|
@ -11,12 +11,12 @@ import { withDispatch } from '@wordpress/data';
|
|||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { Form, Link, TextControl } from '@woocommerce/components';
|
||||
import { Form, Link, Stepper, TextControl } from '@woocommerce/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
|
||||
class PayFast extends Component {
|
||||
getInitialConfigValues = () => {
|
||||
|
@ -54,20 +54,39 @@ class PayFast extends Component {
|
|||
return errors;
|
||||
};
|
||||
|
||||
updateSettings = async ( values ) => {
|
||||
componentDidUpdate( prevProps ) {
|
||||
const {
|
||||
createNotice,
|
||||
isSettingsError,
|
||||
updateOptions,
|
||||
isOptionsRequesting,
|
||||
hasOptionsError,
|
||||
markConfigured,
|
||||
setRequestPending,
|
||||
} = this.props;
|
||||
|
||||
setRequestPending( true );
|
||||
if ( prevProps.isOptionsRequesting && ! isOptionsRequesting ) {
|
||||
if ( ! hasOptionsError ) {
|
||||
markConfigured( 'payfast' );
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'PayFast connected successfully', 'woocommerce-admin' )
|
||||
);
|
||||
} else {
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem saving your payment setings',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateSettings = ( values ) => {
|
||||
const { updateOptions } = this.props;
|
||||
|
||||
// Because the PayFast extension only works with the South African Rand
|
||||
// currency, force the store to use it while setting the PayFast settings
|
||||
await updateOptions( {
|
||||
updateOptions( {
|
||||
woocommerce_currency: 'ZAR',
|
||||
woocommerce_payfast_settings: {
|
||||
merchant_id: values.merchant_id,
|
||||
|
@ -76,30 +95,10 @@ class PayFast extends Component {
|
|||
enabled: 'yes',
|
||||
},
|
||||
} );
|
||||
|
||||
if ( ! isSettingsError ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'payfast',
|
||||
} );
|
||||
setRequestPending( false );
|
||||
markConfigured( 'payfast' );
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'PayFast connected successfully', 'woocommerce-admin' )
|
||||
);
|
||||
} else {
|
||||
setRequestPending( false );
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem saving your payment setings',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
renderConnectStep() {
|
||||
const { isOptionsRequesting } = this.props;
|
||||
const helpText = interpolateComponents( {
|
||||
mixedString: __(
|
||||
'Your API details can be obtained from your {{link}}PayFast account{{/link}}',
|
||||
|
@ -149,16 +148,14 @@ class PayFast extends Component {
|
|||
required
|
||||
{ ...getInputProps( 'pass_phrase' ) }
|
||||
/>
|
||||
<Button onClick={ handleSubmit } isPrimary>
|
||||
<Button
|
||||
isPrimary
|
||||
isBusy={ isOptionsRequesting }
|
||||
onClick={ handleSubmit }
|
||||
>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
<Button
|
||||
onClick={ () => {
|
||||
this.props.markConfigured( 'payfast' );
|
||||
} }
|
||||
>
|
||||
{ __( 'Skip', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
||||
<p>{ helpText }</p>
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -166,9 +163,52 @@ class PayFast extends Component {
|
|||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { installStep, isOptionsRequesting } = this.props;
|
||||
|
||||
return (
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={ ! installStep.isComplete || isOptionsRequesting }
|
||||
currentStep={ installStep.isComplete ? 'connect' : 'install' }
|
||||
steps={ [
|
||||
installStep,
|
||||
{
|
||||
key: 'connect',
|
||||
label: __(
|
||||
'Connect your PayFast account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: this.renderConnectStep(),
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptionsError, isUpdateOptionsRequesting } = select(
|
||||
'wc-api'
|
||||
);
|
||||
const isOptionsRequesting = Boolean(
|
||||
isUpdateOptionsRequesting( [
|
||||
'woocommerce_currency',
|
||||
'woocommerce_payfast_settings',
|
||||
] )
|
||||
);
|
||||
const hasOptionsError = getOptionsError( [
|
||||
'woocommerce_currency',
|
||||
'woocommerce_payfast_settings',
|
||||
] );
|
||||
|
||||
return {
|
||||
hasOptionsError,
|
||||
isOptionsRequesting,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
const { createNotice } = dispatch( 'core/notices' );
|
||||
const { updateOptions } = dispatch( 'wc-api' );
|
||||
|
|
|
@ -2,110 +2,84 @@
|
|||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { Component, Fragment } from '@wordpress/element';
|
||||
import { compose } from '@wordpress/compose';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { WC_ADMIN_NAMESPACE } from 'wc-api/constants';
|
||||
import { Form, Link, Stepper, TextControl } from '@woocommerce/components';
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { Form, Link, TextControl } from '@woocommerce/components';
|
||||
import { WC_ADMIN_NAMESPACE } from 'wc-api/constants';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
|
||||
class PayPal extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
|
||||
this.state = {
|
||||
autoConnectFailed: false,
|
||||
connectURL: '',
|
||||
showManualConfiguration: props.manualConfig,
|
||||
isPending: false,
|
||||
};
|
||||
|
||||
this.updateSettings = this.updateSettings.bind( this );
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { showManualConfiguration } = this.state;
|
||||
const { autoConnectFailed } = this.state;
|
||||
const { createNotice, markConfigured } = this.props;
|
||||
|
||||
const query = getQuery();
|
||||
// Handle redirect back from PayPal
|
||||
if ( query[ 'paypal-connect' ] ) {
|
||||
if ( query[ 'paypal-connect' ] === '1' ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'paypal',
|
||||
} );
|
||||
this.props.markConfigured( 'paypal' );
|
||||
this.props.createNotice(
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'PayPal connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
markConfigured( 'paypal' );
|
||||
return;
|
||||
}
|
||||
|
||||
/* eslint-disable react/no-did-mount-set-state */
|
||||
this.setState( {
|
||||
showManualConfiguration: true,
|
||||
autoConnectFailed: true,
|
||||
} );
|
||||
/* eslint-enable react/no-did-mount-set-state */
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! showManualConfiguration ) {
|
||||
if ( ! autoConnectFailed ) {
|
||||
this.fetchOAuthConnectURL();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate( prevProps, prevState ) {
|
||||
if (
|
||||
prevState.showManualConfiguration === true &&
|
||||
this.state.showManualConfiguration === false
|
||||
) {
|
||||
this.fetchOAuthConnectURL();
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.optionsIsRequesting === false &&
|
||||
this.props.optionsIsRequesting === true
|
||||
) {
|
||||
this.props.setRequestPending( true );
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.optionsIsRequesting === true &&
|
||||
this.props.optionsIsRequesting === false
|
||||
) {
|
||||
this.props.setRequestPending( false );
|
||||
}
|
||||
}
|
||||
|
||||
async fetchOAuthConnectURL() {
|
||||
this.props.setRequestPending( true );
|
||||
this.setState( { isPending: true } );
|
||||
try {
|
||||
const result = await apiFetch( {
|
||||
path: WC_ADMIN_NAMESPACE + '/onboarding/plugins/connect-paypal',
|
||||
method: 'POST',
|
||||
} );
|
||||
if ( ! result || ! result.connectUrl ) {
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( {
|
||||
showManualConfiguration: true,
|
||||
autoConnectFailed: true,
|
||||
} );
|
||||
return;
|
||||
}
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( {
|
||||
connectURL: result.connectUrl,
|
||||
isPending: false,
|
||||
} );
|
||||
} catch ( error ) {
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( {
|
||||
showManualConfiguration: true,
|
||||
autoConnectFailed: true,
|
||||
isPending: false,
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
@ -123,14 +97,14 @@ class PayPal extends Component {
|
|||
const {
|
||||
createNotice,
|
||||
isSettingsError,
|
||||
options,
|
||||
updateOptions,
|
||||
markConfigured,
|
||||
} = this.props;
|
||||
|
||||
this.props.setRequestPending( true );
|
||||
await updateOptions( {
|
||||
woocommerce_ppec_paypal_settings: {
|
||||
...this.props.options.woocommerce_ppec_paypal_settings,
|
||||
...options.woocommerce_ppec_paypal_settings,
|
||||
api_username: values.api_username,
|
||||
api_password: values.api_password,
|
||||
enabled: 'yes',
|
||||
|
@ -138,17 +112,12 @@ class PayPal extends Component {
|
|||
} );
|
||||
|
||||
if ( ! isSettingsError ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'paypal',
|
||||
} );
|
||||
this.props.setRequestPending( false );
|
||||
markConfigured( 'paypal' );
|
||||
this.props.createNotice(
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'PayPal connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
markConfigured( 'paypal' );
|
||||
} else {
|
||||
this.props.setRequestPending( false );
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
|
@ -186,7 +155,7 @@ class PayPal extends Component {
|
|||
}
|
||||
|
||||
renderManualConfig() {
|
||||
const { optionsIsRequesting } = this.props;
|
||||
const { isOptionsRequesting } = this.props;
|
||||
const link = (
|
||||
<Link
|
||||
href="https://docs.woocommerce.com/document/paypal-express-checkout/#section-8"
|
||||
|
@ -233,19 +202,11 @@ class PayPal extends Component {
|
|||
<Button
|
||||
onClick={ handleSubmit }
|
||||
isPrimary
|
||||
disabled={ optionsIsRequesting }
|
||||
disabled={ isOptionsRequesting }
|
||||
>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={ () => {
|
||||
this.props.markConfigured( 'paypal' );
|
||||
} }
|
||||
>
|
||||
{ __( 'Skip', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
||||
<p>{ help }</p>
|
||||
</Fragment>
|
||||
);
|
||||
|
@ -254,18 +215,50 @@ class PayPal extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
getConnectStep() {
|
||||
const { autoConnectFailed, connectURL, isPending } = this.state;
|
||||
const connectStep = {
|
||||
key: 'connect',
|
||||
label: __( 'Connect your PayPal account', 'woocommerce-admin' ),
|
||||
};
|
||||
|
||||
if ( isPending ) {
|
||||
return connectStep;
|
||||
}
|
||||
|
||||
if ( ! autoConnectFailed && connectURL ) {
|
||||
return {
|
||||
...connectStep,
|
||||
description: __(
|
||||
'A Paypal account is required to process payments. You will be redirected to the Paypal website to create the connection.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: this.renderConnectButton(),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...connectStep,
|
||||
description: __(
|
||||
'Connect your store to your PayPal account. Don’t have a PayPal account? Create one.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: this.renderManualConfig(),
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { connectURL, showManualConfiguration } = this.state;
|
||||
const { installStep } = this.props;
|
||||
const { isPending } = this.state;
|
||||
|
||||
if ( connectURL && ! showManualConfiguration ) {
|
||||
return this.renderConnectButton();
|
||||
}
|
||||
|
||||
if ( showManualConfiguration ) {
|
||||
return this.renderManualConfig();
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={ ! installStep.isComplete || isPending }
|
||||
currentStep={ installStep.isComplete ? 'connect' : 'install' }
|
||||
steps={ [ installStep, this.getConnectStep() ] }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -277,13 +270,13 @@ export default compose(
|
|||
withSelect( ( select ) => {
|
||||
const { getOptions, isGetOptionsRequesting } = select( 'wc-api' );
|
||||
const options = getOptions( [ 'woocommerce_ppec_paypal_settings' ] );
|
||||
const optionsIsRequesting = Boolean(
|
||||
const isOptionsRequesting = Boolean(
|
||||
isGetOptionsRequesting( [ 'woocommerce_ppec_paypal_settings' ] )
|
||||
);
|
||||
|
||||
return {
|
||||
options,
|
||||
optionsIsRequesting,
|
||||
isOptionsRequesting,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
|
|
|
@ -5,68 +5,50 @@ import { __ } from '@wordpress/i18n';
|
|||
import { Component, Fragment } from '@wordpress/element';
|
||||
import apiFetch from '@wordpress/api-fetch';
|
||||
import { Button } from '@wordpress/components';
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { withDispatch } from '@wordpress/data';
|
||||
import { compose } from '@wordpress/compose';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { WC_ADMIN_NAMESPACE } from 'wc-api/constants';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
import { Stepper } from '@woocommerce/components';
|
||||
|
||||
class Square extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
|
||||
this.state = {
|
||||
showSkipButton: false,
|
||||
isPending: false,
|
||||
};
|
||||
|
||||
this.connect = this.connect.bind( this );
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { createNotice, markConfigured } = this.props;
|
||||
const query = getQuery();
|
||||
// Handle redirect back from Square
|
||||
if ( query[ 'square-connect' ] ) {
|
||||
if ( query[ 'square-connect' ] === '1' ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'square',
|
||||
} );
|
||||
this.props.markConfigured( 'square' );
|
||||
this.props.createNotice(
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'Square connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
markConfigured( 'square' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate( prevProps ) {
|
||||
if (
|
||||
prevProps.optionsIsRequesting === false &&
|
||||
this.props.optionsIsRequesting === true
|
||||
) {
|
||||
this.props.setRequestPending( true );
|
||||
}
|
||||
|
||||
if (
|
||||
prevProps.optionsIsRequesting === true &&
|
||||
this.props.optionsIsRequesting === false
|
||||
) {
|
||||
this.props.setRequestPending( false );
|
||||
}
|
||||
}
|
||||
|
||||
async connect() {
|
||||
const { updateOptions } = this.props;
|
||||
this.props.setRequestPending( true );
|
||||
const { createNotice, options, updateOptions } = this.props;
|
||||
this.setState( { isPending: true } );
|
||||
|
||||
updateOptions( {
|
||||
woocommerce_stripe_settings: {
|
||||
...this.props.options.woocommerce_stripe_settings,
|
||||
...options.woocommerce_stripe_settings,
|
||||
enabled: 'yes',
|
||||
},
|
||||
} );
|
||||
|
@ -83,39 +65,55 @@ class Square extends Component {
|
|||
} );
|
||||
|
||||
if ( ! result || ! result.connectUrl ) {
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( { showSkipButton: true } );
|
||||
this.props.createNotice( 'error', errorMessage );
|
||||
this.setState( { isPending: false } );
|
||||
createNotice( 'error', errorMessage );
|
||||
return;
|
||||
}
|
||||
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( { isPending: true } );
|
||||
window.location = result.connectUrl;
|
||||
} catch ( error ) {
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( { showSkipButton: true } );
|
||||
this.props.createNotice( 'error', errorMessage );
|
||||
this.setState( { isPending: false } );
|
||||
createNotice( 'error', errorMessage );
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { showSkipButton } = this.state;
|
||||
const { installStep } = this.props;
|
||||
const { isPending } = this.state;
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Button isPrimary isDefault onClick={ this.connect }>
|
||||
{ __( 'Connect', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
{ showSkipButton && (
|
||||
<Button
|
||||
onClick={ () => {
|
||||
this.props.markConfigured( 'square' );
|
||||
} }
|
||||
>
|
||||
{ __( 'Skip', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
) }
|
||||
</Fragment>
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={ ! installStep.isComplete || isPending }
|
||||
currentStep={ installStep.isComplete ? 'connect' : 'install' }
|
||||
steps={ [
|
||||
installStep,
|
||||
{
|
||||
key: 'connect',
|
||||
label: __(
|
||||
'Connect your Square account',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
description: __(
|
||||
'A Square account is required to process payments. You will be redirected to the Square website to create the connection.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: (
|
||||
<Fragment>
|
||||
<Button
|
||||
isPrimary
|
||||
isDefault
|
||||
isBusy={ isPending }
|
||||
onClick={ this.connect }
|
||||
>
|
||||
{ __( 'Connect', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</Fragment>
|
||||
),
|
||||
},
|
||||
] }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,124 +8,149 @@ import apiFetch from '@wordpress/api-fetch';
|
|||
import { withDispatch } from '@wordpress/data';
|
||||
import interpolateComponents from 'interpolate-components';
|
||||
import { Button, Modal } from '@wordpress/components';
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { get } from 'lodash';
|
||||
|
||||
/**
|
||||
* WooCommerce dependencies
|
||||
*/
|
||||
import { Form, Link, TextControl } from '@woocommerce/components';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
import { Form, Link, Stepper, TextControl } from '@woocommerce/components';
|
||||
import { getAdminLink } from '@woocommerce/wc-admin-settings';
|
||||
import { getQuery } from '@woocommerce/navigation';
|
||||
import { WCS_NAMESPACE } from 'wc-api/constants';
|
||||
import { recordEvent } from 'lib/tracks';
|
||||
import withSelect from 'wc-api/with-select';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { getCountryCode } from 'dashboard/utils';
|
||||
|
||||
class Stripe extends Component {
|
||||
constructor( props ) {
|
||||
super( props );
|
||||
|
||||
this.state = {
|
||||
errorMessage: '',
|
||||
connectURL: '',
|
||||
showConnectionButtons:
|
||||
! props.manualConfig && ! props.createAccount,
|
||||
showManualConfiguration: props.manualConfig,
|
||||
autoConnectFailed: false,
|
||||
connectURL: null,
|
||||
errorTitle: null,
|
||||
errorMessage: null,
|
||||
isPending: true,
|
||||
};
|
||||
|
||||
this.autoCreateAccount = this.autoCreateAccount.bind( this );
|
||||
this.updateSettings = this.updateSettings.bind( this );
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const { createAccount, options } = this.props;
|
||||
const { showConnectionButtons } = this.state;
|
||||
|
||||
const { stripeSettings } = this.props;
|
||||
const query = getQuery();
|
||||
|
||||
// Handle redirect back from Stripe.
|
||||
if ( query[ 'stripe-connect' ] && query[ 'stripe-connect' ] === '1' ) {
|
||||
const stripeSettings = get(
|
||||
options,
|
||||
[ 'woocommerce_stripe_settings' ],
|
||||
[]
|
||||
);
|
||||
const isStripeConnected =
|
||||
stripeSettings.publishable_key && stripeSettings.secret_key;
|
||||
|
||||
if ( isStripeConnected ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'stripe',
|
||||
} );
|
||||
this.props.markConfigured( 'stripe' );
|
||||
this.props.createNotice(
|
||||
'success',
|
||||
__( 'Stripe connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
this.completeMethod();
|
||||
return;
|
||||
}
|
||||
|
||||
/* eslint-disable react/no-did-mount-set-state */
|
||||
this.setState( {
|
||||
showConnectionButtons: false,
|
||||
showManualConfiguration: true,
|
||||
autoConnectFailed: true,
|
||||
} );
|
||||
/* eslint-enable react/no-did-mount-set-state */
|
||||
return;
|
||||
}
|
||||
|
||||
if ( createAccount ) {
|
||||
this.autoCreateAccount();
|
||||
}
|
||||
|
||||
if ( showConnectionButtons ) {
|
||||
if ( ! this.requiresManualConfig() ) {
|
||||
this.fetchOAuthConnectURL();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate( prevProps, prevState ) {
|
||||
if (
|
||||
prevState.showConnectionButtons === false &&
|
||||
this.state.showConnectionButtons
|
||||
) {
|
||||
this.fetchOAuthConnectURL();
|
||||
componentDidUpdate( prevProps ) {
|
||||
const {
|
||||
createNotice,
|
||||
isOptionsRequesting,
|
||||
hasOptionsError,
|
||||
} = this.props;
|
||||
|
||||
if ( prevProps.isOptionsRequesting && ! isOptionsRequesting ) {
|
||||
if ( ! hasOptionsError ) {
|
||||
this.completeMethod();
|
||||
} else {
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem saving your payment setings',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
requiresManualConfig() {
|
||||
const { activePlugins, isJetpackConnected } = this.props;
|
||||
const { autoConnectFailed } = this.state;
|
||||
|
||||
return (
|
||||
! isJetpackConnected ||
|
||||
! activePlugins.includes( 'woocommerce-services' ) ||
|
||||
autoConnectFailed
|
||||
);
|
||||
}
|
||||
|
||||
completeMethod() {
|
||||
const { createNotice, markConfigured } = this.props;
|
||||
|
||||
this.setState( { isPending: false } );
|
||||
|
||||
createNotice(
|
||||
'success',
|
||||
__( 'Stripe connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
|
||||
markConfigured( 'stripe' );
|
||||
}
|
||||
|
||||
async fetchOAuthConnectURL() {
|
||||
const { returnUrl } = this.props;
|
||||
try {
|
||||
this.props.setRequestPending( true );
|
||||
this.setState( { isPending: true } );
|
||||
const result = await apiFetch( {
|
||||
path: WCS_NAMESPACE + '/connect/stripe/oauth/init',
|
||||
method: 'POST',
|
||||
data: {
|
||||
returnUrl,
|
||||
returnUrl: getAdminLink(
|
||||
'admin.php?page=wc-admin&task=payments&method=stripe&stripe-connect=1'
|
||||
),
|
||||
},
|
||||
} );
|
||||
if ( ! result || ! result.oauthUrl ) {
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( {
|
||||
showConnectionButtons: false,
|
||||
showManualConfiguration: true,
|
||||
autoConnectFailed: true,
|
||||
isPending: false,
|
||||
} );
|
||||
return;
|
||||
}
|
||||
this.props.setRequestPending( false );
|
||||
this.setState( {
|
||||
connectURL: result.oauthUrl,
|
||||
isPending: false,
|
||||
} );
|
||||
} catch ( error ) {
|
||||
this.props.setRequestPending( false );
|
||||
// Fallback to manual configuration if the OAuth URL cannot be grabbed.
|
||||
this.setState( {
|
||||
showConnectionButtons: false,
|
||||
showManualConfiguration: true,
|
||||
autoConnectFailed: true,
|
||||
isPending: false,
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
async autoCreateAccount() {
|
||||
const { email, countryCode } = this.props;
|
||||
async autoCreateAccount( values ) {
|
||||
const { countryCode } = this.props;
|
||||
const { connectURL } = this.state;
|
||||
const { email } = values;
|
||||
|
||||
try {
|
||||
this.props.setRequestPending( true );
|
||||
this.setState( { isPending: true } );
|
||||
|
||||
const result = await apiFetch( {
|
||||
path: WCS_NAMESPACE + '/connect/stripe/account',
|
||||
method: 'POST',
|
||||
|
@ -136,29 +161,13 @@ class Stripe extends Component {
|
|||
} );
|
||||
|
||||
if ( result ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'stripe',
|
||||
} );
|
||||
this.props.setRequestPending( false );
|
||||
this.props.markConfigured( 'stripe' );
|
||||
this.props.createNotice(
|
||||
'success',
|
||||
__( 'Stripe connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
this.completeMethod();
|
||||
return;
|
||||
}
|
||||
} catch ( error ) {
|
||||
this.props.setRequestPending( false );
|
||||
let errorTitle, errorMessage;
|
||||
// This seems to be the best way to handle this.
|
||||
// github.com/Automattic/woocommerce-services/blob/cfb6173deb3c72897ee1d35b8fdcf29c5a93dea2/woocommerce-services.php#L563-L570
|
||||
if (
|
||||
error.message.indexOf(
|
||||
'Account already exists for the provided email'
|
||||
) === -1
|
||||
) {
|
||||
errorTitle = __( 'Stripe', 'woocommerce-admin' );
|
||||
errorMessage = interpolateComponents( {
|
||||
} catch {
|
||||
if ( ! connectURL ) {
|
||||
const errorTitle = __( 'Stripe', 'woocommerce-admin' );
|
||||
const errorMessage = interpolateComponents( {
|
||||
mixedString: sprintf(
|
||||
__(
|
||||
'We tried to create a Stripe account automatically for {{strong}}%s{{/strong}}, but an error occured. Please try connecting manually to continue.',
|
||||
|
@ -170,30 +179,17 @@ class Stripe extends Component {
|
|||
strong: <strong />,
|
||||
},
|
||||
} );
|
||||
} else {
|
||||
errorTitle = __(
|
||||
'You already have a Stripe account',
|
||||
'woocommerce-admin'
|
||||
);
|
||||
errorMessage = interpolateComponents( {
|
||||
mixedString: sprintf(
|
||||
__(
|
||||
'We tried to create a Stripe account automatically for {{strong}}%s{{/strong}}, but one already exists. Please sign in and connect to continue.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
email
|
||||
),
|
||||
components: {
|
||||
strong: <strong />,
|
||||
},
|
||||
} );
|
||||
}
|
||||
|
||||
this.setState( {
|
||||
showConnectionButtons: true,
|
||||
errorTitle,
|
||||
errorMessage,
|
||||
} );
|
||||
this.setState( {
|
||||
autoConnectFailed: true,
|
||||
errorTitle,
|
||||
errorMessage,
|
||||
isPending: false,
|
||||
} );
|
||||
} else {
|
||||
// An account with that email may exist so send them to Stripe to connect via oAuth.
|
||||
window.location = connectURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,7 +199,7 @@ class Stripe extends Component {
|
|||
<Modal
|
||||
title={ errorTitle }
|
||||
onRequestClose={ () =>
|
||||
this.setState( { errorMessage: '', errorTitle: '' } )
|
||||
this.setState( { errorMessage: null, errorTitle: null } )
|
||||
}
|
||||
className="woocommerce-task-payments__stripe-error-modal"
|
||||
>
|
||||
|
@ -216,8 +212,8 @@ class Stripe extends Component {
|
|||
isDefault
|
||||
onClick={ () =>
|
||||
this.setState( {
|
||||
errorMessage: '',
|
||||
errorTitle: '',
|
||||
errorMessage: null,
|
||||
errorTitle: null,
|
||||
} )
|
||||
}
|
||||
>
|
||||
|
@ -228,53 +224,53 @@ class Stripe extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
renderConnectButton() {
|
||||
const { connectURL } = this.state;
|
||||
renderAutoConnect() {
|
||||
const { isPending } = this.state;
|
||||
|
||||
return (
|
||||
<Button isPrimary isDefault href={ connectURL }>
|
||||
{ __( 'Connect', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
<Form
|
||||
initialValues={ {
|
||||
email: '',
|
||||
} }
|
||||
onSubmitCallback={ this.autoCreateAccount }
|
||||
validate={ this.validateAutoConnect }
|
||||
>
|
||||
{ ( { getInputProps, handleSubmit } ) => {
|
||||
return (
|
||||
<div className="woocommerce-task-payments__woocommerce-services-options">
|
||||
<TextControl
|
||||
label={ __(
|
||||
'Email address',
|
||||
'woocommerce-admin'
|
||||
) }
|
||||
{ ...getInputProps( 'email' ) }
|
||||
/>
|
||||
<Button
|
||||
isPrimary
|
||||
isDefault
|
||||
isBusy={ isPending }
|
||||
onClick={ handleSubmit }
|
||||
>
|
||||
{ __( 'Connect', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
} }
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
async updateSettings( values ) {
|
||||
const {
|
||||
createNotice,
|
||||
isSettingsError,
|
||||
updateOptions,
|
||||
markConfigured,
|
||||
} = this.props;
|
||||
updateSettings( values ) {
|
||||
const { updateOptions, stripeSettings } = this.props;
|
||||
|
||||
this.props.setRequestPending( true );
|
||||
await updateOptions( {
|
||||
updateOptions( {
|
||||
woocommerce_stripe_settings: {
|
||||
...this.props.options.woocommerce_stripe_settings,
|
||||
...stripeSettings,
|
||||
publishable_key: values.publishable_key,
|
||||
secret_key: values.secret_key,
|
||||
enabled: 'yes',
|
||||
},
|
||||
} );
|
||||
|
||||
if ( ! isSettingsError ) {
|
||||
recordEvent( 'tasklist_payment_connect_method', {
|
||||
payment_method: 'stripe',
|
||||
} );
|
||||
this.props.setRequestPending( false );
|
||||
markConfigured( 'stripe' );
|
||||
this.props.createNotice(
|
||||
'success',
|
||||
__( 'Stripe connected successfully.', 'woocommerce-admin' )
|
||||
);
|
||||
} else {
|
||||
this.props.setRequestPending( false );
|
||||
createNotice(
|
||||
'error',
|
||||
__(
|
||||
'There was a problem saving your payment settings.',
|
||||
'woocommerce-admin'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getInitialConfigValues() {
|
||||
|
@ -284,7 +280,7 @@ class Stripe extends Component {
|
|||
};
|
||||
}
|
||||
|
||||
validate( values ) {
|
||||
validateManualConfig( values ) {
|
||||
const errors = {};
|
||||
|
||||
if ( ! values.publishable_key ) {
|
||||
|
@ -303,16 +299,34 @@ class Stripe extends Component {
|
|||
return errors;
|
||||
}
|
||||
|
||||
validateAutoConnect( values ) {
|
||||
const errors = {};
|
||||
|
||||
if ( ! values.email ) {
|
||||
errors.email = __( 'Please enter your email', 'woocommerce-admin' );
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
renderManualConfig() {
|
||||
const { isOptionsRequesting } = this.props;
|
||||
const stripeHelp = interpolateComponents( {
|
||||
mixedString: __(
|
||||
'Your API details can be obtained from your {{link}}Stripe account{{/link}}',
|
||||
'Your API details can be obtained from your {{docsLink}}Stripe account{{/docsLink}}. Don’t have a Stripe account? {{registerLink}}Create one.{{/registerLink}}',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
components: {
|
||||
link: (
|
||||
docsLink: (
|
||||
<Link
|
||||
href="https://stripe.com/docs/account"
|
||||
href="https://stripe.com/docs/keys"
|
||||
target="_blank"
|
||||
type="external"
|
||||
/>
|
||||
),
|
||||
registerLink: (
|
||||
<Link
|
||||
href="https://dashboard.stripe.com/register"
|
||||
target="_blank"
|
||||
type="external"
|
||||
/>
|
||||
|
@ -324,7 +338,7 @@ class Stripe extends Component {
|
|||
<Form
|
||||
initialValues={ this.getInitialConfigValues() }
|
||||
onSubmitCallback={ this.updateSettings }
|
||||
validate={ this.validate }
|
||||
validate={ this.validateManualConfig }
|
||||
>
|
||||
{ ( { getInputProps, handleSubmit } ) => {
|
||||
return (
|
||||
|
@ -346,16 +360,12 @@ class Stripe extends Component {
|
|||
{ ...getInputProps( 'secret_key' ) }
|
||||
/>
|
||||
|
||||
<Button onClick={ handleSubmit } isPrimary>
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={ () => {
|
||||
this.props.markConfigured( 'stripe' );
|
||||
} }
|
||||
isPrimary
|
||||
isBusy={ isOptionsRequesting }
|
||||
onClick={ handleSubmit }
|
||||
>
|
||||
{ __( 'Skip', 'woocommerce-admin' ) }
|
||||
{ __( 'Proceed', 'woocommerce-admin' ) }
|
||||
</Button>
|
||||
|
||||
<p>{ stripeHelp }</p>
|
||||
|
@ -366,36 +376,98 @@ class Stripe extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
errorMessage,
|
||||
showConnectionButtons,
|
||||
connectURL,
|
||||
showManualConfiguration,
|
||||
} = this.state;
|
||||
getConnectStep() {
|
||||
const { autoConnectFailed, connectURL, errorMessage } = this.state;
|
||||
const connectStep = {
|
||||
key: 'connect',
|
||||
label: __( 'Connect your Stripe account', 'woocommerce-admin' ),
|
||||
};
|
||||
|
||||
if ( errorMessage ) {
|
||||
return this.renderErrorModal();
|
||||
return {
|
||||
...connectStep,
|
||||
content: this.renderErrorModal(),
|
||||
};
|
||||
}
|
||||
|
||||
if ( showConnectionButtons && connectURL ) {
|
||||
return this.renderConnectButton();
|
||||
if ( ! this.requiresManualConfig() ) {
|
||||
// We may still be fetching the connect URL.
|
||||
if ( ! autoConnectFailed && ! connectURL ) {
|
||||
return connectStep;
|
||||
}
|
||||
|
||||
return {
|
||||
...connectStep,
|
||||
description: __(
|
||||
'A Stripe account is required to process payments. We’ll create an account for you if you don’t have one already.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: this.renderAutoConnect(),
|
||||
};
|
||||
}
|
||||
|
||||
if ( showManualConfiguration ) {
|
||||
return this.renderManualConfig();
|
||||
}
|
||||
return {
|
||||
...connectStep,
|
||||
description: __(
|
||||
'Connect your store to your Stripe account. Don’t have a Stripe account? Create one.',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
content: this.renderManualConfig(),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
render() {
|
||||
const { installStep, isOptionsRequesting } = this.props;
|
||||
const { isPending } = this.state;
|
||||
|
||||
return (
|
||||
<Stepper
|
||||
isVertical
|
||||
isPending={
|
||||
! installStep.isComplete || isOptionsRequesting || isPending
|
||||
}
|
||||
currentStep={ installStep.isComplete ? 'connect' : 'install' }
|
||||
steps={ [ installStep, this.getConnectStep() ] }
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withSelect( ( select ) => {
|
||||
const { getOptions } = select( 'wc-api' );
|
||||
const options = getOptions( [ 'woocommerce_stripe_settings' ] );
|
||||
return {
|
||||
const {
|
||||
getActivePlugins,
|
||||
getOptions,
|
||||
getOptionsError,
|
||||
isJetpackConnected,
|
||||
isUpdateOptionsRequesting,
|
||||
} = select( 'wc-api' );
|
||||
const options = getOptions( [
|
||||
'woocommerce_stripe_settings',
|
||||
'woocommerce_default_country',
|
||||
] );
|
||||
const countryCode = getCountryCode(
|
||||
options.woocommerce_default_country
|
||||
);
|
||||
const stripeSettings = get(
|
||||
options,
|
||||
[ 'woocommerce_stripe_settings' ],
|
||||
[]
|
||||
);
|
||||
const isOptionsRequesting = Boolean(
|
||||
isUpdateOptionsRequesting( [ 'woocommerce_stripe_settings' ] )
|
||||
);
|
||||
const hasOptionsError = getOptionsError( [
|
||||
'woocommerce_stripe_settings',
|
||||
] );
|
||||
|
||||
return {
|
||||
activePlugins: getActivePlugins(),
|
||||
countryCode,
|
||||
hasOptionsError,
|
||||
isJetpackConnected: isJetpackConnected(),
|
||||
isOptionsRequesting,
|
||||
stripeSettings,
|
||||
};
|
||||
} ),
|
||||
withDispatch( ( dispatch ) => {
|
||||
|
|
|
@ -7,18 +7,39 @@ import { __ } from '@wordpress/i18n';
|
|||
* Plugin slugs and names as key/value pairs.
|
||||
*/
|
||||
export const pluginNames = {
|
||||
jetpack: __( 'Jetpack', 'woocommerce-admin' ),
|
||||
'woocommerce-services': __( 'WooCommerce Services', 'woocommerce-admin' ),
|
||||
'mailchimp-for-woocommerce': __(
|
||||
'Mailchimp for WooCommerce',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'facebook-for-woocommerce': __(
|
||||
'Facebook for WooCommerce',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
jetpack: __( 'Jetpack', 'woocommerce-admin' ),
|
||||
'klarna-checkout-for-woocommerce': __(
|
||||
'Klarna Checkout for WooCommerce',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'klarna-payments-for-woocommerce': __(
|
||||
'Klarna Payments for WooCommerce',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'mailchimp-for-woocommerce': __(
|
||||
'Mailchimp for WooCommerce',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'woocommerce-gateway-paypal-express-checkout': __(
|
||||
'WooCommerce PayPal',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'woocommerce-gateway-stripe': __(
|
||||
'WooCommerce Stripe',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'woocommerce-payfast-gateway': __(
|
||||
'WooCommerce PayFast',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'woocommerce-services': __( 'WooCommerce Services', 'woocommerce-admin' ),
|
||||
'woocommerce-shipstation-integration': __(
|
||||
'WooCommerce ShipStation Gateway',
|
||||
'woocommerce-admin'
|
||||
),
|
||||
'woocommerce-square': __( 'WooCommerce Square', 'woocommerce-admin' ),
|
||||
};
|
||||
|
|
|
@ -317,7 +317,7 @@ class OnboardingPlugins extends \WC_REST_Data_Controller {
|
|||
$redirect_url = apply_filters( 'woocommerce_admin_onboarding_jetpack_connect_redirect_url', esc_url_raw( $request['redirect_url'] ) );
|
||||
$connect_url = \Jetpack::init()->build_connect_url( true, $redirect_url, 'woocommerce-onboarding' );
|
||||
|
||||
$calypso_env = defined( 'WOOCOMMERCE_CALYPSO_ENVIRONMENT' ) && in_array( WOOCOMMERCE_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ) ) ? WOOCOMMERCE_CALYPSO_ENVIRONMENT : 'production';
|
||||
$calypso_env = defined( 'WOOCOMMERCE_CALYPSO_ENVIRONMENT' ) && in_array( WOOCOMMERCE_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ), true ) ? WOOCOMMERCE_CALYPSO_ENVIRONMENT : 'production';
|
||||
$connect_url = add_query_arg( array( 'calypso_env' => $calypso_env ), $connect_url );
|
||||
|
||||
return( array(
|
||||
|
@ -372,7 +372,7 @@ class OnboardingPlugins extends \WC_REST_Data_Controller {
|
|||
\WC_Helper_API::url( 'oauth/authorize' )
|
||||
);
|
||||
|
||||
if ( defined( 'WOOCOMMERCE_CALYPSO_ENVIRONMENT' ) && in_array( WOOCOMMERCE_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ) ) ) {
|
||||
if ( defined( 'WOOCOMMERCE_CALYPSO_ENVIRONMENT' ) && in_array( WOOCOMMERCE_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ), true ) ) {
|
||||
$connect_url = add_query_arg(
|
||||
array(
|
||||
'calypso_env' => WOOCOMMERCE_CALYPSO_ENVIRONMENT,
|
||||
|
@ -463,12 +463,12 @@ class OnboardingPlugins extends \WC_REST_Data_Controller {
|
|||
'env' => 'live',
|
||||
'wc_ppec_ips_admin_nonce' => wp_create_nonce( 'wc_ppec_ips' ),
|
||||
),
|
||||
wc_admin_url( '&task=payments&paypal-connect-finish=1' )
|
||||
wc_admin_url( '&task=payments&method=paypal&paypal-connect-finish=1' )
|
||||
);
|
||||
|
||||
// https://github.com/woocommerce/woocommerce-gateway-paypal-express-checkout/blob/b6df13ba035038aac5024d501e8099a37e13d6cf/includes/class-wc-gateway-ppec-ips-handler.php#L79-L93.
|
||||
$query_args = array(
|
||||
'redirect' => urlencode( $redirect_url ),
|
||||
'redirect' => rawurlencode( $redirect_url ),
|
||||
'countryCode' => WC()->countries->get_base_country(),
|
||||
'merchantId' => md5( site_url( '/' ) . time() ),
|
||||
);
|
||||
|
@ -491,9 +491,9 @@ class OnboardingPlugins extends \WC_REST_Data_Controller {
|
|||
|
||||
$url = \WooCommerce\Square\Handlers\Connection::CONNECT_URL_PRODUCTION;
|
||||
|
||||
$redirect_url = wp_nonce_url( wc_admin_url( '&task=payments&square-connect-finish=1' ), 'wc_square_connected' );
|
||||
$redirect_url = wp_nonce_url( wc_admin_url( '&task=payments&method=square&square-connect-finish=1' ), 'wc_square_connected' );
|
||||
$args = array(
|
||||
'redirect' => urlencode( urlencode( $redirect_url ) ),
|
||||
'redirect' => rawurlencode( rawurlencode( $redirect_url ) ),
|
||||
'scopes' => implode(
|
||||
',',
|
||||
array(
|
||||
|
|
|
@ -655,7 +655,7 @@ class Onboarding {
|
|||
*/
|
||||
public function is_loading( $is_loading ) {
|
||||
$show_profiler = self::should_show_profiler();
|
||||
$is_dashboard = ! isset( $_GET['path'] ); // WPCS: csrf ok.
|
||||
$is_dashboard = ! isset( $_GET['path'] ); // phpcs:ignore csrf ok.
|
||||
|
||||
if ( ! $show_profiler || ! $is_dashboard ) {
|
||||
return $is_loading;
|
||||
|
@ -675,7 +675,7 @@ class Onboarding {
|
|||
if ( substr( $location, -strlen( $settings_page ) ) === $settings_page ) {
|
||||
$settings_array = (array) get_option( 'woocommerce_ppec_paypal_settings', array() );
|
||||
$connected = isset( $settings_array['api_username'] ) && isset( $settings_array['api_password'] ) ? true : false;
|
||||
return wc_admin_url( '&task=payments&paypal-connect=' . $connected );
|
||||
return wc_admin_url( '&task=payments&method=paypal&paypal-connect=' . $connected );
|
||||
}
|
||||
return $location;
|
||||
}
|
||||
|
@ -686,7 +686,7 @@ class Onboarding {
|
|||
public function finish_paypal_connect() {
|
||||
if (
|
||||
! Loader::is_admin_page() ||
|
||||
! isset( $_GET['paypal-connect-finish'] ) // WPCS: CSRF ok.
|
||||
! isset( $_GET['paypal-connect-finish'] ) // phpcs:ignore CSRF ok.
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -711,7 +711,7 @@ class Onboarding {
|
|||
public function overwrite_square_redirect( $location, $status ) {
|
||||
$settings_page = 'page=wc-settings&tab=square';
|
||||
if ( substr( $location, -strlen( $settings_page ) ) === $settings_page ) {
|
||||
return wc_admin_url( '&task=payments&square-connect=1' );
|
||||
return wc_admin_url( '&task=payments&method=square&square-connect=1' );
|
||||
}
|
||||
return $location;
|
||||
}
|
||||
|
@ -722,7 +722,7 @@ class Onboarding {
|
|||
public function finish_square_connect() {
|
||||
if (
|
||||
! Loader::is_admin_page() ||
|
||||
! isset( $_GET['square-connect-finish'] ) // WPCS: CSRF ok.
|
||||
! isset( $_GET['square-connect-finish'] ) // phpcs:ignore CSRF ok.
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -873,9 +873,9 @@ class Onboarding {
|
|||
* Allows quick access to testing the calypso parts of onboarding.
|
||||
*/
|
||||
public static function calypso_tests() {
|
||||
$calypso_env = defined( 'WOOCOMMERCE_CALYPSO_ENVIRONMENT' ) && in_array( WOOCOMMERCE_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ) ) ? WOOCOMMERCE_CALYPSO_ENVIRONMENT : 'production';
|
||||
$calypso_env = defined( 'WOOCOMMERCE_CALYPSO_ENVIRONMENT' ) && in_array( WOOCOMMERCE_CALYPSO_ENVIRONMENT, array( 'development', 'wpcalypso', 'horizon', 'stage' ), true ) ? WOOCOMMERCE_CALYPSO_ENVIRONMENT : 'production';
|
||||
|
||||
if ( Loader::is_admin_page() && class_exists( 'Jetpack' ) && isset( $_GET['test_wc_jetpack_connect'] ) && 1 === absint( $_GET['test_wc_jetpack_connect'] ) ) { // WPCS: CSRF ok.
|
||||
if ( Loader::is_admin_page() && class_exists( 'Jetpack' ) && isset( $_GET['test_wc_jetpack_connect'] ) && 1 === absint( $_GET['test_wc_jetpack_connect'] ) ) { // phpcs:ignore CSRF ok.
|
||||
$redirect_url = esc_url_raw(
|
||||
add_query_arg(
|
||||
array(
|
||||
|
@ -892,7 +892,7 @@ class Onboarding {
|
|||
exit;
|
||||
}
|
||||
|
||||
if ( Loader::is_admin_page() && isset( $_GET['test_wc_helper_connect'] ) && 1 === absint( $_GET['test_wc_helper_connect'] ) ) { // WPCS: CSRF ok.
|
||||
if ( Loader::is_admin_page() && isset( $_GET['test_wc_helper_connect'] ) && 1 === absint( $_GET['test_wc_helper_connect'] ) ) { // phpcs:ignore CSRF ok.
|
||||
include_once WC_ABSPATH . 'includes/admin/helper/class-wc-helper-api.php';
|
||||
|
||||
$redirect_uri = wc_admin_url( '&task=connect&wccom-connected=1' );
|
||||
|
@ -942,12 +942,12 @@ class Onboarding {
|
|||
public static function reset_profiler() {
|
||||
if (
|
||||
! Loader::is_admin_page() ||
|
||||
! isset( $_GET['reset_profiler'] ) // WPCS: CSRF ok.
|
||||
! isset( $_GET['reset_profiler'] ) // phpcs:ignore CSRF ok.
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$previous = 1 === absint( $_GET['reset_profiler'] );
|
||||
$previous = 1 === absint( $_GET['reset_profiler'] ); // phpcs:ignore CSRF ok.
|
||||
$new_value = ! $previous;
|
||||
|
||||
wc_admin_record_tracks_event(
|
||||
|
@ -978,12 +978,12 @@ class Onboarding {
|
|||
public static function reset_task_list() {
|
||||
if (
|
||||
! Loader::is_admin_page() ||
|
||||
! isset( $_GET['reset_task_list'] ) // WPCS: CSRF ok.
|
||||
! isset( $_GET['reset_task_list'] ) // phpcs:ignore CSRF ok.
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
$new_value = 1 === absint( $_GET['reset_task_list'] ) ? 'no' : 'yes'; // WPCS: CSRF ok.
|
||||
$new_value = 1 === absint( $_GET['reset_task_list'] ) ? 'no' : 'yes'; // phpcs:ignore CSRF ok.
|
||||
update_option( 'woocommerce_task_list_hidden', $new_value );
|
||||
wp_safe_redirect( wc_admin_url() );
|
||||
exit;
|
||||
|
|
Loading…
Reference in New Issue