掌握网购DAPP的编写

合约整体流程
首先卖家部署商品合约,声明自己的账户地址、商品的价格、承诺的发货时间。
买家通过商品合约部署订单合约(注意订单合约的msg.sender是商品合约的地址)支付商品价格p+押金p,买家等待卖家接单,期间可以取消购买,退还2p。
卖家如果接单,需要交付价值为p的押金,同时要在自己承诺的发货时间内发货。如果拒绝接单,则合约将钱退还买家。
如果卖家没能在承诺时间发货,买家可以调用checkLate,退回押金,同时作为惩罚,卖家的押金将无法取回(可能有方法取回?)。
卖家确认发货时要填写运单(物流)号,为了验证这个订单号,需要物流公司接入以太坊并提供接口,这里就不模拟了,直接跳过验证。同样,签收的过程也偷懒省略了。
接着买家确认收货,为了防止恶意不确认或买家忘记确认,签收10天后卖家可以自己确认。
最后买家对订单进行评价。合约没有实现退货等功能。

`pragma solidity^0.4.22;
// 商品合约
contract Product {
    
    
    bool public enable;         // 当前商品是否有效
    address public sellerAddr;  // 卖家的地址
    uint public price;          // 商品的单价
    uint public commitTime;     // 卖家承诺发货时间
    address[] public orders;    // 所有订单的地址
    address public lastOrder;   // 最新订单的地址
    modifier onlySeller() {
    
    
        require(
            sellerAddr == msg.sender,
            "卖家账号地址错误!"
        );
        _;
    }
    constructor(bool _enable, uint _price, uint _commitTime)
        public
    {
    
    
        require(
            _price != 0 && _commitTime != 0,
            "参数信息不完整"
        );
        sellerAddr = msg.sender;
        enable = _enable;
        price = _price;
        commitTime = _commitTime;}
    function setEnable(bool _enable)
        public
        onlySeller
    {
    
    
        enable = _enable;
    }
    function setPrice(uint _price)
        public
        onlySeller
    {
    
    
        price = _price;
    }
    function setCommitTime(uint _commitTime)
        public
        onlySeller
    {
    
    
        commitTime = _commitTime;
    }
    function getOrderCount()
        public
        view
        returns(uint _count)
    {
    
    
        return orders.length;
    }
    // 买家创建订单,输入购买数量和两倍原价的msg.value
    event NewOrder(address _orderAddr);
    function newOrder(uint amount)
        public
        payable
    {
    
    
        require(
            enable == true,
            "产品当前无法下单"
        );
        require(
            amount != 0,
            "购买数量不能为0"
        );
        Order order = (new Order).value(msg.value)(msg.sender, sellerAddr, price * amount, commitTime);
        orders.push(order);
        lastOrder = order;
        emit NewOrder(order);
    }
}
// 订单合约
contract Order {
    
    
    // 已支付,已接单,已发货,已签收,已收货,已失效
    enum Status {
    
    
        Paid, Taken, Shipped, Signed, Received, Inactive
    }
    address public buyerAddr;      // 买家的地址
    address public sellerAddr;     // 卖家的地址
    uint public price;             // 商品的总价
    uint public commitTime;        // 卖家承诺发货时间
    Status public status;          // 订单的状态
    uint public createTime;        // 订单的创建(支付)时间
    uint public signTime;          // 订单的签收时间
    string public trackingNumber;  // 订单的物流号
    uint8 public score;            // 订单的评分
    string public assession;       // 订单的评价
    modifier inStatus(Status _status) {
    
    
        require(
            status == _status,
            "订单的状态不可操作"
        );
        _;
    }
    modifier onlyBuyer() {
    
    
        require(
            buyerAddr == msg.sender,
            "买家账号地址错误!"
        );
        _;
    }
    modifier onlySeller() {
    
    
        require(
            sellerAddr == msg.sender,
            "卖家账号地址错误!"
        );
        _;
    }
    function getBalance()
        public
        view
        returns(uint _balance)
    {
    
    
        return address(this).balance;
    }
    constructor(address _buyerAddr, address _sellerAddr, uint _price, uint _commitTime)
        public
        payable
    {
    
    
        require(
            msg.value == _price * 2,
            "买家需要额外支付与商品价格等价的金额作为押金"
        );
        buyerAddr = _buyerAddr;
        sellerAddr = _sellerAddr;
        price = _price;
        commitTime = _commitTime;
        status = Status.Paid;
        createTime = now;
    }
    // 卖家接单之前用户可以取消购买
    function abort()
        public
        onlyBuyer
        payable
        inStatus(Status.Paid)
    {
    
    
        status = Status.Inactive;
        buyerAddr.transfer(price * 2);
    }
    // 卖家选择接单或拒绝接单
    function take(bool _takeOrder)
        public
        onlySeller
        payable
        inStatus(Status.Paid)
    {
    
    
        if (_takeOrder) {
    
    
            require(
                msg.value == price,
                "卖家需要支付与商品价格等价的金额作为押金"
            );
            status = Status.Taken;
        }
        else {
    
    
            status = Status.Inactive;
            buyerAddr.transfer(price * 2);
        }
    }

    // 买家检查卖家是否没按时发货,如果是则退还买家钱,同时作为惩罚,卖家的押金被锁定在合约里了
    function checkLate()
        public
        onlyBuyer
        inStatus(Status.Taken)
    {
    
    
        require(
            now - createTime > commitTime,
            "尚未到卖家发货截止期限"
        );
        status = Status.Inactive;
        buyerAddr.transfer(price * 2);
    }
    // 卖家输入运单号,确认发货
    function ship(string _trackingNumber)
        public
        onlySeller
        payable
        inStatus(Status.Taken)
    {
    
    
        // todo: 检查运单号是否真实存在
        status = Status.Shipped;
        trackingNumber = _trackingNumber;
        sellerAddr.transfer(price); // 卖家发货后退回押金
    }
    // 确认签收
    function sign()
        public
        inStatus(Status.Shipped)
    {
    
    
        // todo: 通过运单号查询物流信息,判断是否签收并获取签收时间
        status = Status.Signed;
        // signTime = getSignTime();
        signTime = now; // 测试用
    }
    // 买家确认收货
    function receive()
        public
        onlyBuyer
        payable
        inStatus(Status.Signed)
    {
    
    
        status = Status.Received;
        buyerAddr.transfer(price);
        sellerAddr.transfer(price);
    }
    // 过了10天买家没确认收货,则卖家可以自己确认
    function confirmBySeller()
        public
        onlySeller
        payable
        inStatus(Status.Signed)
    {
    
    
        require(
            now - signTime > 10 days,
            "卖家超过10天才可以确认"
        );
        status = Status.Received;
        buyerAddr.transfer(price);
        sellerAddr.transfer(price);
    }
    // 买家对订单进行评价
    function assess(uint8 _score, string _assession)
        public
        onlyBuyer
        inStatus(Status.Received)
    {
    
    
        require(
            _score >= 1 && _score <= 5,
            "评分只能是1~5之间的整数"
        );
        score = _score;
        assession = _assession;
        status = Status.Inactive;
    }
}

演示:
1)商品买卖需要两方进行,所以我们构建了两个合约。
2)首先卖家部署商品合约,并设置是否可买、价格和提交时间。(是否可卖用0和1表示)
在这里插入图片描述

3)合约部署之后,卖家可通过setPrice,setEnable和setCommitTime函数对价格、是否买卖和提交时间进行修改。
在这里插入图片描述

4)买家部署合约,在部署之前要输入买卖双方的地址、价格和时间。注意在value中填入商品价格两倍的金额。在这里插入图片描述

5)卖家可以通过take函数判断是都卖出商品。这里要在value中填入等价商品的金额用于保证金。
在这里插入图片描述

6)卖出商品之后,买家可以通过checkLate函数检查是否没按时发货,如果是则退还买家钱,同时作为惩罚,卖家的押金被锁定在合约里了
在这里插入图片描述

7)卖家通过ship函数输入运单号,确认发货
在这里插入图片描述

8)买家收到货物之后通过sign函数签收。
在这里插入图片描述

9)买家通过receive函数确认收货。
在这里插入图片描述

10)买家通过assess函数进行打分评价。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/mlynb/article/details/127816821
今日推荐