Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add BLIK payment method #4043

Merged
merged 26 commits into from
Mar 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ad20d93
Add BLIK payment method behind feature flag
cesarcosta99 Mar 11, 2025
7b060c3
Update PHP unit tests to account for BLIK
cesarcosta99 Mar 11, 2025
850a6e8
Add BLIK-specific logic for processing a payment
cesarcosta99 Mar 17, 2025
b40906b
Merge branch 'develop' into add/3954-blik-payment-processing
cesarcosta99 Mar 19, 2025
d6a93af
Fix test constant value
cesarcosta99 Mar 19, 2025
db3d746
Fix test constant value
cesarcosta99 Mar 19, 2025
18f29dd
Add changelog entry
cesarcosta99 Mar 19, 2025
00592e3
Update BLIK icon and description
cesarcosta99 Mar 19, 2025
285f887
Update BLIK checkout icon
cesarcosta99 Mar 19, 2025
9ff9843
Handle premature validation on BLIK code input
cesarcosta99 Mar 19, 2025
a5ab0f7
Fix PHP test to include Amazon Pay
cesarcosta99 Mar 19, 2025
d1d941d
Update comment
cesarcosta99 Mar 19, 2025
5ece865
Update variable name
cesarcosta99 Mar 21, 2025
1da5950
Make BLIK compatible with Blocks checkout
cesarcosta99 Mar 21, 2025
89d9c16
Merge branch 'develop' into add/3954-blik-payment-processing
cesarcosta99 Mar 21, 2025
6bfb0bc
Fix indentation after fixing conflicts
cesarcosta99 Mar 21, 2025
f5d7f0f
Fix indentation
cesarcosta99 Mar 24, 2025
25c18c0
Merge branch 'develop' into add/3954-blik-payment-processing
cesarcosta99 Mar 24, 2025
7ce2f97
Fix indentation
cesarcosta99 Mar 24, 2025
351e95f
Add BLIK feature flag to dev tools mapping
cesarcosta99 Mar 24, 2025
513f23c
Merge branch 'develop' into add/3954-blik-payment-processing
cesarcosta99 Mar 24, 2025
e449338
Move BLIK code element out of the payment processing logic
cesarcosta99 Mar 25, 2025
4f334fb
Refactor repeated BLIK code validation helper
cesarcosta99 Mar 25, 2025
7ae5136
Extract BLIK code validation clearing to helper
cesarcosta99 Mar 25, 2025
511371b
Merge branch 'develop' into add/3954-blik-payment-processing
cesarcosta99 Mar 25, 2025
176f785
Merge branch 'develop' into add/3954-blik-payment-processing
cesarcosta99 Mar 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions assets/images/blik.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
* Tweak - Updates the Single Payment Element setting copy. Now it is labeled "Smart Checkout".
* Update - Enable/disable Amazon Pay by adding/removing it from the enabled payment methods list.
* Add - Add ACSS payment tokenization.
* Add - Add BLIK payment method.
* Fix - Prevent reuse of payment intents when order total doesn't match intent amount.
* Update - Update payment method type for Amazon Pay orders.
* Fix - Compatibility with email preview in the Auth Requested email
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ValidatedTextInput } from '@woocommerce/blocks-checkout';
import { __ } from '@wordpress/i18n';
import { useState } from 'react';

const BlikCodeElement = () => {
const [ blikCode, setBlikCode ] = useState( '' );

return (
<>
<ValidatedTextInput
id="wc-stripe-blik-code"
label="BLIK Code"
maxLength={ 6 }
onChange={ setBlikCode }
pattern="[0-9]{6}"
value={ blikCode }
customValidityMessage={ ( validity ) => {
if ( validity.valueMissing ) {
return __(
'Please enter a valid BLIK code',
'woocommerce-gateway-stripe'
);
}

if ( validity.patternMismatch ) {
return __(
'BLIK Code is invalid',
'woocommerce-gateway-stripe'
);
}
} }
required
/>
<p
style={ {
marginTop: 'var(--wp--preset--spacing--50)',
} }
>
{ __(
'After submitting your order, please authorize the payment in your mobile banking application.',
'woocommerce-gateway-stripe'
) }
</p>
</>
);
};

export default BlikCodeElement;
82 changes: 55 additions & 27 deletions client/blocks/upe/upe-deferred-intent-creation/payment-processor.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ import { useEffect, useState, useRef } from 'react';
* Internal dependencies
*/
import { usePaymentCompleteHandler, usePaymentFailHandler } from '../hooks';
import BlikCodeElement from './blik-code-element';
import { getBlocksConfiguration } from 'wcstripe/blocks/utils';
import WCStripeAPI from 'wcstripe/api';
import {
maybeShowCashAppLimitNotice,
removeCashAppLimitNotice,
} from 'wcstripe/stripe-utils/cash-app-limit-notice-handler';
import { isLinkEnabled } from 'wcstripe/stripe-utils';
import { isLinkEnabled, validateBlikCode } from 'wcstripe/stripe-utils';
import {
PAYMENT_METHOD_BLIK,
PAYMENT_METHOD_CARD,
PAYMENT_METHOD_CASHAPP,
} from 'wcstripe/stripe-utils/constants';
Expand Down Expand Up @@ -158,6 +160,7 @@ const PaymentProcessor = ( {
: '';
const paymentMethodsConfig = getBlocksConfiguration()?.paymentMethodsConfig;
const gatewayConfig = getPaymentMethods()[ upeMethods[ paymentMethodId ] ];
const isBlikSelected = selectedPaymentMethodType === PAYMENT_METHOD_BLIK;

// Make sure shouldSavePayment is set to true if the cart contains a subscription.
// shouldSavePayment might be set to false because the cart contains a subscription and so the save checkbox isn't shown.
Expand Down Expand Up @@ -192,7 +195,8 @@ const PaymentProcessor = ( {
};
}

if ( ! isPaymentElementComplete ) {
// BLIK is a special case which is not handled through the Stripe element.
if ( ! ( isPaymentElementComplete || isBlikSelected ) ) {
return {
type: 'error',
message: __(
Expand Down Expand Up @@ -222,29 +226,38 @@ const PaymentProcessor = ( {
};
}

await validateElements( elements );
if ( isBlikSelected ) {
validateBlikCode();
} else {
await validateElements( elements );
}

const billingAddress = billing.billingAddress;
const params = {
billing_details: {
name: `${ billingAddress.first_name } ${ billingAddress.last_name }`.trim(),
email: billingAddress.email,
phone: billingAddress.phone || null, // Phone is optional, but an empty string is not allowed by Stripe.
address: {
city: billingAddress.city,
country: billingAddress.country,
line1: billingAddress.address_1,
line2: billingAddress.address_2,
postal_code: billingAddress.postcode,
state: billingAddress.state,
},
},
};
const paymentMethodData = isBlikSelected
? {
billing_details: params.billing_details,
blik: {},
type: selectedPaymentMethodType,
}
: { elements, params };
const paymentMethodObject = await api
.getStripe()
.createPaymentMethod( {
elements,
params: {
billing_details: {
name: `${ billingAddress.first_name } ${ billingAddress.last_name }`.trim(),
email: billingAddress.email,
phone: billingAddress.phone || null, // Phone is optional, but an empty string is not allowed by Stripe.
address: {
city: billingAddress.city,
country: billingAddress.country,
line1: billingAddress.address_1,
line2: billingAddress.address_2,
postal_code: billingAddress.postcode,
state: billingAddress.state,
},
},
},
} );
.createPaymentMethod( paymentMethodData );

if ( paymentMethodObject.error ) {
return {
Expand All @@ -253,10 +266,19 @@ const PaymentProcessor = ( {
};
}

const dynamicPaymentData = isBlikSelected
? {
'wc-stripe-blik-code': document?.querySelector(
'#wc-stripe-blik-code'
)?.value,
}
: {};

return {
type: 'success',
meta: {
paymentMethodData: {
...dynamicPaymentData,
payment_method: upeMethods[ paymentMethodId ],
wc_payment_intent_id: paymentIntentId ?? '',
'wc-stripe-is-deferred-intent': true,
Expand Down Expand Up @@ -296,6 +318,8 @@ const PaymentProcessor = ( {
isPaymentElementComplete,
billing.billingAddress,
paymentIntentId,
selectedPaymentMethodType,
isBlikSelected,
]
);

Expand Down Expand Up @@ -355,12 +379,16 @@ const PaymentProcessor = ( {
__html: testingInstructionsIfAppropriate,
} }
/>
<PaymentElement
options={ getStripeElementOptions() }
onChange={ onSelectedPaymentMethodChange }
onLoadError={ setHasLoadError }
className="wcstripe-payment-element"
/>
{ isBlikSelected ? (
<BlikCodeElement />
) : (
<PaymentElement
options={ getStripeElementOptions() }
onChange={ onSelectedPaymentMethodChange }
onLoadError={ setHasLoadError }
className="wcstripe-payment-element"
/>
) }
</>
);
};
Expand Down
8 changes: 7 additions & 1 deletion client/classic/upe/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import jQuery from 'jquery';
import WCStripeAPI from '../../api';
import { getStripeServerData, getUPETerms } from '../../stripe-utils';
import {
getStripeServerData,
getUPETerms,
maybeClearBlikCodeValidation,
} from '../../stripe-utils';
import { legacyHashchangeHandler } from './legacy-support';
import './style.scss';
import './deferred-intent.js';
Expand Down Expand Up @@ -306,6 +310,8 @@ jQuery( function ( $ ) {
} else {
removeCashAppLimitNotice();
}

maybeClearBlikCodeValidation();
} );

// Add terms parameter to UPE if save payment information checkbox is checked.
Expand Down
20 changes: 18 additions & 2 deletions client/classic/upe/payment-processing.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import {
unblockBlockCheckout,
resetBlockCheckoutPaymentState,
getAdditionalSetupIntentData,
validateBlikCode,
} from '../../stripe-utils';
import { getFontRulesFromPage } from '../../styles/upe';
import {
PAYMENT_INTENT_STATUS_REQUIRES_ACTION,
PAYMENT_METHOD_BLIK,
PAYMENT_METHOD_BOLETO,
PAYMENT_METHOD_CARD,
PAYMENT_METHOD_CASHAPP,
Expand Down Expand Up @@ -276,9 +278,19 @@ function createStripePaymentMethod(
};
}

// BLIK uses a controlled form instead of Stripe Elements.
const paymentMethodData =
paymentMethodType === PAYMENT_METHOD_BLIK
? {
billing_details: params?.billing_details,
blik: {},
type: paymentMethodType,
}
: { elements, params };

return api
.getStripe( paymentMethodType )
.createPaymentMethod( { elements, params } )
.createPaymentMethod( paymentMethodData )
.then( ( paymentMethod ) => {
if ( paymentMethod.error ) {
throw paymentMethod.error;
Expand Down Expand Up @@ -418,7 +430,11 @@ export const processPayment = (
);
}

await validateElements( elements );
if ( paymentMethodType === PAYMENT_METHOD_BLIK ) {
validateBlikCode( jQueryForm );
} else {
await validateElements( elements );
}

const paymentMethodObject = await createStripePaymentMethod(
api,
Expand Down
13 changes: 13 additions & 0 deletions client/payment-method-icons/blik/icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
12 changes: 12 additions & 0 deletions client/payment-method-icons/blik/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react';
import styled from '@emotion/styled';
import IconWithShell from '../styles/icon-with-shell';
import icon from './icon.svg';

const Wrapper = styled( IconWithShell )`
background: #010101;
`;

const BlikIcon = ( props ) => <Wrapper { ...props } src={ icon } />;

export default BlikIcon;
2 changes: 2 additions & 0 deletions client/payment-method-icons/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import AlipayIcon from './alipay';
import BlikIcon from './blik';
import CreditCardIcon from './cards';
import GiropayIcon from './giropay';
import KlarnaIcon from './klarna';
Expand All @@ -22,6 +23,7 @@ import StripeIcon from './stripe';

export default {
alipay: AlipayIcon,
blik: BlikIcon,
card: CreditCardIcon,
giropay: GiropayIcon,
klarna: KlarnaIcon,
Expand Down
17 changes: 17 additions & 0 deletions client/payment-methods-map.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
PAYMENT_METHOD_BACS,
PAYMENT_METHOD_BANCONTACT,
PAYMENT_METHOD_BECS,
PAYMENT_METHOD_BLIK,
PAYMENT_METHOD_BOLETO,
PAYMENT_METHOD_CARD,
PAYMENT_METHOD_CASHAPP,
Expand All @@ -31,6 +32,8 @@ const isAcssEnabled = window.wc_stripe_settings_params?.is_acss_enabled === '1';
const isBacsEnabled = window.wc_stripe_settings_params?.is_bacs_enabled === '1';
const isBecsDebitEnabled =
window.wc_stripe_settings_params?.is_becs_debit_enabled === '1';
const isBlikEnabled = window.wc_stripe_settings_params?.is_blik_enabled === '1';

const paymentMethodsMap = {
card: {
id: PAYMENT_METHOD_CARD,
Expand Down Expand Up @@ -324,4 +327,18 @@ if ( isBecsDebitEnabled ) {
};
}

// Enable BLIK according to feature flag value.
if ( isBlikEnabled ) {
paymentMethodsMap.blik = {
id: PAYMENT_METHOD_BLIK,
label: 'BLIK',
description: __(
'BLIK enables customers in Poland to pay directly via online payouts from their bank account.',
'woocommerce-gateway-stripe'
),
Icon: icons.blik,
currencies: [ 'PLN' ],
};
}

export default paymentMethodsMap;
3 changes: 3 additions & 0 deletions client/stripe-utils/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/**
* Payment method name constants without the `stripe` prefix
*/
export const PAYMENT_METHOD_BLIK = 'blik';
export const PAYMENT_METHOD_CARD = 'card';
export const PAYMENT_METHOD_GIROPAY = 'giropay';
export const PAYMENT_METHOD_EPS = 'eps';
Expand Down Expand Up @@ -32,6 +33,7 @@ export const PAYMENT_METHOD_BECS = 'au_becs_debit';
*/
export const PAYMENT_METHOD_STRIPE_CARD = 'stripe';
export const PAYMENT_METHOD_STRIPE_ACH = 'stripe_us_bank_account';
export const PAYMENT_METHOD_STRIPE_BLIK = 'stripe_blik';
export const PAYMENT_METHOD_STRIPE_GIROPAY = 'stripe_giropay';
export const PAYMENT_METHOD_STRIPE_EPS = 'stripe_eps';
export const PAYMENT_METHOD_STRIPE_IDEAL = 'stripe_ideal';
Expand All @@ -55,6 +57,7 @@ export const PAYMENT_METHOD_STRIPE_BECS = 'stripe_au_becs_debit';

export function getPaymentMethodsConstants() {
return {
blik: PAYMENT_METHOD_STRIPE_BLIK,
card: PAYMENT_METHOD_STRIPE_CARD,
us_bank_account: PAYMENT_METHOD_STRIPE_ACH,
au_becs_debit: PAYMENT_METHOD_STRIPE_BECS,
Expand Down
Loading
Loading