2021SC@SDUSC
本周我们来分析center文件夹下的cart.js中的getorderinfoAction()方法,它主要用来获取订单信息:
async getorderinfoAction() {
if (!this.is_login) {
if (this.isMobile) {
return this.redirect('/center/public/login');
} else {
return this.redirect('/cmswing/error/login');
}
}
首先通过this.is_login判断用户是否登录,若用户未登录,则再通过this.isMobile判断用户的客户端,若是手机,则直接跳转到用户页面,否则返回错误。
let post = this.para('ids');
const addrid = this.get('addrid');
if (think.isEmpty(post)) {
const error = this.controller('cmswing/error');
return error.noAction('木有选项要结算的宝贝');
}
if (think.isEmpty(this.cart.data)) {
const error = this.controller('cmswing/error');
return error.noAction('木有宝贝提交啥订单呢!');
}
之后通过if语句中think.isEmpty(post)方法判断结算时用户的购物车中是否有商品,若没有则返回'木有选项要结算的宝贝'来提示用户添加宝贝。另一个if语句同理,通过think.isEmpty(this.cart.data)判断用户提交订单时是否有商品,没有则返回'木有宝贝提交啥订单呢!'来提醒用户。
if (!think.isEmpty(addrid) && this.isMobile) {
post = JSON.parse(post);
}
this.assign('goodsget', post);
this.assign('goodsget', post);
const ids = [];
if (think.isArray(post)) {
for (const v of post) {
ids.push(v.split('||'));
}
} else {
ids.push(post.split('||'));
}
let order_amount;
let payable_amount;
let real_amount;
let payable_freight;
let real_freight;
const cart_goods = this.cart.data;
const check_goods = [];
for (const val of cart_goods) {
for (const v of ids) {
if (think.isEmpty(v[1]) && think.isEmpty(val.type)) {
if (v[0] == val.product_id) {
check_goods.push(val);
}
} else {
if (v[0] == val.product_id && v[1] == val.type) {
check_goods.push(val);
}
}
}
}
this.assign('check_goods', check_goods);
然后需要手机端接受订单(通过if语句中的this.isMobile来判断使用的是否是手机端),然后构造购物车要结算的宝贝。设置let变量:order_amount为订单金额、payable_amount为应付金额即商品的原价、real_amount为 商品参与获得的价格、payable_freight为应付运费、real_freight为 实际运费。const变量id为购物车Post过来的商品id,需要暂时去购物车内所有的商品,然后筛选要结算的商品。通过for循环与const数组check_goods[],for循环内通过if语句(条件为think.isEmpty(v[1]) 方法与think.isEmpty(val.type)方法返回值的且值,前者判断购物车是否为空,后者判断结算商品是否符合要求)来依次判断筛选要结算的商品。
// console.log(cart_goods);
console.log(check_goods);
const parr = [];
const nums = [];
for (const val of check_goods) {
parr.push(val.price);
nums.push(val.qty);
}
// console.log(parr);
real_amount = eval(parr.join('+'));
this.assign('real_amount', real_amount);
this.assign('nums', eval(nums.join('+')));
console.log(check_goods)方法用来获取订单的应付金额,然后通过for循环将各个商品数量与单价依次保存在数组nums[]与数组parr[]。之后的this.assign('real_amount', real_amount)方法将数组中的数据依次相加,由此获得商品的总数量。
let map;
if (this.isMobile) {
if (think.isEmpty(addrid)) {
map = {user_id: this.user.uid, is_default: 1};
} else {
map = {user_id: this.user.uid, id: addrid};
}
} else {
map = {user_id: this.user.uid};
}
之后通过if语句判断用户是否使用的手机端,将后台计算的结果传送到用户手机端返回给用户。
const addrlist = await this.model('address').where(map).order('is_default DESC,id DESC').select();
if (!think.isEmpty(addrlist)) {
for (const val of addrlist) {
val.province_num = val.province;
val.city_num = val.city;
val.county_num = val.county;
val.province = await this.model('area').where({id: val.province}).getField('name', true);
val.city = await this.model('area').where({id: val.city}).getField('name', true);
val.county = await this.model('area').where({id: val.county}).getField('name', true);
}
}
this.assign('addrlist', addrlist);
addrlist变量用来保存联系人,通过for循环依次记录省市三级的相关信息。
let paylist = await this.model("payment").where({status:1}).order("sort ASC").select();
for(let val of paylist){
val.logo = await this.model("pay_plugin").where({id:val.plugin_id}).getField("logo",true);
}
this.assign("paylist",paylist);
const where = {status: 1};
if (this.isMobile) {
where.type = 2;
} else {
where.type = 1;
}
if (this.isweixin) {
where.channel = ['!=', 'alipay_wap'];
}
const paylist = await this.model('pingxx').where(where).order('sort ASC').select();
this.assign('paylist', paylist);
支付方面现在用ping++集成直接,但接入暂时屏蔽。
在这里介绍一下ping++:Ping++ 是为移动端应用以及 PC 网页量身打造的下一代支付系统,通过一个 SDK 便可以同时支持移动端以及 PC 端网页的多种主流支付渠道。Ping++ SDK 包括 Client SDK 和 Server SDK 两部分,支持主流的七种后端开发语言,适配了 Android,iOS 和 HTML5 三种移动端平台以及 PC 端网页。
cmswing可以根据不同的客户端调用不同的支付方式(通过if语句与this.isMobile方法判断)。还有一点是在微信下要隐藏支付宝支付,通过if语句与this.isweixin来判断是否使用了微信,若返回为true。则使用where.channel = ['!=', 'alipay_wap'];来隐藏支付宝。
let farr = [];
for (const cg of check_goods) {
cg.fare = await this.model('document_shop').where({id: cg.product_id}).getField('fare', true);
if (cg.fare != 0) {
const isd = await this.model('fare').where({id: cg.fare}).getField('is_default', true);
if (isd == 1) {
cg.fare = 0;
}
}
farr.push(cg.fare);
}
farr = think._.uniq(farr);
console.log(farr);
const cgarr = [];
for (const fa of farr) {
const fobj = {};
fobj.id = fa;
fobj.cg = think._.filter(check_goods, ['fare', fa]);
cgarr.push(fobj);
}
const rarr = [];
for (const r of cgarr) {
const rf = await this.model('cmswing/fare').getfare(r.cg, null, this.user.uid, r.id);
rarr.push(rf);
}
// console.log(rarr);
real_freight = think._.sum(rarr);
此部分负责订单运费的计算:如果店铺只使用统一运费,那么顾客下单计算时按最低运费收取;如果店铺只使用一种运费模板规则,那么顾客下单计算时均按此规则收取运费;如果店铺使用了不同的运费模板规则,那么顾客下单时各运费模板规则先单独计算运费再叠加;如果店铺同时使用统一运费和不同的运费模板规则,那么顾客下单时统一运费单独计算运费,不同的运费模板。
首先通过cg.fare拿到运费模板,用变量farr来保存重量。然后通过方法think._.uniq(farr)与一个for循环依次对商品进行去重,将新的重量传给变量farr。在通过另一个for循环计算运费模板,然后将最终的运费保存在变量rarr中。
// console.log(real_freight);
// real_freight = await this.model("fare").getfare(check_goods,null,this.user.uid);
this.assign('real_freight', real_freight);
此方法通过real_freight传递订单促销优惠信息。
// console.log(real_amount);
order_amount = Number(real_amount) + Number(real_freight);
this.assign('order_amount', order_amount);
最后得出订单金额传给变量order_amount,它是由实付金额+邮费-订单优惠金额计算而得。
// this.end(cart_goods);
this.meta_title = '确认订单信息';
this.keywords = this.config('setup.WEB_SITE_KEYWORD') ? this.config('setup.WEB_SITE_KEYWORD') : '';
this.description = this.config('setup.WEB_SITE_DESCRIPTION') ? this.config('setup.WEB_SITE_DESCRIPTION') : '';
return this.display(this.mtpl());
} else {
return this.display();
}
}
getorderinfoAction()方法的最后返回给用户以'确认订单信息'为标题的页面,同样是需要if语句判断用户使用的客户端,依次通过this.display()方法返回不同的页面。