Guest
UID: -----
(function(){ class SPZCustomPlayTopUp extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.bindClickEvent(); } bindClickEvent(){ const myPlan = document.querySelector('.short_me .my-plan'); myPlan.onclick = function(e){ location.href = '/pages/short-subscribe'; } const upBtn = document.querySelector('.my-plan .up-btn'); upBtn.onclick = function(e){ e.stopPropagation(); const subList =document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(subList).then((apis) => { apis.open(); }); window.csTracker.track('topUp', {},['ga','fb','sa']); } } } SPZ.defineElement('spz-custom-subscribe-top-up', SPZCustomPlayTopUp); })()
My Like
My Collection
History
Feedback
Sign Out
(function(){ class SPZCustomCustomerInfo extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.registerAction('fresh', (invocation) => { this.fresh(); }); this.fresh(); } clearCustomerInfo(){ document.cookie = ``; localStorage.removeItem('CUSTOMER_INFO'); } maskMiddleCharacters(name) { const length = name.length; if (length <= 2) { return name; // 如果字符串长度小于等于2,返回原字符串 } const halfLength = Math.floor(length / 2); const halfShowCount = Math.ceil(halfLength / 2); const maskName = name.split('').map((ele, i) => { return (i < halfShowCount || i > length - halfShowCount - 1) ? ele : '*' }).join('') return maskName; } async fresh(){ let hasLoggedIn = false; let customerEmail = ''; let last_name = ''; try{ await fetch(location.origin+'/api/customers/show',{cache: 'no-store'}).then(res=>res.json()).then(res=>{ if(res && res.customer && res.customer.id){ hasLoggedIn = true; customerEmail = res.customer.email; last_name = res.customer.last_name; localStorage.setItem('CUSTOMER_INFO', JSON.stringify(res.customer)); }else{ localStorage.removeItem('CUSTOMER_INFO'); } }) }catch(err){console.warn('[customer]',err)} fetch(location.origin+'/apps/best-short/api/v1/customer/information') .then(res=>res.json()) .then(res=>{ if(res){ const info = res.information; const subInfo = res.subscription_info; const nameDom = document.querySelector('.short_me .profile .nickname'); const uidText = document.querySelector('.short_me .profile .uid .uid_text'); const avatarDom = document.querySelector('.short_me .user .avatar'); const signIn = document.querySelector('.short_me .user .sign_in'); const signOut = document.querySelector('.short_me .funlist_content .sign_out'); const copyIcon = document.querySelector('.short_me .user .copy_icon'); uidText && (uidText.innerText = `UID: ${info.id}`); copyIcon.onclick = function(){ navigator.clipboard.writeText(info.id).then(function() { window.C_APPS_COMMON.plugin_toast.show({content:'Copy successful'}); }); } if(hasLoggedIn){ const avatarUrl = ""; /* 登录 */ nameDom && (nameDom.innerText = this.maskMiddleCharacters(last_name) ); const imgDom = document.createElement('img'); imgDom.className = 'real_icon' imgDom.src = avatarUrl || info.icon_url; avatarDom.innerHTML = imgDom.outerHTML; signIn && (signIn.style = `display: none;`); signOut && (signOut.style = `display: flex;`); }else{ /* 未登录 */ nameDom && (nameDom.innerText = 'Guest'); signIn && (signIn.style = `display: flex;`); signOut && (signOut.style = `display: none;`); } /* 添加 订阅信息 */ const subscribeTitle = document.querySelector('.short_me .my-plan .title'); const des1 = document.querySelector('.short_me .my-plan .des1'); const des2 = document.querySelector('.short_me .my-plan .des2'); const upBtn = document.querySelector('.short_me .my-plan .up-btn'); const myPlan = document.querySelector('.short_me .my-plan'); const vipIcon = document.querySelector('.short_me .profile .vip'); const days = document.querySelector('.short_me .my-plan .days'); if(subInfo && subInfo.id){ upBtn.style = 'display: none;'; vipIcon.style = 'display: flex;'; let expireDate = subInfo?.expired_at?.split(' ')[0].split('-') || ''; expireDate = `${expireDate[1]}/${expireDate[2]}/${expireDate[0].replace('20','')}` const plan = subInfo.subscribe_plan; subscribeTitle && (subscribeTitle.innerText = `${plan.title}`); des1 && (des1.innerText = `Your rights will expire in `); subInfo.expired_at && (des2.innerText = `${expireDate}`); myPlan && (myPlan.onclick = function(e){ location.href = '/pages/short-subscribe'; }) if(subInfo.subscribe_type != 'term_num'){ days && (days.innerText = `Unlock all series for ${subInfo.remaining_days} days`); }else{ days && (days.innerText = ``); } }else{ upBtn.style = 'display: flex;'; vipIcon.style = 'display: none;'; subscribeTitle && (subscribeTitle.innerText = `Free Account`); des1 && (des1.innerText = `The episode is restricted. Please top up to watch your favorite series.`); des2 && (des2.innerText = ``); myPlan && (myPlan.onclick = null); days && (days.innerText = ``); } } }).catch(err=>{ console.error('[information-error]', err); }) return; } } SPZ.defineElement('spz-custom-me-customer-info', SPZCustomCustomerInfo); })()
(function(){ class SPZCustomSubscribeList extends SPZ.BaseElement { trackMode = 1; trackProductId = undefined; constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.CONTAINER; } buildCallback() { this.registerAction('onRender', (invocation) => { this.fixHandleChange(); this.handleConfirm(); const data = invocation?.args?.data?.data || {}; this.listData = invocation?.args?.data?.data || []; this.refreshSubscribeList(data); }); 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', (invocation) => { this.onCloseClick(); }); this.registerAction('onOpen', (invocation) => { const list = document.querySelector('#subscribe_list_render .subscribe_list'); if(list){ list.scrollTo(0,0); } }); } 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; } onCloseClick(){ const listBox = document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(listBox).then(apis=>{ apis.close(); }) const abandonActivityId = this.listData?.market_activity?.entitled_product_ids?.[0]; let abandonActivity = null; if(abandonActivityId){ const subscribePlan = this.listData.subscribe_plans?.find(ele=>ele.id == abandonActivityId); if(!subscribePlan) return; const item = this.listData.line_items.find(ele=>ele.product_id == abandonActivityId) || {}; const info = this.subscribeList.find(ele=>ele.id == abandonActivityId); const config = this.listData?.market_activity?.config; const sellingPlan = this.listData?.selling_plan_info?.[abandonActivityId]; const sellingPlanId = sellingPlan?.selling_plan_options?.[0]?.selling_plan_option_id; abandonActivity = {...item, ...info, config, _selling_plan_option_id: sellingPlanId}; const abandonBox = document.querySelector('#subscribe_ab_dis_box'); SPZ.whenApiDefined(abandonBox).then(apis=>{ apis.open(); }) const abandonLogic = document.querySelector('#subscribe_ab_discount_logic'); SPZ.whenApiDefined(abandonLogic).then(apis=>{ apis.renderContent(abandonActivity); }) this.pureTrackAddToCart({ id: item.product_id, title: item.product_title, price: item.final_line_price, variant_id: item.variant_id, variant: item.variant_id }); } } 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; const abandonActivityId = this.listData?.market_activity?.entitled_product_ids?.[0]; if(abandonActivityId){ showList = showList.filter(item=>item.id != abandonActivityId); } let defaultItem = showList?.[0]; if(showList.length > 1){ let defaultItem = showList?.[1]; } const defaultLineItem = this.listData?.line_items.find(ele=>ele.product_id == defaultItem?.id) || {}; 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: null, product_title: null, price: null, 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: null, name: null, user_id: window.csTracker.getClientId(), items: [ { id: trackId, item_id: trackId, item_name: null, item_list_name: 'product', item_brand: "", item_category: "", item_variant: window.currentVideoPlayer.getCurrentEpisode().no.toString(), price: null, quantity: 1, google_business_vertical: 'retail', } ] }, ['ga']); } } trackViewContent(){ let showlist = this.subscribeList.slice(); const abandonActivityId = this.listData?.market_activity?.entitled_product_ids?.[0]; if(abandonActivityId){ showlist = showlist.filter(item=>item.id != abandonActivityId); } 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('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']); /* if(location.pathname.includes('/products/')){ const name = ""; const id = window.currentVideoPlayer.getCurrentVideoId(); window.csTracker.track('initiateCheck', { name: name, id: id }, ['ga','fb']); } */ } 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 loading = document.querySelector('#subscribe_list_render'); SPZ.whenApiDefined(loading).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.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; 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}; const listItem = this.subscribeList.find(ele=>ele.id == pid); params['_selling_plan_option_id'] = listItem.selling_plan_info.selected_selling_plan_option_id; params['link'] = location.href; params['entry'] = '权益中心'; params['short_id'] = ''; if(location.pathname.includes('/products/')){ params['entry'] = '短剧'; params['short_id'] = window.currentVideoPlayer.getCurrentVideoId(); } const referrer = decodeURIComponent(this.getCookie('latest_referrer') || ''); if(referrer){ const referrerHost = new URL(referrer).hostname; params["_ad_from"] = referrerHost; } /* https://feature-v1-3---short-best.dev.myshoplaza.com/apps/best-short-pay/api/v1/checkout/order */ 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 } }) }) .then(response => response.json()) .then(res=>{ if(res && res.check_out_url){ const lightbox = document.querySelector('#subscribe_lightbox'); SPZ.whenApiDefined(lightbox).then((box)=>{ box.close(); this.hideLoading(); localStorage.setItem('COMMON_NAMESPACE', window.SHOPLAZZA.namespace); localStorage.setItem('BS_PREV_URL', location.href); localStorage.setItem('SHOP_ID', window.C_SETTINGS.shop.shop_id); localStorage.setItem('BS_TRACK_PARAMS', JSON.stringify(window.sa.trackParams)); if(window.fbq){ localStorage.setItem('FBQ_PIXELS', JSON.stringify(window.fbq?.getState?.() || {})); } if (location.pathname.includes('/products/')) { const name = ""; const videoId = window.currentVideoPlayer.getCurrentVideoId(); localStorage.setItem('BS_PRODUCT_VIDEO', JSON.stringify({ name, id: videoId })); localStorage.setItem('BS_VIDEO_VARIANT_ID', JSON.stringify(window.currentVideoPlayer?.getCurrentEpisodeId?.())); } else { localStorage.removeItem('BS_PRODUCT_VIDEO'); localStorage.removeItem('BS_VIDEO_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: 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.market.market_currency, 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: null, product_title: null, price: null, variant_id: window.currentVideoPlayer.getCurrentEpisodeId(), quantity: 1, sku_quantity: 1, entrance: 'product', currency: window.C_SETTINGS.currency_code, content_ids: null }); const gtagAdsCountry = "shoplaza_" + (window.ADS_COUNTRY || "US") + "_"; const variantId = window.currentVideoPlayer.getCurrentEpisodeId(); const trackId = gtagAdsCountry + variantId; window.csTracker.track('begin_checkout', { name: null, value: null, coupon: "", currency: window.C_SETTINGS.currency_code, user_id: window.csTracker.getClientId(), item_id: trackId, items:{ id: trackId, item_id: trackId, item_name: null, item_brand: "", item_category: "", item_variant: window.currentVideoPlayer.getCurrentEpisode().no.toString(), price: null, quantity:1, google_business_vertical: "retail", } }, ['ga']); } location.href=`${location.origin}${res.check_out_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'); } this.hideLoading(); } }).catch((error)=>{ console.error('[error-fetch]', error); }) /* .finally(()=>{ this.trackOrder(name, pid); }) */ } } } SPZ.defineElement('spz-custom-subscribe-list', SPZCustomSubscribeList); })() (function(){ class SPZCustomAbandonDiscount extends SPZ.BaseElement { trackMode = 1; trackProductId = undefined; 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; } buildCallback(){ this.registerAction('onPayNow', (invocation) => { this.onPayNow(); }); this.registerAction('onOpen', (invocation) => { this.onOpen(); }); 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']); } 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 = ''; 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; const skit_uid = this.getCookie('skit-uid'); let params = {_best_short_uid: skit_uid}; params['_selling_plan_option_id'] = this.activity._selling_plan_option_id; params['link'] = location.href; params['entry'] = '权益中心'; params['short_id'] = ''; if(location.pathname.includes('/products/')){ params['entry'] = '短剧'; params['short_id'] = window.currentVideoPlayer.getCurrentVideoId(); } 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 } }) }) .then(response => response.json()) .then(res=>{ if(res && res.check_out_url){ const lightbox = document.querySelector('#subscribe_ab_dis_box'); SPZ.whenApiDefined(lightbox).then((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); if (location.pathname.includes('/products/')) { const name = ""; const videoId = window.currentVideoPlayer.getCurrentVideoId(); localStorage.setItem('BS_PRODUCT_VIDEO', JSON.stringify({ name, id: videoId })); } else { localStorage.removeItem('BS_PRODUCT_VIDEO'); } 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.market.market_currency, quantity: '1', line_items: [{ product_id: pid, variant_id: vid, quantity: 1, properties: params, }], prices: { total_price: this.activity.final_line_price, } } })); location.href=`${location.origin}${res.check_out_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'); } this.hideLoading(); } }).catch((error)=>{ console.error('[error-fetch]', error); }) /* .finally(()=>{ this.trackOrder(name, pid); }) */ } /* 上报 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']); } /* 在 subscribe list 中调用渲染 */ renderContent(abandonActivity){ this.activity = abandonActivity; const boxRender = document.querySelector('#subscribe_ab_dis_box_render'); SPZ.whenApiDefined(boxRender).then(apis=>{ apis.render(abandonActivity); }) } mountCallback() { } } 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; } buildCallback(){ this.registerAction('onOpen', (invocation) => { const btn = document.querySelector('#subscribe_success_box .seconds_btn'); btn && (btn.innerText = '3 seconds to close'); let count = 2; let interval = setInterval(()=>{ if(count==0){ clearInterval(interval); const box = document.querySelector('#subscribe_success_box'); SPZ.whenApiDefined(box).then((apis) => { apis.close(); }); } btn && (btn.innerText = `${count} second${count>1?'s':''} to close`); count--; },1000); }); this.registerAction('reloadstate', (invocation) => { this.reloadstate(); }); } async reloadstate(){ const newUrl = location.href.replace('?success=true','').replace('&success=true',''); if(location.href.includes('success=true')){ location.href = newUrl; } let res = {}; try{ const data = await fetch(location.origin+'/api/customers/show',{cache: 'no-store'}); res = await data.json(); }catch(e){} /* console.info('[res]', res); */ if(res && res.customer && res.customer.id){ location.href = newUrl; }else{ if(!this.payResult?.customer?.registered){ location.href = '/account/register'; }else{ location.href = '/account/login'; } this.payResult = null; } } trackPaySuccess(payResult){ document.dispatchEvent(new CustomEvent('dj.purchase', { detail: { id: payResult?.orderData?.order?.id || '', checkout_page_type: 'single', order_id: payResult?.orderData?.order_id, currency_code: window.C_SETTINGS.market.market_currency, quantity: '1', line_items: [payResult?.orderData?.line_item], prices: { total_price: payResult.orderData?.order?.total, }, config:{ page_type: "single", }, shipping_address:{ email: payResult?.customer?.email || '', phone: '' } } })); const vid = localStorage.getItem('BS_VIDEO_VARIANT_ID') || ''; if(location.pathname.includes('/products/')){ window.sa.track('purchase', { product_id: null, product_title: null, price: null, variant_id: vid, quantity: 1, sku_quantity: 1, entrance: 'product', currency: window.C_SETTINGS.currency_code, content_ids: null }); 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: null, value: null, coupon: "", currency: window.C_SETTINGS.currency_code, user_id: window.csTracker.getClientId(), item_id: trackId, items:{ id: trackId, item_id: trackId, item_name: null, item_brand: "", item_category: "", item_variant: vid, price: null, quantity:1, google_business_vertical: "retail", } }, ['ga']); } localStorage.removeItem('BS_VIDEO_VARIANT_ID'); /* window.csTracker.track('Purchase', { value: payResult.orderData?.order?.total, currency: payResult.orderData?.order?.currency_code, contents: [ { id: payResult?.orderData?.line_item?.product_id, quantity: 1 }], content_type: 'product' }, ['fb']); */ } mountCallback(){ const hasSuccess = location.search.includes('success=true'); let payResult = localStorage.getItem('BS_PAY_RESULT'); if(payResult){ payResult = JSON.parse(payResult); } /* 3DS */ if( (hasSuccess && payResult?.type=='3ds' ) || payResult?.type=='normal'){ this.payResult = payResult; const box = document.querySelector('#subscribe_success_box'); SPZ.whenApiDefined(box).then((apis) => { apis.open(); }); } localStorage.removeItem('BS_PAY_RESULT'); payResult && this.trackPaySuccess(payResult) } } 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 = ""; 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 = ""; 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 SPZCustomPayRegister extends SPZ.BaseElement { constructor(element) { super(element); } isLayoutSupported(layout) { return layout === SPZCore.Layout.LOGIC; } buildCallback(){ this.registerAction('toRegister', (invocation) => { this.toRegister(); }); } toRegister(){ const email = document.querySelector('#subscribe_pay_register_renderer .email')?.innerText; const password = document.querySelector('#subscribe_pay_register_renderer .password')?.value; if(email && password){ const myHeaders = new Headers(); myHeaders.append("content-type", "application/x-www-form-urlencoded"); const urlencoded = new URLSearchParams(); urlencoded.append("email", email); urlencoded.append("password", password); urlencoded.append("newsletter", "false"); fetch(location.origin+'/api/customers/fast_sign_up',{ method: "POST", headers: myHeaders, body: urlencoded, }).then(res=>res.json()).then(res=>{ if(res && res.customer && res.customer.id){ localStorage.setItem('CUSTOMER_INFO', JSON.stringify(res.customer)); const registerBox = document.querySelector('#subscribe_pay_register_lightbox'); SPZ.whenApiDefined(registerBox).then((rBox)=>{ rBox.close(); }); const spzCustomerInfo = document.querySelector('#me_customer_info'); SPZ.whenApiDefined(spzCustomerInfo).then((apis) => { apis.fresh(); }); } }).catch(err=>{ console.info('err', err); }) } } } SPZ.defineElement('spz-custom-pay-register', SPZCustomPayRegister); })() (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(); }) const user = document.querySelector('#me_customer_info'); SPZ.whenApiDefined(user).then(apis=>{ apis.fresh(); }) }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(); }) const user = document.querySelector('#me_customer_info'); SPZ.whenApiDefined(user).then(apis=>{ apis.fresh(); }) }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(); }); const user = document.querySelector('#me_customer_info'); SPZ.whenApiDefined(user).then(apis=>{ apis.fresh(); }) } }) .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; // 删除 Cookie:设置过期时间为过去的日期 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'); location.reload(); /** const user = document.querySelector('#me_customer_info'); SPZ.whenApiDefined(user).then(apis=>{ apis.fresh(); }); const box = document.querySelector('#account_logout_box'); SPZ.whenApiDefined(box).then(apis=>{ apis.close(); }); **/ }) } } 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); })()