Skip to content

Commit

Permalink
2.1.2 -> 2.1.3 Merge changes (#1856)
Browse files Browse the repository at this point in the history
* THEMES-1520: Enable testing (and linting THEMES-1460) (#1809)

* THEMES-1520: Enable testing (and linting THEMES-1460)

* Re-enable test on github action

* try to get stylelint to ignore jsx

* Attempt #2 to get stylelint to ignore jsx

* ASUB-7844 PayPal block (#1806)

* move stripe logic into a button

* add paypal logic

* clean up and try adding styles

* clean up logic and create hooks

* update styles for paypal

* address feedback

* add more strings for intl

* address feedback

* address feedback

* add test for PayPal block

---------

Co-authored-by: Vito Galatro <[email protected]>

* ASUB-7844 Fix issue where identity is not defined in paymentInfo (#1831)

fix issue where identity is not defined in paymentInfo

* Fix paywall Issue (#1824)

* fixing ArcP.run

* attending feedback

* attending feedback

* attending feedback

* attending feedback

* attending feedback

* ASUB-8002 Update payment method (#1813)

* changes

* payments

* remove env file

* update payment method - stripe Intents

* update payment method

* fixing typo

* solving conflict

---------

Co-authored-by: Vito Galatro <[email protected]>

* ASUB-7844 Bug fix (#1836)

fix issue with redirect when user is not logged in and adjust setTimeout delay

* THEMES-1589: Subs phrases added for all locales (#1837)

THEMES-1589: properly added new subs phrases.

* Improvement update payment method - missing message (#1839)

improvement update payment method- missing message

* THEMES-1600: fixed more merge conflicts.

* THEMES-1600: yet more merge conflicts.

---------

Co-authored-by: nschubach <[email protected]>
Co-authored-by: edwardcho1231 <[email protected]>
Co-authored-by: LauraPinilla <[email protected]>
  • Loading branch information
4 people authored Dec 21, 2023
1 parent 0e35554 commit 0e3d9fb
Show file tree
Hide file tree
Showing 15 changed files with 21,899 additions and 1,224 deletions.
23 changes: 21 additions & 2 deletions blocks/identity-block/components/login/index.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import { useEffect, useState } from "react";
import { useIdentity } from "@wpmedia/arc-themes-components";
import appendURLParams from "../../utils/append-url-params";
import validateURL from "../../utils/validate-redirect-url";
import useOIDCLogin from "../../utils/useOIDCLogin";

const useLogin = ({ isAdmin, redirectURL, redirectToPreviousPage, loggedInPageLocation, isOIDC }) => {
const useLogin = ({
isAdmin,
redirectURL,
redirectToPreviousPage,
loggedInPageLocation,
isOIDC,
}) => {

const { Identity } = useIdentity();
const validatedRedirectURL = validateURL(redirectURL);
const [redirectToURL, setRedirectToURL] = useState(validatedRedirectURL);
Expand All @@ -13,7 +21,18 @@ const useLogin = ({ isAdmin, redirectURL, redirectToPreviousPage, loggedInPageLo
useEffect(() => {
if (window?.location?.search) {
const searchParams = new URLSearchParams(window.location.search.substring(1));
const validatedRedirectParam = validateURL(searchParams.get("redirect"));

//redirectURL could have additional params
const params = ["paymentMethodID"];
const aditionalParams = params.map((p) => {
const paramExist = searchParams.has(p)
if(paramExist){
return {[p]:searchParams.get(p)}
}
})

const fullURL = searchParams.get("redirect") ? appendURLParams(searchParams.get("redirect"), aditionalParams.filter(item => item !== undefined)) : null;
const validatedRedirectParam = validateURL(fullURL);
setRedirectQueryParam(validatedRedirectParam);
}

Expand Down
13 changes: 13 additions & 0 deletions blocks/identity-block/utils/append-url-params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Funtion to append additional parameters as part of URL
const appendURLParams = (initURL, params) => {

let fullURL = initURL;
if (params.length) {
const allParams = params.map((x) => Object.keys(x) + "=" + Object.values(x)).join("&");
fullURL = initURL.includes("?") ? `${initURL}&${allParams}` : `${initURL}?${allParams}`;
}

return fullURL;
};

export default appendURLParams;
35 changes: 35 additions & 0 deletions blocks/subscriptions-block/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,41 @@
@include scss.block-components("checkout-payment");
@include scss.block-properties("checkout-payment");

&-info {
@include scss.block-components("checkout-payment-info");
@include scss.block-properties("checkout-payment-info");

&-payments {
@include scss.block-components("checkout-payment-info-payments");
@include scss.block-properties("checkout-payment-info-payments");
}

&-paypal {
@include scss.block-components("checkout-payment-info-paypal");
@include scss.block-properties("checkout-payment-info-paypal");

&-button {
@include scss.block-components("checkout-payment-info-paypal-button");
@include scss.block-properties("checkout-payment-info-paypal-button");

&:hover {
@include scss.block-components("checkout-payment-info-paypal-button-hover");
@include scss.block-properties("checkout-payment-info-paypal-button-hover");
}
}
}

&-divider-container {
@include scss.block-components("checkout-payment-info-divider-container");
@include scss.block-properties("checkout-payment-info-divider-container");
}

&-divider-line {
@include scss.block-components("checkout-payment-info-divider-line");
@include scss.block-properties("checkout-payment-info-divider-line");
}
}

&-form {
@include scss.block-components("checkout-payment-form");
@include scss.block-properties("checkout-payment-form");
Expand Down
29 changes: 29 additions & 0 deletions blocks/subscriptions-block/components/PayPal/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import React from "react";
import { usePaymentRedirect } from "../usePaymentRedirect";
import { usePhrases } from "@wpmedia/arc-themes-components";

export const PaypalCheckout = ({ labelOrderNumber, paypal, orderNumber, successURL }) => {
const phrases = usePhrases();
const params = new URLSearchParams(window.location.search);
const token = params.get("token");

// Paypal can't pass back the orderNumber to us (like other payment methods does, e.g. payment express), we store it in local storage
if (orderNumber) {
localStorage.setItem(labelOrderNumber, orderNumber);
} else {
orderNumber = localStorage[labelOrderNumber];
}

const { error } = usePaymentRedirect(paypal, orderNumber, token, "parameter1", successURL);

return (
<>
<div data-testid="paypal-message-div">{token ? phrases.t("subscriptions-block.paypal-processing") : phrases.t("subscriptions-block.paypal-redirect-label")}</div>
<div data-testid="paypal-error-message-div">{error && phrases.t("subscriptions-block.payment-error") }</div>
</>
);
};

PaypalCheckout.displayName = "PaypalCheckout";

export default PaypalCheckout;
22 changes: 22 additions & 0 deletions blocks/subscriptions-block/components/PayPal/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from "react";
import { render, screen, act } from "@testing-library/react";

import PayPal from "./index";

it("renders", async () => {
await act(
async () => render(
<PayPal
labelOrderNumber = {"ArcSubs_OrderNumber"}
paypal = {{paymentMethodType: 10, paymentMethodID: 4339}}
orderNumber = "XAUEWT5S4PJJTAYY"
successURL = "/success"
isInitialized = {false}
/>
)
)

expect(screen.getByTestId('paypal-message-div').innerHTML).toBe('subscriptions-block.paypal-redirect-label');
expect(screen.getByTestId('paypal-error-message-div')).not.toBeNull();

});
91 changes: 54 additions & 37 deletions blocks/subscriptions-block/components/PaymentForm/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import {
useElements,
CardNumberElement,
CardExpiryElement,
CardCvcElement
CardCvcElement,
} from "@stripe/react-stripe-js";
import {
usePhrases,
Button,
Heading,
HeadingSection,
Paragraph,
Grid,
Input,
Expand All @@ -34,11 +32,13 @@ function PaymentForm({
paymentMethodID,
clientSecret,
stripeInstance,
formTitle,
formLabel,
submitText,
formErrorText,
className,
paymentID,
isPaymentMethodUpdate,
updateText,
successUpdateURL,
}) {
const [formStatus, setFormStatus] = useState(FORM_STATUS.IDLE);
const [cardName, setCardName] = useState("");
Expand Down Expand Up @@ -68,16 +68,19 @@ function PaymentForm({
return;
}

let result;

// if order of $0 there's a different stripe logic
const totalOrder = Sales.currentOrder.total;
// if order of $0 there's a different stripe logic,
let totalOrder;
if (!isPaymentMethodUpdate) {
totalOrder = Sales.currentOrder.total;
}

if (totalOrder > 0) {
let result;
if (totalOrder && totalOrder > 0 && !isPaymentMethodUpdate) {
result = await stripeInstance.confirmCardPayment(clientSecret, {
payment_method: paymentMethod.id,
});
} else {
// User is updating the payment method OR totalOder <= 0
result = await stripeInstance.confirmCardSetup(clientSecret, {
payment_method: paymentMethod.id,
});
Expand All @@ -88,31 +91,45 @@ function PaymentForm({
return;
}

if (totalOrder > 0) {
const nonZeroPriceOutput = await Sales.finalizePayment(
orderNumber,
paymentMethodID,
// using paymentIntent here for greater than 0
result.paymentIntent.id,
);
if (nonZeroPriceOutput.status === "Paid") {
setFormStatus(FORM_STATUS.SUCCESS);
window.location.href = successURL;
if (!isPaymentMethodUpdate) {
if (totalOrder > 0) {
const nonZeroPriceOutput = await Sales.finalizePayment(
orderNumber,
paymentMethodID,
// using paymentIntent here for greater than 0
result.paymentIntent.id,
);
if (nonZeroPriceOutput.status === "Paid") {
setFormStatus(FORM_STATUS.SUCCESS);
window.location.href = successURL;
} else {
setFormStatus(FORM_STATUS.ERROR);
}
} else {
setFormStatus(FORM_STATUS.ERROR);
const zeroPriceOutput = await Sales.finalizePayment(
orderNumber,
paymentMethodID,
// using setupIntent here for 0
result.setupIntent.id,
);
// even if no money changes hands, still shows status 'Paid'
if (zeroPriceOutput.status === "Paid") {
setFormStatus(FORM_STATUS.SUCCESS);
window.location.href = successURL;
} else {
setFormStatus(FORM_STATUS.ERROR);
}
}
} else {
const zeroPriceOutput = await Sales.finalizePayment(
orderNumber,
paymentMethodID,
// using setupIntent here for 0
result.setupIntent.id,
);
// even if no money changes hands, still shows status 'Paid'
if (zeroPriceOutput.status === "Paid") {
try {
await Sales.finalizePaymentUpdate(
paymentID,
paymentMethodID,
result.setupIntent.id,
);
setFormStatus(FORM_STATUS.SUCCESS);
window.location.href = successURL;
} else {
window.location.href = successUpdateURL;
} catch (e) {
setFormStatus(FORM_STATUS.ERROR);
}
}
Expand All @@ -122,11 +139,7 @@ function PaymentForm({

return (
<section className={`${className}__payment`}>
<HeadingSection>
<Heading>{formTitle}</Heading>
</HeadingSection>
<form onSubmit={handleSubmit} className={`${className}__payment-form`}>
<Paragraph>{formLabel}</Paragraph>
<Grid className={`${className}__payment-information`}>
<Stack>
<Input
Expand Down Expand Up @@ -168,9 +181,13 @@ function PaymentForm({
variant="primary"
fullWidth
type="submit"
disabled={(formStatus === FORM_STATUS.PROCESSING || formStatus === FORM_STATUS.SUCCESS) ? true : null}
disabled={
formStatus === FORM_STATUS.PROCESSING || formStatus === FORM_STATUS.SUCCESS
? true
: null
}
>
{submitText}
{!isPaymentMethodUpdate ? submitText : updateText}
</Button>
{formStatus === FORM_STATUS.ERROR ? (
<section role="alert">
Expand Down
66 changes: 66 additions & 0 deletions blocks/subscriptions-block/components/usePaymentOptions.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState, useEffect } from "react";

import useSales from "./useSales";

const STRIPE_PAYMENT_METHOD_ID = 18;
const PAYPAL_METHOD_ID = 10;

const getPaymentMethodByID = (paymentOptions, paymentMethodTypeID, paymentMethodID) => {
const stripeDefault = paymentOptions?.find(
(opts) =>
opts?.paymentMethodType === paymentMethodTypeID && opts?.paymentMethodID === paymentMethodID,
);

if (stripeDefault) {
return stripeDefault;
} else {
const allStripeIntents = paymentOptions?.filter(
(opts) => opts?.paymentMethodType === paymentMethodTypeID,
);

var minStripeIntentsID = allStripeIntents.reduce(function (res, obj) {
return obj.paymentMethodID < res.paymentMethodID ? obj : res;
});
return minStripeIntentsID;
}
};

// On subscriptions side we can setup multiple payment providers with the same typeID.
// This hook is on charge to return the default one or the one with the min paymentMethodID
export const usePaymentOptions = (stripeIntentsDefaultID, paypalDefaultID) => {
const [paymentOpts, setPaymentOpts] = useState();
const [paypal, setPaypal] = useState();
const [stripeIntents, setStripeIntents] = useState();
const [error, setError] = useState();

const { Sales } = useSales();

useEffect(() => {
const fetchData = async () => {
try {
const options = await Sales.getPaymentOptions();
const stripe = getPaymentMethodByID(
options,
STRIPE_PAYMENT_METHOD_ID,
stripeIntentsDefaultID,
);
const paypal = getPaymentMethodByID(options, PAYPAL_METHOD_ID, paypalDefaultID);
setPaymentOpts(options);
setPaypal(paypal);
setStripeIntents(stripe);
} catch (e) {
setError(e);
}
};
fetchData();
}, []);

return {
paymentOpts,
stripeIntents,
paypal,
error
};
};

export default usePaymentOptions;
Loading

0 comments on commit 0e3d9fb

Please sign in to comment.