diff --git a/.gitignore b/.gitignore index 2ccd4569b..3af7246ab 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ vendor/ node_modules/ composer.lock yarn.lock +.pnpm-store/ yarn-error.log lerna-debug.log diff --git a/packages/plugin/src/Resources/js/scripts/front-end/payments/stripe/elements.js b/packages/plugin/src/Resources/js/scripts/front-end/payments/stripe/elements.js index 6e8e7f4be..78a7eeb0c 100644 --- a/packages/plugin/src/Resources/js/scripts/front-end/payments/stripe/elements.js +++ b/packages/plugin/src/Resources/js/scripts/front-end/payments/stripe/elements.js @@ -1 +1,8 @@ -(()=>{var ve={form:{ready:"freeform-ready",reset:"freeform-on-reset",submit:"freeform-on-submit",removeMessages:"freeform-remove-messages",fieldRemoveMessages:"freeform-remove-field-messages",renderSuccess:"freeform-render-success",renderFieldErrors:"freeform-render-field-errors",renderFormErrors:"freeform-render-form-errors",ajaxBeforeSuccess:"freeform-before-ajax-success",ajaxSuccess:"freeform-ajax-success",ajaxError:"freeform-ajax-error",ajaxBeforeSubmit:"freeform-ajax-before-submit",ajaxAfterSubmit:"freeform-ajax-after-submit",afterFailedSubmit:"freeform-after-failed-submit",handleActions:"freeform-handle-actions"},rules:{applied:"freeform-rules-applied"},table:{onAddRow:"freeform-field-table-on-add-row",afterRowAdded:"freeform-field-table-after-row-added",onRemoveRow:"freeform-field-table-on-remove-row",afterRemoveRow:"freeform-field-table-after-remove-row"},dragAndDrop:{renderPreview:"freeform-field-dnd-on-render-preview",renderPreviewRemoveButton:"freeform-field-dnd-on-render-preview-remove-button",renderErrorContainer:"freeform-field-dnd-render-error-container",showGlobalMessage:"freeform-field-dnd-show-global-message",appendErrors:"freeform-field-dnd-append-errors",clearErrors:"freeform-field-dnd-clear-errors",afterErrors:"freeform-field-dnd-after-errors",onChange:"freeform-field-dnd-on-change",onUploadProgress:"freeform-field-dnd-on-upload-progress"},saveAndContinue:{saveFormhandleToken:"freeform-save-form-handle-token"},scripts:{beforeLoad:"freeform-script-before-load",afterLoad:"freeform-script-after-load"},stylesheets:{beforeLoad:"freeform-stylesheet-before-load",afterLoad:"freeform-stylesheet-after-load"}},b=ve;var K=(t,e,r)=>{let{bubbles:n=!1,cancelable:o=!0,...a}=e||{},s=he(t,n,o);return Object.assign(s,a),r&&(r instanceof HTMLElement?r.dispatchEvent(s):Array.from(r).forEach(l=>{l.dispatchEvent(s)})),s},he=(t,e=!0,r=!0)=>new Event(t,{bubbles:e,cancelable:r}),N=(t,e,r,n)=>{Se("add",{elements:t,type:e,callback:r,options:n})};var Se=(t,{type:e,elements:r,callback:n,options:o})=>{let a=Array.isArray(e)?e:[e],s=Array.isArray(r)?r:[r];Array.from(s).forEach(l=>{a.forEach(i=>{t==="add"?l.addEventListener(i,n,o):l.removeEventListener(i,n,o)})})};var z="freeform-stripe",ge={load:`${z}-load`,render:{appearance:`${z}-appearance`}},M=ge;function A(t){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?A=function(e){return typeof e}:A=function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},A(t)}var Z="dahlia",Te=function(e){return e===3?"v3":e},ee="https://js.stripe.com",Le="".concat(ee,"/").concat(Z,"/stripe.js"),be=/^https:\/\/js\.stripe\.com\/v3\/?(\?.*)?$/,we=/^https:\/\/js\.stripe\.com\/(v3|[a-z]+)\/stripe\.js(\?.*)?$/,Q="loadStripe.setLoadParameters was called but an existing Stripe.js script already exists in the document; existing script parameters will be used",Re=function(e){return be.test(e)||we.test(e)},Me=function(){for(var e=document.querySelectorAll('script[src^="'.concat(ee,'"]')),r=0;r element.");return o.appendChild(n),n},Fe=function(e,r){!e||!e._registerWrapper||e._registerWrapper({name:"stripe-js",version:"9.1.0",startTime:r})},F=null,P=null,C=null,He=function(e){return function(r){e(new Error("Failed to load Stripe.js",{cause:r}))}},Pe=function(e,r){return function(){window.Stripe?e(window.Stripe):r(new Error("Stripe.js not available"))}},Ce=function(e){return F!==null?F:(F=new Promise(function(r,n){if(typeof window>"u"||typeof document>"u"){r(null);return}if(window.Stripe&&e&&console.warn(Q),window.Stripe){r(window.Stripe);return}try{var o=Me();if(o&&e)console.warn(Q);else if(!o)o=Y(e);else if(o&&C!==null&&P!==null){var a;o.removeEventListener("load",C),o.removeEventListener("error",P),(a=o.parentNode)===null||a===void 0||a.removeChild(o),o=Y(e)}C=Pe(r,n),P=He(n),o.addEventListener("load",C),o.addEventListener("error",P)}catch(s){n(s);return}}),F.catch(function(r){return F=null,Promise.reject(r)}))},Ae=function(e,r,n){if(e===null)return null;var o=r[0];if(typeof o!="string")throw new Error("Expected publishable key to be of type string, got type ".concat(A(o)," instead."));var a=o.match(/^pk_test/),s=Te(e.version),l=Z;a&&s!==l&&console.warn("Stripe.js@".concat(s," was loaded on the page, but @stripe/stripe-js@").concat("9.1.0"," expected Stripe.js@").concat(l,". This may result in unexpected behavior. For more information, see https://docs.stripe.com/sdks/stripejs-versioning"));var i=e.apply(void 0,r);return Fe(i,n),i},H,te=!1,re=function(){return H||(H=Ce(null).catch(function(e){return H=null,Promise.reject(e)}),H)};Promise.resolve().then(function(){return re()}).catch(function(t){te||console.warn(t)});var ne=function(){for(var e=arguments.length,r=new Array(e),n=0;n{let e=t.querySelector("[data-freeform-stripe-card][data-config]");if(!e)return;let r=JSON.parse(e.dataset.config);return{...r,loadStripe:async()=>{if(!_.has(r.apiKey)){let n=await ne(r.apiKey);_.set(r.apiKey,n)}return _.get(r.apiKey)}}},x=xe;var oe=t=>{let{theme:e="stripe",layout:r="tabs",floatingLabels:n=!1}=t;return{elementOptions:{appearance:{theme:e,labels:n?"floating":"above",variables:{}}},paymentOptions:{layout:{type:r==="tabs"?"tabs":"accordion",defaultCollapsed:!1,radios:r==="accordion-radios",spacedAccordionItems:r!=="accordion-radios"}}}};var X;var ae=async()=>{try{let t=document.querySelector("form[data-csrf-refresh]");if(!t)return Oe();switch(t.dataset.csrfRefresh){case"once":return X===void 0&&(X=await se()),X;case"always":return await se();default:return null}}catch{}return null},Oe=()=>{var n;let t=document.querySelector("form[data-csrf-name]");if(!t)return null;let e=t.dataset.csrfName,r=(n=t.querySelector(`input[name="${e}"]`))==null?void 0:n.value;return!e||!r?null:{name:e,value:r}},se=async()=>{let e=await fetch("/freeform/tokens",{headers:{Accept:"application/json"}}).then(r=>r.json());return e.csrf!==void 0?{name:e.csrf.name,value:e.csrf.value}:null};var O=class t extends Error{constructor(e,r,n){super(e),this.response={...r,data:n},this.status=r.status,Object.setPrototypeOf(this,t.prototype)}};var I=async(t,e,r,n,o)=>{let a=new URL(e,window.location.origin);o!=null&&o.queryParams&&o.queryParams.forEach((i,T)=>{a.searchParams.set(T,i)});let s=o.request||new XMLHttpRequest;s.open(t,a),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("HTTP_X_REQUESTED_WITH","XMLHttpRequest");let l=await ae();return l&&s.setRequestHeader("X-CSRF-Token",l.value),Ie(s,o==null?void 0:o.headers),s.onload=()=>{let i=s.response;try{i=JSON.parse(s.response)}catch{}let T=s.status;if(T<200||T>=300){n(new O(`Request failed with status ${s.statusText}`,s,i));return}r({status:s.status,data:i,request:s})},s.onerror=()=>{n(new Error("Network error"))},s.onabort=()=>{n(new Error("Request aborted"))},o.onUploadProgress&&(s.upload.onprogress=i=>{o.onUploadProgress(i)}),o.cancelToken&&o.cancelToken._setCancelFn(()=>{s.abort()}),s},Ie=(t,e)=>{e&&Object.entries(e).forEach(([r,n])=>{t.setRequestHeader(r,String(n))})};var je=async(t,e={})=>new Promise((r,n)=>{I("GET",t,r,n,e).then(o=>{o.open("GET",t),o.send()})}),qe=async(t,e,r={})=>new Promise((n,o)=>{I("POST",t,n,o,r).then(a=>{e instanceof FormData?a.send(e):(a.setRequestHeader("Content-Type","application/json"),a.send(JSON.stringify(e)))})}),R=(t,e)=>new Promise((r,n)=>{I((e==null?void 0:e.method)||"GET",t,r,n,e).then(o=>{let a=e==null?void 0:e.data;a instanceof FormData?o.send(a):(o.setRequestHeader("Content-Type","application/json"),o.send(JSON.stringify(a)))})});R.get=je;R.post=qe;var G=t=>{let e=new FormData(t);return e.set("method","post"),e.delete("action"),e},ke={create:async(t,e,r)=>{let n=G(e);return R.post("/freeform/payments/stripe/payment-intents",n,{headers:{"FF-STRIPE-INTEGRATION":t},queryParams:new URLSearchParams({site:r})})},updateAmount:async(t,e,r,n)=>{let o=G(e),{data:a}=await R.post(`/freeform/payments/stripe/payment-intents/${r}/amount`,o,{headers:{"FF-STRIPE-INTEGRATION":t},queryParams:new URLSearchParams({site:n})});return a}},De={update:async({integration:t,form:e,paymentIntentId:r,site:n})=>{let o=G(e),{status:a}=await R.post(`/freeform/payments/stripe/payment-intents/${r}/customers`,o,{headers:{"FF-STRIPE-INTEGRATION":t},queryParams:new URLSearchParams({site:n})});return a}},j={paymentIntents:ke,customers:De};var W=t=>{if(t.getAttribute("data-hidden")!==null)return!0;let e=t.parentElement;for(;e;){if(e.getAttribute("data-hidden")!==null)return!0;e=e.parentElement}return!1},ie=(t,e)=>{let r=t.querySelectorAll('[data-field-type="stripe"]');return Array.from(r).filter(n=>{let o=W(n);return!!(o&&e||!o&&!e)})},B=t=>ie(t,!1),me=t=>ie(t,!0);var J=[],ce=new WeakSet,q=t=>async e=>{if(W(e)||ce.has(e))return;ce.add(e);let{site:r,fieldMapping:n,theme:o,layout:a,floatingLabels:s,integration:l,amountFields:i,loadStripe:T}=x(e),{elementMap:d,form:c}=t,m=e.querySelector("[data-freeform-stripe-card]");if(!m||d.has(m))return;let E;d.has(m)&&d.get(m).stripe?E=d.get(m).stripe:E=await T(),c.freeform.disableSubmit("stripe.init"),d.set(m,{empty:!0,stripe:E,elements:null,paymentIntent:null}),m.innerHTML="Loading...",j.paymentIntents.create(l,c,r).then(({data:{id:v,secret:h}})=>{m.parentElement.querySelector("[data-freeform-stripe-intent]").value=v;let{elementOptions:S,paymentOptions:u}=oe({theme:o,layout:a,floatingLabels:s}),f=K(M.render.appearance,{bubbles:!0,elementOptions:S,paymentOptions:u},[m]),g=E.elements({...f.elementOptions,clientSecret:h}),w=g.create("payment",f.paymentOptions);w.mount(m),w.on("change",p=>{d.get(m).empty=p.empty&&!p.complete}),i.forEach(p=>{let y=c.elements.namedItem(p),L=[];y instanceof RadioNodeList?L=Array.from(y):L.push(y),L.forEach(k=>{k==null||k.addEventListener("change",()=>{J.push(p),c.freeform.disableSubmit("stripe.working"),c.freeform.disableForm();let Ee=d.get(m).paymentIntent.id;j.paymentIntents.updateAmount(l,c,Ee,r).then(({id:D,client_secret:U})=>{U?(w.unmount(),g=E.elements({clientSecret:U}),w=g.create("payment",f.paymentOptions),w.mount(m),w.on("change",$=>{d.get(m).empty=$.empty&&!$.complete}),d.set(m,{empty:!0,elements:g,stripe:E,paymentIntent:{id:D,secret:U}})):g.fetchUpdates()}).catch(D=>{c.freeform._renderFieldErrors({[p]:[D.response.data.message]})}).finally(()=>{J.pop(),J.length||(c.freeform.enableSubmit("stripe.working"),c.freeform.enableForm())})})})});let ye=n.some(({target:p})=>p===void 0),V=p=>y=>{let L=y.target.value;j.customers.update({integration:l,form:c,paymentIntentId:v,key:p,value:L,site:r})};ye?c.querySelectorAll('input:not([type="hidden"]), select, textarea').forEach(y=>{y.addEventListener("change",V(y.name))}):n.forEach(({source:p,target:y})=>{var L;(L=c.elements.namedItem(y))==null||L.addEventListener("change",V(p))}),d.set(m,{empty:!0,stripe:E,elements:g,paymentIntent:{id:v,secret:h}})}).catch(v=>{m.innerHTML="Could not load payment element.";let h={};i.forEach(u=>{var f,g;h[u]=[(g=(f=v==null?void 0:v.response)==null?void 0:f.data)==null?void 0:g.message]}),c.freeform._renderFieldErrors(h);let S=()=>{q(t)(e),i.forEach(u=>{var f;(f=c[u])==null||f.removeEventListener("change",S)})};i.forEach(u=>{var f;(f=c[u])==null||f.addEventListener("change",S)})}).finally(()=>{c.freeform.enableSubmit("stripe.init")})};var le=t=>async()=>{let{form:e}=t;B(e).forEach(q(t)),me(e).forEach(r=>{r.addEventListener(b.rules.applied,()=>{q(t)(r)})})},fe=t=>async e=>{e.addCallback(async()=>{if(e.isBackButtonPressed)return;let{elementMap:r,form:n}=t,o=B(n);for(let a of o){let{required:s,integration:l,site:i}=x(a),T=a.querySelector("[data-freeform-stripe-card]"),{empty:d,stripe:c,elements:m,paymentIntent:{id:E,secret:v}}=r.get(T);if(d&&!s)continue;let h=await e.freeform.quickSave(v,E);if(h===!1)return!0;if(h===void 0)return!1;let S=new URL("/freeform/payments/stripe/callback",window.location.origin);S.searchParams.append("integration",l),S.searchParams.append("stripe_token",h),S.searchParams.append("site",i);let{error:u}=await m.submit();if(u)return e.freeform._renderFormErrors([u.message]),e.freeform._scrollToForm(),!1;let{error:f}=await c.confirmPayment({elements:m,confirmParams:{return_url:S.toString()}});return f&&(e.freeform._renderFormErrors([f.message]),e.freeform._scrollToForm()),!1}},100)};var pe=new WeakMap,de=async t=>{if(pe.has(t))return;pe.set(t,!0);let r={elementMap:new WeakMap,form:t},n=le(r);N(t,[b.form.ready,b.form.reset,b.form.ajaxAfterSubmit],n),N(t,[b.form.submit],fe(r))};document.addEventListener(M.load,()=>{document.querySelectorAll("form[data-freeform]").forEach(e=>{de(e)})});document.addEventListener("DOMContentLoaded",()=>{document.dispatchEvent(new CustomEvent(M.load))});var ue=t=>{var e;(t.nodeName==="FORM"||((e=t.dataset)==null?void 0:e.freeform)!==void 0)&&de(t),t==null||t.childNodes.forEach(ue)},Ue=new MutationObserver(t=>{t.forEach(e=>{e.type==="childList"&&e.addedNodes.forEach(r=>{ue(r)})})});Ue.observe(document.body,{childList:!0,subtree:!0});})(); +(()=>{var Re=Object.create;var Y=Object.defineProperty;var Me=Object.getOwnPropertyDescriptor;var Fe=Object.getOwnPropertyNames;var He=Object.getPrototypeOf,Pe=Object.prototype.hasOwnProperty;var Z=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Ce=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Fe(e))!Pe.call(t,n)&&n!==r&&Y(t,n,{get:()=>e[n],enumerable:!(o=Me(e,n))||o.enumerable});return t};var Ae=(t,e,r)=>(r=t!=null?Re(He(t)):{},Ce(e||!t||!t.__esModule?Y(r,"default",{value:t,enumerable:!0}):r,t));var ce=Z(G=>{"use strict";Object.defineProperty(G,"__esModule",{value:!0});function H(t){"@babel/helpers - typeof";return typeof Symbol=="function"&&typeof Symbol.iterator=="symbol"?H=function(e){return typeof e}:H=function(e){return e&&typeof Symbol=="function"&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},H(t)}var se="clover",qe=function(e){return e===3?"v3":e},ae="https://js.stripe.com",ke="".concat(ae,"/").concat(se,"/stripe.js"),De=/^https:\/\/js\.stripe\.com\/v3\/?(\?.*)?$/,Ne=/^https:\/\/js\.stripe\.com\/(v3|[a-z]+)\/stripe\.js(\?.*)?$/,re="loadStripe.setLoadParameters was called but an existing Stripe.js script already exists in the document; existing script parameters will be used",Ue=function(e){return De.test(e)||Ne.test(e)},_e=function(){for(var e=document.querySelectorAll('script[src^="'.concat(ae,'"]')),r=0;r element.");return n.appendChild(o),o},Xe=function(e,r){!e||!e._registerWrapper||e._registerWrapper({name:"stripe-js",version:"8.11.0",startTime:r})},F=null,C=null,A=null,Ge=function(e){return function(r){e(new Error("Failed to load Stripe.js",{cause:r}))}},We=function(e,r){return function(){window.Stripe?e(window.Stripe):r(new Error("Stripe.js not available"))}},Be=function(e){return F!==null?F:(F=new Promise(function(r,o){if(typeof window>"u"||typeof document>"u"){r(null);return}if(window.Stripe&&e&&console.warn(re),window.Stripe){r(window.Stripe);return}try{var n=_e();if(n&&e)console.warn(re);else if(!n)n=ne(e);else if(n&&A!==null&&C!==null){var a;n.removeEventListener("load",A),n.removeEventListener("error",C),(a=n.parentNode)===null||a===void 0||a.removeChild(n),n=ne(e)}A=We(r,o),C=Ge(o),n.addEventListener("load",A),n.addEventListener("error",C)}catch(s){o(s);return}}),F.catch(function(r){return F=null,Promise.reject(r)}))},Je=function(e,r,o){if(e===null)return null;var n=r[0];if(typeof n!="string")throw new Error("Expected publishable key to be of type string, got type ".concat(H(n)," instead."));var a=n.match(/^pk_test/),s=qe(e.version),l=se;a&&s!==l&&console.warn("Stripe.js@".concat(s," was loaded on the page, but @stripe/stripe-js@").concat("8.11.0"," expected Stripe.js@").concat(l,". This may result in unexpected behavior. For more information, see https://docs.stripe.com/sdks/stripejs-versioning"));var i=e.apply(void 0,r);return Xe(i,o),i},oe=function(e){var r=`invalid load parameters; expected object of shape + + {advancedFraudSignals: boolean} + +but received + + `.concat(JSON.stringify(e),` +`);if(e===null||H(e)!=="object")throw new Error(r);if(Object.keys(e).length===1&&typeof e.advancedFraudSignals=="boolean")return e;throw new Error(r)},O,X=!1,ie=function(){for(var e=arguments.length,r=new Array(e),o=0;o{me.exports=ce()});var Oe={form:{ready:"freeform-ready",reset:"freeform-on-reset",submit:"freeform-on-submit",removeMessages:"freeform-remove-messages",fieldRemoveMessages:"freeform-remove-field-messages",renderSuccess:"freeform-render-success",renderFieldErrors:"freeform-render-field-errors",renderFormErrors:"freeform-render-form-errors",ajaxBeforeSuccess:"freeform-before-ajax-success",ajaxSuccess:"freeform-ajax-success",ajaxError:"freeform-ajax-error",ajaxBeforeSubmit:"freeform-ajax-before-submit",ajaxAfterSubmit:"freeform-ajax-after-submit",afterFailedSubmit:"freeform-after-failed-submit",handleActions:"freeform-handle-actions"},rules:{applied:"freeform-rules-applied"},table:{onAddRow:"freeform-field-table-on-add-row",afterRowAdded:"freeform-field-table-after-row-added",onRemoveRow:"freeform-field-table-on-remove-row",afterRemoveRow:"freeform-field-table-after-remove-row"},dragAndDrop:{renderPreview:"freeform-field-dnd-on-render-preview",renderPreviewRemoveButton:"freeform-field-dnd-on-render-preview-remove-button",renderErrorContainer:"freeform-field-dnd-render-error-container",showGlobalMessage:"freeform-field-dnd-show-global-message",appendErrors:"freeform-field-dnd-append-errors",clearErrors:"freeform-field-dnd-clear-errors",afterErrors:"freeform-field-dnd-after-errors",onChange:"freeform-field-dnd-on-change",onUploadProgress:"freeform-field-dnd-on-upload-progress"},saveAndContinue:{saveFormhandleToken:"freeform-save-form-handle-token"},scripts:{beforeLoad:"freeform-script-before-load",afterLoad:"freeform-script-after-load"},stylesheets:{beforeLoad:"freeform-stylesheet-before-load",afterLoad:"freeform-stylesheet-after-load"}},b=Oe;var ee=(t,e,r)=>{let{bubbles:o=!1,cancelable:n=!0,...a}=e||{},s=xe(t,o,n);return Object.assign(s,a),r&&(r instanceof HTMLElement?r.dispatchEvent(s):Array.from(r).forEach(l=>{l.dispatchEvent(s)})),s},xe=(t,e=!0,r=!0)=>new Event(t,{bubbles:e,cancelable:r}),_=(t,e,r,o)=>{je("add",{elements:t,type:e,callback:r,options:o})};var je=(t,{type:e,elements:r,callback:o,options:n})=>{let a=Array.isArray(e)?e:[e],s=Array.isArray(r)?r:[r];Array.from(s).forEach(l=>{a.forEach(i=>{t==="add"?l.addEventListener(i,o,n):l.removeEventListener(i,o,n)})})};var te="freeform-stripe",Ie={load:`${te}-load`,render:{appearance:`${te}-appearance`}},M=Ie;var fe=Ae(le()),Ve="[data-freeform-stripe-card][data-config]",W=new Map,$e=t=>{let e=t.querySelector(Ve);if(!e)throw new Error("Stripe config element not found");let r=JSON.parse(e.dataset.config||"{}");return{...r,loadStripe:async()=>{if(!W.has(r.apiKey)){let o=await(0,fe.loadStripe)(r.apiKey);W.set(r.apiKey,o)}return W.get(r.apiKey)}}},x=$e;var pe=t=>{let{theme:e="stripe",layout:r="tabs",floatingLabels:o=!1}=t;return{elementOptions:{appearance:{theme:e,labels:o?"floating":"above",variables:{}}},paymentOptions:{layout:{type:r==="tabs"?"tabs":"accordion",defaultCollapsed:!1,radios:r==="accordion-radios",spacedAccordionItems:r!=="accordion-radios"}}}};var B;var ue=async()=>{try{let t=document.querySelector("form[data-csrf-refresh]");if(!t)return Ke();switch(t.dataset.csrfRefresh){case"once":return B===void 0&&(B=await de()),B;case"always":return await de();default:return null}}catch{}return null},Ke=()=>{var o;let t=document.querySelector("form[data-csrf-name]");if(!t)return null;let e=t.dataset.csrfName,r=(o=t.querySelector(`input[name="${e}"]`))==null?void 0:o.value;return!e||!r?null:{name:e,value:r}},de=async()=>{let e=await fetch("/freeform/tokens",{headers:{Accept:"application/json"}}).then(r=>r.json());return e.csrf!==void 0?{name:e.csrf.name,value:e.csrf.value}:null};var j=class t extends Error{constructor(e,r,o){super(e),this.response={...r,data:o},this.status=r.status,Object.setPrototypeOf(this,t.prototype)}};var I=async(t,e,r,o,n)=>{let a=new URL(e,window.location.origin);n!=null&&n.queryParams&&n.queryParams.forEach((i,L)=>{a.searchParams.set(L,i)});let s=n.request||new XMLHttpRequest;s.open(t,a),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("HTTP_X_REQUESTED_WITH","XMLHttpRequest");let l=await ue();return l&&s.setRequestHeader("X-CSRF-Token",l.value),ze(s,n==null?void 0:n.headers),s.onload=()=>{let i=s.response;try{i=JSON.parse(s.response)}catch{}let L=s.status;if(L<200||L>=300){o(new j(`Request failed with status ${s.statusText}`,s,i));return}r({status:s.status,data:i,request:s})},s.onerror=()=>{o(new Error("Network error"))},s.onabort=()=>{o(new Error("Request aborted"))},n.onUploadProgress&&(s.upload.onprogress=i=>{n.onUploadProgress(i)}),n.cancelToken&&n.cancelToken._setCancelFn(()=>{s.abort()}),s},ze=(t,e)=>{e&&Object.entries(e).forEach(([r,o])=>{t.setRequestHeader(r,String(o))})};var Qe=async(t,e={})=>new Promise((r,o)=>{I("GET",t,r,o,e).then(n=>{n.open("GET",t),n.send()})}),Ye=async(t,e,r={})=>new Promise((o,n)=>{I("POST",t,o,n,r).then(a=>{e instanceof FormData?a.send(e):(a.setRequestHeader("Content-Type","application/json"),a.send(JSON.stringify(e)))})}),R=(t,e)=>new Promise((r,o)=>{I((e==null?void 0:e.method)||"GET",t,r,o,e).then(n=>{let a=e==null?void 0:e.data;a instanceof FormData?n.send(a):(n.setRequestHeader("Content-Type","application/json"),n.send(JSON.stringify(a)))})});R.get=Qe;R.post=Ye;var J=t=>{let e=new FormData(t);return e.set("method","post"),e.delete("action"),e},Ze={create:async(t,e,r)=>{let o=J(e);return R.post("/freeform/payments/stripe/payment-intents",o,{headers:{"FF-STRIPE-INTEGRATION":t},queryParams:new URLSearchParams({site:r})})},updateAmount:async(t,e,r,o)=>{let n=J(e),{data:a}=await R.post(`/freeform/payments/stripe/payment-intents/${r}/amount`,n,{headers:{"FF-STRIPE-INTEGRATION":t},queryParams:new URLSearchParams({site:o})});return a}},et={update:async({integration:t,form:e,paymentIntentId:r,site:o})=>{let n=J(e),{status:a}=await R.post(`/freeform/payments/stripe/payment-intents/${r}/customers`,n,{headers:{"FF-STRIPE-INTEGRATION":t},queryParams:new URLSearchParams({site:o})});return a}},q={paymentIntents:Ze,customers:et};var V=t=>{if(t.getAttribute("data-hidden")!==null)return!0;let e=t.parentElement;for(;e;){if(e.getAttribute("data-hidden")!==null)return!0;e=e.parentElement}return!1},ye=(t,e)=>{let r=t.querySelectorAll('[data-field-type="stripe"]');return Array.from(r).filter(o=>{let n=V(o);return!!(n&&e||!n&&!e)})},$=t=>ye(t,!1),Ee=t=>ye(t,!0);var tt="[data-freeform-stripe-intent]",K=[],ve=new WeakSet,k=t=>async e=>{var P;if(V(e)||ve.has(e))return;ve.add(e);let{site:r,fieldMapping:o,theme:n,layout:a,floatingLabels:s,integration:l,amountFields:i,loadStripe:L}=x(e),{elementMap:p,form:m}=t,c=e.querySelector("[data-freeform-stripe-card]");if(!c||p.has(c))return;let u;p.has(c)&&((P=p.get(c))!=null&&P.stripe)?u=p.get(c).stripe:u=await L(),m.freeform.disableSubmit("stripe.init"),p.set(c,{empty:!0,stripe:u,elements:null,paymentIntent:null}),c.innerHTML="Loading...",q.paymentIntents.create(l,m,r).then(({data:{id:v,secret:h}})=>{c.parentElement.querySelector(tt).value=v;let{elementOptions:S,paymentOptions:y}=pe({theme:n,layout:a,floatingLabels:s}),f=ee(M.render.appearance,{bubbles:!0,elementOptions:S,paymentOptions:y},[c]),g=u.elements({...f.elementOptions,clientSecret:h}),w=g.create("payment",f.paymentOptions);w.mount(c),w.on("change",d=>{p.get(c).empty=d.empty&&!d.complete}),i.forEach(d=>{let E=m.elements.namedItem(d),T=[];E instanceof RadioNodeList?T=Array.from(E):T.push(E),T.forEach(D=>{D==null||D.addEventListener("change",()=>{K.push(d),m.freeform.disableSubmit("stripe.working"),m.freeform.disableForm();let we=p.get(c).paymentIntent.id;q.paymentIntents.updateAmount(l,m,we,r).then(({id:N,client_secret:U})=>{U?(w.unmount(),g=u.elements({clientSecret:U}),w=g.create("payment",f.paymentOptions),w.mount(c),w.on("change",Q=>{p.get(c).empty=Q.empty&&!Q.complete}),p.set(c,{empty:!0,elements:g,stripe:u,paymentIntent:{id:N,secret:U}})):g.fetchUpdates()}).catch(N=>{m.freeform._renderFieldErrors({[d]:[N.response.data.message]})}).finally(()=>{K.pop(),K.length||(m.freeform.enableSubmit("stripe.working"),m.freeform.enableForm())})})})});let be=o.some(({target:d})=>d===void 0),z=d=>E=>{let T=E.target.value;q.customers.update({integration:l,form:m,paymentIntentId:v,key:d,value:T,site:r})};be?m.querySelectorAll('input:not([type="hidden"]), select, textarea').forEach(E=>{E.addEventListener("change",z(E.name))}):o.forEach(({source:d,target:E})=>{var T;(T=m.elements.namedItem(E))==null||T.addEventListener("change",z(d))}),p.set(c,{empty:!0,stripe:u,elements:g,paymentIntent:{id:v,secret:h}})}).catch(v=>{c.innerHTML="Could not load payment element.";let h={};i.forEach(y=>{var f,g;h[y]=[(g=(f=v==null?void 0:v.response)==null?void 0:f.data)==null?void 0:g.message]}),m.freeform._renderFieldErrors(h);let S=()=>{k(t)(e),i.forEach(y=>{var f;(f=m[y])==null||f.removeEventListener("change",S)})};i.forEach(y=>{var f;(f=m[y])==null||f.addEventListener("change",S)})}).finally(()=>{m.freeform.enableSubmit("stripe.init")})};var rt="[data-freeform-stripe-card]",he=t=>async()=>{let{form:e}=t;$(e).forEach(k(t)),Ee(e).forEach(r=>{r.addEventListener(b.rules.applied,()=>{k(t)(r)})})},Se=t=>async e=>{e.addCallback(async()=>{if(e.isBackButtonPressed)return;let{elementMap:r,form:o}=t,n=$(o);for(let a of n){let{required:s,integration:l,site:i}=x(a),L=a.querySelector(rt),p=r.get(L);if(!p)throw new Error("Stripe element not found for container");let{empty:m,stripe:c,elements:u,paymentIntent:{id:P,secret:v}}=p;if(m&&!s)continue;let h=await e.freeform.quickSave(v,P);if(h===!1)return!0;if(h===void 0)return!1;let S=new URL("/freeform/payments/stripe/callback",window.location.origin);S.searchParams.append("integration",l),S.searchParams.append("stripe_token",h),S.searchParams.append("site",i);let{error:y}=await u.submit();if(y)return e.freeform._renderFormErrors([y.message||"An error occurred while submitting the payment."]),e.freeform._scrollToForm(),!1;let{error:f}=await c.confirmPayment({elements:u,confirmParams:{return_url:S.toString()}});return f&&(e.freeform._renderFormErrors([f.message||"An error occurred while confirming the payment."]),e.freeform._scrollToForm()),!1}},100)};var ge=new WeakMap,Le=async t=>{if(ge.has(t))return;ge.set(t,!0);let r={elementMap:new WeakMap,form:t},o=he(r);_(t,[b.form.ready,b.form.reset,b.form.ajaxAfterSubmit],o),_(t,[b.form.submit],Se(r))};document.addEventListener(M.load,()=>{document.querySelectorAll("form[data-freeform]").forEach(e=>{Le(e)})});document.addEventListener("DOMContentLoaded",()=>{document.dispatchEvent(new CustomEvent(M.load))});var Te=t=>{var r;let e=t;(e.nodeName==="FORM"||((r=e.dataset)==null?void 0:r.freeform)!==void 0)&&Le(t),e==null||e.childNodes.forEach(Te)},nt=new MutationObserver(t=>{t.forEach(e=>{e.type==="childList"&&e.addedNodes.forEach(r=>{Te(r)})})});nt.observe(document.body,{childList:!0,subtree:!0});})(); diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 8dba57bb3..0555fead8 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -16,7 +16,7 @@ "dependencies": { "@friendlycaptcha/sdk": "^1.0.0", "@paypal/paypal-js": "^9.6.0", - "@stripe/stripe-js": "^9.1.0", + "@stripe/stripe-js": "^8.11.0", "expression-language": "^2.5.4" }, "devDependencies": { diff --git a/packages/scripts/src/components/front-end/payments/stripe/elements.config.ts b/packages/scripts/src/components/front-end/payments/stripe/elements.config.ts index 039232e3b..1e720be2c 100644 --- a/packages/scripts/src/components/front-end/payments/stripe/elements.config.ts +++ b/packages/scripts/src/components/front-end/payments/stripe/elements.config.ts @@ -1,29 +1,27 @@ import type { Stripe } from "@stripe/stripe-js"; -import { loadStripe } from "@stripe/stripe-js"; - +import { loadStripe } from "@stripe/stripe-js/pure"; import type { Config } from "./elements.types"; +const selector = "[data-freeform-stripe-card][data-config]"; const stripeInstances = new Map(); -const config = (container: HTMLDivElement): Config | undefined => { - const configElement = container.querySelector( - "[data-freeform-stripe-card][data-config]", - ); +const config = (container: HTMLDivElement): Config => { + const configElement = container.querySelector(selector); if (!configElement) { - return undefined; + throw new Error("Stripe config element not found"); } - const config = JSON.parse(configElement.dataset.config) as Config; + const config = JSON.parse(configElement.dataset.config || "{}") as Config; return { ...config, loadStripe: async (): Promise => { if (!stripeInstances.has(config.apiKey)) { const stripeInstance = await loadStripe(config.apiKey); - stripeInstances.set(config.apiKey, stripeInstance); + stripeInstances.set(config.apiKey, stripeInstance!); } - return stripeInstances.get(config.apiKey); + return stripeInstances.get(config.apiKey)!; }, }; }; diff --git a/packages/scripts/src/components/front-end/payments/stripe/elements.init.ts b/packages/scripts/src/components/front-end/payments/stripe/elements.init.ts index 1db7c7f8d..17bc3d986 100644 --- a/packages/scripts/src/components/front-end/payments/stripe/elements.init.ts +++ b/packages/scripts/src/components/front-end/payments/stripe/elements.init.ts @@ -9,6 +9,8 @@ import queries from "./elements.queries"; import { isHidden } from "./elements.selectors"; import type { StripeFunctionConstructorProps } from "./elements.types"; +const intentSelector = "[data-freeform-stripe-intent]"; + const workers: string[] = []; const initializedContainers = new WeakSet(); @@ -45,8 +47,8 @@ export const initStripe = } let stripe: Stripe; - if (elementMap.has(field) && elementMap.get(field).stripe) { - stripe = elementMap.get(field).stripe; + if (elementMap.has(field) && elementMap.get(field)?.stripe) { + stripe = elementMap.get(field)!.stripe; } else { stripe = await getStripe(); } @@ -67,9 +69,9 @@ export const initStripe = .create(integration, form, site) .then(({ data: { id, secret } }) => { // Set the PaymentIntent ID as the field value - field.parentElement.querySelector( - "[data-freeform-stripe-intent]", - ).value = id; + field.parentElement!.querySelector( + intentSelector, + )!.value = id; const { elementOptions, paymentOptions } = generateElementOptions({ theme, diff --git a/packages/scripts/src/components/front-end/payments/stripe/elements.submit.ts b/packages/scripts/src/components/front-end/payments/stripe/elements.submit.ts index 074390357..a57ab884c 100644 --- a/packages/scripts/src/components/front-end/payments/stripe/elements.submit.ts +++ b/packages/scripts/src/components/front-end/payments/stripe/elements.submit.ts @@ -9,6 +9,8 @@ import { } from "./elements.selectors"; import type { StripeFunctionConstructorProps } from "./elements.types"; +const cardSelector = "[data-freeform-stripe-card]"; + export const loadStripeContainers = (props: StripeFunctionConstructorProps) => async () => { const { form } = props; @@ -33,15 +35,19 @@ export const submitStripe = const containers = selectVisibleContainers(form); for (const container of containers) { const { required, integration, site } = config(container); - const field = container.querySelector( - "[data-freeform-stripe-card]", - ); + const field = container.querySelector(cardSelector)!; + + const element = elementMap.get(field); + if (!element) { + throw new Error("Stripe element not found for container"); + } + const { empty, stripe, elements, paymentIntent: { id, secret }, - } = elementMap.get(field); + } = element; if (empty && !required) { continue; @@ -68,7 +74,10 @@ export const submitStripe = const { error: submitError } = await elements.submit(); if (submitError) { - event.freeform._renderFormErrors([submitError.message]); + event.freeform._renderFormErrors([ + submitError.message || + "An error occurred while submitting the payment.", + ]); event.freeform._scrollToForm(); return false; } @@ -81,7 +90,9 @@ export const submitStripe = }); if (error) { - event.freeform._renderFormErrors([error.message]); + event.freeform._renderFormErrors([ + error.message || "An error occurred while confirming the payment.", + ]); event.freeform._scrollToForm(); } diff --git a/packages/scripts/src/components/front-end/payments/stripe/elements.ts b/packages/scripts/src/components/front-end/payments/stripe/elements.ts index 560dd7ac4..ba5d047e3 100644 --- a/packages/scripts/src/components/front-end/payments/stripe/elements.ts +++ b/packages/scripts/src/components/front-end/payments/stripe/elements.ts @@ -47,12 +47,13 @@ document.addEventListener("DOMContentLoaded", () => { document.dispatchEvent(new CustomEvent(ffStripeEvents.load)); }); -const recursiveFreeformAttachment = (node: HTMLFormElement) => { - if (node.nodeName === "FORM" || node.dataset?.freeform !== undefined) { - attachStripeToForm(node); +const recursiveFreeformAttachment = (node: HTMLFormElement | ChildNode) => { + const element = node as HTMLElement; + if (element.nodeName === "FORM" || element.dataset?.freeform !== undefined) { + attachStripeToForm(node as HTMLFormElement); } - node?.childNodes.forEach(recursiveFreeformAttachment); + element?.childNodes.forEach(recursiveFreeformAttachment); }; // Add an observer which listens for new forms diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd651fa03..8c53e3d2d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -168,8 +168,8 @@ importers: specifier: ^9.6.0 version: 9.6.0 '@stripe/stripe-js': - specifier: ^9.1.0 - version: 9.1.0 + specifier: ^8.11.0 + version: 8.11.0 expression-language: specifier: ^2.5.4 version: 2.5.4 @@ -788,8 +788,8 @@ packages: '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - '@stripe/stripe-js@9.1.0': - resolution: {integrity: sha512-v51LoEfZNiNS/5DcarWPCYgn24w4dqwwALR4GTbMW/N0DDzzj4DgYNoixX6PYvpt6uIJMucGUabn/BHhylggIQ==} + '@stripe/stripe-js@8.11.0': + resolution: {integrity: sha512-3fVF4z3efsgwgyj64nFK+6F4/vMw0mUXD2TBbOfftJtKVNx4JNv3CSfe1fY4DCtCk0JFp8/YPNcRkzgV0HJ8cg==} engines: {node: '>=12.16'} '@tanstack/query-core@5.96.2': @@ -2400,7 +2400,7 @@ snapshots: '@standard-schema/utils@0.3.0': {} - '@stripe/stripe-js@9.1.0': {} + '@stripe/stripe-js@8.11.0': {} '@tanstack/query-core@5.96.2': {}