@nextblock-cms/ecom 0.9.92 → 0.9.98
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/lib/currency-rest-client.cjs.js +1 -1
- package/lib/currency-rest-client.es.js +7 -7
- package/lib/freemius-order-sync.cjs.js +1 -1
- package/lib/freemius-order-sync.es.js +29 -29
- package/lib/pages/cms/orders/server-actions.cjs.js +1 -1
- package/lib/pages/cms/orders/server-actions.es.js +16 -16
- package/lib/providers/freemius.cjs.js +2 -2
- package/lib/providers/freemius.es.js +159 -159
- package/lib/providers/stripe.cjs.js +1 -1
- package/lib/providers/stripe.es.js +51 -51
- package/lib/stripe/checkout.cjs.js +1 -1
- package/lib/stripe/checkout.es.js +25 -25
- package/lib/stripe/order-sync.cjs.js +1 -1
- package/lib/stripe/order-sync.es.js +38 -38
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U=require("../stripe/client.cjs.js"),ke=require("@supabase/supabase-js"),Ee=require("../countries.cjs.js"),Pe=require("../customer.cjs.js"),R=require("../coupon-server.cjs.js"),be=require("../coupons.cjs.js"),_e=require("../customer-addresses.cjs.js"),T=require("../inventory-settings.cjs.js"),w=require("../tax-calculation.cjs.js"),h=require("../currency.cjs.js"),Te=require("../order-tax-details.cjs.js"),we=require("../types.cjs.js"),Ie=require("../variation-utils.cjs.js"),Ae=Ee.countries.map(r=>r.code),De=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"]);function pe(r){if(r)return{line1:r.line1||void 0,line2:r.line2||void 0,city:r.city||void 0,state:r.state||void 0,postal_code:r.postal_code||void 0,country:r.country_code||void 0}}function Me(r){const i=r?.trim().replace("_","-");if(!i)return;const l=[i,i.toLowerCase(),i.split("-")[0].toLowerCase()];for(const d of l)if(De.has(d))return d}function Ue(r,i){return Ie.resolveTranslatedText(r.name,r.name_translations||null,i)}async function Le(r){if(!r.email)return null;const i=pe(r.shippingAddress),l=r.shippingAddress?.recipient_name||r.billingAddress?.recipient_name||void 0,d={email:r.email,name:r.billingAddress?.recipient_name||r.shippingAddress?.recipient_name||void 0,phone:r.phone||void 0,address:pe(r.billingAddress),metadata:r.userId?{userId:r.userId}:void 0,...i&&l?{shipping:{name:l,phone:r.phone||void 0,address:i}}:{}};try{const s=(await U.stripe.customers.list({email:r.email,limit:1})).data[0];return s?(await U.stripe.customers.update(s.id,d),s.id):(await U.stripe.customers.create(d)).id}catch(_){return console.error("Failed to upsert Stripe customer for checkout prefill:",_),null}}class Fe{getProviderName(){return"Stripe"}async createCheckoutSession({items:i,customerEmail:l,customerPhone:d,userId:_,billingAddress:s,shippingAddress:y,shippingMethodId:z,currencyCode:me,locale:B,couponCode:K,couponContextItems:L}){const Q=process.env.NEXT_PUBLIC_SUPABASE_URL,$=process.env.SUPABASE_SERVICE_ROLE_KEY;if(!Q||!$)return console.error("Missing Supabase credentials for checkout (Service Key required)."),{error:"Internal Server Error",url:null};const a=ke.createClient(Q,$),X=process.env.NEXT_PUBLIC_URL||"http://localhost:4200",H=i.some(e=>!we.isDigitalItem(e));if(!i.length)return{error:"Cart is empty",url:null};const{data:he,error:j}=await a.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}),g=he??[];if(j||g.length===0)return console.error("Error fetching currencies for checkout:",j),{error:"Failed to resolve store currencies",url:null};const G=h.getDefaultCurrency(g),p=g.find(e=>e.code===(me||"").toUpperCase())??G,F=p.code.toLowerCase(),V=await T.getEcommerceInventorySettings(a),ve=i.map(e=>e.product_id),W=i.map(e=>e.variant_id).filter(e=>!!e),{data:J,error:Y}=await a.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",ve);if(Y||!J)return console.error("Error fetching products for validation:",Y),{error:"Failed to validate product prices",url:null};const{data:fe,error:Z}=W.length?await a.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",W):{data:[],error:null};if(Z)return console.error("Error fetching variants for validation:",Z),{error:"Failed to validate product variants",url:null};const ee=new Map(J.map(e=>[e.id,e])),te=new Map((fe||[]).map(e=>[e.id,e])),N=new Set,I=new Map;for(const e of i){const t=ee.get(e.product_id);if(!t)continue;const n=(e.variant_id?te.get(e.variant_id):null)?.sku||t.sku;n&&(N.add(n),I.set(n,(I.get(n)??0)+e.quantity))}const{data:ye,error:re}=N.size?await a.from("inventory_items").select("sku, quantity").in("sku",[...N]):{data:[],error:null};if(re)return console.error("Error fetching SKU inventory for validation:",re),{error:"Failed to validate SKU inventory",url:null};const A=new Map((ye||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),S=[],oe=[],ie=[];let v=0,C=0,c=null;if(K){const e=await R.getCouponQuote({client:a,code:K,items:L&&L.length>0?L:i,currencyCode:p.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};c=e.quote}const ge=R.getQuoteLineDiscountMap(c),Se=e=>{const t=e.unitAmount*e.quantity,f=Math.max(0,t-e.lineDiscount);if(f<=0)return;const n=Math.floor(f/e.quantity),P=f-n*e.quantity,k=(b,E)=>{E<=0||b<=0||S.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:w.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||""}},tax_behavior:"exclusive",unit_amount:b},quantity:E})};k(n,e.quantity-P),k(n+1,P)};for(const e of i){const t=ee.get(e.product_id);if(!t)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...T.createInventoryUnavailableError(e.title)};const f=h.resolveEffectivePriceForCurrency({prices:h.normalizePriceMap(t.prices),salePrices:t.sale_prices||{},fallbackPrice:t.price,fallbackSalePrice:t.sale_price,saleStartAt:t.sale_start_at,saleEndAt:t.sale_end_at,scheduledPrice:t.scheduled_price,scheduledPrices:h.normalizePriceMap(t.scheduled_prices),scheduledPriceAt:t.scheduled_price_at,currencyCode:p.code,currencies:g});let n=f.sale_price??f.price,P=t.title,k=null;if(e.variant_id){const o=te.get(e.variant_id);if(!o||o.product_id!==e.product_id)return{url:null,...T.createInventoryUnavailableError(e.title)};const M=I.get(o.sku)??e.quantity,le=A.has(o.sku)?A.get(o.sku)??0:Math.max(0,o.stock_quantity??0);if(V.trackQuantities&&M>le)return{url:null,...T.createInventoryInsufficientError(e.title,le)};const de=h.resolveEffectivePriceForCurrency({prices:h.normalizePriceMap(o.prices),salePrices:o.sale_prices||{},fallbackPrice:o.price,fallbackSalePrice:o.sale_price,saleStartAt:o.sale_start_at,saleEndAt:o.sale_end_at,scheduledPrice:o.scheduled_price,scheduledPrices:h.normalizePriceMap(o.scheduled_prices),scheduledPriceAt:o.scheduled_price_at,currencyCode:p.code,currencies:g});n=de.sale_price??de.price,k=o.id,P=e.variant_label?`${t.title} - ${e.variant_label}`:`${t.title} - ${o.sku}`}else{const o=I.get(t.sku)??e.quantity,M=A.has(t.sku)?A.get(t.sku)??0:Math.max(0,t.stock??0);if(V.trackQuantities&&o>M)return{url:null,...T.createInventoryInsufficientError(e.title,M)}}const b=t.is_taxable??!0;if(n<0)return{error:"A product variation produced an invalid price.",url:null};const E=Math.min(n*e.quantity,ge.get(be.getCartLineCouponKey(e))??0);Se({name:P,currency:F,productId:t.id,variantId:k,isTaxable:b,unitAmount:n,quantity:e.quantity,lineDiscount:E}),v+=n*e.quantity,C+=E,ie.push({product_id:t.id,quantity:e.quantity,price_at_purchase:n,variant_id:k}),oe.push({product_id:t.id,quantity:e.quantity,unit_amount:n,discount_amount:E,is_taxable:b})}if(S.length===0&&C>=v)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(S.length===0)return{error:"No valid items in cart",url:null};let m=0,O=null;if(z){const{data:e,error:t}=await a.from("shipping_zone_methods").select("id, name, name_translations, cost_amount, cost_currency").eq("id",z).single();if(t)return console.error("Failed to load shipping method:",t),{error:"Failed to load shipping method",url:null};m=h.convertMinorUnitAmount({amount:e.cost_amount??0,fromCurrencyCode:e.cost_currency||G.code,toCurrencyCode:p.code,currencies:g}),O=Ue(e,B)}const ae=H?y??s:s;let u;try{u=await w.calculateCheckoutTaxes(a,{items:oe,destination:{country_code:ae?.country_code,state:ae?.state}})}catch(e){return console.error("Failed to calculate checkout taxes:",e),{error:"Failed to calculate taxes",url:null}}m>0&&O&&S.push({price_data:{currency:F,product_data:{name:O,tax_code:u.enabled&&u.mode==="automatic"?w.STRIPE_TAX_CODE_SHIPPING:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:m},quantity:1});const q=u.enabled&&u.mode==="manual"&&!u.isPendingExternalCalculation?u.amount:0;q>0&&S.push({price_data:{currency:F,product_data:{name:"Tax",tax_code:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:q},quantity:1});const Ce=Pe.normalizeOrderCustomerDetails({email:l,phone:d,name:s?.recipient_name,billing:s,shipping:y}),ne=p.code,qe=Te.buildOrderTaxDetailsFromCalculation({calculation:u,subtotal:v,shippingTotal:m,total:Math.max(0,v-C)+m+q,currency:ne}),xe=Math.max(0,v-C)+m+q,{data:ce,error:se}=await a.from("orders").insert({status:"pending",total:xe,currency:ne,exchange_rate_at_purchase:p.exchange_rate,subtotal:v,shipping_total:m,tax_total:q,tax_details:qe,coupon_id:c?.couponId??null,coupon_code:c?.code??null,discount_total:C,discount_details:c?{code:c.code,discount_type:c.discountType,discount_amount:c.discountAmount,provider:"stripe",provider_discounts:c.providerDiscounts,line_discounts:c.lineDiscounts}:null,provider:"stripe",user_id:_,customer_details:Ce}).select("id").single();if(se||!ce)return console.error("Failed to create pending order:",se),{error:"Failed to initiate order",url:null};const x=ce.id,{error:ue}=await a.from("order_items").insert(ie.map(e=>({order_id:x,product_id:e.product_id,variant_id:e.variant_id??null,quantity:e.quantity,price_at_purchase:e.price_at_purchase})));if(ue)return console.error("Failed to insert order items:",ue),await a.from("orders").update({status:"failed"}).eq("id",x),{error:"Failed to record order items",url:null};if(_)try{await _e.upsertDefaultUserAddresses({userId:_,billingAddress:s,shippingAddress:y,client:a}),await _e.fillMissingUserProfileCheckoutDetails({userId:_,fullName:s?.recipient_name??y?.recipient_name??null,phone:d,client:a})}catch(e){console.error("Failed to sync checkout profile defaults before checkout:",e)}c&&await R.recordCouponRedemption({client:a,quote:c,orderId:x,provider:"stripe",discountTotal:C,userId:_,customerEmail:l,metadata:{currency:p.code,subtotal:v,shipping_total:m,tax_total:q}});const D=await Le({email:l,phone:d,userId:_,billingAddress:s,shippingAddress:y});try{const e=await U.stripe.checkout.sessions.create({mode:"payment",success_url:`${X}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${X}/checkout`,locale:Me(B),line_items:S,automatic_tax:u.enabled&&u.mode==="automatic"?{enabled:!0}:void 0,billing_address_collection:"auto",customer:D||void 0,customer_email:D?void 0:l||void 0,customer_creation:D?void 0:"if_required",customer_update:D?{name:"auto",address:"auto",shipping:"auto"}:void 0,shipping_address_collection:H?{allowed_countries:Ae}:void 0,metadata:{orderId:x,taxMode:u.mode,currencyCode:p.code,couponCode:c?.code||""}}),{error:t}=await a.from("orders").update({stripe_session_id:e.id}).eq("id",x);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 a.from("orders").update({status:"failed"}).eq("id",x),{error:e.message,url:null}}}}exports.StripeProvider=Fe;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const U=require("../stripe/client.cjs.js"),xe=require("@supabase/supabase-js"),ke=require("../countries.cjs.js"),Pe=require("../customer.cjs.js"),O=require("../coupon-server.cjs.js"),be=require("../coupons.cjs.js"),_e=require("../customer-addresses.cjs.js"),T=require("../inventory-settings.cjs.js"),w=require("../tax-calculation.cjs.js"),h=require("../currency.cjs.js"),Te=require("../order-tax-details.cjs.js"),we=require("../types.cjs.js"),Ae=require("../variation-utils.cjs.js"),Ie=ke.countries.map(r=>r.code),De=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"]);function pe(r){if(r)return{line1:r.line1||void 0,line2:r.line2||void 0,city:r.city||void 0,state:r.state||void 0,postal_code:r.postal_code||void 0,country:r.country_code||void 0}}function Me(r){const i=r?.trim().replace("_","-");if(!i)return;const l=[i,i.toLowerCase(),i.split("-")[0].toLowerCase()];for(const d of l)if(De.has(d))return d}function Ue(r,i){return Ae.resolveTranslatedText(r.name,r.name_translations||null,i)}async function Le(r){if(!r.email)return null;const i=pe(r.shippingAddress),l=r.shippingAddress?.recipient_name||r.billingAddress?.recipient_name||void 0,d={email:r.email,name:r.billingAddress?.recipient_name||r.shippingAddress?.recipient_name||void 0,phone:r.phone||void 0,address:pe(r.billingAddress),metadata:r.userId?{userId:r.userId}:void 0,...i&&l?{shipping:{name:l,phone:r.phone||void 0,address:i}}:{}};try{const s=(await U.stripe.customers.list({email:r.email,limit:1})).data[0];return s?(await U.stripe.customers.update(s.id,d),s.id):(await U.stripe.customers.create(d)).id}catch(_){return console.error("Failed to upsert Stripe customer for checkout prefill:",_),null}}class Fe{getProviderName(){return"Stripe"}async createCheckoutSession({items:i,customerEmail:l,customerPhone:d,userId:_,billingAddress:s,shippingAddress:y,shippingMethodId:B,currencyCode:me,locale:z,couponCode:K,couponContextItems:L}){const Q=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,$=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!Q||!$)return console.error("Missing Supabase credentials for checkout (Service Key required)."),{error:"Internal Server Error",url:null};const a=xe.createClient(Q,$),X=process.env.NEXT_PUBLIC_URL||"http://localhost:4200",H=i.some(e=>!we.isDigitalItem(e));if(!i.length)return{error:"Cart is empty",url:null};const{data:he,error:j}=await a.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}),g=he??[];if(j||g.length===0)return console.error("Error fetching currencies for checkout:",j),{error:"Failed to resolve store currencies",url:null};const G=h.getDefaultCurrency(g),p=g.find(e=>e.code===(me||"").toUpperCase())??G,F=p.code.toLowerCase(),V=await T.getEcommerceInventorySettings(a),ve=i.map(e=>e.product_id),W=i.map(e=>e.variant_id).filter(e=>!!e),{data:Y,error:J}=await a.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",ve);if(J||!Y)return console.error("Error fetching products for validation:",J),{error:"Failed to validate product prices",url:null};const{data:fe,error:Z}=W.length?await a.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",W):{data:[],error:null};if(Z)return console.error("Error fetching variants for validation:",Z),{error:"Failed to validate product variants",url:null};const ee=new Map(Y.map(e=>[e.id,e])),te=new Map((fe||[]).map(e=>[e.id,e])),R=new Set,A=new Map;for(const e of i){const t=ee.get(e.product_id);if(!t)continue;const n=(e.variant_id?te.get(e.variant_id):null)?.sku||t.sku;n&&(R.add(n),A.set(n,(A.get(n)??0)+e.quantity))}const{data:ye,error:re}=R.size?await a.from("inventory_items").select("sku, quantity").in("sku",[...R]):{data:[],error:null};if(re)return console.error("Error fetching SKU inventory for validation:",re),{error:"Failed to validate SKU inventory",url:null};const I=new Map((ye||[]).map(e=>[e.sku,Math.max(0,e.quantity??0)])),S=[],oe=[],ie=[];let v=0,C=0,c=null;if(K){const e=await O.getCouponQuote({client:a,code:K,items:L&&L.length>0?L:i,currencyCode:p.code});if(!e.success)return{error:e.error,errorKey:e.errorKey,errorStatus:400,url:null};c=e.quote}const ge=O.getQuoteLineDiscountMap(c),Se=e=>{const t=e.unitAmount*e.quantity,f=Math.max(0,t-e.lineDiscount);if(f<=0)return;const n=Math.floor(f/e.quantity),P=f-n*e.quantity,x=(b,k)=>{k<=0||b<=0||S.push({price_data:{currency:e.currency,product_data:{name:e.name,tax_code:w.getStripeTaxCodeForProduct(e.isTaxable),metadata:{productId:e.productId,variantId:e.variantId||""}},tax_behavior:"exclusive",unit_amount:b},quantity:k})};x(n,e.quantity-P),x(n+1,P)};for(const e of i){const t=ee.get(e.product_id);if(!t)return console.warn(`Product ${e.product_id} not found in DB.`),{url:null,...T.createInventoryUnavailableError(e.title)};const f=h.resolveEffectivePriceForCurrency({prices:h.normalizePriceMap(t.prices),salePrices:t.sale_prices||{},fallbackPrice:t.price,fallbackSalePrice:t.sale_price,saleStartAt:t.sale_start_at,saleEndAt:t.sale_end_at,scheduledPrice:t.scheduled_price,scheduledPrices:h.normalizePriceMap(t.scheduled_prices),scheduledPriceAt:t.scheduled_price_at,currencyCode:p.code,currencies:g});let n=f.sale_price??f.price,P=t.title,x=null;if(e.variant_id){const o=te.get(e.variant_id);if(!o||o.product_id!==e.product_id)return{url:null,...T.createInventoryUnavailableError(e.title)};const M=A.get(o.sku)??e.quantity,le=I.has(o.sku)?I.get(o.sku)??0:Math.max(0,o.stock_quantity??0);if(V.trackQuantities&&M>le)return{url:null,...T.createInventoryInsufficientError(e.title,le)};const de=h.resolveEffectivePriceForCurrency({prices:h.normalizePriceMap(o.prices),salePrices:o.sale_prices||{},fallbackPrice:o.price,fallbackSalePrice:o.sale_price,saleStartAt:o.sale_start_at,saleEndAt:o.sale_end_at,scheduledPrice:o.scheduled_price,scheduledPrices:h.normalizePriceMap(o.scheduled_prices),scheduledPriceAt:o.scheduled_price_at,currencyCode:p.code,currencies:g});n=de.sale_price??de.price,x=o.id,P=e.variant_label?`${t.title} - ${e.variant_label}`:`${t.title} - ${o.sku}`}else{const o=A.get(t.sku)??e.quantity,M=I.has(t.sku)?I.get(t.sku)??0:Math.max(0,t.stock??0);if(V.trackQuantities&&o>M)return{url:null,...T.createInventoryInsufficientError(e.title,M)}}const b=t.is_taxable??!0;if(n<0)return{error:"A product variation produced an invalid price.",url:null};const k=Math.min(n*e.quantity,ge.get(be.getCartLineCouponKey(e))??0);Se({name:P,currency:F,productId:t.id,variantId:x,isTaxable:b,unitAmount:n,quantity:e.quantity,lineDiscount:k}),v+=n*e.quantity,C+=k,ie.push({product_id:t.id,quantity:e.quantity,price_at_purchase:n,variant_id:x}),oe.push({product_id:t.id,quantity:e.quantity,unit_amount:n,discount_amount:k,is_taxable:b})}if(S.length===0&&C>=v)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(S.length===0)return{error:"No valid items in cart",url:null};let m=0,N=null;if(B){const{data:e,error:t}=await a.from("shipping_zone_methods").select("id, name, name_translations, cost_amount, cost_currency").eq("id",B).single();if(t)return console.error("Failed to load shipping method:",t),{error:"Failed to load shipping method",url:null};m=h.convertMinorUnitAmount({amount:e.cost_amount??0,fromCurrencyCode:e.cost_currency||G.code,toCurrencyCode:p.code,currencies:g}),N=Ue(e,z)}const ae=H?y??s:s;let u;try{u=await w.calculateCheckoutTaxes(a,{items:oe,destination:{country_code:ae?.country_code,state:ae?.state}})}catch(e){return console.error("Failed to calculate checkout taxes:",e),{error:"Failed to calculate taxes",url:null}}m>0&&N&&S.push({price_data:{currency:F,product_data:{name:N,tax_code:u.enabled&&u.mode==="automatic"?w.STRIPE_TAX_CODE_SHIPPING:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:m},quantity:1});const E=u.enabled&&u.mode==="manual"&&!u.isPendingExternalCalculation?u.amount:0;E>0&&S.push({price_data:{currency:F,product_data:{name:"Tax",tax_code:w.STRIPE_TAX_CODE_NONTAXABLE},tax_behavior:"exclusive",unit_amount:E},quantity:1});const Ce=Pe.normalizeOrderCustomerDetails({email:l,phone:d,name:s?.recipient_name,billing:s,shipping:y}),ne=p.code,Ee=Te.buildOrderTaxDetailsFromCalculation({calculation:u,subtotal:v,shippingTotal:m,total:Math.max(0,v-C)+m+E,currency:ne}),qe=Math.max(0,v-C)+m+E,{data:ce,error:se}=await a.from("orders").insert({status:"pending",total:qe,currency:ne,exchange_rate_at_purchase:p.exchange_rate,subtotal:v,shipping_total:m,tax_total:E,tax_details:Ee,coupon_id:c?.couponId??null,coupon_code:c?.code??null,discount_total:C,discount_details:c?{code:c.code,discount_type:c.discountType,discount_amount:c.discountAmount,provider:"stripe",provider_discounts:c.providerDiscounts,line_discounts:c.lineDiscounts}:null,provider:"stripe",user_id:_,customer_details:Ce}).select("id").single();if(se||!ce)return console.error("Failed to create pending order:",se),{error:"Failed to initiate order",url:null};const q=ce.id,{error:ue}=await a.from("order_items").insert(ie.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(ue)return console.error("Failed to insert order items:",ue),await a.from("orders").update({status:"failed"}).eq("id",q),{error:"Failed to record order items",url:null};if(_)try{await _e.upsertDefaultUserAddresses({userId:_,billingAddress:s,shippingAddress:y,client:a}),await _e.fillMissingUserProfileCheckoutDetails({userId:_,fullName:s?.recipient_name??y?.recipient_name??null,phone:d,client:a})}catch(e){console.error("Failed to sync checkout profile defaults before checkout:",e)}c&&await O.recordCouponRedemption({client:a,quote:c,orderId:q,provider:"stripe",discountTotal:C,userId:_,customerEmail:l,metadata:{currency:p.code,subtotal:v,shipping_total:m,tax_total:E}});const D=await Le({email:l,phone:d,userId:_,billingAddress:s,shippingAddress:y});try{const e=await U.stripe.checkout.sessions.create({mode:"payment",success_url:`${X}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${X}/checkout`,locale:Me(z),line_items:S,automatic_tax:u.enabled&&u.mode==="automatic"?{enabled:!0}:void 0,billing_address_collection:"auto",customer:D||void 0,customer_email:D?void 0:l||void 0,customer_creation:D?void 0:"if_required",customer_update:D?{name:"auto",address:"auto",shipping:"auto"}:void 0,shipping_address_collection:H?{allowed_countries:Ie}:void 0,metadata:{orderId:q,taxMode:u.mode,currencyCode:p.code,couponCode:c?.code||""}}),{error:t}=await a.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 a.from("orders").update({status:"failed"}).eq("id",q),{error:e.message,url:null}}}}exports.StripeProvider=Fe;
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { stripe as D } from "../stripe/client.es.js";
|
|
2
2
|
import { createClient as Ee } from "@supabase/supabase-js";
|
|
3
|
-
import { countries as
|
|
4
|
-
import { normalizeOrderCustomerDetails as
|
|
3
|
+
import { countries as Pe } from "../countries.es.js";
|
|
4
|
+
import { normalizeOrderCustomerDetails as qe } from "../customer.es.js";
|
|
5
5
|
import { getCouponQuote as be, getQuoteLineDiscountMap as we, recordCouponRedemption as Te } from "../coupon-server.es.js";
|
|
6
|
-
import { getCartLineCouponKey as
|
|
7
|
-
import { upsertDefaultUserAddresses as
|
|
8
|
-
import { getEcommerceInventorySettings as
|
|
9
|
-
import { calculateCheckoutTaxes as Le, STRIPE_TAX_CODE_SHIPPING as
|
|
10
|
-
import { getDefaultCurrency as Re, resolveEffectivePriceForCurrency as pe, normalizePriceMap as
|
|
11
|
-
import { buildOrderTaxDetailsFromCalculation as
|
|
12
|
-
import { isDigitalItem as
|
|
6
|
+
import { getCartLineCouponKey as Ae } from "../coupons.es.js";
|
|
7
|
+
import { upsertDefaultUserAddresses as Ie, fillMissingUserProfileCheckoutDetails as De } from "../customer-addresses.es.js";
|
|
8
|
+
import { getEcommerceInventorySettings as Ue, createInventoryUnavailableError as ue, createInventoryInsufficientError as le } from "../inventory-settings.es.js";
|
|
9
|
+
import { calculateCheckoutTaxes as Le, STRIPE_TAX_CODE_SHIPPING as Me, STRIPE_TAX_CODE_NONTAXABLE as de, getStripeTaxCodeForProduct as Fe } from "../tax-calculation.es.js";
|
|
10
|
+
import { getDefaultCurrency as Re, resolveEffectivePriceForCurrency as pe, normalizePriceMap as I, convertMinorUnitAmount as Ne } from "../currency.es.js";
|
|
11
|
+
import { buildOrderTaxDetailsFromCalculation as Be } from "../order-tax-details.es.js";
|
|
12
|
+
import { isDigitalItem as Oe } from "../types.es.js";
|
|
13
13
|
import { resolveTranslatedText as Ke } from "../variation-utils.es.js";
|
|
14
|
-
const Qe =
|
|
14
|
+
const Qe = Pe.map((r) => r.code), ze = /* @__PURE__ */ new Set([
|
|
15
15
|
"bg",
|
|
16
16
|
"cs",
|
|
17
17
|
"da",
|
|
@@ -120,13 +120,13 @@ class nt {
|
|
|
120
120
|
shippingMethodId: R,
|
|
121
121
|
currencyCode: me,
|
|
122
122
|
locale: N,
|
|
123
|
-
couponCode:
|
|
124
|
-
couponContextItems:
|
|
123
|
+
couponCode: B,
|
|
124
|
+
couponContextItems: U
|
|
125
125
|
}) {
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
126
|
+
const O = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, K = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
|
|
127
|
+
if (!O || !K)
|
|
128
128
|
return console.error("Missing Supabase credentials for checkout (Service Key required)."), { error: "Internal Server Error", url: null };
|
|
129
|
-
const i = Ee(
|
|
129
|
+
const i = Ee(O, K), Q = process.env.NEXT_PUBLIC_URL || "http://localhost:4200", z = a.some((e) => !Oe(e));
|
|
130
130
|
if (!a.length)
|
|
131
131
|
return { error: "Cart is empty", url: null };
|
|
132
132
|
const { data: he, error: $ } = await i.from("currencies").select(
|
|
@@ -134,24 +134,24 @@ class nt {
|
|
|
134
134
|
).eq("is_active", !0).order("code", { ascending: !0 }), y = he ?? [];
|
|
135
135
|
if ($ || y.length === 0)
|
|
136
136
|
return console.error("Error fetching currencies for checkout:", $), { error: "Failed to resolve store currencies", url: null };
|
|
137
|
-
const X = Re(y), _ = y.find((e) => e.code === (me || "").toUpperCase()) ?? X, L = _.code.toLowerCase(), H = await
|
|
137
|
+
const X = Re(y), _ = y.find((e) => e.code === (me || "").toUpperCase()) ?? X, L = _.code.toLowerCase(), H = await Ue(i), fe = a.map((e) => e.product_id), G = a.map((e) => e.variant_id).filter((e) => !!e), { data: V, error: W } = await i.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);
|
|
138
138
|
if (W || !V)
|
|
139
139
|
return console.error("Error fetching products for validation:", W), { error: "Failed to validate product prices", url: null };
|
|
140
|
-
const { data: ve, error:
|
|
141
|
-
if (
|
|
142
|
-
return console.error("Error fetching variants for validation:",
|
|
143
|
-
const
|
|
140
|
+
const { data: ve, error: Y } = G.length ? await i.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", G) : { data: [], error: null };
|
|
141
|
+
if (Y)
|
|
142
|
+
return console.error("Error fetching variants for validation:", Y), { error: "Failed to validate product variants", url: null };
|
|
143
|
+
const j = new Map(V.map((e) => [e.id, e])), J = new Map((ve || []).map((e) => [e.id, e])), M = /* @__PURE__ */ new Set(), b = /* @__PURE__ */ new Map();
|
|
144
144
|
for (const e of a) {
|
|
145
|
-
const t =
|
|
145
|
+
const t = j.get(e.product_id);
|
|
146
146
|
if (!t)
|
|
147
147
|
continue;
|
|
148
148
|
const n = (e.variant_id ? J.get(e.variant_id) : null)?.sku || t.sku;
|
|
149
|
-
n && (
|
|
149
|
+
n && (M.add(n), b.set(
|
|
150
150
|
n,
|
|
151
151
|
(b.get(n) ?? 0) + e.quantity
|
|
152
152
|
));
|
|
153
153
|
}
|
|
154
|
-
const { data: ye, error: Z } =
|
|
154
|
+
const { data: ye, error: Z } = M.size ? await i.from("inventory_items").select("sku, quantity").in("sku", [...M]) : { data: [], error: null };
|
|
155
155
|
if (Z)
|
|
156
156
|
return console.error("Error fetching SKU inventory for validation:", Z), { error: "Failed to validate SKU inventory", url: null };
|
|
157
157
|
const w = new Map(
|
|
@@ -161,11 +161,11 @@ class nt {
|
|
|
161
161
|
])
|
|
162
162
|
), g = [], ee = [], te = [];
|
|
163
163
|
let h = 0, S = 0, c = null;
|
|
164
|
-
if (
|
|
164
|
+
if (B) {
|
|
165
165
|
const e = await be({
|
|
166
166
|
client: i,
|
|
167
|
-
code:
|
|
168
|
-
items:
|
|
167
|
+
code: B,
|
|
168
|
+
items: U && U.length > 0 ? U : a,
|
|
169
169
|
currencyCode: _.code
|
|
170
170
|
});
|
|
171
171
|
if (!e.success)
|
|
@@ -181,8 +181,8 @@ class nt {
|
|
|
181
181
|
const t = e.unitAmount * e.quantity, f = Math.max(0, t - e.lineDiscount);
|
|
182
182
|
if (f <= 0)
|
|
183
183
|
return;
|
|
184
|
-
const n = Math.floor(f / e.quantity),
|
|
185
|
-
E <= 0 ||
|
|
184
|
+
const n = Math.floor(f / e.quantity), P = f - n * e.quantity, k = (q, E) => {
|
|
185
|
+
E <= 0 || q <= 0 || g.push({
|
|
186
186
|
price_data: {
|
|
187
187
|
currency: e.currency,
|
|
188
188
|
product_data: {
|
|
@@ -194,34 +194,34 @@ class nt {
|
|
|
194
194
|
}
|
|
195
195
|
},
|
|
196
196
|
tax_behavior: "exclusive",
|
|
197
|
-
unit_amount:
|
|
197
|
+
unit_amount: q
|
|
198
198
|
},
|
|
199
199
|
quantity: E
|
|
200
200
|
});
|
|
201
201
|
};
|
|
202
|
-
k(n, e.quantity -
|
|
202
|
+
k(n, e.quantity - P), k(n + 1, P);
|
|
203
203
|
};
|
|
204
204
|
for (const e of a) {
|
|
205
|
-
const t =
|
|
205
|
+
const t = j.get(e.product_id);
|
|
206
206
|
if (!t)
|
|
207
207
|
return console.warn(`Product ${e.product_id} not found in DB.`), {
|
|
208
208
|
url: null,
|
|
209
209
|
...ue(e.title)
|
|
210
210
|
};
|
|
211
211
|
const f = pe({
|
|
212
|
-
prices:
|
|
212
|
+
prices: I(t.prices),
|
|
213
213
|
salePrices: t.sale_prices || {},
|
|
214
214
|
fallbackPrice: t.price,
|
|
215
215
|
fallbackSalePrice: t.sale_price,
|
|
216
216
|
saleStartAt: t.sale_start_at,
|
|
217
217
|
saleEndAt: t.sale_end_at,
|
|
218
218
|
scheduledPrice: t.scheduled_price,
|
|
219
|
-
scheduledPrices:
|
|
219
|
+
scheduledPrices: I(t.scheduled_prices),
|
|
220
220
|
scheduledPriceAt: t.scheduled_price_at,
|
|
221
221
|
currencyCode: _.code,
|
|
222
222
|
currencies: y
|
|
223
223
|
});
|
|
224
|
-
let n = f.sale_price ?? f.price,
|
|
224
|
+
let n = f.sale_price ?? f.price, P = t.title, k = null;
|
|
225
225
|
if (e.variant_id) {
|
|
226
226
|
const o = J.get(e.variant_id);
|
|
227
227
|
if (!o || o.product_id !== e.product_id)
|
|
@@ -229,47 +229,47 @@ class nt {
|
|
|
229
229
|
url: null,
|
|
230
230
|
...ue(e.title)
|
|
231
231
|
};
|
|
232
|
-
const
|
|
233
|
-
if (H.trackQuantities &&
|
|
232
|
+
const A = b.get(o.sku) ?? e.quantity, ce = w.has(o.sku) ? w.get(o.sku) ?? 0 : Math.max(0, o.stock_quantity ?? 0);
|
|
233
|
+
if (H.trackQuantities && A > ce)
|
|
234
234
|
return {
|
|
235
235
|
url: null,
|
|
236
236
|
...le(e.title, ce)
|
|
237
237
|
};
|
|
238
238
|
const se = pe({
|
|
239
|
-
prices:
|
|
239
|
+
prices: I(o.prices),
|
|
240
240
|
salePrices: o.sale_prices || {},
|
|
241
241
|
fallbackPrice: o.price,
|
|
242
242
|
fallbackSalePrice: o.sale_price,
|
|
243
243
|
saleStartAt: o.sale_start_at,
|
|
244
244
|
saleEndAt: o.sale_end_at,
|
|
245
245
|
scheduledPrice: o.scheduled_price,
|
|
246
|
-
scheduledPrices:
|
|
246
|
+
scheduledPrices: I(o.scheduled_prices),
|
|
247
247
|
scheduledPriceAt: o.scheduled_price_at,
|
|
248
248
|
currencyCode: _.code,
|
|
249
249
|
currencies: y
|
|
250
250
|
});
|
|
251
|
-
n = se.sale_price ?? se.price, k = o.id,
|
|
251
|
+
n = se.sale_price ?? se.price, k = o.id, P = e.variant_label ? `${t.title} - ${e.variant_label}` : `${t.title} - ${o.sku}`;
|
|
252
252
|
} else {
|
|
253
|
-
const o = b.get(t.sku) ?? e.quantity,
|
|
254
|
-
if (H.trackQuantities && o >
|
|
253
|
+
const o = b.get(t.sku) ?? e.quantity, A = w.has(t.sku) ? w.get(t.sku) ?? 0 : Math.max(0, t.stock ?? 0);
|
|
254
|
+
if (H.trackQuantities && o > A)
|
|
255
255
|
return {
|
|
256
256
|
url: null,
|
|
257
|
-
...le(e.title,
|
|
257
|
+
...le(e.title, A)
|
|
258
258
|
};
|
|
259
259
|
}
|
|
260
|
-
const
|
|
260
|
+
const q = t.is_taxable ?? !0;
|
|
261
261
|
if (n < 0)
|
|
262
262
|
return { error: "A product variation produced an invalid price.", url: null };
|
|
263
263
|
const E = Math.min(
|
|
264
264
|
n * e.quantity,
|
|
265
|
-
ge.get(
|
|
265
|
+
ge.get(Ae(e)) ?? 0
|
|
266
266
|
);
|
|
267
267
|
Se({
|
|
268
|
-
name:
|
|
268
|
+
name: P,
|
|
269
269
|
currency: L,
|
|
270
270
|
productId: t.id,
|
|
271
271
|
variantId: k,
|
|
272
|
-
isTaxable:
|
|
272
|
+
isTaxable: q,
|
|
273
273
|
unitAmount: n,
|
|
274
274
|
quantity: e.quantity,
|
|
275
275
|
lineDiscount: E
|
|
@@ -283,7 +283,7 @@ class nt {
|
|
|
283
283
|
quantity: e.quantity,
|
|
284
284
|
unit_amount: n,
|
|
285
285
|
discount_amount: E,
|
|
286
|
-
is_taxable:
|
|
286
|
+
is_taxable: q
|
|
287
287
|
});
|
|
288
288
|
}
|
|
289
289
|
if (g.length === 0 && S >= h)
|
|
@@ -325,7 +325,7 @@ class nt {
|
|
|
325
325
|
currency: L,
|
|
326
326
|
product_data: {
|
|
327
327
|
name: F,
|
|
328
|
-
tax_code: u.enabled && u.mode === "automatic" ?
|
|
328
|
+
tax_code: u.enabled && u.mode === "automatic" ? Me : de
|
|
329
329
|
},
|
|
330
330
|
tax_behavior: "exclusive",
|
|
331
331
|
unit_amount: m
|
|
@@ -345,13 +345,13 @@ class nt {
|
|
|
345
345
|
},
|
|
346
346
|
quantity: 1
|
|
347
347
|
});
|
|
348
|
-
const Ce =
|
|
348
|
+
const Ce = qe({
|
|
349
349
|
email: l,
|
|
350
350
|
phone: d,
|
|
351
351
|
name: s?.recipient_name,
|
|
352
352
|
billing: s,
|
|
353
353
|
shipping: v
|
|
354
|
-
}), oe = _.code, xe =
|
|
354
|
+
}), oe = _.code, xe = Be({
|
|
355
355
|
calculation: u,
|
|
356
356
|
subtotal: h,
|
|
357
357
|
shippingTotal: m,
|
|
@@ -396,7 +396,7 @@ class nt {
|
|
|
396
396
|
return console.error("Failed to insert order items:", ne), await i.from("orders").update({ status: "failed" }).eq("id", x), { error: "Failed to record order items", url: null };
|
|
397
397
|
if (p)
|
|
398
398
|
try {
|
|
399
|
-
await
|
|
399
|
+
await Ie({
|
|
400
400
|
userId: p,
|
|
401
401
|
billingAddress: s,
|
|
402
402
|
shippingAddress: v,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const b=require("./client.cjs.js"),k=require("@supabase/supabase-js"),L=require("@nextblock-cms/db/server"),N=require("../shipping/resolver.cjs.js"),C=require("../currency.cjs.js"),T=async(n,d,P,A)=>{const m=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,h=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!m||!h)return console.error("Missing Supabase credentials for checkout (Service Key required)."),{error:"Internal Server Error",url:null};const t=k.createClient(m,h),f=process.env.NEXT_PUBLIC_URL||"http://localhost:4200";if(!n.length)return{error:"Cart is empty",url:null};const{data:q}=await t.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}),u=q??[],U=C.getDefaultCurrency(u),s=u.find(e=>e.code===(A||"").toUpperCase())??U;if(!await L.verifyPackageOnline("ecommerce"))return{error:"E-Commerce Package not active. Please purchase a license to accept payments.",url:null};const w=n.map(e=>e.product_id),{data:g,error:y}=await t.from("products").select("id, title, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at").in("id",w);if(y||!g)return console.error("Error fetching products for validation:",y),{error:"Failed to validate product prices",url:null};const I=new Map(g.map(e=>[e.id,e])),l=[];let c=0;const E=[];for(const e of n){const r=I.get(e.product_id);if(!r){console.warn(`Product ${e.product_id} not found in DB, skipping.`);continue}const v=C.resolveEffectivePriceForCurrency({prices: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:r.scheduled_prices||{},scheduledPriceAt:r.scheduled_price_at,currencyCode:s.code,currencies:u}),a=v.sale_price??v.price;a<=0&&console.warn(`[Checkout Session Warning] Product ${r.title} has zero or negative price!`),l.push({price_data:{currency:s.code.toLowerCase(),product_data:{name:r.title,images:[],metadata:{productId:r.id}},unit_amount:a},quantity:e.quantity}),c+=a*e.quantity,E.push({product_id:r.id,quantity:e.quantity,price_at_purchase:a})}if(l.length===0)return{error:"No valid items in cart",url:null};const{data:o,error:_}=await t.from("orders").insert({total:c,user_id:d,currency:s.code,exchange_rate_at_purchase:s.exchange_rate}).select("id").single();if(_||!o)return console.error("Failed to create pending order:",_),console.error("Order Data attempted:",{status:"pending",total:c}),{error:`Failed to initiate order: ${_?.message||"Unknown error"}`,url:null};const R=E.map(e=>({order_id:o.id,product_id:e.product_id,quantity:e.quantity,price_at_purchase:e.price_at_purchase})),{error:S}=await t.from("order_items").insert(R);S&&console.error("Failed to insert order items:",S);let p=[],i=P;if(!i&&d){const{data:e}=await t.from("user_addresses").select("country_code, state_code, postal_code").eq("user_id",d).eq("address_type","shipping").limit(1).single();e&&(i={country:e.country_code,state:e.state_code,postal_code:e.postal_code})}i&&(p=(await N.resolveShippingOptions(c,i,null,s.code)).map(r=>({shipping_rate_data:{type:"fixed_amount",fixed_amount:{amount:r.amount,currency:r.currency.toLowerCase()},display_name:r.name}})));try{const e=await b.stripe.checkout.sessions.create({mode:"payment",success_url:`${f}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,cancel_url:`${f}/`,line_items:l,billing_address_collection:"required",shipping_address_collection:{allowed_countries:["US","CA","GB","AU","NZ","IE","FR","DE","IT","ES","MX","BR","AR","CL","CO","PE","ZA","NG","KE","IN","JP","KR","CN","SG","MY","PH","TH","VN","ID","AE","SA","EG","MA","DZ","TN","PT","NL","BE","CH","AT","SE","NO","DK","FI","PL","CZ","HU","RO","BG","GR","TR","IL","CY","MT"]},shipping_options:p.length>0?p:void 0,metadata:{orderId:o.id}});return await t.from("orders").update({stripe_session_id:e.id}).eq("id",o.id),{url:e.url}}catch(e){return console.error("Stripe session creation failed:",e),{error:e.message,url:null}}};exports.createCheckoutSession=T;
|
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { stripe as
|
|
2
|
-
import { createClient as
|
|
3
|
-
import { verifyPackageOnline as
|
|
4
|
-
import { resolveShippingOptions as
|
|
5
|
-
import { getDefaultCurrency as
|
|
6
|
-
const M = async (n, d,
|
|
7
|
-
const m = process.env.NEXT_PUBLIC_SUPABASE_URL, h = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
1
|
+
import { stripe as q } from "./client.es.js";
|
|
2
|
+
import { createClient as L } from "@supabase/supabase-js";
|
|
3
|
+
import { verifyPackageOnline as N } from "@nextblock-cms/db/server";
|
|
4
|
+
import { resolveShippingOptions as k } from "../shipping/resolver.es.js";
|
|
5
|
+
import { getDefaultCurrency as B, resolveEffectivePriceForCurrency as T } from "../currency.es.js";
|
|
6
|
+
const M = async (n, d, v, P) => {
|
|
7
|
+
const m = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, h = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
|
|
8
8
|
if (!m || !h)
|
|
9
9
|
return console.error("Missing Supabase credentials for checkout (Service Key required)."), { error: "Internal Server Error", url: null };
|
|
10
|
-
const t =
|
|
10
|
+
const t = L(m, h), f = process.env.NEXT_PUBLIC_URL || "http://localhost:4200";
|
|
11
11
|
if (!n.length)
|
|
12
12
|
return { error: "Cart is empty", url: null };
|
|
13
13
|
const { data: A } = await t.from("currencies").select(
|
|
14
14
|
"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"
|
|
15
|
-
).eq("is_active", !0).order("code", { ascending: !0 }), u = A ?? [],
|
|
16
|
-
if (!await
|
|
15
|
+
).eq("is_active", !0).order("code", { ascending: !0 }), u = A ?? [], U = B(u), o = u.find((e) => e.code === (P || "").toUpperCase()) ?? U;
|
|
16
|
+
if (!await N("ecommerce"))
|
|
17
17
|
return { error: "E-Commerce Package not active. Please purchase a license to accept payments.", url: null };
|
|
18
|
-
const
|
|
19
|
-
if (
|
|
20
|
-
return console.error("Error fetching products for validation:",
|
|
21
|
-
const
|
|
18
|
+
const w = n.map((e) => e.product_id), { data: g, error: E } = await t.from("products").select("id, title, price, prices, sale_price, sale_prices, sale_start_at, sale_end_at, scheduled_price, scheduled_prices, scheduled_price_at").in("id", w);
|
|
19
|
+
if (E || !g)
|
|
20
|
+
return console.error("Error fetching products for validation:", E), { error: "Failed to validate product prices", url: null };
|
|
21
|
+
const I = new Map(g.map((e) => [e.id, e])), l = [];
|
|
22
22
|
let c = 0;
|
|
23
|
-
const
|
|
23
|
+
const y = [];
|
|
24
24
|
for (const e of n) {
|
|
25
|
-
const r =
|
|
25
|
+
const r = I.get(e.product_id);
|
|
26
26
|
if (!r) {
|
|
27
27
|
console.warn(`Product ${e.product_id} not found in DB, skipping.`);
|
|
28
28
|
continue;
|
|
29
29
|
}
|
|
30
|
-
const
|
|
30
|
+
const C = T({
|
|
31
31
|
prices: r.prices || {},
|
|
32
32
|
salePrices: r.sale_prices || {},
|
|
33
33
|
fallbackPrice: r.price,
|
|
@@ -39,7 +39,7 @@ const M = async (n, d, S, P) => {
|
|
|
39
39
|
scheduledPriceAt: r.scheduled_price_at,
|
|
40
40
|
currencyCode: o.code,
|
|
41
41
|
currencies: u
|
|
42
|
-
}), a =
|
|
42
|
+
}), a = C.sale_price ?? C.price;
|
|
43
43
|
a <= 0 && console.warn(`[Checkout Session Warning] Product ${r.title} has zero or negative price!`), l.push({
|
|
44
44
|
price_data: {
|
|
45
45
|
currency: o.code.toLowerCase(),
|
|
@@ -54,7 +54,7 @@ const M = async (n, d, S, P) => {
|
|
|
54
54
|
unit_amount: a
|
|
55
55
|
},
|
|
56
56
|
quantity: e.quantity
|
|
57
|
-
}), c += a * e.quantity,
|
|
57
|
+
}), c += a * e.quantity, y.push({
|
|
58
58
|
product_id: r.id,
|
|
59
59
|
quantity: e.quantity,
|
|
60
60
|
price_at_purchase: a
|
|
@@ -70,14 +70,14 @@ const M = async (n, d, S, P) => {
|
|
|
70
70
|
}).select("id").single();
|
|
71
71
|
if (p || !s)
|
|
72
72
|
return console.error("Failed to create pending order:", p), console.error("Order Data attempted:", { status: "pending", total: c }), { error: `Failed to initiate order: ${p?.message || "Unknown error"}`, url: null };
|
|
73
|
-
const
|
|
73
|
+
const R = y.map((e) => ({
|
|
74
74
|
order_id: s.id,
|
|
75
75
|
product_id: e.product_id,
|
|
76
76
|
quantity: e.quantity,
|
|
77
77
|
price_at_purchase: e.price_at_purchase
|
|
78
|
-
})), { error:
|
|
79
|
-
|
|
80
|
-
let _ = [], i =
|
|
78
|
+
})), { error: S } = await t.from("order_items").insert(R);
|
|
79
|
+
S && console.error("Failed to insert order items:", S);
|
|
80
|
+
let _ = [], i = v;
|
|
81
81
|
if (!i && d) {
|
|
82
82
|
const { data: e } = await t.from("user_addresses").select("country_code, state_code, postal_code").eq("user_id", d).eq("address_type", "shipping").limit(1).single();
|
|
83
83
|
e && (i = {
|
|
@@ -86,7 +86,7 @@ const M = async (n, d, S, P) => {
|
|
|
86
86
|
postal_code: e.postal_code
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
|
-
i && (_ = (await
|
|
89
|
+
i && (_ = (await k(
|
|
90
90
|
c,
|
|
91
91
|
i,
|
|
92
92
|
null,
|
|
@@ -103,7 +103,7 @@ const M = async (n, d, S, P) => {
|
|
|
103
103
|
}
|
|
104
104
|
})));
|
|
105
105
|
try {
|
|
106
|
-
const e = await
|
|
106
|
+
const e = await q.checkout.sessions.create({
|
|
107
107
|
mode: "payment",
|
|
108
108
|
success_url: `${f}/checkout/success?session_id={CHECKOUT_SESSION_ID}`,
|
|
109
109
|
cancel_url: `${f}/`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I=require("@supabase/supabase-js"),d=require("../customer.cjs.js"),C=require("../customer-addresses.cjs.js"),w=require("../order-inventory.cjs.js"),f=require("../order-tax-details.cjs.js"),U=require("../invoice-server.cjs.js"),E=require("./client.cjs.js"),O=["total_details.breakdown"],R=["data.taxes.rate"];function P(){const r=process.env.NEXT_PUBLIC_SUPABASE_URL||process.env.SUPABASE_URL,t=process.env.SUPABASE_SERVICE_ROLE_KEY||process.env.SUPABASE_SECRET_KEY;if(!r||!t)throw new Error("Missing Supabase Service Role environment variables");return I.createClient(r,t,{auth:{autoRefreshToken:!1,persistSession:!1}})}function x(r,t){return r?d.normalizeCustomerAddress({recipient_name:t,line1:r.line1??null,line2:r.line2??null,city:r.city??null,state:r.state??null,postal_code:r.postal_code??null,country_code:r.country??null}):null}function q(r){const t=r??{};return d.normalizeOrderCustomerDetails({email:typeof t.email=="string"?t.email:null,name:typeof t.name=="string"?t.name:null,phone:typeof t.phone=="string"?t.phone:null,billing:t.billing??null,shipping:t.shipping??null})}async function z(r){const t=P();let i=r;try{i=await E.stripe.checkout.sessions.retrieve(r.id,{expand:[...O]})}catch(c){console.error("[Stripe Sync] Failed to rehydrate session tax details:",c)}const u=i.metadata?.orderId;let p=t.from("orders").select("id, user_id, status, total, currency, subtotal, shipping_total, tax_total, tax_details, customer_details").eq("stripe_session_id",r.id).maybeSingle();u&&(p=t.from("orders").select("id, user_id, status, total, currency, subtotal, shipping_total, tax_total, tax_details, customer_details").eq("id",u).maybeSingle());const{data:e,error:m}=await p;if(m||!e)throw new Error(m?.message||"Order lookup failed");const s=q(e.customer_details),n=f.normalizeOrderTaxDetails(e.tax_details),v=x(i.customer_details?.address,i.customer_details?.name??s.name),_=i,A=x(_.shipping_details?.address,_.shipping_details?.name??s.name),o=d.normalizeOrderCustomerDetails({email:i.customer_details?.email??s.email,name:i.customer_details?.name??s.name,phone:i.customer_details?.phone??s.phone,billing:s.billing??v,shipping:s.shipping??A}),T=e.status==="paid",D=await E.stripe.checkout.sessions.listLineItems(i.id,{limit:100,expand:[...R]}),l=f.buildOrderTaxDetailsFromStripeSession({session:i,lineItems:D.data,subtotal:typeof e.subtotal=="number"?e.subtotal:n?.subtotal??0,shippingTotal:typeof e.shipping_total=="number"?e.shipping_total:n?.shipping_total??0,fallbackMode:n?.mode??"automatic",currency:(i.currency??e.currency??n?.currency??"USD").toUpperCase()}),a=l.tax_total>0||l.lines.length>0?l:n??l,y=a?.tax_total??(typeof e.tax_total=="number"?e.tax_total:0),S=(i.currency??e.currency??a?.currency??"USD").toUpperCase(),g={status:"paid",stripe_session_id:i.id,payment_intent_id:typeof i.payment_intent=="string"?i.payment_intent:null,provider:"stripe",customer_details:o,total:typeof i.amount_total=="number"?i.amount_total:e.total,currency:S,tax_total:y,tax_details:a},{error:h}=await t.from("orders").update(g).eq("id",e.id);if(h)throw new Error(h.message);if(e.user_id)try{await C.upsertDefaultUserAddresses({userId:e.user_id,billingAddress:o.billing,shippingAddress:o.shipping,client:t})}catch(c){console.error("[Stripe Sync] Failed to refresh saved customer addresses:",c)}const b=await U.assignInvoiceMetadata({orderId:e.id,client:t});return await w.applyOrderInventoryDeduction(t,e.id),{orderId:e.id,alreadyPaid:T,customerDetails:o,order:{id:e.id,invoice_number:b.invoiceNumber,paid_at:b.paidAt,total:g.total,currency:S,subtotal:typeof e.subtotal=="number"?e.subtotal:a?.subtotal??0,shipping_total:typeof e.shipping_total=="number"?e.shipping_total:a?.shipping_total??0,tax_total:y,tax_details:a}}}exports.syncStripeOrderFromSession=z;
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { createClient as
|
|
2
|
-
import { normalizeOrderCustomerDetails as
|
|
3
|
-
import { upsertDefaultUserAddresses as
|
|
4
|
-
import { applyOrderInventoryDeduction as
|
|
1
|
+
import { createClient as D } from "@supabase/supabase-js";
|
|
2
|
+
import { normalizeOrderCustomerDetails as E, normalizeCustomerAddress as I } from "../customer.es.js";
|
|
3
|
+
import { upsertDefaultUserAddresses as C } from "../customer-addresses.es.js";
|
|
4
|
+
import { applyOrderInventoryDeduction as w } from "../order-inventory.es.js";
|
|
5
5
|
import { normalizeOrderTaxDetails as U, buildOrderTaxDetailsFromStripeSession as R } from "../order-tax-details.es.js";
|
|
6
|
-
import { assignInvoiceMetadata as
|
|
7
|
-
import { stripe as
|
|
8
|
-
const
|
|
6
|
+
import { assignInvoiceMetadata as P } from "../invoice-server.es.js";
|
|
7
|
+
import { stripe as h } from "./client.es.js";
|
|
8
|
+
const O = ["total_details.breakdown"], z = ["data.taxes.rate"];
|
|
9
9
|
function k() {
|
|
10
|
-
const r = process.env.NEXT_PUBLIC_SUPABASE_URL, t = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
|
10
|
+
const r = process.env.NEXT_PUBLIC_SUPABASE_URL || process.env.SUPABASE_URL, t = process.env.SUPABASE_SERVICE_ROLE_KEY || process.env.SUPABASE_SECRET_KEY;
|
|
11
11
|
if (!r || !t)
|
|
12
12
|
throw new Error("Missing Supabase Service Role environment variables");
|
|
13
|
-
return
|
|
13
|
+
return D(r, t, {
|
|
14
14
|
auth: {
|
|
15
15
|
autoRefreshToken: !1,
|
|
16
16
|
persistSession: !1
|
|
17
17
|
}
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
|
-
function
|
|
21
|
-
return r ?
|
|
20
|
+
function b(r, t) {
|
|
21
|
+
return r ? I({
|
|
22
22
|
recipient_name: t,
|
|
23
23
|
line1: r.line1 ?? null,
|
|
24
24
|
line2: r.line2 ?? null,
|
|
@@ -28,9 +28,9 @@ function S(r, t) {
|
|
|
28
28
|
country_code: r.country ?? null
|
|
29
29
|
}) : null;
|
|
30
30
|
}
|
|
31
|
-
function
|
|
31
|
+
function B(r) {
|
|
32
32
|
const t = r ?? {};
|
|
33
|
-
return
|
|
33
|
+
return E({
|
|
34
34
|
email: typeof t.email == "string" ? t.email : null,
|
|
35
35
|
name: typeof t.name == "string" ? t.name : null,
|
|
36
36
|
phone: typeof t.phone == "string" ? t.phone : null,
|
|
@@ -42,8 +42,8 @@ async function H(r) {
|
|
|
42
42
|
const t = k();
|
|
43
43
|
let i = r;
|
|
44
44
|
try {
|
|
45
|
-
i = await
|
|
46
|
-
expand: [...
|
|
45
|
+
i = await h.checkout.sessions.retrieve(r.id, {
|
|
46
|
+
expand: [...O]
|
|
47
47
|
});
|
|
48
48
|
} catch (d) {
|
|
49
49
|
console.error("[Stripe Sync] Failed to rehydrate session tax details:", d);
|
|
@@ -58,29 +58,29 @@ async function H(r) {
|
|
|
58
58
|
const { data: e, error: u } = await c;
|
|
59
59
|
if (u || !e)
|
|
60
60
|
throw new Error(u?.message || "Order lookup failed");
|
|
61
|
-
const
|
|
61
|
+
const s = B(e.customer_details), o = U(e.tax_details), x = b(
|
|
62
62
|
i.customer_details?.address,
|
|
63
|
-
i.customer_details?.name ??
|
|
64
|
-
), m = i,
|
|
63
|
+
i.customer_details?.name ?? s.name
|
|
64
|
+
), m = i, A = b(
|
|
65
65
|
m.shipping_details?.address,
|
|
66
|
-
m.shipping_details?.name ??
|
|
67
|
-
), n =
|
|
68
|
-
email: i.customer_details?.email ??
|
|
69
|
-
name: i.customer_details?.name ??
|
|
70
|
-
phone: i.customer_details?.phone ??
|
|
71
|
-
billing:
|
|
72
|
-
shipping:
|
|
73
|
-
}),
|
|
66
|
+
m.shipping_details?.name ?? s.name
|
|
67
|
+
), n = E({
|
|
68
|
+
email: i.customer_details?.email ?? s.email,
|
|
69
|
+
name: i.customer_details?.name ?? s.name,
|
|
70
|
+
phone: i.customer_details?.phone ?? s.phone,
|
|
71
|
+
billing: s.billing ?? x,
|
|
72
|
+
shipping: s.shipping ?? A
|
|
73
|
+
}), T = e.status === "paid", v = await h.checkout.sessions.listLineItems(i.id, {
|
|
74
74
|
limit: 100,
|
|
75
75
|
expand: [...z]
|
|
76
76
|
}), l = R({
|
|
77
77
|
session: i,
|
|
78
|
-
lineItems:
|
|
78
|
+
lineItems: v.data,
|
|
79
79
|
subtotal: typeof e.subtotal == "number" ? e.subtotal : o?.subtotal ?? 0,
|
|
80
80
|
shippingTotal: typeof e.shipping_total == "number" ? e.shipping_total : o?.shipping_total ?? 0,
|
|
81
81
|
fallbackMode: o?.mode ?? "automatic",
|
|
82
82
|
currency: (i.currency ?? e.currency ?? o?.currency ?? "USD").toUpperCase()
|
|
83
|
-
}),
|
|
83
|
+
}), a = l.tax_total > 0 || l.lines.length > 0 ? l : o ?? l, _ = a?.tax_total ?? (typeof e.tax_total == "number" ? e.tax_total : 0), y = (i.currency ?? e.currency ?? a?.currency ?? "USD").toUpperCase(), f = {
|
|
84
84
|
status: "paid",
|
|
85
85
|
stripe_session_id: i.id,
|
|
86
86
|
payment_intent_id: typeof i.payment_intent == "string" ? i.payment_intent : null,
|
|
@@ -89,13 +89,13 @@ async function H(r) {
|
|
|
89
89
|
total: typeof i.amount_total == "number" ? i.amount_total : e.total,
|
|
90
90
|
currency: y,
|
|
91
91
|
tax_total: _,
|
|
92
|
-
tax_details:
|
|
92
|
+
tax_details: a
|
|
93
93
|
}, { error: g } = await t.from("orders").update(f).eq("id", e.id);
|
|
94
94
|
if (g)
|
|
95
95
|
throw new Error(g.message);
|
|
96
96
|
if (e.user_id)
|
|
97
97
|
try {
|
|
98
|
-
await
|
|
98
|
+
await C({
|
|
99
99
|
userId: e.user_id,
|
|
100
100
|
billingAddress: n.billing,
|
|
101
101
|
shippingAddress: n.shipping,
|
|
@@ -104,24 +104,24 @@ async function H(r) {
|
|
|
104
104
|
} catch (d) {
|
|
105
105
|
console.error("[Stripe Sync] Failed to refresh saved customer addresses:", d);
|
|
106
106
|
}
|
|
107
|
-
const
|
|
107
|
+
const S = await P({
|
|
108
108
|
orderId: e.id,
|
|
109
109
|
client: t
|
|
110
110
|
});
|
|
111
|
-
return await
|
|
111
|
+
return await w(t, e.id), {
|
|
112
112
|
orderId: e.id,
|
|
113
|
-
alreadyPaid:
|
|
113
|
+
alreadyPaid: T,
|
|
114
114
|
customerDetails: n,
|
|
115
115
|
order: {
|
|
116
116
|
id: e.id,
|
|
117
|
-
invoice_number:
|
|
118
|
-
paid_at:
|
|
117
|
+
invoice_number: S.invoiceNumber,
|
|
118
|
+
paid_at: S.paidAt,
|
|
119
119
|
total: f.total,
|
|
120
120
|
currency: y,
|
|
121
|
-
subtotal: typeof e.subtotal == "number" ? e.subtotal :
|
|
122
|
-
shipping_total: typeof e.shipping_total == "number" ? e.shipping_total :
|
|
121
|
+
subtotal: typeof e.subtotal == "number" ? e.subtotal : a?.subtotal ?? 0,
|
|
122
|
+
shipping_total: typeof e.shipping_total == "number" ? e.shipping_total : a?.shipping_total ?? 0,
|
|
123
123
|
tax_total: _,
|
|
124
|
-
tax_details:
|
|
124
|
+
tax_details: a
|
|
125
125
|
}
|
|
126
126
|
};
|
|
127
127
|
}
|