blocks
1 month ago
acceptjs-echeck-handler.js
1 month ago
acceptjs-handler.js
1 month ago
blocks-authorizenet.js
1 month ago
easyauthnet-authorizenet-admin.js
1 month ago
easyauthnet-review-ajax.js
1 month ago
googlepay-express.js
1 month ago
googlepay-handler.js
1 month ago
blocks-authorizenet.js
439 lines
| 1 | (function () { |
| 2 | const { createElement, useEffect, useState } = wp.element; |
| 3 | const { getSetting } = wc.wcSettings; |
| 4 | const { registerPaymentMethod } = wc.wcBlocksRegistry; |
| 5 | const { decodeEntities } = wp.htmlEntities; |
| 6 | const { __ } = wp.i18n; |
| 7 | |
| 8 | function base64EncodeUnicode(str) { |
| 9 | try { |
| 10 | return btoa(unescape(encodeURIComponent(str))); |
| 11 | } catch (e) { |
| 12 | try { |
| 13 | return btoa(str); |
| 14 | } catch (err) { |
| 15 | return ''; |
| 16 | } |
| 17 | } |
| 18 | } |
| 19 | |
| 20 | |
| 21 | function getCheckoutTotalMajor() { |
| 22 | // Returns the checkout total in major currency units (e.g., 10.99). |
| 23 | let totals = null; |
| 24 | |
| 25 | try { |
| 26 | if (window.wc && wc.wcBlocksData && wc.wcBlocksData.checkout && typeof wc.wcBlocksData.checkout.getCheckoutTotals === 'function') { |
| 27 | totals = wc.wcBlocksData.checkout.getCheckoutTotals(); |
| 28 | } |
| 29 | } catch (e) {} |
| 30 | |
| 31 | // Fallback: Woo Blocks data store. |
| 32 | if (!totals) { |
| 33 | try { |
| 34 | if (window.wp && wp.data && typeof wp.data.select === 'function') { |
| 35 | const cartStore = wp.data.select('wc/store/cart'); |
| 36 | if (cartStore) { |
| 37 | if (typeof cartStore.getCartTotals === 'function') { |
| 38 | totals = cartStore.getCartTotals(); |
| 39 | } else if (typeof cartStore.getCartData === 'function') { |
| 40 | const cartData = cartStore.getCartData(); |
| 41 | totals = cartData && cartData.totals ? cartData.totals : null; |
| 42 | } |
| 43 | } |
| 44 | } |
| 45 | } catch (e) {} |
| 46 | } |
| 47 | |
| 48 | const minor = totals && (totals.total_price ?? totals.totalPrice ?? totals.total); |
| 49 | const minorNum = Number(minor); |
| 50 | return Number.isFinite(minorNum) ? (minorNum / 100) : 0; |
| 51 | } |
| 52 | |
| 53 | function registerIfConfigured(gatewayId, settingKey, config) { |
| 54 | const settings = getSetting(settingKey, {}); |
| 55 | if (!settings || !settings.title) return; |
| 56 | |
| 57 | const title = decodeEntities(settings.title || ''); |
| 58 | const description = decodeEntities(settings.description || ''); |
| 59 | const icons = settings.icons || []; |
| 60 | |
| 61 | const label = createElement( |
| 62 | 'span', |
| 63 | { style: { display: 'inline-flex', alignItems: 'center' } }, |
| 64 | title, |
| 65 | icons.length |
| 66 | ? createElement( |
| 67 | 'span', |
| 68 | { style: { display: 'flex', gap: '4px', marginLeft: '8px' } }, |
| 69 | icons.map((icon, i) => |
| 70 | createElement('img', { |
| 71 | key: `icon-${gatewayId}-${i}`, |
| 72 | src: icon.src, |
| 73 | alt: icon.alt || '', |
| 74 | style: { display: 'inline-block', verticalAlign: 'middle', height: '24px' }, |
| 75 | }) |
| 76 | ) |
| 77 | ) |
| 78 | : null |
| 79 | ); |
| 80 | |
| 81 | registerPaymentMethod({ |
| 82 | name: gatewayId, |
| 83 | label, |
| 84 | ariaLabel: settings.ariaLabel || title, |
| 85 | canMakePayment: () => true, |
| 86 | content: config.content(settings), |
| 87 | edit: config.content(settings), |
| 88 | supports: config.supports(settings), |
| 89 | paymentMethodId: gatewayId, |
| 90 | }); |
| 91 | } |
| 92 | |
| 93 | // ----------------------------- |
| 94 | // Card (Accept.js) |
| 95 | // ----------------------------- |
| 96 | function cardContent(settings) { |
| 97 | return ({ eventRegistration, emitResponse }) => { |
| 98 | const { onPaymentProcessing } = eventRegistration; |
| 99 | const [isProcessing, setIsProcessing] = useState(false); |
| 100 | |
| 101 | useEffect(() => { |
| 102 | jQuery(document.body).trigger('wc-credit-card-form-init'); |
| 103 | |
| 104 | const unsubscribe = onPaymentProcessing(async () => { |
| 105 | setIsProcessing(true); |
| 106 | const form = jQuery('form.wc-block-checkout__form'); |
| 107 | const handler = new EPAcceptJsHandler('easyauthnet_authorizenet', window.easyauthnet_authorizenet_params || {}); |
| 108 | |
| 109 | try { |
| 110 | const savedToken = jQuery('input[name="wc-easyauthnet_authorizenet-payment-token"]:checked').val(); |
| 111 | if (savedToken && savedToken !== 'new') { |
| 112 | return { |
| 113 | type: emitResponse.responseTypes.SUCCESS, |
| 114 | meta: { |
| 115 | paymentMethodData: { |
| 116 | easyauthnet_authorizenet_use_saved_token: savedToken, |
| 117 | 'wc-easyauthnet_authorizenet-new-payment-method': false, |
| 118 | }, |
| 119 | }, |
| 120 | }; |
| 121 | } |
| 122 | |
| 123 | if (!handler.validateCardFields()) { |
| 124 | throw new Error(__('Please check your card details and try again.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 125 | } |
| 126 | |
| 127 | const cardData = handler.collectCardData(); |
| 128 | const { token = '', last4 = '', expiry = '', cardType = 'unknown' } = await new Promise((resolve, reject) => |
| 129 | handler.sendToAcceptJs(cardData, form, resolve, reject) |
| 130 | ); |
| 131 | |
| 132 | return { |
| 133 | type: emitResponse.responseTypes.SUCCESS, |
| 134 | meta: { |
| 135 | paymentMethodData: { |
| 136 | easyauthnet_authorizenet_token: token, |
| 137 | easyauthnet_authorizenet_card_last4: last4, |
| 138 | easyauthnet_authorizenet_card_expiry: expiry, |
| 139 | easyauthnet_authorizenet_card_type: cardType, |
| 140 | 'wc-easyauthnet_authorizenet-new-payment-method': false, |
| 141 | }, |
| 142 | }, |
| 143 | }; |
| 144 | } catch (error) { |
| 145 | return { |
| 146 | type: emitResponse.responseTypes.ERROR, |
| 147 | message: error.message || __('Payment processing failed. Please try again.', 'payment-gateway-for-authorize-net-for-woocommerce'), |
| 148 | }; |
| 149 | } finally { |
| 150 | setIsProcessing(false); |
| 151 | form.removeClass('easyauthnet-authorizenet-submitting'); |
| 152 | } |
| 153 | }); |
| 154 | |
| 155 | return () => unsubscribe(); |
| 156 | }, [onPaymentProcessing, emitResponse.responseTypes]); |
| 157 | |
| 158 | return createElement( |
| 159 | 'div', |
| 160 | { id: 'wc-easyauthnet_authorizenet-form', className: `wc-credit-card-form wc-payment-form ${isProcessing ? 'processing' : ''}` }, |
| 161 | createElement( |
| 162 | 'div', |
| 163 | { className: 'easyauthnet_authorizenet-field full-width' }, |
| 164 | createElement('label', { htmlFor: 'easyauthnet_authorizenet-card-number' }, __('Card number', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 165 | createElement('input', { |
| 166 | id: 'easyauthnet_authorizenet-card-number', |
| 167 | className: 'input-text wc-credit-card-form-card-number unknown', |
| 168 | type: 'tel', |
| 169 | inputMode: 'numeric', |
| 170 | autoComplete: 'cc-number', |
| 171 | placeholder: '•••• •••• •••• ••••', |
| 172 | disabled: isProcessing, |
| 173 | }) |
| 174 | ), |
| 175 | createElement( |
| 176 | 'div', |
| 177 | { className: 'easyauthnet_authorizenet-field half-width' }, |
| 178 | createElement('label', { htmlFor: 'easyauthnet_authorizenet-card-expiry' }, __('Expiration date', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 179 | createElement('input', { |
| 180 | id: 'easyauthnet_authorizenet-card-expiry', |
| 181 | className: 'input-text wc-credit-card-form-card-expiry', |
| 182 | type: 'tel', |
| 183 | inputMode: 'numeric', |
| 184 | autoComplete: 'cc-exp', |
| 185 | placeholder: 'MM / YY', |
| 186 | disabled: isProcessing, |
| 187 | }) |
| 188 | ), |
| 189 | createElement( |
| 190 | 'div', |
| 191 | { className: 'easyauthnet_authorizenet-field half-width' }, |
| 192 | createElement('label', { htmlFor: 'easyauthnet_authorizenet-card-cvc' }, __('Security code', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 193 | createElement('input', { |
| 194 | id: 'easyauthnet_authorizenet-card-cvc', |
| 195 | className: 'input-text wc-credit-card-form-card-cvc', |
| 196 | type: 'tel', |
| 197 | inputMode: 'numeric', |
| 198 | autoComplete: 'off', |
| 199 | maxLength: 4, |
| 200 | placeholder: 'CVV', |
| 201 | disabled: isProcessing, |
| 202 | }) |
| 203 | ) |
| 204 | ); |
| 205 | }; |
| 206 | } |
| 207 | |
| 208 | function cardSupports(settings) { |
| 209 | return settings.supports || {}; |
| 210 | } |
| 211 | |
| 212 | // ----------------------------- |
| 213 | // eCheck (Accept.js bankData) |
| 214 | // ----------------------------- |
| 215 | function echeckContent(settings) { |
| 216 | return ({ eventRegistration, emitResponse }) => { |
| 217 | const { onPaymentProcessing } = eventRegistration; |
| 218 | const [isProcessing, setIsProcessing] = useState(false); |
| 219 | |
| 220 | useEffect(() => { |
| 221 | const unsubscribe = onPaymentProcessing(async () => { |
| 222 | setIsProcessing(true); |
| 223 | const form = jQuery('form.wc-block-checkout__form'); |
| 224 | const handler = new EPAcceptJsEcheckHandler('easyauthnet_authorizenet_echeck', window.easyauthnet_authorizenet_params || {}); |
| 225 | |
| 226 | try { |
| 227 | const data = handler.collectBankData(); |
| 228 | if (!handler.validateBankFields(data)) { |
| 229 | throw new Error(__('Please fill in all bank details.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 230 | } |
| 231 | |
| 232 | const { token = '' } = await new Promise((resolve, reject) => handler.sendToAcceptJs(data, form, resolve, reject)); |
| 233 | if (!token) { |
| 234 | throw new Error(__('Payment tokenization failed.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 235 | } |
| 236 | |
| 237 | return { |
| 238 | type: emitResponse.responseTypes.SUCCESS, |
| 239 | meta: { |
| 240 | paymentMethodData: { |
| 241 | easyauthnet_authorizenet_echeck_token: token, |
| 242 | easyauthnet_authorizenet_echeck_nonce: settings.nonce || '', |
| 243 | }, |
| 244 | }, |
| 245 | }; |
| 246 | } catch (error) { |
| 247 | return { |
| 248 | type: emitResponse.responseTypes.ERROR, |
| 249 | message: error.message || __('Payment processing failed. Please try again.', 'payment-gateway-for-authorize-net-for-woocommerce'), |
| 250 | }; |
| 251 | } finally { |
| 252 | setIsProcessing(false); |
| 253 | form.removeClass('easyauthnet-authorizenet-submitting'); |
| 254 | } |
| 255 | }); |
| 256 | |
| 257 | return () => unsubscribe(); |
| 258 | }, [onPaymentProcessing, emitResponse.responseTypes]); |
| 259 | |
| 260 | return createElement( |
| 261 | 'div', |
| 262 | { className: `wc-payment-form ${isProcessing ? 'processing' : ''}` }, |
| 263 | createElement( |
| 264 | 'p', |
| 265 | { className: 'form-row form-row-wide' }, |
| 266 | createElement('label', { htmlFor: 'easyauthnet_echeck_name' }, __('Name on account', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 267 | createElement('input', { id: 'easyauthnet_echeck_name', type: 'text', disabled: isProcessing }) |
| 268 | ), |
| 269 | createElement( |
| 270 | 'p', |
| 271 | { className: 'form-row form-row-wide' }, |
| 272 | createElement('label', { htmlFor: 'easyauthnet_echeck_routing' }, __('Routing number', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 273 | createElement('input', { id: 'easyauthnet_echeck_routing', type: 'tel', inputMode: 'numeric', disabled: isProcessing }) |
| 274 | ), |
| 275 | createElement( |
| 276 | 'p', |
| 277 | { className: 'form-row form-row-wide' }, |
| 278 | createElement('label', { htmlFor: 'easyauthnet_echeck_account' }, __('Account number', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 279 | createElement('input', { id: 'easyauthnet_echeck_account', type: 'tel', inputMode: 'numeric', disabled: isProcessing }) |
| 280 | ), |
| 281 | createElement( |
| 282 | 'p', |
| 283 | { className: 'form-row form-row-wide' }, |
| 284 | createElement('label', { htmlFor: 'easyauthnet_echeck_type' }, __('Account type', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 285 | createElement( |
| 286 | 'select', |
| 287 | { id: 'easyauthnet_echeck_type', disabled: isProcessing }, |
| 288 | createElement('option', { value: 'checking' }, __('Checking', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 289 | createElement('option', { value: 'savings' }, __('Savings', 'payment-gateway-for-authorize-net-for-woocommerce')), |
| 290 | createElement('option', { value: 'businessChecking' }, __('Business checking', 'payment-gateway-for-authorize-net-for-woocommerce')) |
| 291 | ) |
| 292 | ) |
| 293 | ); |
| 294 | }; |
| 295 | } |
| 296 | |
| 297 | function echeckSupports(settings) { |
| 298 | return settings.supports || {}; |
| 299 | } |
| 300 | |
| 301 | // ----------------------------- |
| 302 | // Google Pay |
| 303 | // ----------------------------- |
| 304 | function googlePayContent(settings) { |
| 305 | return ({ eventRegistration, emitResponse }) => { |
| 306 | const { onPaymentProcessing } = eventRegistration; |
| 307 | const [isProcessing, setIsProcessing] = useState(false); |
| 308 | |
| 309 | useEffect(() => { |
| 310 | const unsubscribe = onPaymentProcessing(async () => { |
| 311 | setIsProcessing(true); |
| 312 | try { |
| 313 | if (!settings.gatewayMerchantId) { |
| 314 | throw new Error(__('Google Pay is not configured. Please contact the store owner.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 315 | } |
| 316 | if (!window.google || !google.payments || !google.payments.api) { |
| 317 | throw new Error((settings.i18n && settings.i18n.failed) || __('Google Pay unavailable.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 318 | } |
| 319 | |
| 320 | const client = new google.payments.api.PaymentsClient({ |
| 321 | environment: settings.environment === 'live' ? 'PRODUCTION' : 'TEST', |
| 322 | }); |
| 323 | |
| 324 | const readyResp = await client.isReadyToPay({ |
| 325 | apiVersion: 2, |
| 326 | apiVersionMinor: 0, |
| 327 | allowedPaymentMethods: [ |
| 328 | { |
| 329 | type: 'CARD', |
| 330 | parameters: { |
| 331 | allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], |
| 332 | allowedCardNetworks: ['AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'], |
| 333 | }, |
| 334 | }, |
| 335 | ], |
| 336 | }); |
| 337 | |
| 338 | if (!readyResp || !readyResp.result) { |
| 339 | throw new Error((settings.i18n && settings.i18n.not_ready) || __('Google Pay not available.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 340 | } |
| 341 | |
| 342 | // Total is calculated server-side too; here it is only for the wallet sheet. |
| 343 | const totalRaw = getCheckoutTotalMajor(); |
| 344 | |
| 345 | const paymentData = await client.loadPaymentData({ |
| 346 | apiVersion: 2, |
| 347 | apiVersionMinor: 0, |
| 348 | allowedPaymentMethods: [ |
| 349 | { |
| 350 | type: 'CARD', |
| 351 | parameters: { |
| 352 | allowedAuthMethods: ['PAN_ONLY', 'CRYPTOGRAM_3DS'], |
| 353 | allowedCardNetworks: ['AMEX', 'DISCOVER', 'JCB', 'MASTERCARD', 'VISA'], |
| 354 | }, |
| 355 | tokenizationSpecification: { |
| 356 | type: 'PAYMENT_GATEWAY', |
| 357 | parameters: { |
| 358 | gateway: 'authorizenet', |
| 359 | gatewayMerchantId: settings.gatewayMerchantId, |
| 360 | }, |
| 361 | }, |
| 362 | }, |
| 363 | ], |
| 364 | merchantInfo: (function () { |
| 365 | var mi = { merchantName: settings.merchantName || '' }; |
| 366 | if (settings.googleMerchantId) { |
| 367 | mi.merchantId = String(settings.googleMerchantId); |
| 368 | } |
| 369 | return mi; |
| 370 | })(), |
| 371 | transactionInfo: { |
| 372 | totalPriceStatus: 'FINAL', |
| 373 | totalPrice: (Number(totalRaw || 0)).toFixed(2), |
| 374 | currencyCode: settings.currency || 'USD', |
| 375 | countryCode: settings.countryCode || 'US', |
| 376 | }, |
| 377 | }); |
| 378 | |
| 379 | const token = paymentData?.paymentMethodData?.tokenizationData?.token || ''; |
| 380 | if (!token) { |
| 381 | throw new Error((settings.i18n && settings.i18n.failed) || __('Google Pay token missing.', 'payment-gateway-for-authorize-net-for-woocommerce')); |
| 382 | } |
| 383 | |
| 384 | return { |
| 385 | type: emitResponse.responseTypes.SUCCESS, |
| 386 | meta: { |
| 387 | paymentMethodData: { |
| 388 | easyauthnet_authorizenet_googlepay_token: base64EncodeUnicode(token), |
| 389 | easyauthnet_authorizenet_googlepay_nonce: settings.nonce || '', |
| 390 | }, |
| 391 | }, |
| 392 | }; |
| 393 | } catch (error) { |
| 394 | return { |
| 395 | type: emitResponse.responseTypes.ERROR, |
| 396 | message: error.message || __('Payment processing failed. Please try again.', 'payment-gateway-for-authorize-net-for-woocommerce'), |
| 397 | }; |
| 398 | } finally { |
| 399 | setIsProcessing(false); |
| 400 | } |
| 401 | }); |
| 402 | |
| 403 | return () => unsubscribe(); |
| 404 | }, [onPaymentProcessing, emitResponse.responseTypes]); |
| 405 | |
| 406 | return createElement( |
| 407 | 'div', |
| 408 | { className: `wc-payment-form ${isProcessing ? 'processing' : ''}` }, |
| 409 | createElement('p', null, descriptionOrFallback(settings.description, __('You will be prompted to approve the payment in Google Pay.', 'payment-gateway-for-authorize-net-for-woocommerce'))) |
| 410 | ); |
| 411 | }; |
| 412 | } |
| 413 | |
| 414 | function walletSupports(settings) { |
| 415 | return settings.supports || {}; |
| 416 | } |
| 417 | |
| 418 | function descriptionOrFallback(desc, fallback) { |
| 419 | const d = (desc || '').toString().trim(); |
| 420 | return d ? decodeEntities(d) : fallback; |
| 421 | } |
| 422 | |
| 423 | // Register all gateways if present. |
| 424 | registerIfConfigured('easyauthnet_authorizenet', 'easyauthnet_authorizenet_data', { |
| 425 | content: cardContent, |
| 426 | supports: cardSupports, |
| 427 | }); |
| 428 | |
| 429 | registerIfConfigured('easyauthnet_authorizenet_echeck', 'easyauthnet_authorizenet_echeck_data', { |
| 430 | content: echeckContent, |
| 431 | supports: echeckSupports, |
| 432 | }); |
| 433 | |
| 434 | registerIfConfigured('easyauthnet_authorizenet_googlepay', 'easyauthnet_authorizenet_googlepay_data', { |
| 435 | content: googlePayContent, |
| 436 | supports: walletSupports, |
| 437 | }); |
| 438 | })(); |
| 439 |