2019-10-03 16:03:29 +00:00
/ * *
* External dependencies
* /
2020-04-24 00:28:29 +00:00
import { _ _ } from '@wordpress/i18n' ;
2019-10-03 16:03:29 +00:00
import { Component , Fragment } from '@wordpress/element' ;
import { compose } from '@wordpress/compose' ;
import apiFetch from '@wordpress/api-fetch' ;
2020-06-10 23:49:27 +00:00
import { withDispatch , withSelect } from '@wordpress/data' ;
2019-10-03 16:03:29 +00:00
import interpolateComponents from 'interpolate-components' ;
2020-04-24 00:28:29 +00:00
import { Button } from '@wordpress/components' ;
2020-03-15 21:45:19 +00:00
import { Form , Link , Stepper , TextControl } from '@woocommerce/components' ;
import { getAdminLink } from '@woocommerce/wc-admin-settings' ;
import { getQuery } from '@woocommerce/navigation' ;
2020-09-03 21:45:40 +00:00
import {
PLUGINS _STORE _NAME ,
OPTIONS _STORE _NAME ,
WCS _NAMESPACE ,
} from '@woocommerce/data' ;
2020-08-13 02:05:22 +00:00
2019-10-03 16:03:29 +00:00
class Stripe extends Component {
constructor ( props ) {
super ( props ) ;
this . state = {
2020-04-24 00:28:29 +00:00
oAuthConnectFailed : false ,
2020-03-15 21:45:19 +00:00
connectURL : null ,
2020-04-24 00:28:29 +00:00
isPending : false ,
2019-10-03 16:03:29 +00:00
} ;
this . updateSettings = this . updateSettings . bind ( this ) ;
}
componentDidMount ( ) {
2020-11-19 02:00:53 +00:00
const { oAuthConnectFailed } = this . state ;
2020-03-15 21:45:19 +00:00
const { stripeSettings } = this . props ;
2019-10-03 16:03:29 +00:00
const query = getQuery ( ) ;
// Handle redirect back from Stripe.
2020-02-14 02:23:21 +00:00
if ( query [ 'stripe-connect' ] && query [ 'stripe-connect' ] === '1' ) {
const isStripeConnected =
stripeSettings . publishable _key && stripeSettings . secret _key ;
2019-10-03 16:03:29 +00:00
if ( isStripeConnected ) {
2020-03-15 21:45:19 +00:00
this . completeMethod ( ) ;
2019-10-03 16:03:29 +00:00
return ;
}
}
2020-11-19 02:00:53 +00:00
if ( ! oAuthConnectFailed ) {
2019-10-03 16:03:29 +00:00
this . fetchOAuthConnectURL ( ) ;
}
}
2020-03-15 21:45:19 +00:00
componentDidUpdate ( prevProps ) {
2020-06-10 23:49:27 +00:00
const { activePlugins } = this . props ;
2020-03-16 11:09:29 +00:00
if (
! prevProps . activePlugins . includes (
'woocommerce-gateway-stripe'
) &&
activePlugins . includes ( 'woocommerce-gateway-stripe' )
) {
this . fetchOAuthConnectURL ( ) ;
}
2019-10-03 16:03:29 +00:00
}
2020-03-15 21:45:19 +00:00
completeMethod ( ) {
const { createNotice , markConfigured } = this . props ;
this . setState ( { isPending : false } ) ;
createNotice (
'success' ,
_ _ ( 'Stripe connected successfully.' , 'woocommerce-admin' )
) ;
markConfigured ( 'stripe' ) ;
}
2019-10-03 16:03:29 +00:00
async fetchOAuthConnectURL ( ) {
2020-03-16 11:09:29 +00:00
const { activePlugins } = this . props ;
if ( ! activePlugins . includes ( 'woocommerce-gateway-stripe' ) ) {
return ;
}
2019-10-03 16:03:29 +00:00
try {
2020-03-15 21:45:19 +00:00
this . setState ( { isPending : true } ) ;
2019-10-03 16:03:29 +00:00
const result = await apiFetch ( {
path : WCS _NAMESPACE + '/connect/stripe/oauth/init' ,
method : 'POST' ,
data : {
2020-03-15 21:45:19 +00:00
returnUrl : getAdminLink (
'admin.php?page=wc-admin&task=payments&method=stripe&stripe-connect=1'
) ,
2019-10-03 16:03:29 +00:00
} ,
} ) ;
if ( ! result || ! result . oauthUrl ) {
this . setState ( {
2020-04-24 00:28:29 +00:00
oAuthConnectFailed : true ,
2020-03-15 21:45:19 +00:00
isPending : false ,
2019-10-03 16:03:29 +00:00
} ) ;
return ;
}
this . setState ( {
connectURL : result . oauthUrl ,
2020-03-15 21:45:19 +00:00
isPending : false ,
2019-10-03 16:03:29 +00:00
} ) ;
} catch ( error ) {
this . setState ( {
2020-04-24 00:28:29 +00:00
oAuthConnectFailed : true ,
2020-03-15 21:45:19 +00:00
isPending : false ,
2019-10-03 16:03:29 +00:00
} ) ;
}
}
2020-04-24 00:28:29 +00:00
renderConnectButton ( ) {
2020-03-15 21:45:19 +00:00
const { connectURL } = this . state ;
2019-10-03 16:03:29 +00:00
return (
2020-06-11 19:22:20 +00:00
< Button isPrimary href = { connectURL } >
2020-04-24 00:28:29 +00:00
{ _ _ ( 'Connect' , 'woocommerce-admin' ) }
< / B u t t o n >
2019-10-03 16:03:29 +00:00
) ;
}
2020-06-10 23:49:27 +00:00
async updateSettings ( values ) {
const { updateOptions , stripeSettings , createNotice } = this . props ;
2019-10-03 16:03:29 +00:00
2020-11-11 20:09:44 +00:00
const prefix = values . publishable _key . match ( /^pk_live_/ )
? ''
: 'test_' ;
2020-06-10 23:49:27 +00:00
const update = await updateOptions ( {
2019-10-03 16:03:29 +00:00
woocommerce _stripe _settings : {
2020-03-15 21:45:19 +00:00
... stripeSettings ,
2020-11-11 20:09:44 +00:00
[ prefix + 'publishable_key' ] : values . publishable _key ,
[ prefix + 'secret_key' ] : values . secret _key ,
testmode : prefix === 'test_' ? 'yes' : 'no' ,
2019-10-03 16:03:29 +00:00
enabled : 'yes' ,
} ,
} ) ;
2020-06-10 23:49:27 +00:00
if ( update . success ) {
this . completeMethod ( ) ;
} else {
createNotice (
'error' ,
_ _ (
2020-11-11 20:09:44 +00:00
'There was a problem saving your payment settings' ,
2020-06-10 23:49:27 +00:00
'woocommerce-admin'
)
) ;
}
2019-10-03 16:03:29 +00:00
}
getInitialConfigValues ( ) {
return {
publishable _key : '' ,
secret _key : '' ,
} ;
}
2020-03-15 21:45:19 +00:00
validateManualConfig ( values ) {
2019-10-03 16:03:29 +00:00
const errors = { } ;
2020-10-05 18:52:12 +00:00
if (
values . publishable _key . match ( /^pk_(live|test)_[a-zA-Z0-9_]+/ ) ===
null
) {
2020-02-14 02:23:21 +00:00
errors . publishable _key = _ _ (
2020-11-11 20:09:44 +00:00
'Please enter a valid publishable key (starting with "pk_").' ,
2020-02-14 02:23:21 +00:00
'woocommerce-admin'
) ;
2019-10-03 16:03:29 +00:00
}
2020-10-05 18:52:12 +00:00
if (
values . secret _key . match ( /^[rs]k_(live|test)_[a-zA-Z0-9_]+/ ) ===
null
) {
2020-02-14 02:23:21 +00:00
errors . secret _key = _ _ (
2020-11-11 20:09:44 +00:00
'Please enter a valid secret key (starting with "sk_" or "rk_").' ,
'woocommerce-admin'
) ;
} else if (
values . secret _key . slice ( 3 , 7 ) !==
values . publishable _key . slice ( 3 , 7 )
) {
errors . secret _key = _ _ (
'Please enter a secret key in the same mode as the publishable key.' ,
2020-02-14 02:23:21 +00:00
'woocommerce-admin'
) ;
2019-10-03 16:03:29 +00:00
}
return errors ;
}
renderManualConfig ( ) {
2020-06-10 23:49:27 +00:00
const { isOptionsUpdating } = this . props ;
2019-10-03 16:03:29 +00:00
const stripeHelp = interpolateComponents ( {
mixedString : _ _ (
2020-07-28 02:32:58 +00:00
'Your API details can be obtained from your {{docsLink}}Stripe account{{/docsLink}}. Don’ t have a Stripe account? {{registerLink}}Create one.{{/registerLink}}' ,
2019-10-03 16:03:29 +00:00
'woocommerce-admin'
) ,
components : {
2020-03-15 21:45:19 +00:00
docsLink : (
2020-02-14 02:23:21 +00:00
< Link
2020-03-15 21:45:19 +00:00
href = "https://stripe.com/docs/keys"
target = "_blank"
type = "external"
/ >
) ,
registerLink : (
< Link
href = "https://dashboard.stripe.com/register"
2020-02-14 02:23:21 +00:00
target = "_blank"
type = "external"
/ >
) ,
2019-10-03 16:03:29 +00:00
} ,
} ) ;
return (
< Form
initialValues = { this . getInitialConfigValues ( ) }
onSubmitCallback = { this . updateSettings }
2020-03-15 21:45:19 +00:00
validate = { this . validateManualConfig }
2019-10-03 16:03:29 +00:00
>
{ ( { getInputProps , handleSubmit } ) => {
return (
< Fragment >
< TextControl
2020-02-14 02:23:21 +00:00
label = { _ _ (
2020-10-05 18:52:12 +00:00
'Publishable Key' ,
2020-02-14 02:23:21 +00:00
'woocommerce-admin'
) }
2019-10-03 16:03:29 +00:00
required
{ ... getInputProps ( 'publishable_key' ) }
/ >
< TextControl
2020-02-14 02:23:21 +00:00
label = { _ _ (
2020-10-05 18:52:12 +00:00
'Secret Key' ,
2020-02-14 02:23:21 +00:00
'woocommerce-admin'
) }
2019-10-03 16:03:29 +00:00
required
{ ... getInputProps ( 'secret_key' ) }
/ >
< Button
2020-03-15 21:45:19 +00:00
isPrimary
2020-06-10 23:49:27 +00:00
isBusy = { isOptionsUpdating }
2020-03-15 21:45:19 +00:00
onClick = { handleSubmit }
2019-10-03 16:03:29 +00:00
>
2020-03-15 21:45:19 +00:00
{ _ _ ( 'Proceed' , 'woocommerce-admin' ) }
2019-10-03 16:03:29 +00:00
< / B u t t o n >
< p > { stripeHelp } < / p >
< / F r a g m e n t >
) ;
} }
< / F o r m >
) ;
}
2020-11-19 02:00:53 +00:00
renderOauthConfig ( ) {
const tosPrompt = interpolateComponents ( {
mixedString : _ _ (
'By clicking "Connect," you agree to the {{tosLink}}Terms of Service{{/tosLink}}. Or {{manualConfigLink}}manually enter your Stripe API details{{/manualConfigLink}} instead.' ,
'woocommerce-admin'
) ,
components : {
tosLink : (
< Link
href = "https://wordpress.com/tos"
target = "_blank"
type = "external"
/ >
) ,
manualConfigLink : (
< Button
isLink
onClick = { ( ) => {
this . setState ( {
connectURL : null ,
} ) ;
} }
/ >
) ,
} ,
} ) ;
return (
< Fragment >
< p > { this . renderConnectButton ( ) } < / p >
{ tosPrompt }
< / F r a g m e n t >
) ;
}
2020-03-15 21:45:19 +00:00
getConnectStep ( ) {
2020-04-24 00:28:29 +00:00
const { connectURL , isPending , oAuthConnectFailed } = this . state ;
2020-03-15 21:45:19 +00:00
const connectStep = {
key : 'connect' ,
label : _ _ ( 'Connect your Stripe account' , 'woocommerce-admin' ) ,
} ;
2019-10-03 16:03:29 +00:00
2020-04-24 00:28:29 +00:00
if ( isPending ) {
return connectStep ;
2019-10-03 16:03:29 +00:00
}
2020-04-24 00:28:29 +00:00
if ( ! oAuthConnectFailed && connectURL ) {
2020-03-15 21:45:19 +00:00
return {
... connectStep ,
description : _ _ (
2020-04-24 00:28:29 +00:00
'A Stripe account is required to process payments.' ,
2020-03-15 21:45:19 +00:00
'woocommerce-admin'
) ,
2020-11-19 02:00:53 +00:00
content : this . renderOauthConfig ( ) ,
2020-03-15 21:45:19 +00:00
} ;
2019-10-03 16:03:29 +00:00
}
2020-03-15 21:45:19 +00:00
return {
... connectStep ,
content : this . renderManualConfig ( ) ,
} ;
}
render ( ) {
2020-06-10 23:49:27 +00:00
const { installStep , isOptionsUpdating } = this . props ;
2020-03-15 21:45:19 +00:00
const { isPending } = this . state ;
return (
< Stepper
isVertical
isPending = {
2020-06-10 23:49:27 +00:00
! installStep . isComplete || isOptionsUpdating || isPending
2020-03-15 21:45:19 +00:00
}
currentStep = { installStep . isComplete ? 'connect' : 'install' }
steps = { [ installStep , this . getConnectStep ( ) ] }
/ >
) ;
2019-10-03 16:03:29 +00:00
}
}
export default compose (
2020-02-14 02:23:21 +00:00
withSelect ( ( select ) => {
2020-06-10 23:49:27 +00:00
const { getOption , isOptionsUpdating } = select ( OPTIONS _STORE _NAME ) ;
2020-11-19 02:00:53 +00:00
const { getActivePlugins } = select ( PLUGINS _STORE _NAME ) ;
2020-03-15 21:45:19 +00:00
return {
activePlugins : getActivePlugins ( ) ,
2020-06-10 23:49:27 +00:00
isOptionsUpdating : isOptionsUpdating ( ) ,
stripeSettings : getOption ( 'woocommerce_stripe_settings' ) || [ ] ,
2019-10-03 16:03:29 +00:00
} ;
} ) ,
2020-02-14 02:23:21 +00:00
withDispatch ( ( dispatch ) => {
2019-10-03 16:03:29 +00:00
const { createNotice } = dispatch ( 'core/notices' ) ;
2020-06-10 23:49:27 +00:00
const { updateOptions } = dispatch ( OPTIONS _STORE _NAME ) ;
2019-10-03 16:03:29 +00:00
return {
createNotice ,
updateOptions ,
} ;
} )
) ( Stripe ) ;