Compare commits
2 Commits
5df46cba7e
...
b997e14fe6
| Author | SHA1 | Date | |
|---|---|---|---|
| b997e14fe6 | |||
| ee1ce09508 |
@@ -9,6 +9,103 @@ if (!defined('ABSPATH')) {
|
||||
|
||||
class WC_Aluxpay_Payment_Gateway extends WC_Payment_Gateway {
|
||||
|
||||
/**
|
||||
* Reusable: HTML notice for Thank You page + HTML emails
|
||||
*/
|
||||
protected function get_generic_notice_html(): string {
|
||||
// Keep inline styles for email clients; translate strings
|
||||
$html .= '<p><strong>' . esc_html__( 'Thank you for your payment!', 'aluxpay-payment-gateway' ) . '</strong> ';
|
||||
$html .= esc_html__( 'Your order has been successfully processed, and a confirmation email has been sent from our webstore.', 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$html .= '<h5>' . esc_html__( 'Important Note:', 'aluxpay-payment-gateway' ) . '</h5>';
|
||||
$html .= '<p>' . esc_html__( "Because of the nature of our business and how our website integrates with PayPal, you’ll also receive a PayPal payment confirmation email. That email will display a generic product name instead of the specific item(s) you purchased.", 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$html .= '<p>' . esc_html__( 'Rest assured — your order is fully confirmed, and the webstore confirmation email contains the correct details of your purchase.', 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$html .= '<p>' . esc_html__( "If you have any questions or need assistance, please don’t hesitate to contact our support team.", 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
// For frontend we can allow basic tags; for email we echo directly.
|
||||
$allowed = array(
|
||||
'p' => array('style'=>true),
|
||||
'h5' => array('style'=>true),
|
||||
'strong' => array(),
|
||||
);
|
||||
return wp_kses( $html, $allowed );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reusable: Plain-text version for plain emails
|
||||
*/
|
||||
protected function get_generic_notice_plain(): string {
|
||||
$lines = array(
|
||||
__( 'Thank you for your payment! Your order has been successfully processed, and a confirmation email has been sent from our webstore.', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
__( 'Important Note:', 'aluxpay-payment-gateway' ),
|
||||
__( "Because of the nature of our business and how our website integrates with PayPal, you’ll also receive a PayPal payment confirmation email. That email will display a generic product name instead of the specific item(s) you purchased.", 'aluxpay-payment-gateway' ),
|
||||
__( 'Rest assured — your order is fully confirmed, and the webstore confirmation email contains the correct details of your purchase.', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
__( "If you have any questions or need assistance, please don’t hesitate to contact our support team.", 'aluxpay-payment-gateway' ),
|
||||
);
|
||||
return implode( PHP_EOL, $lines ) . PHP_EOL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reusable: HTML notice for Failed Order emails
|
||||
*/
|
||||
protected function get_failed_notice_html(): string {
|
||||
$html = '';
|
||||
$html .= '<p><strong>' . esc_html__( 'Payment Failed', 'aluxpay-payment-gateway' ) . '</strong></p>';
|
||||
$html .= '<p>' . esc_html__( 'Unfortunately, your payment could not be processed. This may have occurred for one of the following reasons:', 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$html .= '<ul style="margin-left: 20px;">';
|
||||
$html .= '<li>' . esc_html__( 'Insufficient funds in your account', 'aluxpay-payment-gateway' ) . '</li>';
|
||||
$html .= '<li>' . esc_html__( 'Payment was cancelled during the process', 'aluxpay-payment-gateway' ) . '</li>';
|
||||
$html .= '<li>' . esc_html__( 'Payment method declined the transaction', 'aluxpay-payment-gateway' ) . '</li>';
|
||||
$html .= '<li>' . esc_html__( 'Technical issue during payment processing', 'aluxpay-payment-gateway' ) . '</li>';
|
||||
$html .= '</ul>';
|
||||
|
||||
$html .= '<p>' . esc_html__( 'Your order has not been completed and no charges have been made to your account.', 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$html .= '<h5>' . esc_html__( 'What to do next:', 'aluxpay-payment-gateway' ) . '</h5>';
|
||||
$html .= '<p>' . esc_html__( 'You can try placing your order again by visiting our website. If you continue to experience issues, please contact us for assistance.', 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$html .= '<p>' . esc_html__( 'We apologize for any inconvenience this may have caused.', 'aluxpay-payment-gateway' ) . '</p>';
|
||||
|
||||
$allowed = array(
|
||||
'p' => array('style'=>true),
|
||||
'h5' => array('style'=>true),
|
||||
'ul' => array('style'=>true),
|
||||
'li' => array(),
|
||||
'strong' => array(),
|
||||
);
|
||||
return wp_kses( $html, $allowed );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reusable: Plain-text version for Failed Order emails
|
||||
*/
|
||||
protected function get_failed_notice_plain(): string {
|
||||
$lines = array(
|
||||
__( 'Payment Failed', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
__( 'Unfortunately, your payment could not be processed. This may have occurred for one of the following reasons:', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
'- ' . __( 'Insufficient funds in your account', 'aluxpay-payment-gateway' ),
|
||||
'- ' . __( 'Payment was cancelled during the process', 'aluxpay-payment-gateway' ),
|
||||
'- ' . __( 'Payment method declined the transaction', 'aluxpay-payment-gateway' ),
|
||||
'- ' . __( 'Technical issue during payment processing', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
__( 'Your order has not been completed and no charges have been made to your account.', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
__( 'What to do next:', 'aluxpay-payment-gateway' ),
|
||||
__( 'You can try placing your order again by visiting our website. If you continue to experience issues, please contact us for assistance.', 'aluxpay-payment-gateway' ),
|
||||
'',
|
||||
__( 'We apologize for any inconvenience this may have caused.', 'aluxpay-payment-gateway' ),
|
||||
);
|
||||
return implode( PHP_EOL, $lines ) . PHP_EOL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@@ -42,8 +139,12 @@ class WC_Aluxpay_Payment_Gateway extends WC_Payment_Gateway {
|
||||
add_action('woocommerce_api_' . $this->id, array($this, 'webhook_handler'));
|
||||
add_action('woocommerce_thankyou_' . $this->id, array($this, 'thankyou_page'));
|
||||
|
||||
// Customer Emails
|
||||
// Customer Emails - Success
|
||||
add_action('woocommerce_email_before_order_table', array($this, 'email_instructions'), 10, 3);
|
||||
|
||||
// Customer Emails - Failed Orders
|
||||
add_action('woocommerce_email_before_order_table', array($this, 'failed_email_instructions'), 10, 3);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -233,24 +334,58 @@ class WC_Aluxpay_Payment_Gateway extends WC_Payment_Gateway {
|
||||
*/
|
||||
public function thankyou_page($order_id) {
|
||||
|
||||
if ($this->description) {
|
||||
/**if ($this->description) {
|
||||
echo wpautop(wptexturize($this->description));
|
||||
}
|
||||
}*/
|
||||
|
||||
$order = wc_get_order($order_id);
|
||||
|
||||
if ($order && $order->get_status() === 'processing') {
|
||||
echo '<p>' . __('Your payment has been received and your order is being processed.', 'aluxpay-payment-gateway') . '</p>';
|
||||
echo $this->get_generic_notice_html();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add content to the WC emails
|
||||
* Add content to the WC emails for successful orders
|
||||
*/
|
||||
public function email_instructions($order, $sent_to_admin, $plain_text = false) {
|
||||
|
||||
if ($this->description && !$sent_to_admin && $this->id === $order->get_payment_method()) {
|
||||
echo wpautop(wptexturize($this->description)) . PHP_EOL;
|
||||
/** if ($this->description && !$sent_to_admin && $this->id === $order->get_payment_method()) {
|
||||
* echo wpautop(wptexturize($this->description)) . PHP_EOL;
|
||||
*} */
|
||||
|
||||
if ( $sent_to_admin ) return; // customers only
|
||||
if ( ! $order instanceof WC_Order ) return;
|
||||
if ( $order->get_payment_method() !== $this->id ) return;
|
||||
|
||||
// Only show for completed/processing orders
|
||||
if ( ! in_array( $order->get_status(), array( 'processing', 'completed' ) ) ) return;
|
||||
|
||||
// Pick the right format for the email renderer
|
||||
if ( $plain_text ) {
|
||||
echo $this->get_generic_notice_plain();
|
||||
} else {
|
||||
echo $this->get_generic_notice_html();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add content to the WC emails for failed orders
|
||||
*/
|
||||
public function failed_email_instructions($order, $sent_to_admin, $plain_text = false) {
|
||||
|
||||
if ( $sent_to_admin ) return; // customers only
|
||||
if ( ! $order instanceof WC_Order ) return;
|
||||
if ( $order->get_payment_method() !== $this->id ) return;
|
||||
|
||||
// Only show for failed orders
|
||||
if ( $order->get_status() !== 'failed' ) return;
|
||||
|
||||
// Pick the right format for the email renderer
|
||||
if ( $plain_text ) {
|
||||
echo $this->get_failed_notice_plain();
|
||||
} else {
|
||||
echo $this->get_failed_notice_html();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,17 +160,20 @@ router.post('/capture-order', validateCaptureOrder, async (req, res) => {
|
||||
tokenLength: token?.length
|
||||
});
|
||||
|
||||
// Declare tokenData at function scope
|
||||
let tokenData = null;
|
||||
|
||||
// Verify token (optional in development)
|
||||
const skipTokenValidation = process.env.NODE_ENV === 'development' && process.env.SKIP_TOKEN_VALIDATION === 'true';
|
||||
|
||||
if (token && !skipTokenValidation) {
|
||||
const tokenData = verifyToken(token);
|
||||
tokenData = verifyToken(token);
|
||||
console.log('Token verification result:', {
|
||||
isValid: !!tokenData,
|
||||
tokenData: tokenData
|
||||
});
|
||||
|
||||
if (!tokenData || tokenData.wc_order_id !== parseInt(wc_order_id)) {
|
||||
if (!tokenData || tokenData.wc_order_id !== String(wc_order_id)) {
|
||||
console.error('Token validation failed:', {
|
||||
tokenData,
|
||||
expectedOrderId: wc_order_id,
|
||||
|
||||
@@ -39,11 +39,11 @@ function App() {
|
||||
gap={4}
|
||||
>
|
||||
<Image width="550px" src={logo} className="logo react" alt="React logo" />
|
||||
<Center>
|
||||
<Button variant="outline" onClick={toggleColorMode} >
|
||||
{colorMode === "light" ? <><LuSun /> Toggle Light mode</> : <><LuMoon /> Toogle Dark mode</>}
|
||||
</Button>
|
||||
</Center>
|
||||
{/*<Center>*/}
|
||||
{/* <Button variant="outline" onClick={toggleColorMode} >*/}
|
||||
{/* {colorMode === "light" ? <><LuSun /> Toggle Light mode</> : <><LuMoon /> Toogle Dark mode</>}*/}
|
||||
{/* </Button>*/}
|
||||
{/*</Center>*/}
|
||||
</Grid>
|
||||
<Flex direction="row" gap="4" justify="space-between" align="center" mb="10">
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ const OrderSummary = ({ orderData, loading, order }) => {
|
||||
<DataList.ItemValue>{orderData.customer_email}</DataList.ItemValue>
|
||||
</DataList.Item>
|
||||
)}*/}
|
||||
{order.shipping.method &&
|
||||
<DataList.Item pt="4">
|
||||
<DataList.ItemLabel>
|
||||
<Badge colorPalette="teal" variant="solid">
|
||||
@@ -72,7 +73,7 @@ const OrderSummary = ({ orderData, loading, order }) => {
|
||||
</Badge>
|
||||
</DataList.ItemLabel>
|
||||
<DataList.ItemValue>{formatCurrency(order.shipping.total, orderData.currency)}</DataList.ItemValue>
|
||||
</DataList.Item>
|
||||
</DataList.Item> }
|
||||
</> }
|
||||
<DataList.Item pt="4" textStyle="xl">
|
||||
<DataList.ItemLabel><strong>Total Amount:</strong></DataList.ItemLabel>
|
||||
|
||||
@@ -1,13 +1,18 @@
|
||||
import { Provider } from "@/components/ui/provider"
|
||||
import { StrictMode } from 'react'
|
||||
import { createRoot } from 'react-dom/client'
|
||||
import { ChakraProvider } from "@chakra-ui/react";
|
||||
import { system } from "./theme";
|
||||
import './index.css'
|
||||
import App from './App.jsx'
|
||||
import {ThemeProvider} from "next-themes";
|
||||
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<StrictMode>
|
||||
<Provider>
|
||||
<ChakraProvider value={system}>
|
||||
<ThemeProvider attribute="class" defaultTheme="light" enableSystem={false}>
|
||||
<App />
|
||||
</Provider>
|
||||
</ThemeProvider>
|
||||
</ChakraProvider>
|
||||
</StrictMode>,
|
||||
)
|
||||
|
||||
@@ -16,20 +16,40 @@ const Cancel = () => {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const error = searchParams.get('error');
|
||||
const orderId = searchParams.get('order_id');
|
||||
const orderId = searchParams.get('order_id') || searchParams.get('wc_order_id');
|
||||
const paypalToken = searchParams.get('token');
|
||||
|
||||
const orderTotal = searchParams.get('total');
|
||||
const currency = searchParams.get('currency') || 'USD';
|
||||
const description = searchParams.get('description');
|
||||
const customerEmail = searchParams.get('customer_email');
|
||||
const cancelUrl = searchParams.get('cancel_url');
|
||||
const returnUrl = searchParams.get('return_url');
|
||||
|
||||
const formatCurrency = (amount, curr = 'USD') => {
|
||||
return new Intl.NumberFormat('en-US', {
|
||||
style: 'currency',
|
||||
currency: curr,
|
||||
}).format(parseFloat(amount));
|
||||
};
|
||||
|
||||
const getErrorMessage = () => {
|
||||
if (error) {
|
||||
return decodeURIComponent(error);
|
||||
}
|
||||
return 'Your payment was cancelled. You can try again or choose a different payment method.';
|
||||
};
|
||||
|
||||
const handleRetryPayment = () => {
|
||||
// Build the payment URL with original parameters
|
||||
const paymentUrl = new URL('/payment', window.location.origin);
|
||||
|
||||
if (orderId) {
|
||||
paymentUrl.searchParams.set('wc_order_id', orderId);
|
||||
// You might want to fetch original order details here
|
||||
paymentUrl.searchParams.set('total', '25.99'); // This should come from order data
|
||||
}
|
||||
// Preserve all original order parameters
|
||||
if (orderId) paymentUrl.searchParams.set('wc_order_id', orderId);
|
||||
if (orderTotal) paymentUrl.searchParams.set('total', orderTotal);
|
||||
if (currency) paymentUrl.searchParams.set('currency', currency);
|
||||
if (description) paymentUrl.searchParams.set('description', description);
|
||||
if (customerEmail) paymentUrl.searchParams.set('customer_email', customerEmail);
|
||||
if (returnUrl) paymentUrl.searchParams.set('return_url', returnUrl);
|
||||
if (cancelUrl) paymentUrl.searchParams.set('cancel_url', cancelUrl);
|
||||
|
||||
window.location.href = paymentUrl.toString();
|
||||
};
|
||||
@@ -41,7 +61,7 @@ const Cancel = () => {
|
||||
<Alert.Content>
|
||||
<Alert.Title>Payment Cancelled</Alert.Title>
|
||||
<Alert.Description>
|
||||
<Text>Your payment was cancelled. You can try again or choose a different payment method.</Text>
|
||||
<Text>{getErrorMessage()}</Text>
|
||||
</Alert.Description>
|
||||
</Alert.Content>
|
||||
</Alert.Root>
|
||||
@@ -63,6 +83,13 @@ const Cancel = () => {
|
||||
<strong>Order ID:</strong>
|
||||
<span className="badge bg-secondary ms-2">{orderId}</span>
|
||||
<br/>
|
||||
{orderTotal && (
|
||||
<>
|
||||
<strong>Order Total:</strong>
|
||||
<span className="ms-2">{formatCurrency(orderTotal, currency)}</span>
|
||||
<br/>
|
||||
</>
|
||||
)}
|
||||
<small className="mt-2 d-block">
|
||||
Your order is still pending. You can complete the payment to process your order.
|
||||
</small>
|
||||
@@ -121,7 +148,7 @@ const Cancel = () => {
|
||||
<Accordion.ItemIndicator/>
|
||||
</Accordion.ItemTrigger>
|
||||
<Accordion.ItemContent>
|
||||
<Accordion.ItemBody>Text</Accordion.ItemBody>
|
||||
<Accordion.ItemBody>Contact Support: Reach us anytime at {import.meta.env.VITE_REACT_APP_SUPPORT_EMAIL} or through live chat.</Accordion.ItemBody>
|
||||
</Accordion.ItemContent>
|
||||
</Accordion.Item>
|
||||
</Accordion.Root>
|
||||
|
||||
@@ -190,7 +190,7 @@ const Payment = () => {
|
||||
<Grid
|
||||
templateColumns={{ base: "1fr", md: "repeat(3, 1fr)" }}
|
||||
templateRows="repeat(1, 1fr)"
|
||||
gap="6"
|
||||
// gap="6"
|
||||
>
|
||||
<GridItem colSpan={2}>
|
||||
<Center>
|
||||
|
||||
8
frontend/src/theme.js
Normal file
8
frontend/src/theme.js
Normal file
@@ -0,0 +1,8 @@
|
||||
import { createSystem, defaultConfig, defineConfig } from "@chakra-ui/react";
|
||||
|
||||
const config = defineConfig({
|
||||
// put tokens/recipes if you need; not required just to force light mode
|
||||
theme: {},
|
||||
});
|
||||
|
||||
export const system = createSystem(defaultConfig, config);
|
||||
Reference in New Issue
Block a user