Skip to content

Commit b22d960

Browse files
committed
Google Pay Button & Merchant Configuration
1 parent 866d3ac commit b22d960

6 files changed

Lines changed: 232 additions & 108 deletions

File tree

assets/build/blocks.asset.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-blocks-registry', 'wp-data', 'wp-element', 'wp-i18n', 'wp-is-shallow-equal'), 'version' => 'e284af85d187e4817c0c');
1+
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-blocks-registry', 'wp-data', 'wp-element', 'wp-i18n', 'wp-is-shallow-equal'), 'version' => 'cd0acd671ccb69ff2ad8');

assets/build/blocks.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client/blocks/googlepay/index.jsx

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import {PAYONE_ASSETS_URL} from '../../constants';
55
import getPaymentMethodConfig from '../../services/getPaymentMethodConfig';
66
import AssetService from '../../services/AssetService';
77

8+
const PLACE_ORDER_BUTTON_SELECTOR = '.wc-block-components-checkout-place-order-button';
9+
810
const PayoneGooglePay = ({
911
eventRegistration,
1012
emitResponse,
@@ -21,6 +23,7 @@ const PayoneGooglePay = ({
2123

2224
const googlePayFinishedRef = useRef(false);
2325
const googlePayTokenRef = useRef(null);
26+
const buttonContainerRef = useRef(null);
2427

2528
// Load Google Pay SDK via AssetService
2629
useEffect(() => {
@@ -32,23 +35,67 @@ const PayoneGooglePay = ({
3235
});
3336
}, []);
3437

35-
// Intercept checkout validation — open Google Pay popup
36-
useEffect(() => onCheckoutValidation(async () => {
37-
if (googlePayFinishedRef.current) {
38-
return true;
38+
// Render Google Pay button once SDK is ready
39+
useEffect(() => {
40+
if (!sdkReady || !buttonContainerRef.current) {
41+
return;
3942
}
4043

41-
if (!sdkReady) {
42-
setErrorMessage(__('Google Pay wird geladen, bitte versuchen Sie es erneut.', 'payone-woocommerce-3'));
43-
return false;
44+
const baseCardPaymentMethod = {
45+
type: 'CARD',
46+
parameters: {
47+
allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'],
48+
allowedCardNetworks: ['MASTERCARD', 'VISA'],
49+
allowPrepaidCards: true,
50+
allowCreditCards: true,
51+
},
52+
};
53+
54+
const paymentsClient = new google.payments.api.PaymentsClient({
55+
environment: googlePayConfig.environment,
56+
});
57+
58+
paymentsClient.isReadyToPay({
59+
apiVersion: 2,
60+
apiVersionMinor: 0,
61+
allowedPaymentMethods: [baseCardPaymentMethod],
62+
}).then((response) => {
63+
if (response.result) {
64+
const button = paymentsClient.createButton({
65+
onClick: handleGooglePayClick,
66+
buttonColor: 'black',
67+
buttonType: 'buy',
68+
buttonSizeMode: 'fill',
69+
buttonLocale: 'de',
70+
allowedPaymentMethods: [baseCardPaymentMethod],
71+
});
72+
buttonContainerRef.current.innerHTML = '';
73+
buttonContainerRef.current.appendChild(button);
74+
togglePlaceOrderButton(false);
75+
}
76+
}).catch((err) => {
77+
console.error('Google Pay isReadyToPay error:', err);
78+
});
79+
80+
return () => {
81+
togglePlaceOrderButton(true);
82+
};
83+
}, [sdkReady]);
84+
85+
const togglePlaceOrderButton = (show) => {
86+
const placeOrderButton = document.querySelector(PLACE_ORDER_BUTTON_SELECTOR);
87+
if (placeOrderButton) {
88+
placeOrderButton.style.display = show ? '' : 'none';
4489
}
90+
};
4591

92+
const handleGooglePayClick = () => {
4693
const baseRequest = {apiVersion: 2, apiVersionMinor: 0};
4794
const tokenizationSpecification = {
4895
type: 'PAYMENT_GATEWAY',
4996
parameters: {
50-
gateway: 'payonegmbh',
51-
gatewayMerchantId: googlePayConfig.gatewayMerchantId,
97+
gateway: googlePayConfig.merchantName,
98+
gatewayMerchantId: googlePayConfig.googlePayMerchantId,
5299
},
53100
};
54101
const baseCardPaymentMethod = {
@@ -65,13 +112,11 @@ const PayoneGooglePay = ({
65112
tokenizationSpecification,
66113
};
67114

68-
// Get cart totals from WooCommerce Blocks store
69115
const {CART_STORE_KEY} = wc.wcBlocksData;
70116
const store = select(CART_STORE_KEY);
71117
const cartTotals = store.getCartTotals();
72118
const cartData = store.getCartData();
73119

74-
// total_price is in minor units as string (e.g. "1999" for 19.99 EUR)
75120
const totalPrice = (parseInt(cartTotals.total_price, 10) / 100).toFixed(2);
76121
const currencyCode = cartTotals.currency_code;
77122
const countryCode = cartData.billingAddress.country;
@@ -80,48 +125,40 @@ const PayoneGooglePay = ({
80125
environment: googlePayConfig.environment,
81126
});
82127

83-
try {
84-
const readyResponse = await paymentsClient.isReadyToPay({
85-
...baseRequest,
86-
allowedPaymentMethods: [baseCardPaymentMethod],
87-
});
88-
89-
if (readyResponse.result) {
90-
const paymentData = await paymentsClient.loadPaymentData({
91-
...baseRequest,
92-
allowedPaymentMethods: [cardPaymentMethod],
93-
transactionInfo: {
94-
totalPriceStatus: 'FINAL',
95-
totalPrice,
96-
currencyCode,
97-
countryCode,
98-
},
99-
});
100-
101-
const token = btoa(paymentData.paymentMethodData.tokenizationData.token);
102-
googlePayTokenRef.current = token;
103-
googlePayFinishedRef.current = true;
104-
setGooglePayToken(token);
105-
setGooglePayFinished(true);
106-
}
107-
} catch (err) {
128+
paymentsClient.loadPaymentData({
129+
...baseRequest,
130+
allowedPaymentMethods: [cardPaymentMethod],
131+
transactionInfo: {
132+
totalPriceStatus: 'FINAL',
133+
totalPrice,
134+
currencyCode,
135+
countryCode,
136+
},
137+
}).then((paymentData) => {
138+
const token = btoa(paymentData.paymentMethodData.tokenizationData.token);
139+
googlePayTokenRef.current = token;
140+
googlePayFinishedRef.current = true;
141+
setGooglePayToken(token);
142+
setGooglePayFinished(true);
143+
}).catch((err) => {
108144
googlePayFinishedRef.current = false;
109145
setGooglePayFinished(false);
110-
111-
// User cancelled the popup — silently reset, no error message
112146
if (err.statusCode !== 'CANCELED') {
113147
setErrorMessage(
114148
err.message
115149
|| __('Google Pay konnte nicht durchgeführt werden.', 'payone-woocommerce-3'),
116150
);
117151
console.error('Google Pay error:', err);
118152
}
119-
}
153+
});
154+
};
120155

121-
return false;
122-
}), [onCheckoutValidation, googlePayFinished, sdkReady]);
156+
// Validate checkout — only allow submit when token is present
157+
useEffect(() => onCheckoutValidation(() => {
158+
return !!(googlePayFinishedRef.current && googlePayTokenRef.current);
159+
}), [onCheckoutValidation]);
123160

124-
// Register onPaymentSetup and trigger re-submit when token arrives (Klarna pattern)
161+
// Provide token on payment setup and trigger re-submit
125162
useEffect(() => {
126163
const unsubscribe = onPaymentSetup(() => {
127164
if (errorMessage) {
@@ -158,7 +195,7 @@ const PayoneGooglePay = ({
158195
return unsubscribe;
159196
}, [onPaymentSetup, googlePayFinished, googlePayToken]);
160197

161-
return null;
198+
return <div ref={buttonContainerRef} />;
162199
};
163200

164201
export default getPaymentMethodConfig(

src/Payone/Gateway/GooglePay.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public function __construct() {
1717

1818
public function init_form_fields() {
1919
$this->init_common_form_fields( 'PAYONE ' . __( 'Google Pay', 'payone-woocommerce-3' ) );
20+
$this->add_googlepay_merchant_info_fields();
2021
$this->form_fields['countries']['default'] = [ 'DE', 'AT' ];
2122
}
2223

@@ -64,4 +65,25 @@ public function order_status_changed( \WC_Order $order, $from_status, $to_status
6465
$this->capture( $order );
6566
}
6667
}
68+
69+
public function get_googlepay_merchant_id() {
70+
return isset( $this->settings[ 'googlepay_merchant_id' ] ) ? $this->settings[ 'googlepay_merchant_id' ] : '';
71+
}
72+
73+
public function get_googlepay_merchant_name() {
74+
return isset( $this->settings[ 'googlepay_merchant_name' ] ) ? $this->settings[ 'googlepay_merchant_name' ] : '';
75+
}
76+
77+
protected function add_googlepay_merchant_info_fields() {
78+
$this->form_fields['googlepay_merchant_id'] = [
79+
'title' => __( 'Google Pay Merchant ID', 'payone-woocommerce-3' ),
80+
'type' => 'text',
81+
'default' => false,
82+
];
83+
$this->form_fields['googlepay_merchant_name'] = [
84+
'title' => __( 'Google Pay Merchant Name', 'payone-woocommerce-3' ),
85+
'type' => 'text',
86+
'default' => false,
87+
];
88+
}
6789
}

src/Payone/Gateway/PayoneBlocksSupport.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -365,10 +365,13 @@ public function get_payment_method_data() {
365365
'expressWorkorderId' => Plugin::get_session_value( AmazonPayBase::SESSION_KEY_WORKORDERID ),
366366
];
367367

368+
$googlePayGateway = $this->getGooglePayGateway();
368369
$data['googlePayConfig'] = [
369-
'sdkUrl' => 'https://pay.google.com/gp/p/js/pay.js',
370-
'gatewayMerchantId' => $this->getGooglePayGateway()->get_merchant_id(),
371-
'environment' => $this->getGooglePayGateway()->get_mode() === 'test' ? 'TEST' : 'PRODUCTION',
370+
'sdkUrl' => 'https://pay.google.com/gp/p/js/pay.js',
371+
'gatewayMerchantId' => $googlePayGateway->get_merchant_id(),
372+
'googlePayMerchantId' => $googlePayGateway->get_googlepay_merchant_id(),
373+
'merchantName' => $googlePayGateway->get_googlepay_merchant_name(),
374+
'environment' => $googlePayGateway->get_mode() === 'test' ? 'TEST' : 'PRODUCTION',
372375
];
373376

374377
// TODO: installmentMonthOptions müssen hier befüllt werden

0 commit comments

Comments
 (0)