浏览代码

add buy now in order

StephenArk30 5 年之前
父节点
当前提交
2206d19b20

+ 6 - 5
README.md

@@ -9,6 +9,12 @@
 本项目需要配合微信小程序端使用,GitHub: [https://github.com/tumobi/nideshop-mini-program](https://github.com/tumobi/nideshop-mini-program)
 
 
+### Guides
++ [thinkjs](https://thinkjs.org/zh-cn/doc/index.html)
++ 页面在```src/api/controller```下,```controller/xxx.js```的```yyyAction```对应url: ```/xxx/yyy```
++ 可以被访问的url在```api/config/config.js```
++ ```src/admin```疑似后台管理系统
+
 ### 本地开发环境配置
 + 克隆项目到本地
 ```
@@ -97,8 +103,3 @@ npm start
 + 完整的购物流程,商品的加入、编辑、删除、批量选择,收货地址的选择,下单支付
 + 会员中心(订单、收藏、足迹、收货地址、意见反馈)
 ....
-
-### 交流
-喜欢别忘了 Star,有问题可通过微信、公众号、QQ 群联系我,谢谢您的关注。
-
-![联系方式](http://nideshop-static.nideshop.com/nideshop-qrcode.png)

+ 6 - 0
src/admin/model/order.js

@@ -76,6 +76,12 @@ module.exports = class extends think.Model {
       case 0:
         statusText = '未付款';
         break;
+      case 1:
+        statusText = '未兑换';
+        break;
+      case 2:
+        statusText = '已兑换';
+        break;
     }
 
     return statusText;

+ 3 - 1
src/admin/service/token.js

@@ -1,16 +1,18 @@
 const jwt = require('jsonwebtoken');
-const secret = 'SLDLKKDS323ssdd@#@@gf';
+const secret = 'red';
 
 module.exports = class extends think.Service {
   /**
    * 根据header中的X-Nideshop-Token值获取用户id
    */
   async getUserId(token) {
+    think.logger.debug('decode start');
     if (!token) {
       return 0;
     }
 
     const result = await this.parse(token);
+    think.logger.debug('decode: ' + result);
     if (think.isEmpty(result) || result.user_id <= 0) {
       return 0;
     }

+ 8 - 7
src/api/controller/auth.js

@@ -17,20 +17,21 @@ module.exports = class extends Base {
     if (think.isEmpty(userId)) {
       // 注册
       userId = await this.model('user').add({
-        username: '微信用户' + think.uuid(6),
+        name: '微信用户' + think.uuid(6),
         password: '',
-        register_time: parseInt(new Date().getTime() / 1000),
+        // createdAt: parseInt(new Date().getTime() / 1000),
+        createdAt: new Date().getTime(),
         register_ip: clientIp,
-        mobile: '',
-        weixin_openid: userInfo.openId,
-        avatar: userInfo.avatarUrl || '',
+        phone: '',
+        openid: userInfo.openId,
+        avatar_url: userInfo.avatarUrl || '',
         gender: userInfo.gender || 1, // 性别 0:未知、1:男、2:女
-        nickname: userInfo.nickName
+        nickName: userInfo.nickName
       });
     }
 
     // 查询用户信息
-    const newUserInfo = await this.model('user').field(['id', 'username', 'nickname', 'gender', 'avatar', 'birthday']).where({ id: userId }).find();
+    const newUserInfo = await this.model('user').field(['id', 'name', 'nickName', 'gender', 'avatar_url', 'birthday']).where({ id: userId }).find();
 
     // 更新登录信息
     userId = await this.model('user').where({ id: userId }).update({

+ 1 - 0
src/api/controller/base.js

@@ -2,6 +2,7 @@ module.exports = class extends think.Controller {
   async __before() {
     // 根据token值获取用户id
     this.ctx.state.token = this.ctx.header['x-nideshop-token'] || '';
+    think.logger.debug('token: ' + this.ctx.state.token);
     const tokenSerivce = think.service('token', 'api');
     this.ctx.state.userId = await tokenSerivce.getUserId(this.ctx.state.token);
 

+ 3 - 3
src/api/controller/cart.js

@@ -142,9 +142,9 @@ module.exports = class extends Base {
       // 添加规格名和值
       let goodsSepcifition = [];
       if (!think.isEmpty(productInfo.goods_specification_ids)) {
-        goodsSepcifition = await this.model('goods_specification').field(['nideshop_goods_specification.*', 'nideshop_specification.name']).join('nideshop_specification ON nideshop_specification.id=nideshop_goods_specification.specification_id').where({
-          'nideshop_goods_specification.goods_id': goodsId,
-          'nideshop_goods_specification.id': {'in': productInfo.goods_specification_ids.split('_')}
+        goodsSepcifition = await this.model('goods_specification').field(['redhat_goods_specification.*', 'redhat_specification.name']).join('redhat_specification ON redhat_specification.id=redhat_goods_specification.specification_id').where({
+          'redhat_goods_specification.goods_id': goodsId,
+          'redhat_goods_specification.id': {'in': productInfo.goods_specification_ids.split('_')}
         }).select();
       }
 

+ 13 - 4
src/api/controller/goods.js

@@ -1,3 +1,12 @@
+/*
+*  ApiRootUrl + 'goods/count',  //统计商品总数
+*  ApiRootUrl + 'goods/list',  //获得商品列表
+*  ApiRootUrl + 'goods/category',  //获得分类数据
+*  ApiRootUrl + 'goods/detail',  //获得商品的详情
+*  ApiRootUrl + 'goods/new',  //新品
+*  ApiRootUrl + 'goods/hot',  //热门
+*  ApiRootUrl + 'goods/related',  //商品详情页的关联商品(大家都在看)
+* */
 const Base = require('./base.js');
 
 module.exports = class extends Base {
@@ -32,19 +41,19 @@ module.exports = class extends Base {
 
     const info = await model.where({'id': goodsId}).find();
     const gallery = await this.model('goods_gallery').where({goods_id: goodsId}).limit(4).select();
-    const attribute = await this.model('goods_attribute').field('nideshop_goods_attribute.value, nideshop_attribute.name').join('nideshop_attribute ON nideshop_goods_attribute.attribute_id=nideshop_attribute.id').order({'nideshop_goods_attribute.id': 'asc'}).where({'nideshop_goods_attribute.goods_id': goodsId}).select();
+    const attribute = await this.model('goods_attribute').field('redhat_goods_attribute.value, redhat_attribute.name').join('redhat_attribute ON redhat_goods_attribute.attribute_id=redhat_attribute.id').order({'redhat_goods_attribute.id': 'asc'}).where({'redhat_goods_attribute.goods_id': goodsId}).select();
     const issue = await this.model('goods_issue').select();
     const brand = await this.model('brand').where({id: info.brand_id}).find();
     const commentCount = await this.model('comment').where({value_id: goodsId, type_id: 0}).count();
     const hotComment = await this.model('comment').where({value_id: goodsId, type_id: 0}).find();
     let commentInfo = {};
     if (!think.isEmpty(hotComment)) {
-      const commentUser = await this.model('user').field(['nickname', 'username', 'avatar']).where({id: hotComment.user_id}).find();
+      const commentUser = await this.model('user').field(['nicNkame', 'name', 'avatar_url']).where({id: hotComment.user_id}).find();
       commentInfo = {
         content: Buffer.from(hotComment.content, 'base64').toString(),
         add_time: think.datetime(new Date(hotComment.add_time * 1000)),
-        nickname: commentUser.nickname,
-        avatar: commentUser.avatar,
+        nickname: commentUser.nickName,
+        avatar: commentUser.avatar_url,
         pic_list: await this.model('comment_picture').where({comment_id: hotComment.id}).select()
       };
     }

+ 108 - 11
src/api/controller/order.js

@@ -143,19 +143,19 @@ module.exports = class extends Base {
 
     // 统计商品总价
     const orderGoodsData = [];
-    for (const goodsItem of checkedGoodsList) {
+    for (const checkedGoods of checkedGoodsList) {
       orderGoodsData.push({
         order_id: orderId,
-        goods_id: goodsItem.goods_id,
-        goods_sn: goodsItem.goods_sn,
-        product_id: goodsItem.product_id,
-        goods_name: goodsItem.goods_name,
-        list_pic_url: goodsItem.list_pic_url,
-        market_price: goodsItem.market_price,
-        retail_price: goodsItem.retail_price,
-        number: goodsItem.number,
-        goods_specifition_name_value: goodsItem.goods_specifition_name_value,
-        goods_specifition_ids: goodsItem.goods_specifition_ids
+        goods_id: checkedGoods.goods_id,
+        goods_sn: checkedGoods.goods_sn,
+        product_id: checkedGoods.product_id,
+        goods_name: checkedGoods.goods_name,
+        list_pic_url: checkedGoods.list_pic_url,
+        market_price: checkedGoods.market_price,
+        retail_price: checkedGoods.retail_price,
+        number: checkedGoods.number,
+        goods_specifition_name_value: checkedGoods.goods_specifition_name_value,
+        goods_specifition_ids: checkedGoods.goods_specifition_ids
       });
     }
 
@@ -177,4 +177,101 @@ module.exports = class extends Base {
     const latestExpressInfo = await this.model('order_express').getLatestOrderExpress(orderId);
     return this.success(latestExpressInfo);
   }
+
+  /**
+   * 立即购买(一件商品)
+   * @returns {Promise.<void>}
+   * post:
+   * brandId: 商户的id
+   * goodsId: 购买的商品的id
+   * goodsCount: 购买数量
+   */
+  async buynowAction() {
+    // 获取收货地址信息和计算运费
+    const brandId = this.post('brandId'); // 商户id
+    let checkedAddress = await this.model('address').where({ brandId: brandId }).find(); // 商户地址
+    if (think.isEmpty(checkedAddress)) {
+      checkedAddress = await this.model('address').where({ id: 1 }).find(); // 默认地址
+    }
+
+    // 获取要购买的商品
+    const checkedGoodsId = this.post('goodsId');
+    const checkedGoods = await this.model('goods').where({ id: checkedGoodsId }).find(); // 获取商品信息
+    if (think.isEmpty(checkedGoods)) {
+      return this.fail('商品已下架');
+    }
+
+    // 统计商品总价
+    const goodsTotalPrice = parseInt(this.post('goodsCount')) * Math.ceil(checkedGoods.retail_price / 50) * 50; // 价格取整
+
+    const currentTime = parseInt(this.getTime() / 1000);
+    // 更新用户余额
+    const user = await this.model('user').where({id: this.getLoginUserId()}).find();
+    if (think.isEmpty(user) || parseInt(user.isAuthen) === 0) return this.fail('用户未注册');
+    if (user.balance < goodsTotalPrice) return this.fail('余额不足');
+    think.logger.debug(user.balance + '-=' + goodsTotalPrice);
+    await this.model('user').where({id: this.getLoginUserId()}).update({
+      balance: user.balance - goodsTotalPrice
+    });
+    // 更新商品数量
+    if (checkedGoods.goods_number < this.post('goodsCount')) this.fail('库存不足');
+    await this.model('goods').where({id: checkedGoodsId}).update({
+      goods_number: checkedGoods.goods_number - this.post('goodsCount')
+    });
+
+    const orderInfo = {
+      order_sn: this.model('order').generateOrderNumber(),
+      user_id: this.getLoginUserId(),
+
+      // 收货地址和运费
+      consignee: checkedAddress.name,
+      mobile: checkedAddress.mobile,
+      province: checkedAddress.province_id,
+      city: checkedAddress.city_id,
+      district: checkedAddress.district_id,
+      address: checkedAddress.address,
+      freight_price: 0.00,
+
+      // 留言
+      postscript: '',
+
+      // 使用的优惠券
+      coupon_id: 0,
+      coupon_price: 0,
+
+      add_time: currentTime,
+      goods_price: goodsTotalPrice,
+      order_price: goodsTotalPrice,
+      actual_price: goodsTotalPrice
+    };
+
+    // 开启事务,插入订单信息和订单商品
+    const orderId = await this.model('order').add(orderInfo);
+    orderInfo.id = orderId;
+    if (!orderId) {
+      return this.fail('订单提交失败');
+    }
+
+    // 统计商品总价
+    const orderGoodsData = [];
+    for (let i = 0; i < this.post('goodsCount'); i++) {
+      orderGoodsData.push({
+        order_id: orderId,
+        goods_id: checkedGoods.goods_id,
+        goods_sn: checkedGoods.goods_sn,
+        product_id: checkedGoods.product_id,
+        goods_name: checkedGoods.goods_name,
+        list_pic_url: checkedGoods.list_pic_url,
+        market_price: checkedGoods.market_price,
+        retail_price: checkedGoods.retail_price,
+        number: checkedGoods.number,
+        goods_specifition_name_value: checkedGoods.goods_specifition_name_value,
+        goods_specifition_ids: checkedGoods.goods_specifition_ids
+      });
+    }
+
+    await this.model('order_goods').addMany(orderGoodsData);
+
+    return this.success({ orderInfo: orderInfo });
+  }
 };

+ 6 - 0
src/api/model/order.js

@@ -76,6 +76,12 @@ module.exports = class extends think.Model {
       case 0:
         statusText = '未付款';
         break;
+      case 1:
+        statusText = '未兑换';
+        break;
+      case 2:
+        statusText = '已兑换';
+        break;
     }
 
     return statusText;

+ 3 - 3
src/api/service/token.js

@@ -1,5 +1,5 @@
 const jwt = require('jsonwebtoken');
-const secret = 'SLDLKKDS323ssdd@#@@gf';
+const secret = 'red';
 
 module.exports = class extends think.Service {
   /**
@@ -11,11 +11,11 @@ module.exports = class extends think.Service {
     }
 
     const result = await this.parse(token);
-    if (think.isEmpty(result) || result.user_id <= 0) {
+    if (think.isEmpty(result) || result.payload.id <= 0) {
       return 0;
     }
 
-    return result.user_id;
+    return result.payload.id;
   }
 
   async create(userInfo) {

+ 7 - 0
src/api/service/weixin.js

@@ -17,7 +17,14 @@ module.exports = class extends think.Service {
         }
       };
 
+      think.logger.debug(options);
+      // https://api.weixin.qq.com/sns/jscode2session?
+      // appid=wx1d9f4b163c12a533&
+      // secret=7496465d9fd3e1d3374acd78632b2d11&
+      // js_code=033xbBxq1rswzj03LPwq1Onvxq1xbBxV&
+      // grant_type=authorization_code
       let sessionData = await rp(options);
+      think.logger.debug(sessionData);
       sessionData = JSON.parse(sessionData);
       if (!sessionData.openid) {
         return null;

+ 4 - 4
src/common/config/config.js

@@ -2,10 +2,10 @@
 module.exports = {
   default_module: 'api',
   weixin: {
-    appid: '', // 小程序 appid
-    secret: '', // 小程序密钥
-    mch_id: '', // 商户帐号ID
-    partner_key: '', // 微信支付密钥
+    appid: 'wx1d9f4b163c12a533', // 小程序 appid
+    secret: '7496465d9fd3e1d3374acd78632b2d11', // 小程序密钥
+    mch_id: '1489349402', // 商户帐号ID
+    partner_key: '8Y7GxRqWiM9hFZVmFQxyrN4CkHjMQp6X', // 微信支付密钥
     notify_url: '' // 微信异步通知,例:https://www.nideshop.com/api/pay/notify
   },
   express: {

+ 4 - 4
src/common/config/database.js

@@ -2,12 +2,12 @@ const mysql = require('think-model-mysql');
 
 module.exports = {
   handle: mysql,
-  database: 'nideshop',
-  prefix: 'nideshop_',
+  database: 'usedbooksredhat',
+  prefix: 'redhat_',
   encoding: 'utf8mb4',
   host: 'south.niimei.com',
   port: '3306',
-  user: 'nideshop',
-  password: 'nideshop123',
+  user: 'usedbooksredhat',
+  password: '2YDnBaJBRKEQX822',
   dateStrings: true
 };