API统一接口使用示例.md 9.6 KB

API统一接口使用示例

概述

为了简化API接口,我们将原来的两个计算接口合并为一个统一的 /api/order/calculate 接口,通过 type 参数区分计算模式。

统一的计算接口

接口地址

POST /api/order/calculate

参数说明

参数 类型 必填 说明
type string 计算类型:cart(购物车模式)或 goods(商品规格模式)
address_id int 收货地址ID
user_coupon_id int 优惠券ID
cart_ids array 条件必填 购物车ID列表(当 type=cart 时必填)
goods_list array 条件必填 商品列表(当 type=goods 时必填)

使用示例

1. 商品规格模式计算

前端请求:

// 立即购买场景:用户在商品详情页选择规格后点击"立即购买"
const calculateByGoods = async (goodsId, skuId, nums, addressId) => {
    const response = await fetch('/api/order/calculate', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            type: 'goods',          // 商品规格模式
            goods_list: [
                {
                    goods_id: goodsId,
                    goods_sku_id: skuId,
                    nums: nums
                }
            ],
            address_id: addressId,
            user_coupon_id: 0       // 暂不使用优惠券
        })
    });
    
    const result = await response.json();
    console.log('订单预览信息:', result.data);
    return result.data;
};

// 调用示例
calculateByGoods(1, 5, 2, 10);

后端响应:

{
    "code": 1,
    "msg": "获取成功",
    "data": {
        "coupons": [],
        "goods_list": [
            {
                "goods_id": 1,
                "goods_sku_id": 5,
                "nums": 2,
                "goods": {
                    "id": 1,
                    "title": "测试商品",
                    "image": "/uploads/goods/1.jpg",
                    "price": "99.00"
                },
                "sku": {
                    "id": 5,
                    "price": "99.00"
                },
                "sku_attr": "颜色:红色,尺寸:XL"
            }
        ],
        "order_info": {
            "goodsprice": "198.00",
            "shippingfee": "10.00",
            "discount": "0.00",
            "amount": "208.00",
            "saleamount": "208.00"
        },
        "couponTotalPrice": 198.00
    }
}

2. 购物车模式计算

前端请求:

// 购物车结算场景:用户在购物车页面选择商品后点击"去结算"
const calculateByCart = async (cartIds, addressId, couponId) => {
    const response = await fetch('/api/order/calculate', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            type: 'cart',           // 购物车模式
            cart_ids: cartIds,
            address_id: addressId,
            user_coupon_id: couponId || 0
        })
    });
    
    const result = await response.json();
    console.log('订单预览信息:', result.data);
    return result.data;
};

// 调用示例
calculateByCart([1, 2, 3], 10, 5);

后端响应:

{
    "code": 1,
    "msg": "获取成功",
    "data": {
        "coupons": [
            {
                "id": 5,
                "title": "满200减20",
                "condition": 200,
                "money": 20
            }
        ],
        "goods_list": [
            {
                "goods_id": 1,
                "nums": 2,
                "goods": {
                    "title": "商品A",
                    "price": "99.00"
                }
            },
            {
                "goods_id": 2,
                "nums": 1,
                "goods": {
                    "title": "商品B",
                    "price": "150.00"
                }
            }
        ],
        "order_info": {
            "goodsprice": "348.00",
            "shippingfee": "15.00",
            "discount": "20.00",
            "amount": "363.00",
            "saleamount": "343.00"
        },
        "couponTotalPrice": 348.00
    }
}

3. 批量购买模式计算

前端请求:

// 批量购买场景:用户选择多个商品进行批量购买
const calculateBatch = async (goodsList, addressId) => {
    const response = await fetch('/api/order/calculate', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json'
        },
        body: JSON.stringify({
            type: 'goods',          // 商品规格模式
            goods_list: goodsList,  // 多个商品
            address_id: addressId,
            user_coupon_id: 0
        })
    });
    
    return await response.json();
};

// 调用示例:购买3个不同商品
const batchGoods = [
    { goods_id: 1, goods_sku_id: 5, nums: 2 },  // 商品A,红色XL,2件
    { goods_id: 2, goods_sku_id: 0, nums: 1 },  // 商品B,单规格,1件
    { goods_id: 3, goods_sku_id: 8, nums: 3 }   // 商品C,蓝色L,3件
];

calculateBatch(batchGoods, 10);

错误处理

1. 参数验证错误

{
    "code": 0,
    "msg": "计算类型只能是cart或goods",
    "data": null
}

2. 商品不存在错误

{
    "code": 0,
    "msg": "商品已下架",
    "data": null
}

3. 库存不足错误

{
    "code": 0,
    "msg": "商品库存不足,请重新修改数量",
    "data": null
}

4. 购物车为空错误

{
    "code": 0,
    "msg": "购物车ID列表不能为空",
    "data": null
}

前端集成指南

Vue.js 组件示例

<template>
  <div class="order-calculate">
    <button @click="calculateOrder">计算订单</button>
    <div v-if="orderInfo">
      <p>商品金额:¥{{ orderInfo.goodsprice }}</p>
      <p>运费:¥{{ orderInfo.shippingfee }}</p>
      <p>优惠:-¥{{ orderInfo.discount }}</p>
      <p>应付:¥{{ orderInfo.saleamount }}</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      orderInfo: null,
      goodsList: [
        { goods_id: 1, goods_sku_id: 5, nums: 2 }
      ],
      cartIds: [1, 2, 3],
      addressId: 10,
      calculateType: 'goods' // 或 'cart'
    }
  },
  methods: {
    async calculateOrder() {
      try {
        const params = {
          type: this.calculateType,
          address_id: this.addressId,
          user_coupon_id: 0
        };
        
        if (this.calculateType === 'goods') {
          params.goods_list = this.goodsList;
        } else {
          params.cart_ids = this.cartIds;
        }
        
        const response = await this.$http.post('/api/order/calculate', params);
        
        if (response.data.code === 1) {
          this.orderInfo = response.data.data.order_info;
        } else {
          this.$message.error(response.data.msg);
        }
      } catch (error) {
        console.error('计算订单失败:', error);
        this.$message.error('计算订单失败');
      }
    }
  }
}
</script>

React Hook 示例

import { useState, useCallback } from 'react';

const useOrderCalculate = () => {
  const [orderInfo, setOrderInfo] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  const calculate = useCallback(async (type, data) => {
    setLoading(true);
    setError(null);
    
    try {
      const params = {
        type,
        address_id: data.addressId,
        user_coupon_id: data.couponId || 0
      };
      
      if (type === 'goods') {
        params.goods_list = data.goodsList;
      } else {
        params.cart_ids = data.cartIds;
      }
      
      const response = await fetch('/api/order/calculate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(params)
      });
      
      const result = await response.json();
      
      if (result.code === 1) {
        setOrderInfo(result.data.order_info);
      } else {
        setError(result.msg);
      }
    } catch (err) {
      setError('计算订单失败');
    } finally {
      setLoading(false);
    }
  }, []);

  return { orderInfo, loading, error, calculate };
};

// 使用示例
const OrderPage = () => {
  const { orderInfo, loading, error, calculate } = useOrderCalculate();

  const handleCalculate = () => {
    calculate('goods', {
      goodsList: [{ goods_id: 1, goods_sku_id: 5, nums: 2 }],
      addressId: 10,
      couponId: 0
    });
  };

  return (
    <div>
      <button onClick={handleCalculate} disabled={loading}>
        {loading ? '计算中...' : '计算订单'}
      </button>
      {error && <div className="error">{error}</div>}
      {orderInfo && (
        <div className="order-info">
          <p>商品金额:¥{orderInfo.goodsprice}</p>
          <p>运费:¥{orderInfo.shippingfee}</p>
          <p>优惠:-¥{orderInfo.discount}</p>
          <p>应付:¥{orderInfo.saleamount}</p>
        </div>
      )}
    </div>
  );
};

优势总结

  1. 接口统一:只需要维护一个计算接口,减少了API复杂度
  2. 参数清晰:通过 type 参数明确区分计算模式
  3. 响应一致:两种模式返回相同的数据结构
  4. 易于扩展:未来如需新增计算模式,只需增加新的 type
  5. 向后兼容:保持了原有的功能特性
  6. 错误统一:统一的错误处理和验证机制

这种设计使得前端开发更加简洁,同时保持了功能的完整性和扩展性。