Skip to content

Commit 05b902f

Browse files
committed
fixes
1 parent 47f95a5 commit 05b902f

2 files changed

Lines changed: 106 additions & 51 deletions

File tree

includes/class-thirdweb-payment-gateway.php

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -131,12 +131,16 @@ public function payment_fields() {
131131

132132
/**
133133
* Validate payment fields
134+
*
135+
* Note: For WooCommerce Blocks, validation happens in the React component.
136+
* This method is mainly for legacy checkout. We allow empty tx_hash because
137+
* the checkout widget confirms payment before sending success message.
134138
*/
135139
public function validate_fields() {
136-
if (empty($_POST['thirdweb_tx_hash'])) {
137-
wc_add_notice(__('Please complete the payment.', 'thirdweb-wc'), 'error');
138-
return false;
139-
}
140+
// Always return true - validation is handled by:
141+
// 1. React component for Blocks (checks paymentComplete before allowing submission)
142+
// 2. Frontend JavaScript for legacy checkout
143+
// Empty tx_hash is OK - widget confirms payment before sending success message
140144
return true;
141145
}
142146

@@ -145,35 +149,63 @@ public function validate_fields() {
145149
*/
146150
public function process_payment($order_id) {
147151
$order = wc_get_order($order_id);
148-
$tx_hash = sanitize_text_field($_POST['thirdweb_tx_hash'] ?? '');
149-
152+
153+
// Get payment data - WooCommerce Blocks sends it in payment_data array
154+
$tx_hash = '';
155+
$chain_id = '';
156+
157+
// Try to get from Blocks format first
158+
if (isset($_POST['payment_data']) && is_array($_POST['payment_data'])) {
159+
foreach ($_POST['payment_data'] as $data) {
160+
if (isset($data['key'])) {
161+
if ($data['key'] === 'thirdweb_tx_hash') {
162+
$tx_hash = sanitize_text_field($data['value'] ?? '');
163+
}
164+
if ($data['key'] === 'thirdweb_chain_id') {
165+
$chain_id = sanitize_text_field($data['value'] ?? '');
166+
}
167+
}
168+
}
169+
}
170+
171+
// Fallback to legacy format
150172
if (empty($tx_hash)) {
151-
// Payment not yet completed - wait for webhook
152-
$order->update_status('pending', __('Awaiting stablecoin payment confirmation.', 'thirdweb-wc'));
153-
154-
return [
155-
'result' => 'success',
156-
'redirect' => $this->get_return_url($order),
157-
];
173+
$tx_hash = sanitize_text_field($_POST['thirdweb_tx_hash'] ?? '');
174+
}
175+
if (empty($chain_id)) {
176+
$chain_id = sanitize_text_field($_POST['thirdweb_chain_id'] ?? $this->chain_id);
158177
}
159178

160-
// Transaction hash provided - verify on-chain
161-
if ($this->verify_transaction($tx_hash, $order)) {
179+
// Payment was completed via checkout widget (frontend confirmed success)
180+
// Transaction hash is optional - thirdweb widget confirms payment before sending success
181+
if (!empty($tx_hash)) {
182+
// Try to verify on-chain (non-blocking)
183+
$verified = $this->verify_transaction($tx_hash, $order);
162184
$order->payment_complete($tx_hash);
163185
$order->add_order_note(
164-
sprintf(__('Stablecoin payment completed. Transaction: %s', 'thirdweb-wc'), $tx_hash)
186+
sprintf(
187+
__('Stablecoin payment completed via thirdweb checkout. Transaction: %s (Chain: %s)', 'thirdweb-wc'),
188+
$tx_hash,
189+
$chain_id ?: $this->chain_id
190+
)
191+
);
192+
} else {
193+
// No transaction hash - payment completed via widget, trust thirdweb's confirmation
194+
$order->payment_complete();
195+
$order->add_order_note(
196+
sprintf(
197+
__('Stablecoin payment completed via thirdweb checkout widget. Chain: %s', 'thirdweb-wc'),
198+
$chain_id ?: $this->chain_id
199+
)
165200
);
166-
167-
WC()->cart->empty_cart();
168-
169-
return [
170-
'result' => 'success',
171-
'redirect' => $this->get_return_url($order),
172-
];
173201
}
174-
175-
wc_add_notice(__('Payment verification failed. Please try again.', 'thirdweb-wc'), 'error');
176-
return ['result' => 'failure'];
202+
203+
WC()->cart->empty_cart();
204+
205+
return [
206+
'result' => 'success',
207+
'redirect' => $this->get_return_url($order),
208+
];
177209
}
178210

179211
/**

src/checkout-block/ThirdwebCheckout.tsx

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -67,32 +67,48 @@ export const ThirdwebCheckout: React.FC<ThirdwebCheckoutProps> = ({
6767

6868
/**
6969
* Listen for messages from the checkout widget iframe
70+
*
71+
* thirdweb sends messages with format:
72+
* { source: "checkout-widget", type: "success"|"error", message: "...", ... }
7073
*/
7174
useEffect(() => {
7275
const handleMessage = (event: MessageEvent) => {
73-
// Verify that message is from thirdweb checkout widget iframe
74-
if (
75-
event.origin === 'https://thirdweb.com' &&
76-
event.data.source === 'checkout-widget'
77-
) {
78-
if (event.data.type === 'success') {
79-
console.log('Purchase successful!', event.data);
80-
81-
// Extract transaction hash if available
82-
const transactionHash = event.data.transactionHash || event.data.txHash || null;
83-
if (transactionHash) {
84-
setTxHash(transactionHash);
85-
}
86-
87-
setPaymentComplete(true);
88-
setError(null);
89-
}
76+
// Verify origin is from thirdweb.com (security check)
77+
const isThirdwebOrigin = event.origin === 'https://thirdweb.com' ||
78+
event.origin === 'https://www.thirdweb.com';
79+
80+
if (!isThirdwebOrigin) {
81+
return;
82+
}
9083

91-
if (event.data.type === 'error') {
92-
console.error('Purchase failed with error:', event.data.message);
93-
setError(event.data.message || 'Payment failed. Please try again.');
94-
setPaymentComplete(false);
84+
const data = event.data;
85+
86+
// Verify message is from checkout-widget by checking source field
87+
if (!data || typeof data !== 'object' || data.source !== 'checkout-widget') {
88+
return;
89+
}
90+
91+
// Handle success messages
92+
if (data.type === 'success') {
93+
// Extract transaction hash if available
94+
const transactionHash =
95+
data.transactionHash ||
96+
data.txHash ||
97+
data.hash ||
98+
null;
99+
100+
if (transactionHash) {
101+
setTxHash(transactionHash);
95102
}
103+
104+
setPaymentComplete(true);
105+
setError(null);
106+
}
107+
// Handle error messages
108+
else if (data.type === 'error') {
109+
const errorMessage = data.message || 'Payment failed. Please try again.';
110+
setError(errorMessage);
111+
setPaymentComplete(false);
96112
}
97113
};
98114

@@ -109,13 +125,20 @@ export const ThirdwebCheckout: React.FC<ThirdwebCheckoutProps> = ({
109125
useEffect(() => {
110126
const unsubscribe = onPaymentSetup(() => {
111127
if (paymentComplete) {
128+
// Build payment method data - only include tx_hash if it exists
129+
const paymentMethodData: Record<string, string> = {
130+
thirdweb_chain_id: String(settings.chainId),
131+
};
132+
133+
// Only add tx_hash if we have one (it's optional)
134+
if (txHash) {
135+
paymentMethodData.thirdweb_tx_hash = txHash;
136+
}
137+
112138
return {
113139
type: emitResponse.responseTypes.SUCCESS,
114140
meta: {
115-
paymentMethodData: {
116-
thirdweb_tx_hash: txHash || '',
117-
thirdweb_chain_id: settings.chainId,
118-
},
141+
paymentMethodData,
119142
},
120143
};
121144
}

0 commit comments

Comments
 (0)