• 掌握网购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
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237

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

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

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

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

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

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

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

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

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

  • 相关阅读:
    基于流谱理论的SSL/TLS协议攻击检测方法
    性能与效果平衡:选择适合项目的直播实时美颜SDK
    可持久化01Trie
    web前端期末大作业——基于html+css+javascript+jquery+bootstrap响应式户外旅游网站
    推荐一个专利检索的网站
    vue3使用postcss-px-to-viewport适配屏幕
    Git 代码提交注释管理规范
    【Java从入门到精通 08】:面向对象编程(进阶部分)
    【FPGA教程案例34】通信案例4——基于FPGA的QPSK调制信号产生,通过matlab测试其星座图
    mybatisplus多租户原理略解
  • 原文地址:https://blog.csdn.net/mlynb/article/details/127816821