(function(){ class SPZCustomSubscribeList extends SPZ.BaseElement { trackMode = 1; trackProductId = undefined; mounting = false; marketActivitieIds = new Set(); constructor(element) { super(element); this.subscribeList = []; this.paymentSettings = null; } isLayoutSupported(layout) { return layout === SPZCore.Layout.CONTAINER; } setMarketActivitieIds(marketActivities) { const set = new Set(); if(marketActivities && marketActivities.length > 0){ marketActivities.forEach(item=> set.add(item.entitled_product_ids?.[0])); this.marketActivitieIds = set; } } buildCallback() { this.registerAction('onRender', (invocation) => { this.fixHandleChange(); this.handleConfirm(); this.setMarketActivitieIds(invocation?.args?.data?.data?.market_activities || []); const data = invocation?.args?.data?.data || {}; this.listData = invocation?.args?.data?.data || []; this.refreshSubscribeList(data); setTimeout(()=>{ this.preloadAbandonImg(); }, 100); }); this.registerAction('track', (invocation) => { if ('currentVideoPlayer' in window) { this.trackMode = 2; this.trackProductId = window.currentVideoPlayer.getCurrentVideoId(); } else { this.trackMode = 1; this.trackProductId = undefined; } this.trackViewContent(); setTimeout(()=>{ this.trackImpression(); }, 2000); }); this.registerAction('onCloseClick', () => { this.onCloseClick(); }); this.registerAction('onOpen', () => { const list = document.querySelector('#subscribe_list_render .subscribe_list'); if(list){ list.scrollTo(0,0); if (!this.paymentSettings || !this.mounting) { this.renderECList(); } } }); this.registerAction('storeData', (invocation) => { window.shortSellingType = invocation?.args?.data?.data?.selling_type; }); } async getPaymentSettings() { try { const res = await fetch("/apps/bs-pay/api/v1/checkout/payment/setting"); const data = await res.json(); return data; } catch (error) { console.error('[getPaymentSettings] error', error); return undefined; } finally { const confirm = document.querySelector('#subscribe_lightbox .confirm'); if(confirm){ confirm.style.pointerEvents = 'auto'; } } } async renderECList(isFirst) { const domSelector = { ...(isFirst ? { paypal: "#payment-ec-paypal-container" } : {}), apple: "#payment-ec-applepay-container", google: "#payment-ec-googlepay-container", } const checked = document.querySelector('#subscribe_lightbox .subscribe_list .item-checked'); const pid = checked?.dataset?.pid; const vid = checked?.dataset?.vid; const price = checked?.dataset?.price; const name = checked?.dataset?.name; const cycleDays = +checked?.dataset?.days; const listItem = this.subscribeList.find(ele=>ele.id === pid); const sellingPlanOptionId = listItem.selling_plan_info.selected_selling_plan_option_id; const lineItem = { variant_id: vid, product_id: pid, product_title: name, price, selling_plan_option_id: sellingPlanOptionId, cycle_days: cycleDays, }; window.shortLineItem = lineItem; this.mounting = true; window.BSPublicJSReady(() => { window.mountBSECPayment(domSelector, this.paymentSettings, lineItem, { onConfirm: () => { this.showLoading(); }, onFinish: () => { this.hideLoading(); }, onError: () => { this.hideLoading(); }, onCancel: () => { this.hideLoading(); }, onInit: (channel) => { this.hideLoading(); } }).then(() => { this.hideLoading(); this.mounting = false; }).catch((err) => { this.hideLoading(); this.mounting = false; }); }); } preloadAbandonImg() { const abandonLogic = document.getElementById('subscribe_ab_discount_logic'); const activities = this.getAbandonActivities(); if (!abandonLogic || !activities) return; SPZ.whenApiDefined(abandonLogic).then((apis) =>{ activities.forEach(activity => { apis.preloadImg(activity); }); }); } async refreshSubscribeList(data){ const plans = data.subscribe_plans || []; const info = data.selling_plan_info || {}; const items = data.line_items || []; const mergedPlans = plans.map(plan=>{ let finalPrice = plan.price; const discount = info[plan.id] || {}; const item = items.find(i=>i.product_id === plan.id); finalPrice = item?.final_line_price; return { ...plan, final_price: finalPrice, selling_plan_info: discount } }); this.subscribeList = mergedPlans; this.paymentSettings = await this.getPaymentSettings(); this.renderECList(true); this.updatePlayerSubscribeData(); } getAbandonActivities() { const marketActivities = this.listData?.market_activities; if (!marketActivities || !Array.isArray(marketActivities)) { return []; } const abandonActivities = []; marketActivities.forEach(marketActivity => { const abandonActivityId = marketActivity?.entitled_product_ids?.[0]; if (abandonActivityId) { const subscribePlan = this.listData.subscribe_plans?.find(ele => ele.id == abandonActivityId); if (!subscribePlan) return; if (!this.listData.line_items) return; const item = this.listData.line_items.find(ele => ele.product_id == abandonActivityId) || {}; const info = this.subscribeList.find(ele => ele.id == abandonActivityId); const config = marketActivity?.config; const sellingPlan = this.listData?.selling_plan_info?.[abandonActivityId]; const sellingPlanId = sellingPlan?.selling_plan_options?.[0]?.selling_plan_option_id; const abandonActivity = { ...item, ...info, config, _selling_plan_option_id: sellingPlanId }; abandonActivities.push(abandonActivity); } }); return abandonActivities; } onCloseClick(){ const listBox = document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(listBox).then(apis=>{ apis.close(); }) const abandonActivities = this.getAbandonActivities(); const abandonLogic = document.querySelector('#subscribe_ab_discount_logic'); SPZ.whenApiDefined(abandonLogic).then(async (apis)=>{ await apis.startModalSequence(abandonActivities); }); } trackImpression() { window.csTracker.track('function_expose', { event_name: 'function_expose', event_type: 'popup_expose', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), mode: this.trackMode, product_id: this.trackProductId, }), }, ['sa']); /* 需要排除掉支付挽留,默认第二个 */ let showList = this.listData?.subscribe_plans || []; const line_items = this.listData?.line_items || []; if(this.marketActivitieIds.size > 0){ showList = showList.filter(item=>!this.marketActivitieIds.has(item.id)); } showList = showList.filter(item=> +line_items?.find(ele=>ele?.product_id === item?.id)?.final_line_price > 0); let defaultItem = showList?.[0]; if(showList.length > 1){ defaultItem = showList?.[1]; } const checkedItemDOM = document.querySelector('#subscribe_lightbox .item-wrapper.item-checked'); const checkedProductId = checkedItemDOM?.dataset?.pid; const defaultLineItem = line_items.find(ele=>ele.product_id === checkedProductId) || {}; defaultItem = { ...defaultItem, ...defaultLineItem } if(defaultItem){ this.pureTrackAddToCart({ id: defaultItem.id, title: defaultItem.title, price: defaultItem.final_line_price, variant_id: defaultItem.variant_id, }); } window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), mode: this.trackMode, opt_type: 5, product_id: this.trackProductId, plan_id: defaultItem.id, }), }, ['sa']); if(location.pathname.includes('/products/')){ window.sa.track('add_to_cart', { product_id: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10", product_title: "Conflicted Hearts", price: "0", variant_id: window.currentVideoPlayer.getCurrentEpisodeId(), quantity: 1, sku_quantity: 1, entrance: 'product', currency: window.C_SETTINGS.currency_code, }); const gtagAdsCountry = "shoplaza_" + (window.ADS_COUNTRY || "US") + "_"; const variantId = window.currentVideoPlayer.getCurrentEpisodeId(); const trackId = gtagAdsCountry + variantId; window.csTracker.track('add_to_cart', { currency: window.C_SETTINGS.currency_code, value: "0", name: "Conflicted Hearts", user_id: window.csTracker.getClientId(), items: [ { id: trackId, item_id: trackId, item_name: "Conflicted Hearts", item_list_name: 'product', item_brand: "", item_category: "", item_variant: window.currentVideoPlayer.getCurrentEpisode().no.toString(), price: "0", quantity: 1, google_business_vertical: 'retail', } ] }, ['ga']); } } trackViewContent(){ let showlist = this.subscribeList.slice(); if(this.marketActivitieIds.size > 0){ showlist = showlist.filter(item=>!this.marketActivitieIds.has(item.id)); } showlist = showlist.filter(ele=>!!ele.final_price); const maxCount = Number("4") || 4; showlist = showlist.slice(0,maxCount); showlist.forEach(item=>{ window.csTracker.track('ViewContent', { name: item.title, id: item.variant_id, content_ids: [item.variant_id], content_name: item.title, num_items: 1, currency: window.C_SETTINGS.currency_code, value: item.final_price }, ['fb']); }); /* 套餐曝光 */ const product_ids = showlist.map(item=>item.id); window.csTracker.track('function_expose', { event_name: 'function_expose', event_type: 'expose', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), product_ids, expose_type: 2, }), }, ['sa']); } pureTrackAddToCart(item) { document.dispatchEvent(new CustomEvent('dj.addToCart', { detail: { event_time: new Date().getTime(), product_id: item.id, name: item.title, item_price: item.price, variant_id: item.variant_id, variant: { option1: item.title, }, quantity: '1', number: '1' } })); } /* 上报 initiateCheckRate */ trackOrder(name, pid){ window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), opt_type: 1, mode: this.trackMode, product_id: this.trackProductId, }), }, ['sa']); } showLoading(){ const loading = document.querySelector('#subscribe_loading'); SPZ.whenApiDefined(loading).then(apis=>{ apis.show_(); }) } hideLoading(){ const loading = document.querySelector('#subscribe_loading'); SPZ.whenApiDefined(loading).then(apis=>{ apis.close_(); }) } mountCallback() { const listRender = document.querySelector('#subscribe_list_render'); SPZ.whenApiDefined(listRender).then(apis=>{ apis.render(); }); } fixHandleChange(){ const list = document.querySelectorAll('#subscribe_lightbox .subscribe_list .item-wrapper'); list.forEach(item => { item.onclick = () => { const checkedItem = document.querySelector('.subscribe_list .item-checked'); if(item.dataset.pid == checkedItem.dataset.pid){ return; } const list = document.querySelectorAll('#subscribe_lightbox .subscribe_list .item-wrapper'); list.forEach(item=>{ item.classList.remove('item-checked')}) item.classList.add('item-checked'); const listItem = this.subscribeList.find(ele=>ele.id === item.dataset.pid); this.renderECList(); // GPay APay 刷新 this.pureTrackAddToCart({ id: listItem.id, title: listItem.title, price: listItem.final_price, variant_id: listItem.variant_id, }); window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), mode: this.trackMode, opt_type: 5, product_id: this.trackProductId, plan_id: listItem.id, }), }, ['sa']); } }) } getCookie(name) { // 创建正则表达式来匹配指定名称的 Cookie const regex = new RegExp('(^|; )' + encodeURIComponent(name) + '=([^;]*)'); const match = document.cookie.match(regex); // 如果找到匹配项,则返回解码后的值,否则返回 null return match ? decodeURIComponent(match[2]) : null; } handleConfirm(){ const skit_uid = this.getCookie('skit-uid'); const confirm = document.querySelector('#subscribe_lightbox .confirm'); confirm.onclick = async()=>{ document.dispatchEvent(new CustomEvent('dj.checkoutSubmit', { detail: {} })); this.showLoading(); const checked = document.querySelector('#subscribe_lightbox .subscribe_list .item-checked'); const pid = checked.dataset.pid; const vid = checked.dataset.vid; const name = checked.dataset.name; const cycleDays = +checked.dataset.days; let userEmail = ''; let lastName = ''; try{ await fetch(location.origin+'/api/customers/show').then(res=>res.json()).then(res=>{ if(res && res.customer && res.customer.id){ userEmail = res.customer.email; lastName = res.customer.last_name; localStorage.setItem('CUSTOMER_INFO', JSON.stringify(res.customer)); }else{ localStorage.removeItem('CUSTOMER_INFO'); } }) }catch(e){ console.error('[customer-show]', e) } window._local_id_email = userEmail; window._local_last_name = lastName; window._disable_show_agree = true; let params = { _best_short_uid: skit_uid }; params['_dj_selling_type'] = window.shortSellingType; params['cycle_days'] = cycleDays; const listItem = this.subscribeList.find(ele => ele.id == pid); if (window.shortSellingType === 'DJ') { params['_selling_plan_dj_option_id'] = listItem.selling_plan_info.selected_selling_plan_option_id; } else { params['_selling_plan_option_id'] = listItem.selling_plan_info.selected_selling_plan_option_id; } params['link'] = location.href; params['entry'] = 'page'; params['short_id'] = ''; params['_sa_track_params'] = window.sa?.trackParams; params['_is_login'] = !!window.C_SETTINGS?.customer?.customer_id; if(location.pathname.includes('/products/')){ params['entry'] = 'product'; params['short_id'] = window.currentVideoPlayer.getCurrentVideoId(); params['short_title'] = "Conflicted Hearts" || ''; params['short_variant_id'] = window.currentVideoPlayer?.getCurrentEpisodeId?.() || ''; } const referrer = decodeURIComponent(this.getCookie('latest_referrer') || ''); if(referrer){ const referrerHost = new URL(referrer).hostname; params["_ad_from"] = referrerHost; } fetch(`${location.origin}/apps/bs-pay/api/v1/checkout/order`, { method: 'POST', headers:{ "Content-Type": "application/json" }, body: JSON.stringify({ line_items: [{quantity:"1", product_id: pid, properties: params, note:"",variant_id:vid }], refer_info: { source :"buy_now", create_identity: btoa(window.C_SETTINGS.shop.shop_id)}, options: { with_uid: true, selling_type: window.shortSellingType } }) }) .then(response => response.json()) .then(res=>{ if(res && res.check_out_url){ const lightbox = document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(lightbox).then((box)=>{ localStorage.setItem('COMMON_NAMESPACE', window.SHOPLAZZA.namespace); localStorage.setItem('BS_PREV_URL', location.href); localStorage.setItem('SHOP_ID', window.C_SETTINGS.shop.shop_id); window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), mode: this.trackMode, opt_type: 1, product_id: this.trackProductId, plan_id: pid }), }, ['sa']); let orderId = ''; if (res && res.check_out_url) { const match = res.check_out_url.match(/\/order\/(\d+)/); if (match && match[1]) { orderId = `/order/${match[1]}`; } } document.dispatchEvent(new CustomEvent('dj.initiateCheckout', { detail: { id: orderId, checkout_page_type: 'single', order_id: orderId, currency: window.C_SETTINGS.currency_code, quantity: '1', line_items: [{ product_id: pid, variant_id: vid, quantity: 1, properties: params, }], prices: { total_price: this.subscribeList.find(item => item.id === pid).final_price, } } })); if(location.pathname.includes('/products/')){ window.sa.track('begin_checkout', { product_id: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10", product_title: "Conflicted Hearts", price: "0", variant_id: window.currentVideoPlayer.getCurrentEpisodeId(), quantity: 1, sku_quantity: 1, entrance: 'product', currency: window.C_SETTINGS.currency_code, content_ids: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10" }); const gtagAdsCountry = "shoplaza_" + (window.ADS_COUNTRY || "US") + "_"; const variantId = window.currentVideoPlayer.getCurrentEpisodeId(); const trackId = gtagAdsCountry + variantId; window.csTracker.track('begin_checkout', { name: "Conflicted Hearts", value: "0", coupon: "", currency: window.C_SETTINGS.currency_code, user_id: window.csTracker.getClientId(), item_id: trackId, items:{ id: trackId, item_id: trackId, item_name: "Conflicted Hearts", item_brand: "", item_category: "", item_variant: window.currentVideoPlayer.getCurrentEpisode().no.toString(), price: "0", quantity:1, google_business_vertical: "retail", } }, ['ga']); } this.hideLoading(); const blockOr = this.paymentSettings?.settings?.express_checkout_config?.express_channels?.join(','); const url = blockOr ? `${res.check_out_url}?block_or=${blockOr}&select_payment_method=shoplazzapayment` : `${res.check_out_url}?select_payment_method=shoplazzapayment`; setTimeout(()=>{ location.href = url; }); }); }else{ if(res.message || res.error){ window.customToast(res.message || res.error,'error'); }else{ window.customToast('Order failed','error'); } this.hideLoading(); } }).catch((error)=>{ console.error('[error-fetch]', error); this.hideLoading(); }) } } updatePlayerSubscribeData() { if (!window.BSPlayerMountReady) return; window.BSPlayerMountReady(() => { if (!window.currentVideoPlayer) return; const marketActivities = this.listData?.market_activities; let filteredList = this.subscribeList; if(marketActivities && marketActivities.length > 0){ const set = new Set(); marketActivities.forEach(item=> set.add(item.entitled_product_ids?.[0])); filteredList = this.subscribeList.filter(item=>!set.has(item.id)); } filteredList = filteredList.filter(item=> !!item.final_price); const maxCount = Number("4") || 4; filteredList = filteredList.slice(0, maxCount); window.currentVideoPlayer.setSubscriptionData(filteredList); }); } } SPZ.defineElement('spz-custom-subscribe-list', SPZCustomSubscribeList); })() (function(){ class SPZCustomSubscribeSubscript extends SPZ.BaseElement { constructor(element) { super(element); this.payResult = null; } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.registerAction('showsubscript', () => { this.showSubscript(); }); } async showSubscript(){ const listItems = document.querySelectorAll('.subscribe_list .item-wrapper:not(:has(.custom_subscript_item))'); if(listItems.length<=0) return; const productIds = []; listItems.forEach(ele=>{ productIds.push(ele.getAttribute('data-pid')); }); if(productIds.length==0) return; let result = []; try{ const res = await fetch(location.origin+"/apps/best-short/api/v1/subscript", { method:"POST", body: JSON.stringify({ type:'subscription', resource_ids: productIds })}) .then(res=>res.json()); result = res?.data || []; }catch(e){ console.warn('[subscript get error]', e); } result.forEach(ele=>{ const index = productIds.indexOf(ele.id); if(index>=0 && ele.styles?.length>0){ const listItem = listItems[index]; ele.styles.forEach(style=>{ const _item = document.createElement('div'); _item.classList.add('custom_subscript_item'); _item.classList.add('custom_position_'+style.position); _item.classList.add(style.icon); const _span = document.createElement('span'); _span.classList.add('custom_subscript_item_text'); _span.innerHTML = style.content; _item.appendChild(_span); listItem.appendChild(_item.cloneNode(true)); }) } }) } } SPZ.defineElement('spz-custom-subscribe-subscript', SPZCustomSubscribeSubscript); })() (function(){ class SPZCustomAbandonDiscount extends SPZ.BaseElement { currentModalPromise = null; trackMode = 1; trackProductId = undefined; paymentSettings = null; ecMounted = false; ecMounting = false; ecDomSelector = { apple: '#bs-abandon-ec-shoplazza-apple-pay', google: '#bs-abandon-ec-shoplazza-google-pay', paypal: '#bs-abandon-ec-paypal', }; lastECLineItem = null; activeChannelInited = false; optionTouched = false; constructor(element) { super(element); this.activity = null; } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } getCookie(name) { // 创建正则表达式来匹配指定名称的 Cookie const regex = new RegExp('(^|; )' + encodeURIComponent(name) + '=([^;]*)'); const match = document.cookie.match(regex); // 如果找到匹配项,则返回解码后的值,否则返回 null return match ? decodeURIComponent(match[2]) : null; } async startModalSequence(abandonActivities) { for (let i = 0; i < abandonActivities.length; i++) { const activity = abandonActivities[i]; await this.showModal(activity, i); // 添加延迟效果 if (i < abandonActivities.length - 1) { await new Promise(resolve => setTimeout(resolve, 300)); } } } showModal(activity, index) { return new Promise((resolve) => { const abandonBox = document.querySelector('#subscribe_ab_dis_box'); if(abandonBox){ index===1 ? abandonBox.classList.add('second') : abandonBox.classList.remove('second'); } this.renderContent(activity); this.pureTrackAddToCart(activity); SPZ.whenApiDefined(abandonBox).then(apis=>{ apis.open(); }); this.currentModalPromise = resolve; }); } closeModal() { console.log('closeModal:'); if (this.currentModalPromise) { this.currentModalPromise(); this.currentModalPromise = null; } } pureTrackAddToCart(item) { const subscribeLogic = document.querySelector('#subscribe_list_logic'); SPZ.whenApiDefined(subscribeLogic).then(apis=>{ apis.pureTrackAddToCart(item); }); } buildCallback(){ this.registerAction('onPayNow', (invocation) => { this.onPayNow(); }); this.registerAction('onOpen', (invocation) => { this.onOpen(); if (window.currentVideoPlayer) { window.currentVideoPlayer.toggleGestureDisabled(true); } }); this.registerAction('onClose', (invocation) => { this.closeModal(); if (window.currentVideoPlayer) { window.currentVideoPlayer.toggleGestureDisabled(false); } }); this.registerAction('refreshEC', (invocation) => { this.renderECList(this.activity); }); if ('currentVideoPlayer' in window) { this.trackMode = 2; this.trackProductId = window.currentVideoPlayer.getCurrentVideoId(); } else { this.trackMode = 1; this.trackProductId = undefined; } } onOpen(){ window.csTracker.track('function_expose', { event_name: 'function_expose', event_type: 'expose', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), product_ids: [this.activity?.product_id], expose_type: 2 }), }, ['sa']); window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), mode: this.trackMode, opt_type: 5, product_id: this.trackProductId, plan_id: this.activity?.product_id }), }, ['sa']); } getCircleDays(data) { if (!data) return 0; let result = 0; if (data.interval === 'day') { result = +data.interval_count; } else if (data.interval === 'month') { result = +data.interval_count * 30; } else if (data.interval === 'week') { result = +data.interval_count * 7; } else if (data.interval === 'year') { result = +data.interval_count * 365; } return result; } async onPayNow(){ if (!this.activity) return; const pid = this.activity.product_id; const vid = this.activity.variant_id; const name = this.activity.product_title; let userEmail = ''; let lastName = ''; await this.updateLoading(true); try{ await fetch(location.origin+'/api/customers/show').then(res=>res.json()).then(res=>{ if(res && res.customer && res.customer.id){ userEmail = res.customer.email; lastName = res.customer.last_name; localStorage.setItem('CUSTOMER_INFO', JSON.stringify(res.customer)); }else{ localStorage.removeItem('CUSTOMER_INFO'); } }) }catch(e){ console.error('[customer-show]', e); await this.updateLoading(false); } window._local_id_email = userEmail; window._local_last_name = lastName; window._disable_show_agree = true; const skit_uid = this.getCookie('skit-uid'); let params = { _best_short_uid: skit_uid }; const circleDays = this.getCircleDays(this.activity?.selling_plan_info?.selling_plan_options?.[0]); params['_dj_selling_type'] = window.shortSellingType; params['cycle_days'] = circleDays; if (window.shortSellingType === 'DJ') { params['_selling_plan_dj_option_id'] = this.activity._selling_plan_option_id; } else { params['_selling_plan_option_id'] = this.activity._selling_plan_option_id; } params['link'] = location.href; params['entry'] = 'page'; params['short_id'] = ''; params['_sa_track_params'] = window.sa.trackParams; if(location.pathname.includes('/products/')){ params['entry'] = 'product'; params['short_id'] = window.currentVideoPlayer.getCurrentVideoId(); params['short_title'] = "Conflicted Hearts" || ''; params['short_variant_id'] = window.currentVideoPlayer?.getCurrentEpisodeId?.() || ''; } const referrer = decodeURIComponent(this.getCookie('latest_referrer') || ''); if(referrer){ const referrerHost = new URL(referrer).hostname; params["_ad_from"] = referrerHost; } fetch(`${location.origin}/apps/bs-pay/api/v1/checkout/order`, { method: 'POST', headers:{ "Content-Type": "application/json" }, body: JSON.stringify({ line_items: [{quantity:"1", product_id: pid, properties: params, note:"",variant_id:vid }], refer_info: { source :"buy_now", create_identity: btoa(window.C_SETTINGS.shop.shop_id)}, options: { with_uid: true, selling_type: window.shortSellingType } }) }) .then(response => response.json()) .then(async (res) =>{ if(res && res.check_out_url){ const lightbox = document.querySelector('#subscribe_ab_dis_box'); SPZ.whenApiDefined(lightbox).then(async (box)=>{ box.close(); localStorage.setItem('COMMON_NAMESPACE', window.SHOPLAZZA.namespace); localStorage.setItem('BS_PREV_URL', location.href); localStorage.setItem('SHOP_ID', window.C_SETTINGS.shop.shop_id); window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), mode: this.trackMode, opt_type: 1, product_id: window.currentVideoPlayer?.getCurrentVideoId?.(), plan_id: this.activity?.product_id }), }, ['sa']); let orderId = ''; if (res && res.check_out_url) { const match = res.check_out_url.match(/\/order\/(\d+)/); if (match && match[1]) { orderId = `/order/${match[1]}`; } } document.dispatchEvent(new CustomEvent('dj.initiateCheckout', { detail: { checkout_page_type: 'single', order_id: orderId, id: orderId, currency: window.C_SETTINGS.currency_code, quantity: '1', line_items: [{ product_id: pid, variant_id: vid, quantity: 1, properties: params, }], prices: { total_price: this.activity.final_line_price, } } })); await this.updateLoading(false); const blockOr = this.paymentSettings?.settings?.express_checkout_config?.express_channels?.join(','); const url = blockOr ? `${res.check_out_url}?block_or=${blockOr}&select_payment_method=shoplazzapayment` : `${res.check_out_url}?select_payment_method=shoplazzapayment`; setTimeout(()=>{ location.href = url; }); }); }else{ console.error('[order-error]', res); if(res.message || res.error){ window.customToast(res.message || res.error,'error'); }else{ window.customToast('Order failed','error'); } await this.updateLoading(false); } }).catch(async (error) => { console.error('[error-fetch]', error); await this.updateLoading(false); }) } /* 上报 initiateCheckRate */ trackOrder(name, pid){ /* window.csTracker.track('initiateCheck', { name: name, id: pid }, ['ga','fb']); */ window.csTracker.track('function_click', { event_name: 'function_click', event_type: 'click', event_info: JSON.stringify({ skit_user_id: window.csTracker.getSkitUid(), opt_type: 1, mode: this.trackMode, product_id: this.trackProductId, }), }, ['sa']); } async refreshPaymentSettings() { if (this.paymentSettings) { return this.paymentSettings; } try { const res = await fetch("/apps/bs-pay/api/v1/checkout/payment/setting"); const data = await res.json(); this.paymentSettings = data; return data; } catch (error) { console.error('[refreshPaymentSettings] error', error); return; } finally { const confirm = document.querySelector('#subscribe_ab_dis_box #bs-abandon-ec-credit-card'); if(confirm){ confirm.style.pointerEvents = 'auto'; } } } updateLoading(show) { const loadingDom = document.querySelector('#subscribe_ab_dis_box_loading'); return SPZ.whenApiDefined(loadingDom).then(apis=>{ if (show) { apis.show_(); } else { apis.close_(); } }); } setInitActiveChannel(visibleTabs) { let visibleTabId = 'credit-card'; if (visibleTabs.length > 0) { visibleTabId = visibleTabs[0]; } const tabsDom = document.querySelector('#subscribe_ab_dis_box_tabs'); if (!tabsDom) { return; } tabsDom.classList.add('show'); document.querySelectorAll('#subscribe_ab_dis_box_tabs li[data-panel]').forEach(dom => { if (visibleTabId === dom.dataset.panel) { dom.classList.add('active'); } else { dom.classList.remove('active'); } }); document.querySelectorAll('#subscribe_ab_dis_box_tabs li[data-id]').forEach(dom => { if (visibleTabId === dom.dataset.id) { dom.classList.remove('hidden'); } else { dom.classList.add('hidden'); } }); } hideUnsupportedPayments() { const domSelector = { "credit-card": '#bs-abandon-ec-credit-card', apple: '#bs-abandon-ec-shoplazza-apple-pay .bs-shoplazza-ec-content', google: '#bs-abandon-ec-shoplazza-google-pay .bs-shoplazza-ec-content', paypal: '#bs-abandon-ec-paypal', }; // 定义优先级映射,数字越小优先级越高 const priorityMap = { 'apple': 1, 'credit-card': 2, 'paypal': 3, 'google': 4 }; const originalOrder = { 'apple': 0, 'credit-card': 1, 'paypal': 2, 'google': 3 }; const selectorArr = ['apple','credit-card','paypal','google'].sort((a, b) => { const priorityDiff = priorityMap[a] - priorityMap[b]; // 如果优先级相同,则按原始顺序排序 return priorityDiff !== 0 ? priorityDiff : originalOrder[a] - originalOrder[b]; }); const visibleTabs = []; selectorArr.forEach(key => { const dom = document.querySelector(domSelector[key]); if(dom && dom.children.length !== 0) { const targetTab = document.querySelector(`#subscribe_ab_dis_box_render li[data-panel="${key}"]`); targetTab.classList.remove('hidden'); const buttonDomSelector = domSelector[key]; const buttonDom = document.querySelector(buttonDomSelector); const isFailed = buttonDom.parentElement.hasAttribute('failed'); if (!isFailed) { buttonDom.style.visibility = 'visible'; visibleTabs.push(key); } } }); if (!this.optionTouched) { this.setInitActiveChannel(visibleTabs); } console.log('hideUnsupportedPayments', this.optionTouched, visibleTabs); this.initEvents(); } initEvents() { const self = this; document.querySelector("#subscribe_ab_dis_box_tabs .payment-tabs")?.addEventListener('click', function(e) { const liTarget = e.target.closest('li'); if (!(liTarget && liTarget.dataset.panel)) { return; } const targetPanel = liTarget.dataset.panel; const panelDomList = document.querySelectorAll("#subscribe_ab_dis_box_tabs li[data-id]"); Array.from(panelDomList).forEach(function(dom) { const panelId = dom.dataset.id; const targetTabDom = document.querySelector(`#subscribe_ab_dis_box_tabs li[data-panel="${panelId}"]`); self.optionTouched = true; if (panelId === targetPanel) { dom.classList.remove('hidden'); targetTabDom.classList.add('active'); } else { dom.classList.add('hidden'); targetTabDom.classList.remove('active'); } }); }); } isEqualToLastECParams(lineItem) { const isNotEqual = Object.keys(lineItem).some(k => { return this.lastECLineItem[k] !== lineItem[k]; }); return !isNotEqual; } /* 渲染 EC 支付列表 */ async renderECList() { let renderPrice = this.activity.final_line_price; if (renderPrice === undefined) { renderPrice = this.activity.price; } const circleDays = this.getCircleDays(this.activity?.selling_plan_info?.selling_plan_options?.[0]); const lineItem = { variant_id: this.activity.variant_id, product_id: this.activity.product_id, product_title: this.activity.product_title, price: renderPrice, selling_plan_option_id: this.activity._selling_plan_option_id, cycle_days: circleDays, }; await this.refreshPaymentSettings(); window.shortLineItem = lineItem; const self = this; console.log('renderECList: ready to render'); window.BSPublicJSReady(() => { const fixedSelector = { ...this.ecDomSelector }; if (self.ecMounted) { delete fixedSelector['paypal']; } console.log('renderECList: mounting...', fixedSelector, self.paymentSettings, lineItem); self.updateLoading(true); window.mountBSECPayment(fixedSelector, self.paymentSettings, lineItem, { google: { buttonColor: 'black', }, onConfirm: () => { self.updateLoading(true); }, onFinish: () => { self.updateLoading(false); }, onCancel: () => { self.updateLoading(false); }, onError: () => { self.updateLoading(false); }, onInit: (channel) => { console.log('renderECList: onInit', channel); self.ecMounted = true; self.lastECLineItem = lineItem; self.hideUnsupportedPayments(); self.updateLoading(false); } }).finally(() => { self.hideUnsupportedPayments(); self.updateLoading(false); }); }); } /* 在 subscribe list 中调用渲染 */ renderContent(abandonActivity){ this.activity = abandonActivity; const boxRender = document.querySelector('#subscribe_ab_dis_box_render'); SPZ.whenApiDefined(boxRender).then(apis=>{ apis.render(abandonActivity); }); } preloadImg(activity) { if (!activity) return; if (!activity.config?.background_material?.file_url || !activity?._selling_plan_option_id) return; const img = new Image(); img.src = activity.config.background_material.file_url; img.onload = () => { document.body.removeChild(img); }; img.onerror = () => { document.body.removeChild(img); }; document.body.appendChild(img); } mountCallback() { } trigger_(name, data) { const event = SPZUtils.Event.create(this.win, 'spz-custom-accordion.${name}', { data }); this.action_.trigger(this.element, name, event); } } SPZ.defineElement('spz-custom-subscribe-ab-discount', SPZCustomAbandonDiscount); })() (function(){ class SPZCustomPaySuccess extends SPZ.BaseElement { constructor(element) { super(element); this.payResult = null; } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } async reloadstate(){ let res = {}; try{ const data = await fetch(location.origin+'/api/customers/show',{cache: 'no-store'}); res = await data.json(); } catch (e) { res = {}; } if(!res?.customer?.id){ const recordEmail = this.payResult?.customer?.email; const isNotRegistered = !this.payResult?.customer?.registered; if(recordEmail) { localStorage.setItem('bind_modal_email', recordEmail); } if(isNotRegistered) { localStorage.setItem('BS_IS_NOT_REGISTERED', 'Y'); } } } getCookie(name) { const reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'), arr = document.cookie.match(reg); return arr ? decodeURIComponent(arr[2]) : ''; }; trackPaySuccess(payResult){ console.info('[payResult]', payResult); const line_items = [payResult?.orderData?.line_item]; const order_id = payResult?.orderData?.order?.id || ''; const saParams = { order_id: order_id, checkout_page_type: 'single', currency: window.C_SETTINGS.currency_code, quantity: 1, sku_quantity: 1, content_ids: line_items.map(function (item) { return item.product_id; }), total: payResult.orderData?.order?.total, AD_em: payResult?.customer?.email || '', AD_fn: '', AD_ln: '', AD_ph: '', AD_ct: '', AD_st: '', AD_zp: '', AD_cc: '', AD_fbc: this.getCookie('_fbc') || this.getCookie('fbclid'), AD_fbp: this.getCookie('_fbp'), AD_variant_ids: line_items.map(function (item) { return item.variant_id; }), AD_event_id: order_id + '_' + new Date(payResult?.orderData?.order?.updated_at).getTime(), order_time: payResult?.orderData?.order?.created_at || '', payment_method: payResult?.customInfo?.payment_method || '', payment_channel: payResult?.customInfo?.payment_channel || '', package_id: payResult?.orderData?.line_item?.product_id, package_title: payResult?.orderData?.line_item?.product_title, product_id: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10" || '', user_id: window.csTracker.getClientId(), device_type: navigator.userAgent, }; window.sa?.track?.('purchase', saParams); const isGtagVariantId = window.ADS_ID_FORMAT === "gtag_variant_id"; const adsCountry = "shoplaza_" + (window.ADS_COUNTRY || "US") + "_"; const gaParams = { transaction_id: order_id, affiliation: window.C_SETTINGS.shop.shop_id, value: payResult.orderData?.order?.total, currency: window.C_SETTINGS.currency_code, user_id: window.csTracker.getClientId(), items: line_items.map((item, i) => { const id = isGtagVariantId ? adsCountry + item.variant_id : item.product_id; return { id: id, item_id: id, item_name: item.product_title, item_brand: item.vendor, item_category: "", item_variant: item.variant_title, index: i, price: item.price, quantity: item.quantity, google_business_vertical: "retail", }; }), order_time: payResult?.orderData?.order?.created_at || '', payment_method: payResult?.customInfo?.payment_method || '', payment_channel: payResult?.customInfo?.payment_channel || '', package_id: payResult?.orderData?.line_item?.product_id, package_title: payResult?.orderData?.line_item?.product_title, product_id: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10" || '', device_type: navigator.userAgent, }; window.gtag?.('event', 'purchase', gaParams); const inlineScriptPixels = [...document.getElementsByTagName("script")] .map(function (s) { return ( s.innerHTML.match(/fbevents\.js(.*)['"](\d{15,17})['"]/ms) ?.[2] || "" ); }) .filter(function (p) { return p; }); const pixels = [...inlineScriptPixels, ...(window.AD_TRACK_ASSETS?.track_config?.meta?.pixels?.map(p => p?.pixel) || [])]; const fbqParams = { shoplazza_order_token: order_id, value: payResult.orderData?.order?.total, currency: window.C_SETTINGS.currency_code, content_type: "product", content_name: "", content_ids: line_items?.map(function (item) { return item.variant_id; }), num_items: 1, order_time: payResult?.orderData?.order?.created_at || '', payment_method: payResult?.customInfo?.payment_method || '', payment_channel: payResult?.customInfo?.payment_channel || '', package_id: payResult?.orderData?.line_item?.product_id, package_title: payResult?.orderData?.line_item?.product_title, product_id: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10" || '', user_id: window.csTracker.getClientId(), device_type: navigator.userAgent, }; pixels?.forEach(function(pixel){ window.fbq?.( 'trackSingle', pixel, 'Purchase', fbqParams, { eventID: 'Purchase' + order_id.replace("-", ""), } ); }); const vid = localStorage.getItem('BS_VIDEO_VARIANT_ID') || ''; if(location.pathname.includes('/products/')){ window.sa.track('purchase', { product_id: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10", product_title: "Conflicted Hearts", price: "0", variant_id: vid, quantity: 1, sku_quantity: 1, entrance: 'product', currency: window.C_SETTINGS.currency_code, content_ids: "600f6ed4-b865-4c7b-ae6a-fb38e6078e10" }); const gtagAdsCountry = "shoplaza_" + (window.ADS_COUNTRY || "US") + "_"; const variantId = vid; const trackId = gtagAdsCountry + variantId; window.csTracker.track('purchase', { transaction_id: trackId, affiliation: window.C_SETTINGS.shop.shop_id, name: "Conflicted Hearts", value: "0", coupon: "", currency: window.C_SETTINGS.currency_code, user_id: window.csTracker.getClientId(), item_id: trackId, items:{ id: trackId, item_id: trackId, item_name: "Conflicted Hearts", item_brand: "", item_category: "", item_variant: vid, price: "0", quantity:1, google_business_vertical: "retail", } }, ['ga']); } localStorage.removeItem('BS_VIDEO_VARIANT_ID'); } mountCallback() { let payResult = localStorage.getItem('BS_PAY_RESULT'); localStorage.removeItem('BS_PAY_RESULT'); if(payResult) { payResult = JSON.parse(payResult); this.payResult = payResult; // 存储全局 this.trackPaySuccess(payResult); this.reloadstate(); } } } SPZ.defineElement('spz-custom-subscribe-success', SPZCustomPaySuccess); })() (function(){ class SPZCustomSubscribeCheckout extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.CONTAINER; } buildCallback() { /* console.info('[window]', window); */ this.addIFrameCallback(); } hideLoading(){ const loading = document.querySelector('#subscribe_loading'); SPZ.whenApiDefined(loading).then(apis=>{ apis.close_(); }) } trackPayCount(params){ window.csTracker.track('checkoutStepPayment', params, ['ga','fb']); if(location.pathname.includes('/products/')){ const name = "Conflicted Hearts"; const id = window.currentVideoPlayer.getCurrentVideoId(); window.csTracker.track('checkoutStepPayment', { name: name, id: id }, ['ga','fb']); } } trackPaySuccess(params){ window.csTracker.track('purchase', params, ['ga','fb']); if(location.pathname.includes('/products/')){ const name = "Conflicted Hearts"; const id = window.currentVideoPlayer.getCurrentVideoId(); window.csTracker.track('purchase', { ...params, name: name, id: id }, ['ga','fb']); } } payCallback(val){ if(val.res.state == 'success'){ const checkout = document.querySelector('#subscribe_checkout_lightbox'); SPZ.whenApiDefined(checkout).then(async(apis)=>{ apis.close(); let hasLoggedIn = false; try{ await fetch(location.origin+'/api/customers/show').then(res=>res.json()).then(res=>{ if(res && res.customer && res.customer.id){ hasLoggedIn = true; } }) }catch(e){ console.error('[pay-customers/show]', e); } if(location.pathname.includes('pages/short-me')){ const customer = document.querySelector('#me_customer_info'); SPZ.whenApiDefined(customer).then((apis) => { apis.fresh(); }); } /* 已登录 提示成功,未登录 让注册 */ if(hasLoggedIn){ const okBox = document.querySelector('#subscribe_pay_logged_ok_box'); SPZ.whenApiDefined(okBox).then((apis) => { apis.open(); }); }else{ location.href = '/account/register'; /* const meElement =document.querySelector('#me_account_element'); SPZ.whenApiDefined(meElement).then((apis)=>{ if(val.res.email){ apis.presetEmail(val.res.email); } apis.showType('account_register'); }) const accountBox = document.querySelector('#me_account_lightbox'); SPZ.whenApiDefined(accountBox).then((apis)=>{ apis.open(); }) */ } }); this.trackPaySuccess(val.params) } } addIFrameCallback(){ window.receivedata = (val) => { console.info('[receive]', val); /* Checkout Ready */ if(val && val.type=='READY'){ const lightbox = document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(lightbox).then((box)=>{ box.close(); const checkout = document.querySelector('#subscribe_checkout_lightbox'); SPZ.whenApiDefined(checkout).then((apis)=>{ apis.open(); this.hideLoading(); }) }); const loader = document.querySelector('#subscribe_checkout_lightbox .cs_checkout_mask'); loader && (loader.style = 'display: none') } /* 支付结果 */ if(val && val.type=='PAY'){ this.payCallback(val); } /* LOADING */ if(val && val.type=="LOADING"){ const loader = document.querySelector('#subscribe_checkout_lightbox .cs_checkout_mask'); loader && (loader.style = 'display: flex'); } /* 上报 */ if(val && val.type=="PAY_TRACK"){ this.trackPayCount(val.params); } } } } SPZ.defineElement('spz-custom-subscribe-checkout', SPZCustomSubscribeCheckout); })() (function(){ class SPZCustomMeAccount extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.registerAction('showType', (invocation) => { this.showType(invocation.args.showclass); }); this.registerAction('reset', (invocation) => { this.reset(); }); this.registerAction('signin', (invocation) => { this.signIn(); }); this.registerAction('register', (invocation) => { this.register(); }); this.registerAction('sendemail', (invocation) => { this.sendEmail(); }); this.registerAction('resetpassword', (invocation) => { this.resetpassword(); }); this.registerAction('signout', (invocation) => { this.signOut(); }); } reset(){ const inputs = document.querySelectorAll('#me_account_lightbox input'); inputs.forEach(ele=>{ ele.value = ''; ele.disabled = false; }); this.showType('account_login'); } presetEmail(resetEmail){ const loginEmailDom = document.querySelector('#me_account_lightbox .account_login .email'); if(loginEmailDom){ loginEmailDom.value = resetEmail; loginEmailDom.disabled = true; } const registerEmailDom = document.querySelector('#me_account_lightbox .account_register .email'); if(registerEmailDom){ registerEmailDom.value = resetEmail; registerEmailDom.disabled = true; } const setEmailDom = document.querySelector('#me_account_lightbox .account_email .email'); if(setEmailDom){ setEmailDom.value = resetEmail; setEmailDom.disabled = true; } const pass = document.querySelectorAll('#me_account_lightbox .password'); pass.forEach(ele=>{ ele.value = ''; }); } getCookie(name) { // 创建正则表达式来匹配指定名称的 Cookie const regex = new RegExp('(^|; )' + encodeURIComponent(name) + '=([^;]*)'); const match = document.cookie.match(regex); // 如果找到匹配项,则返回解码后的值,否则返回 null return match ? decodeURIComponent(match[2]) : null; } showType(showclass){ const modules = document.querySelectorAll('.box_content'); modules.forEach(ele=>{ if(ele.classList.contains(showclass)){ ele.classList.remove('hide'); ele.classList.add('show'); }else{ ele.classList.remove('show'); ele.classList.add('hide') } }) } signIn(){ const email = document.querySelector('.account_login .email').value; const password = document.querySelector('.account_login .password').value; const formData = new URLSearchParams(); formData.append('email', email); formData.append('password', password); fetch(location.origin+'/api/customers/sign_in',{ method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: formData }).then(res=>res.json()) .then(res=>{ if(res && res.customer && res.customer.id){ const box = document.querySelector('#me_account_lightbox'); SPZ.whenApiDefined(box).then(apis=>{ apis.close(); }) location.reload(); }else if(res && res.errors && res.errors[0]){ window.customToast(res.errors[0], 'error') } }).catch(err=>console.error('[signIn-err]', err)) } register(){ const email = document.querySelector('.account_register .email').value; const password = document.querySelector('.account_register .password').value; const checked = document.querySelector('.account_register .email_subscribe .check').checked; const regex = /^([^@]+)/; const match = email.match(regex); const name = match ? match[1] : '-'; // 返回用户名或 null const formData = new FormData(); formData.append('email', email); formData.append('password', password); formData.append('first_name', 'Guest'); formData.append('last_name', name); formData.append('newsletter', checked); fetch(location.origin+'/api/customers/sign_up',{ method: 'POST', body: formData }).then(res=>res.json()) .then(res=>{ if(res && res.customer && res.customer.id){ const box = document.querySelector('#me_account_lightbox'); SPZ.whenApiDefined(box).then(apis=>{ apis.close(); }) location.reload(); }else if(res && res.errors && res.errors[0]){ window.customToast(res.errors[0], 'error') } }).catch(err=>console.error('[signIn-err]', err)) } sendEmail(){ const email = document.querySelector('.account_email .email').value; const formData = new FormData(); formData.append('email', email); fetch(location.origin+'/api/customers/password_reset_email',{body: formData, method: 'POST'}) .then(res=>res.json()) .then(res=>{ if(res.errors && res.errors[0]){ window.customToast(res.errors[0], 'error'); if(res.errors[0].includes('This email has not been registered')){ this.showType('account_register'); } }else{ this.to_reset_email = email; this.showType('account_reset'); window.customToast('send successful'); } }).catch(err=>console.error('[sendEmail-err]', err)); } resetpassword(){ const formData = new FormData(); const verifyCode = document.querySelector('.account_reset .verifycode').value; const pwd1 = document.querySelector('.account_reset .pwd1').value; const pwd2 = document.querySelector('.account_reset .pwd2').value; if(pwd1!==pwd2){ /* TODO toast */ window.customToast('Your password and confirmation password do not match', 'error'); return; } formData.append('email', this.to_reset_email); formData.append('code', verifyCode); formData.append('password', pwd1); formData.append('confirm_password', pwd2); fetch(location.origin+'/api/customers/password_reset', { method: 'PATCH', body: formData, }) .then(res => res.json()) .then(res=>{ if(res.errors && res.errors[0]){ window.customToast(res.errors[0], 'error'); }else{ const box = document.querySelector('#me_account_lightbox'); SPZ.whenApiDefined(box).then(apis=>{ apis.close(); }); location.reload(); } }) .catch(err => console.error('[resetpassword-err]:', err)); } expireCookie(){ const cookies = document.cookie.split("; "); for (let cookie of cookies) { const eqPos = cookie.indexOf("="); const name = eqPos > -1 ? cookie.substr(0, eqPos) : cookie; if (name === '_c_frill') { continue; } document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;`; } } /* 在 我的 页面调用 */ signOut(){ const token = this.getCookie('CSRF-TOKEN'); fetch(location.origin+'/api/customers/sign_out', { method: 'POST', headers: { "x-csrf-token": token }, }).then(res=>res.json()) .then(res=>{ console.info('[signout res]', res); }) .catch(err=>console.error('[signOut-err]', err)) .finally(()=>{ this.expireCookie(); localStorage.removeItem('csp-video-progress'); localStorage.removeItem('bind_modal_email'); localStorage.removeItem('BS_IS_NOT_REGISTERED'); window.keepRightsManager?.removeSignatureQueryParams(); location.reload(); }) } } SPZ.defineElement('spz-custom-me-account', SPZCustomMeAccount); })() (function(){ class SPZCustomSubscribeUtilize extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.registerAction('confirm', (invocation) => { this.confirmUtilize(); }); } showUtilizeBox(pid, vid, cost_info){ const {currently_available, maximum_available} = cost_info || {}; const leftTime = Number(maximum_available||0) - Number(currently_available||0); this.pid = pid; this.vid = vid; const desc2 = document.querySelector('#subscribe_utilization_box .desc2'); desc2.innerText = `You still have 3 benefits remaining, and you have used ${leftTime}/3 times.`; const useBox = document.querySelector('#subscribe_utilization_box'); SPZ.whenApiDefined(useBox).then(apis=>{ apis.open(); }) } confirmUtilize(){ fetch(location.origin+'/apps/best-short/api/v1/preview/submit', {method: 'POST', body: JSON.stringify({skit_id: this.pid, skit_series_id: this.vid})}) .then(res=>res.json()) .then(res=>{ if(res && res.is_subscription){ /* 解锁成功 */ const useBox = document.querySelector('#subscribe_utilization_box'); SPZ.whenApiDefined(useBox).then(apis=>{ apis.close(); }) location.reload(); }else{ window.customToast('unlock fails', 'error') } }).catch(err=> console.error('[confirmUtilize-err]', err)) } } SPZ.defineElement('spz-custom-subscribe-utilize', SPZCustomSubscribeUtilize); })() (function(){ class SPZCustomCheckRight extends SPZ.BaseElement { constructor(element) { super(element); this.currentAbortController = null; } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } /* 唤起列表 */ showSubscribeList(){ const listDom = document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(listDom).then(apis=>{ apis.open(); }) } checkright(pid, vid){ if (this.currentAbortController) { this.currentAbortController.abort(); } this.currentAbortController = new AbortController(); const signal = this.currentAbortController.signal; fetch(window.keepRightsManager?.addSignatureQueryParams(location.origin+'/apps/best-short/api/v1/customer/information'), { signal: signal }) .then(res=>res.json()) .then(res=>{ if (res) { window.keepRightsManager?.keepRights(res?.signature); const info = res.information; const right = res.subscription_info; /* 已经有了权益 */ if(right){ if(right.subscribe_type == "term_num"){ if(Number(right?.cost_info?.currently_available) > 0 ){ const useBox = document.querySelector('#subscribe_utilize_logic'); SPZ.whenApiDefined(useBox).then(apis=>{ apis.showUtilizeBox(pid, vid, right.cost_info); }) }else{ this.showSubscribeList(); } } }else{ this.showSubscribeList(); } } }) .catch(err => { if (err.name === 'AbortError') { return; } console.error('检查权益失败:', err); }); } } SPZ.defineElement('spz-custom-check-right', SPZCustomCheckRight); })() (function(){ class SPZCustomProductShare extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.request(); this.registerAction('finish', (invocation) => { this.finish(); }); } request () { const { productId } = document.querySelector('#bs-player').dataset; this.productId = productId; fetch(`/api/products/${productId}?extra_fields=description`) .then(res => res.json()) .then(res => { const { product = {} } = res.data; const container = document.querySelector('#custom_product_share_render_container'); SPZ.whenApiDefined(container).then((apis) => { apis.render({ product }).then(() => { const descDom = container.querySelector('.share-desc'); if (descDom) { container.querySelector('.share-desc').innerHTML = product.description; } }); }); }) .catch(err => { console.log('request error:', err); }) } finish () { const trackShare = async () => { await fetch('/apps/best-short/api/v1/preview/share', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ event_type: "PET_SHARE", msg: { skit_id: this.productId, skit_series_id: window.currentVideoPlayer.getCurrentEpisodeId(), } }) }).catch(err => {}) }; const box = document.querySelector('#custom-solution-product-share'); const copyBtn = box.querySelector('.copy-link'); copyBtn.addEventListener('click', function() { const url = window.location.href; trackShare(); navigator.clipboard.writeText(url).then(function() { window.C_APPS_COMMON.plugin_toast.show({content:'Copy link success'}); }); }); const shareFacebook = box.querySelector('.share-facebook'); const shareTwitter = box.querySelector('.share-twitter'); const onClick = function(e) { const url = window.location.href; const originHref = this.getAttribute('href') + encodeURIComponent(url); trackShare(); window.open(originHref, '_blank'); }; shareFacebook.addEventListener('click', onClick); shareTwitter.addEventListener('click', onClick); } } SPZ.defineElement('spz-custom-product-share', SPZCustomProductShare); })()