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

ASUB-7844 PayPal block #1806

Merged
merged 11 commits into from
Dec 4, 2023
27 changes: 27 additions & 0 deletions blocks/subscriptions-block/components/PayPal/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React from "react";
vgalatro marked this conversation as resolved.
Show resolved Hide resolved
import {usePaymentRedirect} from "../usePaymentRedirect"

export const PaypalCheckout = ({orderNumber}) => {
const params = new URLSearchParams(window.location.search);
const token = params.get('token');

// because paypal can't pass back the orderNumber to us (like payment express does), we store it in local storage
if (orderNumber) {
localStorage.setItem('ArcSubs_OrderNumber', orderNumber);
} else {
orderNumber = localStorage.ArcSubs_OrderNumber;
}

const { error } = usePaymentRedirect(10, orderNumber, token, 'parameter1');

return (
<>
<div>{token ? 'Processing...' : 'Redirecting to paypal page...'}</div>
<pre>{error && JSON.stringify(error, null, 2)}</pre>
</>
);
};

PaypalCheckout.displayName = 'PaypalCheckout';

export default PaypalCheckout;
105 changes: 105 additions & 0 deletions blocks/subscriptions-block/components/usePaymentRedirect.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { useState, useEffect } from 'react';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [stylelint] reported by reviewdog 🐶
Unknown word (CssSyntaxError) CssSyntaxError

import Identity from '@arc-publishing/sdk-identity';
import useSales from "./useSales";

export const usePaymentRedirect = (
paymentMethodType,
orderNumber,
token,
redirectURLParameterName = 'parameter1',
captchaToken
) => {
const {Sales} = useSales();
const [error, setError] = useState();
const [currentMerchantId, setCurrentMerchantId] = useState();
const [currentOrder, setCurrentOrder] = useState();
const [isLoggedIn, setIsLoggedIn] = useState(false);
console.log(orderNumber);
useEffect(() => {
const fetchData = async () => {
try {

await Sales.getPaymentOptions();
const option =
Sales.paymentOptions.find(option => option.paymentMethodType === paymentMethodType) || {};
console.log(option);
setCurrentMerchantId(option.paymentMethodID);
const loggedIn = await Identity.isLoggedIn();
setIsLoggedIn(loggedIn);
console.log(Sales.currentOrder, token, isLoggedIn);
if (!Sales.currentOrder && !token && isLoggedIn) {
const order = await Sales.getOrderDetails(orderNumber);
console.log(order);

setCurrentOrder(order);
} else if (Sales.currentOrder) {

setCurrentOrder(Sales.currentOrder);
} else if (token || (!isLoggedIn && orderNumber)) {

setCurrentOrder({ orderNumber });
} else {

setError('No order number found');
}
} catch (e) {
console.error(e);
setError(e);
}
};

console.log('fetch');
fetchData();
}, []);

useEffect(() => {

console.log(token, currentMerchantId);
Fixed Show fixed Hide fixed
if (token && currentMerchantId) {
const finalizePayment = async () => {

try {
await Sales.finalizePayment(orderNumber, currentMerchantId, token, null, captchaToken);
localStorage.setItem('captcha', '');
window.location.href = '/success';
} catch (e) {
setError(e);
}
};

if (currentOrder) {
finalizePayment();
}
} else {
console.log(currentOrder);
const initPayment = async () => {
const config = await Sales.getConfig();

try {
if (
currentOrder &&
currentOrder.orderNumber &&
(!config.checkoutRecaptchaEnabled ||
(config.checkoutRecaptchaEnabled && captchaToken && captchaToken !== 'null'))
) {
const payment = await Sales.initializePayment(
currentOrder.orderNumber,
currentMerchantId
);
console.log(payment[redirectURLParameterName]);
window.location.href = payment[redirectURLParameterName];
}
} catch (e) {
setError(e);
}
};

if (currentOrder && currentMerchantId) {

initPayment();
}
}
}, [currentOrder, currentMerchantId, captchaToken, token]);

return { error };
};
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import React, { useEffect, useState } from "react";
vgalatro marked this conversation as resolved.
Show resolved Hide resolved
import { Elements } from "@stripe/react-stripe-js";
import { loadStripe } from "@stripe/stripe-js";
import useSales from "../../../../components/useSales";

import { usePhrases } from "@wpmedia/arc-themes-components";
import { usePhrases, Button } from "@wpmedia/arc-themes-components";

import PaymentForm from "../../../../components/PaymentForm";
import PayPal from "../../../../components/PayPal";

const PaymentInfo = ({ orderNumber, paymentDetails, paymentMethodID, successURL, className }) => {
const [stripeInstance, setStripeInstance] = useState(null);
const PaymentInfo = ({ successURL, className, userInfo, offerURL, paypal }) => {
const {Sales} = useSales();

const [stripeInstance, setStripeInstance] = useState(null);
const [isStripe, setIsStripe] = useState(false);
const [isPayPal, setIsPayPal] = useState(false);
// initialized payment doc https://redirector.arcpublishing.com/alc/en/arc-xp-subscriptions-sdks?id=kb_article_view&sys_kb_id=7770d58747447990eee38788436d4362&spa=1
const { parameter2: stripeKey, parameter1: clientSecret } = paymentDetails;

const [orderNumber, setOrderNumber] = useState();
const [payment, setPayment] = useState({});
const [paymentMethodID, setPaymentMethodID] = useState();
const phrases = usePhrases();

const formErrorText = phrases.t("subscriptions-block.payment-error");
Expand All @@ -20,32 +26,82 @@ const PaymentInfo = ({ orderNumber, paymentDetails, paymentMethodID, successURL,
const submitText = phrases.t("subscriptions-block.submit-payment");

// load stripe key via payment details stripe key string
const { parameter2: stripeKey, parameter1: clientSecret } = payment;

useEffect(() => {
// stripe docs https://stripe.com/docs/stripe-js/react#elements-provider
loadStripe(stripeKey).then((newStripePromise) => setStripeInstance(newStripePromise));
}, [stripeKey]);
if(isStripe) {
const STRIPE_PAYMENT_METHOD_ID = 18;
Sales.getCart().then((cart) => {
if (!cart?.items?.length) {
window.location.href = offerURL;
return;
}else{
const {country, email} = userInfo;
Sales.createNewOrder({ country }, email).then((order) => {
setOrderNumber(order.orderNumber);
Sales.getPaymentOptions().then((paymentOptions) => {
if(paymentOptions){
const stripe = paymentOptions?.find(opts => opts?.paymentMethodType === STRIPE_PAYMENT_METHOD_ID);
Sales.initializePayment(order.orderNumber, stripe?.paymentMethodID).then(
(paymentObject) => {
setPayment(paymentObject);
setPaymentMethodID(stripe?.paymentMethodID);
},
);
}
});
}).catch(e => console.error(e));
}
});
}
}, [isStripe]);

if (stripeInstance) {
// elements wrapper has to contain any stripe hooks
return (
<Elements stripe={stripeInstance}>
<PaymentForm
clientSecret={clientSecret}
formErrorText={formErrorText}
formLabel={formLabel}
formTitle={formTitle}
orderNumber={orderNumber}
paymentMethodID={paymentMethodID}
stripeInstance={stripeInstance}
submitText={submitText}
successURL={successURL}
className={className}
/>
</Elements>
);
useEffect(() => {
if(isStripe && stripeKey) {
// stripe docs https://stripe.com/docs/stripe-js/react#elements-provider
loadStripe(stripeKey).then((newStripePromise) => setStripeInstance(newStripePromise));
}
}, [isStripe, stripeKey])

const handlePayPal = () => {
setIsPayPal(true)
Sales.getCart().then((cart) => {
if (!cart?.items?.length) {
window.location.href = offerURL;
return;
}else{
const {country, email} = userInfo;
Sales.createNewOrder({ country }, email).then((order) => {
setOrderNumber(order.orderNumber);
}).catch(e => console.error(e));
}
})
}
console.log(orderNumber);
return (
<>
{paypal && <Button onClick={handlePayPal}>PayPal</Button>}
{isPayPal && <PayPal orderNumber={orderNumber}/>}
{isStripe && stripeInstance ?
<Elements stripe={stripeInstance}>

return null;
<PaymentForm
clientSecret={clientSecret}
formErrorText={formErrorText}
formLabel={formLabel}
formTitle={formTitle}
orderNumber={orderNumber}
paymentMethodID={paymentMethodID}
stripeInstance={stripeInstance}
submitText={submitText}
successURL={successURL}
className={className}
/>
</Elements> :
<Button onClick={() => setIsStripe(true)}>Stripe</Button>
}
</>
);
};

export default PaymentInfo;
Loading