@nextblock-cms/ecom 0.22.1 → 0.22.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -43
- package/index.cjs +1 -1
- package/index.es.js +31 -31
- package/lib/components/Checkout.cjs +1 -1
- package/lib/components/Checkout.es.js +1 -0
- package/lib/components/SubscriptionSelector.cjs +1 -1
- package/lib/components/SubscriptionSelector.es.js +91 -92
- package/lib/coupon-server.cjs +1 -1
- package/lib/coupon-server.es.js +78 -61
- package/lib/coupons.cjs +1 -1
- package/lib/coupons.d.ts +9 -0
- package/lib/coupons.es.js +11 -2
- package/lib/currency-sync.cjs +1 -1
- package/lib/currency-sync.es.js +1 -1
- package/lib/freemius-coupons.cjs +1 -1
- package/lib/freemius-coupons.es.js +88 -92
- package/lib/freemius-license-claim.cjs +1 -1
- package/lib/freemius-license-claim.d.ts +13 -0
- package/lib/freemius-license-claim.es.js +44 -29
- package/lib/freemius-license.cjs +1 -1
- package/lib/freemius-license.es.js +19 -17
- package/lib/freemius-order-sync.cjs +1 -1
- package/lib/freemius-order-sync.d.ts +44 -0
- package/lib/freemius-order-sync.es.js +164 -77
- package/lib/freemius-pricing-server.cjs +1 -0
- package/lib/freemius-pricing-server.d.ts +65 -0
- package/lib/freemius-pricing-server.es.js +82 -0
- package/lib/freemius-pricing.cjs +1 -0
- package/lib/freemius-pricing.d.ts +53 -0
- package/lib/freemius-pricing.es.js +51 -0
- package/lib/invoice-server.cjs +1 -1
- package/lib/invoice-server.es.js +1 -0
- package/lib/pages/cms/coupons/CouponsPage.cjs +1 -1
- package/lib/pages/cms/coupons/CouponsPage.es.js +1 -0
- package/lib/pages/cms/coupons/EditCouponPage.cjs +1 -1
- package/lib/pages/cms/coupons/EditCouponPage.es.js +1 -0
- package/lib/pages/cms/coupons/actions.cjs +1 -1
- package/lib/pages/cms/coupons/actions.es.js +1 -0
- package/lib/pages/cms/orders/actions.cjs +1 -1
- package/lib/pages/cms/orders/actions.es.js +1 -0
- package/lib/pages/cms/orders/export-actions.cjs +1 -1
- package/lib/pages/cms/orders/export-actions.es.js +1 -0
- package/lib/pages/cms/orders/server-actions.cjs +1 -1
- package/lib/pages/cms/orders/server-actions.es.js +1 -0
- package/lib/pages/cms/products/ProductsPage.cjs +1 -1
- package/lib/pages/cms/products/ProductsPage.es.js +1 -0
- package/lib/pages/cms/products/[id]/edit/EditProductPage.cjs +1 -1
- package/lib/pages/cms/products/[id]/edit/EditProductPage.es.js +1 -0
- package/lib/pages/cms/products/actions.cjs +3 -3
- package/lib/pages/cms/products/actions.d.ts +11 -5
- package/lib/pages/cms/products/actions.es.js +45 -12
- package/lib/pages/cms/products/inventory/actions.cjs +1 -1
- package/lib/pages/cms/products/inventory/actions.es.js +1 -0
- package/lib/pages/cms/products/new/NewProductPage.cjs +1 -1
- package/lib/pages/cms/products/new/NewProductPage.es.js +1 -0
- package/lib/pages/cms/products/server-actions.cjs +1 -1
- package/lib/pages/cms/products/server-actions.es.js +1 -0
- package/lib/pages/cms/shipping/ShippingPage.cjs +1 -1
- package/lib/pages/cms/shipping/ShippingPage.es.js +1 -0
- package/lib/pages/cms/shipping/server-actions.cjs +1 -1
- package/lib/pages/cms/shipping/server-actions.es.js +1 -0
- package/lib/pages/cms/taxes/TaxesPage.cjs +1 -1
- package/lib/pages/cms/taxes/TaxesPage.es.js +1 -0
- package/lib/payment-config.cjs +1 -1
- package/lib/payment-config.es.js +1 -0
- package/lib/providers/freemius.cjs +1 -1
- package/lib/providers/freemius.es.js +200 -187
- package/lib/providers/stripe.cjs +1 -1
- package/lib/providers/stripe.es.js +151 -150
- package/lib/server-actions/coupon-actions.cjs +1 -1
- package/lib/server-actions/coupon-actions.es.js +1 -0
- package/lib/server-actions/customer-actions.d.ts +6 -1
- package/lib/server-actions/require-ecom-role.cjs +1 -1
- package/lib/server-actions/require-ecom-role.es.js +22 -10
- package/lib/server-actions/tax-actions.cjs +1 -1
- package/lib/server-actions/tax-actions.es.js +1 -0
- package/lib/shared-inventory.cjs +1 -1
- package/lib/shared-inventory.es.js +1 -1
- package/lib/stripe/checkout.cjs +1 -1
- package/lib/stripe/checkout.es.js +1 -0
- package/lib/stripe/order-sync.cjs +1 -1
- package/lib/stripe/order-sync.es.js +1 -0
- package/lib/stripe/webhooks.cjs +1 -1
- package/lib/stripe/webhooks.d.ts +10 -0
- package/lib/stripe/webhooks.es.js +23 -10
- package/package.json +4 -4
- package/server.cjs +1 -1
- package/server.es.js +31 -31
package/lib/providers/stripe.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=require("../types.cjs"),t=require("../currency.cjs"),n=require("../coupons.cjs"),r=require("../coupon-server.cjs"),i=require("../countries.cjs"),a=require("../shipping/checkout-shipping-method.cjs"),o=require("../inventory-settings.cjs"),s=require("../tax-calculation.cjs"),c=require("../customer.cjs"),l=require("../customer-addresses.cjs"),u=require("./checkout-items.cjs"),ee=require("../order-tax-details.cjs"),d=require("../stripe/client.cjs");let te=require("@supabase/supabase-js");var ne=i.countries.map(e=>e.code),f=new Set(`bg.cs.da.de.el.en.en-GB.es.es-419.et.fi.fil.fr.hr.hu.id.it.ja.ko.lt.lv.ms.mt.nb.nl.pl.pt.pt-BR.ro.ru.sk.sl.sv.th.tr.vi.zh.zh-HK.zh-TW`.split(`.`));function p(e){if(e)return{line1:e.line1||void 0,line2:e.line2||void 0,city:e.city||void 0,state:e.state||void 0,postal_code:e.postal_code||void 0,country:e.country_code||void 0}}function re(e){let t=e?.trim().replace(`_`,`-`);if(!t)return;let n=[t,t.toLowerCase(),t.split(`-`)[0].toLowerCase()];for(let e of n)if(f.has(e))return e}async function ie(e){if(!e.email)return null;let t=await d.getStripeClient(),n=p(e.shippingAddress),r=e.shippingAddress?.recipient_name||e.billingAddress?.recipient_name||void 0,i={email:e.email,name:e.billingAddress?.recipient_name||e.shippingAddress?.recipient_name||void 0,phone:e.phone||void 0,address:p(e.billingAddress),metadata:e.userId?{userId:e.userId}:void 0,...n&&r?{shipping:{name:r,phone:e.phone||void 0,address:n}}:{}};try{let n=(await t.customers.list({email:e.email,limit:1})).data[0];return n?(await t.customers.update(n.id,i),n.id):(await t.customers.create(i)).id}catch(e){return console.error(`Failed to upsert Stripe customer for checkout prefill:`,e),null}}var m=class{getProviderName(){return`Stripe`}async createCheckoutSession({items:i,customerEmail:f,customerPhone:p,userId:m,billingAddress:h,shippingAddress:g,shippingMethodId:_,currencyCode:ae,locale:v,couponCode:y,couponContextItems:b}){let oe=await d.getStripeClient(),x=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,S=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!x||!S)return console.error(`Missing Supabase credentials for checkout (Service Key required).`),{error:`Internal Server Error`,url:null};let C=(0,te.createClient)(x,S),se=process.env.NEXT_PUBLIC_URL||`http://localhost:4200`;if(!i?.length)return{error:`Cart is empty`,url:null};let w=u.normalizeCheckoutItems(i);if(!w.ok)return{url:null,...w.error};let T=w.items,ce=T;if(b&&b.length>0){let e=u.normalizeCheckoutItems(b);if(!e.ok)return{url:null,...e.error};ce=e.items}let E=T.some(t=>!e.isDigitalItem(t)),{data:le,error:ue}=await C.from(`currencies`).select(`code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount`).eq(`is_active`,!0).order(`code`,{ascending:!0}),D=le??[];if(ue||D.length===0)return console.error(`Error fetching currencies for checkout:`,ue),{error:`Failed to resolve store currencies`,url:null};let de=t.getDefaultCurrency(D),O=D.find(e=>e.code===(ae||``).toUpperCase())??de,k=O.code.toLowerCase(),A=await o.getEcommerceInventorySettings(C),fe=T.map(e=>e.product_id),j=T.map(e=>e.variant_id).filter(e=>!!e),{data:M,error:N}=await C.from(`products`).select(`id, title, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock, is_taxable`).in(`id`,fe);if(N||!M)return console.error(`Error fetching products for validation:`,N),{error:`Failed to validate product prices`,url:null};let{data:pe,error:P}=j.length?await C.from(`product_variants`).select(`id, product_id, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock_quantity`).in(`id`,j):{data:[],error:null};if(P)return console.error(`Error fetching variants for validation:`,P),{error:`Failed to validate product variants`,url:null};let F=new Map(M.map(e=>[e.id,e])),I=new Map((pe||[]).map(e=>[e.id,e])),L=new Set,R=new Map;for(let e of T){let t=F.get(e.product_id);if(!t)continue;let n=(e.variant_id?I.get(e.variant_id):null)?.sku||t.sku;n&&(L.add(n),R.set(n,(R.get(n)??0)+e.quantity))}let{data:me,error:z}=L.size?await C.from(`inventory_items`).select(`sku, quantity`).in(`sku`,[...L]):{data:[],error:null};if(z)return console.error(`Error fetching SKU inventory for validation:`,z),{error:`Failed to validate SKU inventory`,url:null};let B=new Map((me||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),V=[],H=[],U=[],W=0,G=0,K=null;if(y){let e=await r.getCouponQuote({client:C,code:y,items:ce,currencyCode:O.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};K=e.quote}let he=r.getQuoteLineDiscountMap(K),ge=e=>{let t=e.unitAmount*e.quantity,n=Math.max(0,t-e.lineDiscount);if(n<=0)return;let r=Math.floor(n/e.quantity),i=n-r*e.quantity,a=(t,n)=>{n<=0||t<=0||V.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:s.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||``}},tax_behavior:`exclusive`,unit_amount:t},quantity:n})};a(r,e.quantity-i),a(r+1,i)};for(let e of T){let r=F.get(e.product_id);if(!r)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...o.createInventoryUnavailableError(e.title)};let i=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(r.prices),salePrices:r.sale_prices||{},fallbackPrice:r.price,fallbackSalePrice:r.sale_price,saleStartAt:r.sale_start_at,saleEndAt:r.sale_end_at,scheduledPrice:r.scheduled_price,scheduledPrices:t.normalizePriceMap(r.scheduled_prices),scheduledPriceAt:r.scheduled_price_at,currencyCode:O.code,currencies:D}),a=i.sale_price??i.price,s=r.title,c=null;if(e.variant_id){let n=I.get(e.variant_id);if(!n||n.product_id!==e.product_id)return{url:null,...o.createInventoryUnavailableError(e.title)};let i=R.get(n.sku)??e.quantity,l=B.has(n.sku)?B.get(n.sku)??0:Math.max(0,n.stock_quantity??0);if(A.trackQuantities&&i>l)return{url:null,...o.createInventoryInsufficientError(e.title,l)};let u=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(n.prices),salePrices:n.sale_prices||{},fallbackPrice:n.price,fallbackSalePrice:n.sale_price,saleStartAt:n.sale_start_at,saleEndAt:n.sale_end_at,scheduledPrice:n.scheduled_price,scheduledPrices:t.normalizePriceMap(n.scheduled_prices),scheduledPriceAt:n.scheduled_price_at,currencyCode:O.code,currencies:D});a=u.sale_price??u.price,c=n.id,s=e.variant_label?`${r.title} - ${e.variant_label}`:`${r.title} - ${n.sku}`}else{let t=R.get(r.sku)??e.quantity,n=B.has(r.sku)?B.get(r.sku)??0:Math.max(0,r.stock??0);if(A.trackQuantities&&t>n)return{url:null,...o.createInventoryInsufficientError(e.title,n)}}let l=r.is_taxable??!0;if(a<0)return{error:`A product variation produced an invalid price.`,url:null};let u=Math.min(a*e.quantity,he.get(n.getCartLineCouponKey(e))??0);ge({name:s,currency:k,productId:r.id,variantId:c,isTaxable:l,unitAmount:a,quantity:e.quantity,lineDiscount:u}),W+=a*e.quantity,G+=u,U.push({product_id:r.id,quantity:e.quantity,price_at_purchase:a,variant_id:c}),H.push({product_id:r.id,quantity:e.quantity,unit_amount:a,discount_amount:u,is_taxable:l})}if(V.length===0&&G>=W)return{error:`This coupon would reduce the Stripe order to zero. Use a smaller discount for Stripe checkout.`,errorKey:`ecommerce.coupon_zero_total_not_supported`,errorStatus:400,url:null};if(V.length===0)return{error:`No valid items in cart`,url:null};let q=0,J=null;if(E){let e=a.normalizeShippingDestination({country:g?.country_code,state:g?.state,postal_code:g?.postal_code});if(!e)return{url:null,...a.createShippingAddressRequiredError()};let t={destination:e,cartTotal:Math.max(0,W-G),currencies:D,currencyCode:O.code};if(_){let e=await a.resolveCheckoutShippingMethod(C,{...t,methodId:_,languageCode:v});if(!e.ok)return e.reason===`load_failed`?(console.error(`Failed to load shipping method:`,e.error),{error:`Failed to load shipping method`,url:null}):(console.warn(`Checkout rejected shipping method ${_}: ${e.reason}`),{url:null,...a.createInvalidShippingMethodError()});q=e.method.amount,J=e.method.name}else{let e=await a.listEligibleShippingMethods(C,t);if(!e.ok)return console.error(`Failed to load shipping methods:`,e.error),{error:`Failed to load shipping method`,url:null};if(e.methods.length>0)return{url:null,...a.createShippingMethodRequiredError()}}}let _e=E?g??h:h,Y;try{Y=await s.calculateCheckoutTaxes(C,{items:H,destination:{country_code:_e?.country_code,state:_e?.state}})}catch(e){return console.error(`Failed to calculate checkout taxes:`,e),{error:`Failed to calculate taxes`,url:null}}q>0&&J&&V.push({price_data:{currency:k,product_data:{name:J,tax_code:Y.enabled&&Y.mode===`automatic`?s.STRIPE_TAX_CODE_SHIPPING:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:q},quantity:1});let X=Y.enabled&&Y.mode===`manual`&&!Y.isPendingExternalCalculation?Y.amount:0;X>0&&V.push({price_data:{currency:k,product_data:{name:`Tax`,tax_code:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:X},quantity:1});let ve=c.normalizeOrderCustomerDetails({email:f,phone:p,name:h?.recipient_name,billing:h,shipping:g}),Z=O.code,ye=ee.buildOrderTaxDetailsFromCalculation({calculation:Y,subtotal:W,shippingTotal:q,total:Math.max(0,W-G)+q+X,currency:Z}),be=Math.max(0,W-G)+q+X,{data:xe,error:Se}=await C.from(`orders`).insert({status:`pending`,total:be,currency:Z,exchange_rate_at_purchase:O.exchange_rate,subtotal:W,shipping_total:q,tax_total:X,tax_details:ye,coupon_id:K?.couponId??null,coupon_code:K?.code??null,discount_total:G,discount_details:K?{code:K.code,discount_type:K.discountType,discount_amount:K.discountAmount,provider:`stripe`,provider_discounts:K.providerDiscounts,line_discounts:K.lineDiscounts}:null,provider:`stripe`,user_id:m,customer_details:ve}).select(`id`).single();if(Se||!xe)return console.error(`Failed to create pending order:`,Se),{error:`Failed to initiate order`,url:null};let Q=xe.id,{error:Ce}=await C.from(`order_items`).insert(U.map(e=>({order_id:Q,product_id:e.product_id,variant_id:e.variant_id??null,quantity:e.quantity,price_at_purchase:e.price_at_purchase})));if(Ce)return console.error(`Failed to insert order items:`,Ce),await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),{error:`Failed to record order items`,url:null};if(m)try{await l.upsertDefaultUserAddresses({userId:m,billingAddress:h,shippingAddress:g,client:C}),await l.fillMissingUserProfileCheckoutDetails({userId:m,fullName:h?.recipient_name??g?.recipient_name??null,phone:p,client:C})}catch(e){console.error(`Failed to sync checkout profile defaults before checkout:`,e)}if(K&&!(await r.recordCouponRedemption({client:C,quote:K,orderId:Q,provider:`stripe`,discountTotal:G,userId:m,customerEmail:f,metadata:{currency:O.code,subtotal:W,shipping_total:q,tax_total:X}})).success)return await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),{url:null,error:`Coupon is no longer available.`,errorKey:`ecommerce.coupon_invalid`};let $=await ie({email:f,phone:p,userId:m,billingAddress:h,shippingAddress:g});try{let e=await oe.checkout.sessions.create({mode:`payment`,success_url:`${se}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${se}/checkout`,locale:re(v),line_items:V,automatic_tax:Y.enabled&&Y.mode===`automatic`?{enabled:!0}:void 0,billing_address_collection:`auto`,customer:$||void 0,customer_email:$?void 0:f||void 0,customer_creation:$?void 0:`if_required`,customer_update:$?{name:`auto`,address:`auto`,shipping:`auto`}:void 0,shipping_address_collection:E?{allowed_countries:ne}:void 0,metadata:{orderId:Q,taxMode:Y.mode,currencyCode:O.code,couponCode:K?.code||``}}),{error:t}=await C.from(`orders`).update({stripe_session_id:e.id}).eq(`id`,Q);return t&&console.error(`Failed to save Stripe session ID on order:`,t),{url:e.url}}catch(e){return console.error(`Stripe session creation failed:`,e),await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),e?.name===`StripeNotConfiguredError`||e?.type===`StripeAuthenticationError`?{error:`This store is not able to take payments right now. Please contact the seller to complete your purchase.`,errorKey:`ecommerce.checkout_payments_unavailable`,errorStatus:503,url:null}:{error:`Something went wrong while preparing your checkout. Please try again.`,errorKey:`ecommerce.checkout_internal_server_error`,url:null}}}};exports.StripeProvider=m;
|
|
1
|
+
const e=require("../types.cjs"),t=require("../currency.cjs"),n=require("../coupons.cjs"),r=require("../coupon-server.cjs"),i=require("../countries.cjs"),a=require("../shipping/checkout-shipping-method.cjs"),o=require("../inventory-settings.cjs"),s=require("../tax-calculation.cjs"),c=require("../customer.cjs"),l=require("../customer-addresses.cjs"),u=require("./checkout-items.cjs"),ee=require("../order-tax-details.cjs"),d=require("../stripe/client.cjs");require("server-only");let te=require("@supabase/supabase-js");var ne=i.countries.map(e=>e.code),f=new Set(`bg.cs.da.de.el.en.en-GB.es.es-419.et.fi.fil.fr.hr.hu.id.it.ja.ko.lt.lv.ms.mt.nb.nl.pl.pt.pt-BR.ro.ru.sk.sl.sv.th.tr.vi.zh.zh-HK.zh-TW`.split(`.`));function p(e){if(e)return{line1:e.line1||void 0,line2:e.line2||void 0,city:e.city||void 0,state:e.state||void 0,postal_code:e.postal_code||void 0,country:e.country_code||void 0}}function re(e){let t=e?.trim().replace(`_`,`-`);if(!t)return;let n=[t,t.toLowerCase(),t.split(`-`)[0].toLowerCase()];for(let e of n)if(f.has(e))return e}async function ie(e){if(!e.email)return null;let t=await d.getStripeClient(),n=p(e.shippingAddress),r=e.shippingAddress?.recipient_name||e.billingAddress?.recipient_name||void 0,i={email:e.email,name:e.billingAddress?.recipient_name||e.shippingAddress?.recipient_name||void 0,phone:e.phone||void 0,address:p(e.billingAddress),metadata:e.userId?{userId:e.userId}:void 0,...n&&r?{shipping:{name:r,phone:e.phone||void 0,address:n}}:{}};try{let n=(await t.customers.list({email:e.email,limit:1})).data[0];return n?(await t.customers.update(n.id,i),n.id):(await t.customers.create(i)).id}catch(e){return console.error(`Failed to upsert Stripe customer for checkout prefill:`,e),null}}var m=class{getProviderName(){return`Stripe`}async createCheckoutSession({items:i,customerEmail:f,customerPhone:p,userId:m,billingAddress:h,shippingAddress:g,shippingMethodId:_,currencyCode:ae,locale:v,couponCode:y,couponContextItems:b}){let oe=await d.getStripeClient(),x=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,S=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!x||!S)return console.error(`Missing Supabase credentials for checkout (Service Key required).`),{error:`Internal Server Error`,url:null};let C=(0,te.createClient)(x,S),se=process.env.NEXT_PUBLIC_URL||`http://localhost:4200`;if(!i?.length)return{error:`Cart is empty`,url:null};let w=u.normalizeCheckoutItems(i);if(!w.ok)return{url:null,...w.error};let T=w.items,ce=T;if(b&&b.length>0){let e=u.normalizeCheckoutItems(b);if(!e.ok)return{url:null,...e.error};ce=n.reconcileCouponContextItems(T,e.items)}let E=T.some(t=>!e.isDigitalItem(t)),{data:le,error:ue}=await C.from(`currencies`).select(`code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount`).eq(`is_active`,!0).order(`code`,{ascending:!0}),D=le??[];if(ue||D.length===0)return console.error(`Error fetching currencies for checkout:`,ue),{error:`Failed to resolve store currencies`,url:null};let de=t.getDefaultCurrency(D),O=D.find(e=>e.code===(ae||``).toUpperCase())??de,k=O.code.toLowerCase(),A=await o.getEcommerceInventorySettings(C),fe=T.map(e=>e.product_id),j=T.map(e=>e.variant_id).filter(e=>!!e),{data:M,error:N}=await C.from(`products`).select(`id, title, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock, is_taxable`).in(`id`,fe);if(N||!M)return console.error(`Error fetching products for validation:`,N),{error:`Failed to validate product prices`,url:null};let{data:pe,error:P}=j.length?await C.from(`product_variants`).select(`id, product_id, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock_quantity`).in(`id`,j):{data:[],error:null};if(P)return console.error(`Error fetching variants for validation:`,P),{error:`Failed to validate product variants`,url:null};let F=new Map(M.map(e=>[e.id,e])),I=new Map((pe||[]).map(e=>[e.id,e])),L=new Set,R=new Map;for(let e of T){let t=F.get(e.product_id);if(!t)continue;let n=(e.variant_id?I.get(e.variant_id):null)?.sku||t.sku;n&&(L.add(n),R.set(n,(R.get(n)??0)+e.quantity))}let{data:me,error:z}=L.size?await C.from(`inventory_items`).select(`sku, quantity`).in(`sku`,[...L]):{data:[],error:null};if(z)return console.error(`Error fetching SKU inventory for validation:`,z),{error:`Failed to validate SKU inventory`,url:null};let B=new Map((me||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),V=[],H=[],U=[],W=0,G=0,K=null;if(y){let e=await r.getCouponQuote({client:C,code:y,items:ce,currencyCode:O.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};K=e.quote}let he=r.getQuoteLineDiscountMap(K),ge=e=>{let t=e.unitAmount*e.quantity,n=Math.max(0,t-e.lineDiscount);if(n<=0)return;let r=Math.floor(n/e.quantity),i=n-r*e.quantity,a=(t,n)=>{n<=0||t<=0||V.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:s.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||``}},tax_behavior:`exclusive`,unit_amount:t},quantity:n})};a(r,e.quantity-i),a(r+1,i)};for(let e of T){let r=F.get(e.product_id);if(!r)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...o.createInventoryUnavailableError(e.title)};let i=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(r.prices),salePrices:r.sale_prices||{},fallbackPrice:r.price,fallbackSalePrice:r.sale_price,saleStartAt:r.sale_start_at,saleEndAt:r.sale_end_at,scheduledPrice:r.scheduled_price,scheduledPrices:t.normalizePriceMap(r.scheduled_prices),scheduledPriceAt:r.scheduled_price_at,currencyCode:O.code,currencies:D}),a=i.sale_price??i.price,s=r.title,c=null;if(e.variant_id){let n=I.get(e.variant_id);if(!n||n.product_id!==e.product_id)return{url:null,...o.createInventoryUnavailableError(e.title)};let i=R.get(n.sku)??e.quantity,l=B.has(n.sku)?B.get(n.sku)??0:Math.max(0,n.stock_quantity??0);if(A.trackQuantities&&i>l)return{url:null,...o.createInventoryInsufficientError(e.title,l)};let u=t.resolveEffectivePriceForCurrency({prices:t.normalizePriceMap(n.prices),salePrices:n.sale_prices||{},fallbackPrice:n.price,fallbackSalePrice:n.sale_price,saleStartAt:n.sale_start_at,saleEndAt:n.sale_end_at,scheduledPrice:n.scheduled_price,scheduledPrices:t.normalizePriceMap(n.scheduled_prices),scheduledPriceAt:n.scheduled_price_at,currencyCode:O.code,currencies:D});a=u.sale_price??u.price,c=n.id,s=e.variant_label?`${r.title} - ${e.variant_label}`:`${r.title} - ${n.sku}`}else{let t=R.get(r.sku)??e.quantity,n=B.has(r.sku)?B.get(r.sku)??0:Math.max(0,r.stock??0);if(A.trackQuantities&&t>n)return{url:null,...o.createInventoryInsufficientError(e.title,n)}}let l=r.is_taxable??!0;if(a<0)return{error:`A product variation produced an invalid price.`,url:null};let u=Math.min(a*e.quantity,he.get(n.getCartLineCouponKey(e))??0);ge({name:s,currency:k,productId:r.id,variantId:c,isTaxable:l,unitAmount:a,quantity:e.quantity,lineDiscount:u}),W+=a*e.quantity,G+=u,U.push({product_id:r.id,quantity:e.quantity,price_at_purchase:a,variant_id:c}),H.push({product_id:r.id,quantity:e.quantity,unit_amount:a,discount_amount:u,is_taxable:l})}if(V.length===0&&G>=W)return{error:`This coupon would reduce the Stripe order to zero. Use a smaller discount for Stripe checkout.`,errorKey:`ecommerce.coupon_zero_total_not_supported`,errorStatus:400,url:null};if(V.length===0)return{error:`No valid items in cart`,url:null};let q=0,J=null;if(E){let e=a.normalizeShippingDestination({country:g?.country_code,state:g?.state,postal_code:g?.postal_code});if(!e)return{url:null,...a.createShippingAddressRequiredError()};let t={destination:e,cartTotal:Math.max(0,W-G),currencies:D,currencyCode:O.code};if(_){let e=await a.resolveCheckoutShippingMethod(C,{...t,methodId:_,languageCode:v});if(!e.ok)return e.reason===`load_failed`?(console.error(`Failed to load shipping method:`,e.error),{error:`Failed to load shipping method`,url:null}):(console.warn(`Checkout rejected shipping method ${_}: ${e.reason}`),{url:null,...a.createInvalidShippingMethodError()});q=e.method.amount,J=e.method.name}else{let e=await a.listEligibleShippingMethods(C,t);if(!e.ok)return console.error(`Failed to load shipping methods:`,e.error),{error:`Failed to load shipping method`,url:null};if(e.methods.length>0)return{url:null,...a.createShippingMethodRequiredError()}}}let _e=E?g??h:h,Y;try{Y=await s.calculateCheckoutTaxes(C,{items:H,destination:{country_code:_e?.country_code,state:_e?.state}})}catch(e){return console.error(`Failed to calculate checkout taxes:`,e),{error:`Failed to calculate taxes`,url:null}}q>0&&J&&V.push({price_data:{currency:k,product_data:{name:J,tax_code:Y.enabled&&Y.mode===`automatic`?s.STRIPE_TAX_CODE_SHIPPING:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:q},quantity:1});let X=Y.enabled&&Y.mode===`manual`&&!Y.isPendingExternalCalculation?Y.amount:0;X>0&&V.push({price_data:{currency:k,product_data:{name:`Tax`,tax_code:s.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:`exclusive`,unit_amount:X},quantity:1});let ve=c.normalizeOrderCustomerDetails({email:f,phone:p,name:h?.recipient_name,billing:h,shipping:g}),Z=O.code,ye=ee.buildOrderTaxDetailsFromCalculation({calculation:Y,subtotal:W,shippingTotal:q,total:Math.max(0,W-G)+q+X,currency:Z}),be=Math.max(0,W-G)+q+X,{data:xe,error:Se}=await C.from(`orders`).insert({status:`pending`,total:be,currency:Z,exchange_rate_at_purchase:O.exchange_rate,subtotal:W,shipping_total:q,tax_total:X,tax_details:ye,coupon_id:K?.couponId??null,coupon_code:K?.code??null,discount_total:G,discount_details:K?{code:K.code,discount_type:K.discountType,discount_amount:K.discountAmount,provider:`stripe`,provider_discounts:K.providerDiscounts,line_discounts:K.lineDiscounts}:null,provider:`stripe`,user_id:m,customer_details:ve}).select(`id`).single();if(Se||!xe)return console.error(`Failed to create pending order:`,Se),{error:`Failed to initiate order`,url:null};let Q=xe.id,{error:Ce}=await C.from(`order_items`).insert(U.map(e=>({order_id:Q,product_id:e.product_id,variant_id:e.variant_id??null,quantity:e.quantity,price_at_purchase:e.price_at_purchase})));if(Ce)return console.error(`Failed to insert order items:`,Ce),await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),{error:`Failed to record order items`,url:null};if(m)try{await l.upsertDefaultUserAddresses({userId:m,billingAddress:h,shippingAddress:g,client:C}),await l.fillMissingUserProfileCheckoutDetails({userId:m,fullName:h?.recipient_name??g?.recipient_name??null,phone:p,client:C})}catch(e){console.error(`Failed to sync checkout profile defaults before checkout:`,e)}if(K&&!(await r.recordCouponRedemption({client:C,quote:K,orderId:Q,provider:`stripe`,discountTotal:G,userId:m,customerEmail:f,metadata:{currency:O.code,subtotal:W,shipping_total:q,tax_total:X}})).success)return await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),{url:null,error:`Coupon is no longer available.`,errorKey:`ecommerce.coupon_invalid`};let $=await ie({email:f,phone:p,userId:m,billingAddress:h,shippingAddress:g});try{let e=await oe.checkout.sessions.create({mode:`payment`,success_url:`${se}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${se}/checkout`,locale:re(v),line_items:V,automatic_tax:Y.enabled&&Y.mode===`automatic`?{enabled:!0}:void 0,billing_address_collection:`auto`,customer:$||void 0,customer_email:$?void 0:f||void 0,customer_creation:$?void 0:`if_required`,customer_update:$?{name:`auto`,address:`auto`,shipping:`auto`}:void 0,shipping_address_collection:E?{allowed_countries:ne}:void 0,metadata:{orderId:Q,taxMode:Y.mode,currencyCode:O.code,couponCode:K?.code||``}}),{error:t}=await C.from(`orders`).update({stripe_session_id:e.id}).eq(`id`,Q);return t&&console.error(`Failed to save Stripe session ID on order:`,t),{url:e.url}}catch(e){return console.error(`Stripe session creation failed:`,e),await C.from(`orders`).update({status:`failed`}).eq(`id`,Q),e?.name===`StripeNotConfiguredError`||e?.type===`StripeAuthenticationError`?{error:`This store is not able to take payments right now. Please contact the seller to complete your purchase.`,errorKey:`ecommerce.checkout_payments_unavailable`,errorStatus:503,url:null}:{error:`Something went wrong while preparing your checkout. Please try again.`,errorKey:`ecommerce.checkout_internal_server_error`,url:null}}}};exports.StripeProvider=m;
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
import { isDigitalItem as e } from "../types.es.js";
|
|
2
2
|
import { getDefaultCurrency as t, normalizePriceMap as n, resolveEffectivePriceForCurrency as r } from "../currency.es.js";
|
|
3
|
-
import { getCartLineCouponKey as i } from "../coupons.es.js";
|
|
4
|
-
import { getCouponQuote as
|
|
5
|
-
import { countries as
|
|
6
|
-
import { createInvalidShippingMethodError as
|
|
7
|
-
import { createInventoryInsufficientError as
|
|
8
|
-
import { STRIPE_TAX_CODE_NONTAXABLE as
|
|
9
|
-
import { normalizeOrderCustomerDetails as
|
|
10
|
-
import { fillMissingUserProfileCheckoutDetails as
|
|
11
|
-
import { normalizeCheckoutItems as
|
|
12
|
-
import { buildOrderTaxDetailsFromCalculation as
|
|
13
|
-
import { getStripeClient as
|
|
14
|
-
import
|
|
3
|
+
import { getCartLineCouponKey as i, reconcileCouponContextItems as a } from "../coupons.es.js";
|
|
4
|
+
import { getCouponQuote as o, getQuoteLineDiscountMap as s, recordCouponRedemption as c } from "../coupon-server.es.js";
|
|
5
|
+
import { countries as l } from "../countries.es.js";
|
|
6
|
+
import { createInvalidShippingMethodError as u, createShippingAddressRequiredError as ee, createShippingMethodRequiredError as te, listEligibleShippingMethods as ne, normalizeShippingDestination as re, resolveCheckoutShippingMethod as ie } from "../shipping/checkout-shipping-method.es.js";
|
|
7
|
+
import { createInventoryInsufficientError as ae, createInventoryUnavailableError as oe, getEcommerceInventorySettings as se } from "../inventory-settings.es.js";
|
|
8
|
+
import { STRIPE_TAX_CODE_NONTAXABLE as ce, STRIPE_TAX_CODE_SHIPPING as le, calculateCheckoutTaxes as ue, getStripeTaxCodeForProduct as de } from "../tax-calculation.es.js";
|
|
9
|
+
import { normalizeOrderCustomerDetails as fe } from "../customer.es.js";
|
|
10
|
+
import { fillMissingUserProfileCheckoutDetails as pe, upsertDefaultUserAddresses as me } from "../customer-addresses.es.js";
|
|
11
|
+
import { normalizeCheckoutItems as d } from "./checkout-items.es.js";
|
|
12
|
+
import { buildOrderTaxDetailsFromCalculation as he } from "../order-tax-details.es.js";
|
|
13
|
+
import { getStripeClient as f } from "../stripe/client.es.js";
|
|
14
|
+
import "server-only";
|
|
15
|
+
import { createClient as ge } from "@supabase/supabase-js";
|
|
15
16
|
//#region src/lib/providers/stripe.ts
|
|
16
|
-
var
|
|
17
|
-
function
|
|
17
|
+
var _e = l.map((e) => e.code), p = /* @__PURE__ */ new Set(/* @__PURE__ */ "bg.cs.da.de.el.en.en-GB.es.es-419.et.fi.fil.fr.hr.hu.id.it.ja.ko.lt.lv.ms.mt.nb.nl.pl.pt.pt-BR.ro.ru.sk.sl.sv.th.tr.vi.zh.zh-HK.zh-TW".split("."));
|
|
18
|
+
function m(e) {
|
|
18
19
|
if (e) return {
|
|
19
20
|
line1: e.line1 || void 0,
|
|
20
21
|
line2: e.line2 || void 0,
|
|
@@ -24,7 +25,7 @@ function h(e) {
|
|
|
24
25
|
country: e.country_code || void 0
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
|
-
function
|
|
28
|
+
function ve(e) {
|
|
28
29
|
let t = e?.trim().replace("_", "-");
|
|
29
30
|
if (!t) return;
|
|
30
31
|
let n = [
|
|
@@ -32,15 +33,15 @@ function ge(e) {
|
|
|
32
33
|
t.toLowerCase(),
|
|
33
34
|
t.split("-")[0].toLowerCase()
|
|
34
35
|
];
|
|
35
|
-
for (let e of n) if (
|
|
36
|
+
for (let e of n) if (p.has(e)) return e;
|
|
36
37
|
}
|
|
37
|
-
async function
|
|
38
|
+
async function ye(e) {
|
|
38
39
|
if (!e.email) return null;
|
|
39
|
-
let t = await
|
|
40
|
+
let t = await f(), n = m(e.shippingAddress), r = e.shippingAddress?.recipient_name || e.billingAddress?.recipient_name || void 0, i = {
|
|
40
41
|
email: e.email,
|
|
41
42
|
name: e.billingAddress?.recipient_name || e.shippingAddress?.recipient_name || void 0,
|
|
42
43
|
phone: e.phone || void 0,
|
|
43
|
-
address:
|
|
44
|
+
address: m(e.billingAddress),
|
|
44
45
|
metadata: e.userId ? { userId: e.userId } : void 0,
|
|
45
46
|
...n && r ? { shipping: {
|
|
46
47
|
name: r,
|
|
@@ -58,75 +59,75 @@ async function _e(e) {
|
|
|
58
59
|
return console.error("Failed to upsert Stripe customer for checkout prefill:", e), null;
|
|
59
60
|
}
|
|
60
61
|
}
|
|
61
|
-
var
|
|
62
|
+
var h = class {
|
|
62
63
|
getProviderName() {
|
|
63
64
|
return "Stripe";
|
|
64
65
|
}
|
|
65
|
-
async createCheckoutSession({ items:
|
|
66
|
-
let
|
|
67
|
-
if (!
|
|
66
|
+
async createCheckoutSession({ items: l, customerEmail: p, customerPhone: m, userId: h, billingAddress: g, shippingAddress: _, shippingMethodId: v, currencyCode: be, locale: y, couponCode: b, couponContextItems: x }) {
|
|
67
|
+
let xe = await f(), Se = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, S = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
|
|
68
|
+
if (!Se || !S) return console.error("Missing Supabase credentials for checkout (Service Key required)."), {
|
|
68
69
|
error: "Internal Server Error",
|
|
69
70
|
url: null
|
|
70
71
|
};
|
|
71
|
-
let
|
|
72
|
-
if (!
|
|
72
|
+
let C = ge(Se, S), w = process.env.NEXT_PUBLIC_URL || "http://localhost:4200";
|
|
73
|
+
if (!l?.length) return {
|
|
73
74
|
error: "Cart is empty",
|
|
74
75
|
url: null
|
|
75
76
|
};
|
|
76
|
-
let
|
|
77
|
-
if (!
|
|
77
|
+
let T = d(l);
|
|
78
|
+
if (!T.ok) return {
|
|
78
79
|
url: null,
|
|
79
|
-
...
|
|
80
|
+
...T.error
|
|
80
81
|
};
|
|
81
|
-
let
|
|
82
|
-
if (
|
|
83
|
-
let e =
|
|
82
|
+
let E = T.items, D = E;
|
|
83
|
+
if (x && x.length > 0) {
|
|
84
|
+
let e = d(x);
|
|
84
85
|
if (!e.ok) return {
|
|
85
86
|
url: null,
|
|
86
87
|
...e.error
|
|
87
88
|
};
|
|
88
|
-
|
|
89
|
+
D = a(E, e.items);
|
|
89
90
|
}
|
|
90
|
-
let
|
|
91
|
-
if (
|
|
91
|
+
let O = E.some((t) => !e(t)), { data: Ce, error: k } = await C.from("currencies").select("code, symbol, exchange_rate, is_default, is_active, auto_sync_product_prices, auto_update_exchange_rate, exchange_rate_source, exchange_rate_updated_at, rounding_mode, rounding_increment, rounding_charm_amount").eq("is_active", !0).order("code", { ascending: !0 }), A = Ce ?? [];
|
|
92
|
+
if (k || A.length === 0) return console.error("Error fetching currencies for checkout:", k), {
|
|
92
93
|
error: "Failed to resolve store currencies",
|
|
93
94
|
url: null
|
|
94
95
|
};
|
|
95
|
-
let
|
|
96
|
-
if (
|
|
96
|
+
let we = t(A), j = A.find((e) => e.code === (be || "").toUpperCase()) ?? we, M = j.code.toLowerCase(), N = await se(C), Te = E.map((e) => e.product_id), P = E.map((e) => e.variant_id).filter((e) => !!e), { data: F, error: I } = await C.from("products").select("id, title, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock, is_taxable").in("id", Te);
|
|
97
|
+
if (I || !F) return console.error("Error fetching products for validation:", I), {
|
|
97
98
|
error: "Failed to validate product prices",
|
|
98
99
|
url: null
|
|
99
100
|
};
|
|
100
|
-
let { data:
|
|
101
|
+
let { data: Ee, error: L } = P.length ? await C.from("product_variants").select("id, product_id, sku, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at, stock_quantity").in("id", P) : {
|
|
101
102
|
data: [],
|
|
102
103
|
error: null
|
|
103
104
|
};
|
|
104
|
-
if (
|
|
105
|
+
if (L) return console.error("Error fetching variants for validation:", L), {
|
|
105
106
|
error: "Failed to validate product variants",
|
|
106
107
|
url: null
|
|
107
108
|
};
|
|
108
|
-
let
|
|
109
|
-
for (let e of
|
|
110
|
-
let t =
|
|
109
|
+
let R = new Map(F.map((e) => [e.id, e])), z = new Map((Ee || []).map((e) => [e.id, e])), B = /* @__PURE__ */ new Set(), V = /* @__PURE__ */ new Map();
|
|
110
|
+
for (let e of E) {
|
|
111
|
+
let t = R.get(e.product_id);
|
|
111
112
|
if (!t) continue;
|
|
112
|
-
let n = (e.variant_id ?
|
|
113
|
-
n && (
|
|
113
|
+
let n = (e.variant_id ? z.get(e.variant_id) : null)?.sku || t.sku;
|
|
114
|
+
n && (B.add(n), V.set(n, (V.get(n) ?? 0) + e.quantity));
|
|
114
115
|
}
|
|
115
|
-
let { data:
|
|
116
|
+
let { data: De, error: H } = B.size ? await C.from("inventory_items").select("sku, quantity").in("sku", [...B]) : {
|
|
116
117
|
data: [],
|
|
117
118
|
error: null
|
|
118
119
|
};
|
|
119
|
-
if (
|
|
120
|
+
if (H) return console.error("Error fetching SKU inventory for validation:", H), {
|
|
120
121
|
error: "Failed to validate SKU inventory",
|
|
121
122
|
url: null
|
|
122
123
|
};
|
|
123
|
-
let U = new Map((
|
|
124
|
-
if (
|
|
125
|
-
let e = await
|
|
126
|
-
client:
|
|
127
|
-
code:
|
|
128
|
-
items:
|
|
129
|
-
currencyCode:
|
|
124
|
+
let U = new Map((De || []).map((e) => [e.sku, Math.max(0, e.quantity ?? 0)])), W = [], Oe = [], ke = [], G = 0, K = 0, q = null;
|
|
125
|
+
if (b) {
|
|
126
|
+
let e = await o({
|
|
127
|
+
client: C,
|
|
128
|
+
code: b,
|
|
129
|
+
items: D,
|
|
130
|
+
currencyCode: j.code
|
|
130
131
|
});
|
|
131
132
|
if (!e.success) return {
|
|
132
133
|
error: e.error,
|
|
@@ -136,7 +137,7 @@ var g = class {
|
|
|
136
137
|
};
|
|
137
138
|
q = e.quote;
|
|
138
139
|
}
|
|
139
|
-
let
|
|
140
|
+
let Ae = s(q), je = (e) => {
|
|
140
141
|
let t = e.unitAmount * e.quantity, n = Math.max(0, t - e.lineDiscount);
|
|
141
142
|
if (n <= 0) return;
|
|
142
143
|
let r = Math.floor(n / e.quantity), i = n - r * e.quantity, a = (t, n) => {
|
|
@@ -145,7 +146,7 @@ var g = class {
|
|
|
145
146
|
currency: e.currency,
|
|
146
147
|
product_data: {
|
|
147
148
|
name: e.name,
|
|
148
|
-
tax_code:
|
|
149
|
+
tax_code: de(e.isTaxable),
|
|
149
150
|
metadata: {
|
|
150
151
|
productId: e.productId,
|
|
151
152
|
variantId: e.variantId || ""
|
|
@@ -159,11 +160,11 @@ var g = class {
|
|
|
159
160
|
};
|
|
160
161
|
a(r, e.quantity - i), a(r + 1, i);
|
|
161
162
|
};
|
|
162
|
-
for (let e of
|
|
163
|
-
let t =
|
|
163
|
+
for (let e of E) {
|
|
164
|
+
let t = R.get(e.product_id);
|
|
164
165
|
if (!t) return console.warn(`Product ${e.product_id} not found in DB.`), {
|
|
165
166
|
url: null,
|
|
166
|
-
...
|
|
167
|
+
...oe(e.title)
|
|
167
168
|
};
|
|
168
169
|
let a = r({
|
|
169
170
|
prices: n(t.prices),
|
|
@@ -175,19 +176,19 @@ var g = class {
|
|
|
175
176
|
scheduledPrice: t.scheduled_price,
|
|
176
177
|
scheduledPrices: n(t.scheduled_prices),
|
|
177
178
|
scheduledPriceAt: t.scheduled_price_at,
|
|
178
|
-
currencyCode:
|
|
179
|
-
currencies:
|
|
179
|
+
currencyCode: j.code,
|
|
180
|
+
currencies: A
|
|
180
181
|
}), o = a.sale_price ?? a.price, s = t.title, c = null;
|
|
181
182
|
if (e.variant_id) {
|
|
182
|
-
let i =
|
|
183
|
+
let i = z.get(e.variant_id);
|
|
183
184
|
if (!i || i.product_id !== e.product_id) return {
|
|
184
185
|
url: null,
|
|
185
|
-
...
|
|
186
|
+
...oe(e.title)
|
|
186
187
|
};
|
|
187
|
-
let a =
|
|
188
|
-
if (
|
|
188
|
+
let a = V.get(i.sku) ?? e.quantity, l = U.has(i.sku) ? U.get(i.sku) ?? 0 : Math.max(0, i.stock_quantity ?? 0);
|
|
189
|
+
if (N.trackQuantities && a > l) return {
|
|
189
190
|
url: null,
|
|
190
|
-
...
|
|
191
|
+
...ae(e.title, l)
|
|
191
192
|
};
|
|
192
193
|
let u = r({
|
|
193
194
|
prices: n(i.prices),
|
|
@@ -199,15 +200,15 @@ var g = class {
|
|
|
199
200
|
scheduledPrice: i.scheduled_price,
|
|
200
201
|
scheduledPrices: n(i.scheduled_prices),
|
|
201
202
|
scheduledPriceAt: i.scheduled_price_at,
|
|
202
|
-
currencyCode:
|
|
203
|
-
currencies:
|
|
203
|
+
currencyCode: j.code,
|
|
204
|
+
currencies: A
|
|
204
205
|
});
|
|
205
206
|
o = u.sale_price ?? u.price, c = i.id, s = e.variant_label ? `${t.title} - ${e.variant_label}` : `${t.title} - ${i.sku}`;
|
|
206
207
|
} else {
|
|
207
|
-
let n =
|
|
208
|
-
if (
|
|
208
|
+
let n = V.get(t.sku) ?? e.quantity, r = U.has(t.sku) ? U.get(t.sku) ?? 0 : Math.max(0, t.stock ?? 0);
|
|
209
|
+
if (N.trackQuantities && n > r) return {
|
|
209
210
|
url: null,
|
|
210
|
-
...
|
|
211
|
+
...ae(e.title, r)
|
|
211
212
|
};
|
|
212
213
|
}
|
|
213
214
|
let l = t.is_taxable ?? !0;
|
|
@@ -215,22 +216,22 @@ var g = class {
|
|
|
215
216
|
error: "A product variation produced an invalid price.",
|
|
216
217
|
url: null
|
|
217
218
|
};
|
|
218
|
-
let u = Math.min(o * e.quantity,
|
|
219
|
-
|
|
219
|
+
let u = Math.min(o * e.quantity, Ae.get(i(e)) ?? 0);
|
|
220
|
+
je({
|
|
220
221
|
name: s,
|
|
221
|
-
currency:
|
|
222
|
+
currency: M,
|
|
222
223
|
productId: t.id,
|
|
223
224
|
variantId: c,
|
|
224
225
|
isTaxable: l,
|
|
225
226
|
unitAmount: o,
|
|
226
227
|
quantity: e.quantity,
|
|
227
228
|
lineDiscount: u
|
|
228
|
-
}), G += o * e.quantity, K += u,
|
|
229
|
+
}), G += o * e.quantity, K += u, ke.push({
|
|
229
230
|
product_id: t.id,
|
|
230
231
|
quantity: e.quantity,
|
|
231
232
|
price_at_purchase: o,
|
|
232
233
|
variant_id: c
|
|
233
|
-
}),
|
|
234
|
+
}), Oe.push({
|
|
234
235
|
product_id: t.id,
|
|
235
236
|
quantity: e.quantity,
|
|
236
237
|
unit_amount: o,
|
|
@@ -249,55 +250,55 @@ var g = class {
|
|
|
249
250
|
url: null
|
|
250
251
|
};
|
|
251
252
|
let J = 0, Y = null;
|
|
252
|
-
if (
|
|
253
|
-
let e =
|
|
254
|
-
country:
|
|
255
|
-
state:
|
|
256
|
-
postal_code:
|
|
253
|
+
if (O) {
|
|
254
|
+
let e = re({
|
|
255
|
+
country: _?.country_code,
|
|
256
|
+
state: _?.state,
|
|
257
|
+
postal_code: _?.postal_code
|
|
257
258
|
});
|
|
258
259
|
if (!e) return {
|
|
259
260
|
url: null,
|
|
260
|
-
...
|
|
261
|
+
...ee()
|
|
261
262
|
};
|
|
262
263
|
let t = {
|
|
263
264
|
destination: e,
|
|
264
265
|
cartTotal: Math.max(0, G - K),
|
|
265
|
-
currencies:
|
|
266
|
-
currencyCode:
|
|
266
|
+
currencies: A,
|
|
267
|
+
currencyCode: j.code
|
|
267
268
|
};
|
|
268
|
-
if (
|
|
269
|
-
let e = await
|
|
269
|
+
if (v) {
|
|
270
|
+
let e = await ie(C, {
|
|
270
271
|
...t,
|
|
271
|
-
methodId:
|
|
272
|
-
languageCode:
|
|
272
|
+
methodId: v,
|
|
273
|
+
languageCode: y
|
|
273
274
|
});
|
|
274
275
|
if (!e.ok) return e.reason === "load_failed" ? (console.error("Failed to load shipping method:", e.error), {
|
|
275
276
|
error: "Failed to load shipping method",
|
|
276
277
|
url: null
|
|
277
|
-
}) : (console.warn(`Checkout rejected shipping method ${
|
|
278
|
+
}) : (console.warn(`Checkout rejected shipping method ${v}: ${e.reason}`), {
|
|
278
279
|
url: null,
|
|
279
|
-
...
|
|
280
|
+
...u()
|
|
280
281
|
});
|
|
281
282
|
J = e.method.amount, Y = e.method.name;
|
|
282
283
|
} else {
|
|
283
|
-
let e = await
|
|
284
|
+
let e = await ne(C, t);
|
|
284
285
|
if (!e.ok) return console.error("Failed to load shipping methods:", e.error), {
|
|
285
286
|
error: "Failed to load shipping method",
|
|
286
287
|
url: null
|
|
287
288
|
};
|
|
288
289
|
if (e.methods.length > 0) return {
|
|
289
290
|
url: null,
|
|
290
|
-
...
|
|
291
|
+
...te()
|
|
291
292
|
};
|
|
292
293
|
}
|
|
293
294
|
}
|
|
294
|
-
let
|
|
295
|
+
let Me = O ? _ ?? g : g, X;
|
|
295
296
|
try {
|
|
296
|
-
X = await
|
|
297
|
-
items:
|
|
297
|
+
X = await ue(C, {
|
|
298
|
+
items: Oe,
|
|
298
299
|
destination: {
|
|
299
|
-
country_code:
|
|
300
|
-
state:
|
|
300
|
+
country_code: Me?.country_code,
|
|
301
|
+
state: Me?.state
|
|
301
302
|
}
|
|
302
303
|
});
|
|
303
304
|
} catch (e) {
|
|
@@ -308,10 +309,10 @@ var g = class {
|
|
|
308
309
|
}
|
|
309
310
|
J > 0 && Y && W.push({
|
|
310
311
|
price_data: {
|
|
311
|
-
currency:
|
|
312
|
+
currency: M,
|
|
312
313
|
product_data: {
|
|
313
314
|
name: Y,
|
|
314
|
-
tax_code: X.enabled && X.mode === "automatic" ?
|
|
315
|
+
tax_code: X.enabled && X.mode === "automatic" ? le : ce
|
|
315
316
|
},
|
|
316
317
|
tax_behavior: "exclusive",
|
|
317
318
|
unit_amount: J
|
|
@@ -321,37 +322,37 @@ var g = class {
|
|
|
321
322
|
let Z = X.enabled && X.mode === "manual" && !X.isPendingExternalCalculation ? X.amount : 0;
|
|
322
323
|
Z > 0 && W.push({
|
|
323
324
|
price_data: {
|
|
324
|
-
currency:
|
|
325
|
+
currency: M,
|
|
325
326
|
product_data: {
|
|
326
327
|
name: "Tax",
|
|
327
|
-
tax_code:
|
|
328
|
+
tax_code: ce
|
|
328
329
|
},
|
|
329
330
|
tax_behavior: "exclusive",
|
|
330
331
|
unit_amount: Z
|
|
331
332
|
},
|
|
332
333
|
quantity: 1
|
|
333
334
|
});
|
|
334
|
-
let
|
|
335
|
-
email:
|
|
336
|
-
phone:
|
|
337
|
-
name:
|
|
338
|
-
billing:
|
|
339
|
-
shipping:
|
|
340
|
-
}),
|
|
335
|
+
let Ne = fe({
|
|
336
|
+
email: p,
|
|
337
|
+
phone: m,
|
|
338
|
+
name: g?.recipient_name,
|
|
339
|
+
billing: g,
|
|
340
|
+
shipping: _
|
|
341
|
+
}), Pe = j.code, Fe = he({
|
|
341
342
|
calculation: X,
|
|
342
343
|
subtotal: G,
|
|
343
344
|
shippingTotal: J,
|
|
344
345
|
total: Math.max(0, G - K) + J + Z,
|
|
345
|
-
currency:
|
|
346
|
-
}),
|
|
346
|
+
currency: Pe
|
|
347
|
+
}), Ie = Math.max(0, G - K) + J + Z, { data: Le, error: Re } = await C.from("orders").insert({
|
|
347
348
|
status: "pending",
|
|
348
|
-
total:
|
|
349
|
-
currency:
|
|
350
|
-
exchange_rate_at_purchase:
|
|
349
|
+
total: Ie,
|
|
350
|
+
currency: Pe,
|
|
351
|
+
exchange_rate_at_purchase: j.exchange_rate,
|
|
351
352
|
subtotal: G,
|
|
352
353
|
shipping_total: J,
|
|
353
354
|
tax_total: Z,
|
|
354
|
-
tax_details:
|
|
355
|
+
tax_details: Fe,
|
|
355
356
|
coupon_id: q?.couponId ?? null,
|
|
356
357
|
coupon_code: q?.code ?? null,
|
|
357
358
|
discount_total: K,
|
|
@@ -364,93 +365,93 @@ var g = class {
|
|
|
364
365
|
line_discounts: q.lineDiscounts
|
|
365
366
|
} : null,
|
|
366
367
|
provider: "stripe",
|
|
367
|
-
user_id:
|
|
368
|
-
customer_details:
|
|
368
|
+
user_id: h,
|
|
369
|
+
customer_details: Ne
|
|
369
370
|
}).select("id").single();
|
|
370
|
-
if (
|
|
371
|
+
if (Re || !Le) return console.error("Failed to create pending order:", Re), {
|
|
371
372
|
error: "Failed to initiate order",
|
|
372
373
|
url: null
|
|
373
374
|
};
|
|
374
|
-
let Q =
|
|
375
|
+
let Q = Le.id, { error: ze } = await C.from("order_items").insert(ke.map((e) => ({
|
|
375
376
|
order_id: Q,
|
|
376
377
|
product_id: e.product_id,
|
|
377
378
|
variant_id: e.variant_id ?? null,
|
|
378
379
|
quantity: e.quantity,
|
|
379
380
|
price_at_purchase: e.price_at_purchase
|
|
380
381
|
})));
|
|
381
|
-
if (
|
|
382
|
+
if (ze) return console.error("Failed to insert order items:", ze), await C.from("orders").update({ status: "failed" }).eq("id", Q), {
|
|
382
383
|
error: "Failed to record order items",
|
|
383
384
|
url: null
|
|
384
385
|
};
|
|
385
|
-
if (
|
|
386
|
-
await
|
|
387
|
-
userId:
|
|
388
|
-
billingAddress:
|
|
389
|
-
shippingAddress:
|
|
390
|
-
client:
|
|
391
|
-
}), await
|
|
392
|
-
userId:
|
|
393
|
-
fullName:
|
|
394
|
-
phone:
|
|
395
|
-
client:
|
|
386
|
+
if (h) try {
|
|
387
|
+
await me({
|
|
388
|
+
userId: h,
|
|
389
|
+
billingAddress: g,
|
|
390
|
+
shippingAddress: _,
|
|
391
|
+
client: C
|
|
392
|
+
}), await pe({
|
|
393
|
+
userId: h,
|
|
394
|
+
fullName: g?.recipient_name ?? _?.recipient_name ?? null,
|
|
395
|
+
phone: m,
|
|
396
|
+
client: C
|
|
396
397
|
});
|
|
397
398
|
} catch (e) {
|
|
398
399
|
console.error("Failed to sync checkout profile defaults before checkout:", e);
|
|
399
400
|
}
|
|
400
|
-
if (q && !(await
|
|
401
|
-
client:
|
|
401
|
+
if (q && !(await c({
|
|
402
|
+
client: C,
|
|
402
403
|
quote: q,
|
|
403
404
|
orderId: Q,
|
|
404
405
|
provider: "stripe",
|
|
405
406
|
discountTotal: K,
|
|
406
|
-
userId:
|
|
407
|
-
customerEmail:
|
|
407
|
+
userId: h,
|
|
408
|
+
customerEmail: p,
|
|
408
409
|
metadata: {
|
|
409
|
-
currency:
|
|
410
|
+
currency: j.code,
|
|
410
411
|
subtotal: G,
|
|
411
412
|
shipping_total: J,
|
|
412
413
|
tax_total: Z
|
|
413
414
|
}
|
|
414
|
-
})).success) return await
|
|
415
|
+
})).success) return await C.from("orders").update({ status: "failed" }).eq("id", Q), {
|
|
415
416
|
url: null,
|
|
416
417
|
error: "Coupon is no longer available.",
|
|
417
418
|
errorKey: "ecommerce.coupon_invalid"
|
|
418
419
|
};
|
|
419
|
-
let $ = await
|
|
420
|
-
email:
|
|
421
|
-
phone:
|
|
422
|
-
userId:
|
|
423
|
-
billingAddress:
|
|
424
|
-
shippingAddress:
|
|
420
|
+
let $ = await ye({
|
|
421
|
+
email: p,
|
|
422
|
+
phone: m,
|
|
423
|
+
userId: h,
|
|
424
|
+
billingAddress: g,
|
|
425
|
+
shippingAddress: _
|
|
425
426
|
});
|
|
426
427
|
try {
|
|
427
|
-
let e = await
|
|
428
|
+
let e = await xe.checkout.sessions.create({
|
|
428
429
|
mode: "payment",
|
|
429
|
-
success_url: `${
|
|
430
|
-
cancel_url: `${
|
|
431
|
-
locale:
|
|
430
|
+
success_url: `${w}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
|
|
431
|
+
cancel_url: `${w}/checkout`,
|
|
432
|
+
locale: ve(y),
|
|
432
433
|
line_items: W,
|
|
433
434
|
automatic_tax: X.enabled && X.mode === "automatic" ? { enabled: !0 } : void 0,
|
|
434
435
|
billing_address_collection: "auto",
|
|
435
436
|
customer: $ || void 0,
|
|
436
|
-
customer_email: $ ? void 0 :
|
|
437
|
+
customer_email: $ ? void 0 : p || void 0,
|
|
437
438
|
customer_creation: $ ? void 0 : "if_required",
|
|
438
439
|
customer_update: $ ? {
|
|
439
440
|
name: "auto",
|
|
440
441
|
address: "auto",
|
|
441
442
|
shipping: "auto"
|
|
442
443
|
} : void 0,
|
|
443
|
-
shipping_address_collection:
|
|
444
|
+
shipping_address_collection: O ? { allowed_countries: _e } : void 0,
|
|
444
445
|
metadata: {
|
|
445
446
|
orderId: Q,
|
|
446
447
|
taxMode: X.mode,
|
|
447
|
-
currencyCode:
|
|
448
|
+
currencyCode: j.code,
|
|
448
449
|
couponCode: q?.code || ""
|
|
449
450
|
}
|
|
450
|
-
}), { error: t } = await
|
|
451
|
+
}), { error: t } = await C.from("orders").update({ stripe_session_id: e.id }).eq("id", Q);
|
|
451
452
|
return t && console.error("Failed to save Stripe session ID on order:", t), { url: e.url };
|
|
452
453
|
} catch (e) {
|
|
453
|
-
return console.error("Stripe session creation failed:", e), await
|
|
454
|
+
return console.error("Stripe session creation failed:", e), await C.from("orders").update({ status: "failed" }).eq("id", Q), e?.name === "StripeNotConfiguredError" || e?.type === "StripeAuthenticationError" ? {
|
|
454
455
|
error: "This store is not able to take payments right now. Please contact the seller to complete your purchase.",
|
|
455
456
|
errorKey: "ecommerce.checkout_payments_unavailable",
|
|
456
457
|
errorStatus: 503,
|
|
@@ -464,4 +465,4 @@ var g = class {
|
|
|
464
465
|
}
|
|
465
466
|
};
|
|
466
467
|
//#endregion
|
|
467
|
-
export {
|
|
468
|
+
export { h as StripeProvider };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use server";const e=require("../coupons.cjs"),t=require("../coupon-server.cjs");let n=require("next/headers"),r=require("@nextblock-cms/db/server");async function i(i){try{let a=await(0,n.headers)();if(!t.consumeCouponValidationToken(t.resolveCouponValidationThrottleKey(a)))return{success:!1,error:e.COUPON_THROTTLED_ERROR_MESSAGE,errorKey:e.COUPON_THROTTLED_ERROR_KEY};let o=(0,r.getServiceRoleSupabaseClient)();return await t.getCouponQuote({client:o,code:i.code,items:Array.isArray(i.items)?i.items:[],currencyCode:i.currencyCode})}catch(e){return console.error(`Failed to validate coupon:`,e),{success:!1,error:`We couldn't validate this coupon. Try again.`,errorKey:`ecommerce.coupon_validation_failed`}}}exports.getCouponQuoteAction=i;
|
|
1
|
+
"use server";const e=require("../coupons.cjs"),t=require("../coupon-server.cjs");require("server-only");let n=require("next/headers"),r=require("@nextblock-cms/db/server");async function i(i){try{let a=await(0,n.headers)();if(!t.consumeCouponValidationToken(t.resolveCouponValidationThrottleKey(a)))return{success:!1,error:e.COUPON_THROTTLED_ERROR_MESSAGE,errorKey:e.COUPON_THROTTLED_ERROR_KEY};let o=(0,r.getServiceRoleSupabaseClient)();return await t.getCouponQuote({client:o,code:i.code,items:Array.isArray(i.items)?i.items:[],currencyCode:i.currencyCode})}catch(e){return console.error(`Failed to validate coupon:`,e),{success:!1,error:`We couldn't validate this coupon. Try again.`,errorKey:`ecommerce.coupon_validation_failed`}}}exports.getCouponQuoteAction=i;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use server";
|
|
2
2
|
import { COUPON_THROTTLED_ERROR_KEY as e, COUPON_THROTTLED_ERROR_MESSAGE as t } from "../coupons.es.js";
|
|
3
3
|
import { consumeCouponValidationToken as n, getCouponQuote as r, resolveCouponValidationThrottleKey as i } from "../coupon-server.es.js";
|
|
4
|
+
import "server-only";
|
|
4
5
|
import { headers as a } from "next/headers";
|
|
5
6
|
import { getServiceRoleSupabaseClient as o } from "@nextblock-cms/db/server";
|
|
6
7
|
//#region src/lib/server-actions/coupon-actions.ts
|