電商系統設計之訂單

GraceDevelopment發表於2018-07-30

前言

使用者交易將經歷一段艱辛的歷程,一般使用者感覺不到,實際程式是經歷了一段生死離別。具體付款流程如下

電商系統設計之訂單

不(wo)是(gu)這(yi)張(chuan)圖(de),請看正經流程圖

電商系統設計之訂單

之前的幾篇文章介紹了

  • 購物車如何設計
  • 使用者系統如何設計
  • 商品系統如何設計

其實他們都在為交易系統做鋪墊,一個產品如果沒有收入,那這隻能是寺廟的公益產品。任何產品最終都要走向這步 (收錢)。

付款

使用者付款過程中有很多場景也會出現意外,以下是我碰到的“天災人禍”

成功

  • 使用者發起微信支付併成功支付
  • 使用者發起支付寶支付併成功支付
  • 使用者發起銀聯支付併成功支付
  • 使用者發起其他支付併成功支付

人禍

  • 使用者發起微信支付但取消支付
  • 使用者發起支付寶支付但取消支付
  • 使用者發起銀聯支付但取消支付
  • 使用者發起其他支付但取消支付

天災

  • 使用者發起微信支付“手機爆炸了”
  • 使用者發起支付寶支付“瞬間沒網了”
  • 使用者發起銀聯支付“老婆來電話了”
  • 使用者發起其他支付“老闆進來了”

註釋

遇到以上的情況,不要害怕、不要驚慌,並且不要“理會”,你只需要將這些操作記錄下來即可。 正常我們都會將使用者通過哪種支付方式儲存到訂單表中,方便查詢。我想說這種做法沒錯,但是少了點什麼,你應該有一張交易記錄表,來記錄使用者發起了多少次支付,只有支付成功的時候方可記錄到訂單表中。這樣做的優點有以下兩點

  • 訂單表是比較重要的,迫不得已儘量不要操作這張表,防止出現意外,訂單表除了收貨發貨外一般沒有其他需要操作的地方。
  • 可以記錄每次使用者發起支付的時間,通過所謂大資料分析使用者對產品的需求度和認可度,如果使用者多次發起付款但取消支付,那就說明(他沒錢)他可能很期望得到,但是因為某種原因一直在猶豫,這個時候可以針對當前使用者做優惠處理,例如發一張優惠券等等。

電商系統設計之訂單

表結構

交易表

CREATE TABLE `transaction` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_sn` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易單號',
  `member_id` bigint(20) NOT NULL COMMENT '交易的使用者ID',
  `amount` decimal(8,2) NOT NULL COMMENT '交易金額',
  `integral` int(11) NOT NULL DEFAULT '0' COMMENT '使用的積分',
  `pay_state` tinyint(4) NOT NULL COMMENT '支付型別 0:餘額 1:微信 2:支付寶 3:xxx',
  `source` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '支付來源 wx app web wap',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付狀態 -1:取消 0 未完成 1已完成 -2:異常',
  `completion_time` int(11) NOT NULL COMMENT '交易完成時間',
  `note` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '備註',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `transaction_order_sn_member_id_pay_state_source_status_index` (`order_sn`(191),`member_id`,`pay_state`,`source`(191),`status`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
複製程式碼

支付記錄表

CREATE TABLE `transaction_record` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_sn` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `events` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '事件詳情',
  `result` text COLLATE utf8mb4_unicode_ci COMMENT '結果詳情',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
複製程式碼

這個記錄表可能讓你匪夷所思,不知你對日誌有什麼概念,但我能說的就是,將使用者的所有動作全部記錄下來。這是很重要的,早晚你會懂。

訂單表

CREATE TABLE `order` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '訂單編號',
  `order_sn` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '交易號',
  `member_id` int(11) NOT NULL COMMENT '客戶編號',
  `supplier_id` int(11) NOT NULL COMMENT '商戶編碼',
  `supplier_name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '商戶名稱',
  `order_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '訂單狀態 0未付款,1已付款,2已發貨,3已簽收,-1退貨申請,-2退貨中,-3已退貨,-4取消交易',
  `after_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '使用者售後狀態 0 未發起售後 1 申請售後 -1 售後已取消 2 處理中 200 處理完畢',
  `product_count` int(11) NOT NULL DEFAULT '0' COMMENT '商品數量',
  `product_amount_total` decimal(12,4) NOT NULL COMMENT '商品總價',
  `order_amount_total` decimal(12,4) NOT NULL DEFAULT '0.0000' COMMENT '實際付款金額',
  `logistics_fee` decimal(12,4) NOT NULL COMMENT '運費金額',
  `address_id` int(11) NOT NULL COMMENT '收貨地址編碼',
  `pay_channel` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付渠道 0餘額 1微信 2支付寶',
  `out_trade_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '訂單支付單號',
  `escrow_trade_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '第三方支付流水號',
  `pay_time` int(11) NOT NULL DEFAULT '0' COMMENT '付款時間',
  `delivery_time` int(11) NOT NULL DEFAULT '0' COMMENT '發貨時間',
  `order_settlement_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '訂單結算狀態 0未結算 1已結算',
  `order_settlement_time` int(11) NOT NULL DEFAULT '0' COMMENT '訂單結算時間',
  `is_package` enum('0','1') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '是否是套餐',
  `is_integral` enum('0','1') COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '是否是積分產品',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  `deleted_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_order_sn_unique` (`order_sn`),
  KEY `order_order_sn_member_id_order_status_out_trade_no_index` (`order_sn`,`member_id`,`order_status`,`out_trade_no`(191))
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
複製程式碼

運輸

使用者付款結束後接下來就是快遞公司的事了,當然我們們不搭理送快遞的。到這一步我們就應該給客戶展示運輸資訊。現在一些api開放平臺都有快遞查詢的服務,有收費有免費的,效能方面差異也不大。但這裡要注意一點。不是每次使用者都會查詢到新的資訊。對於小公司來說,這樣成本極高。所以我們應該定時去查詢快遞物流資訊。這個地方有個簡單的演算法。

if(使用者點選檢視了){
    從使用者點選檢視兩小時後更新物流資訊 // 這裡是按照兩小時來更新的,也可以拉長這個時間
}else{
    每兩小時更新一次物流資訊
}
複製程式碼

這種頻繁的更新絕對要使用nosql,當使用者確認收貨後再儲存到mysql等資料庫中。

收貨

當使用者收到貨後,這其實是最難伺候的時候,使用者對產品的各種不滿意就可能導致退換貨,收貨操作既改變訂單狀態為已收貨,複雜點的可能還需要im,簡訊,推送提醒下。一般都直接提醒,量大的話加入佇列內處理。

退換貨

退換貨淘寶是這樣處理的。 淘寶將訂單分兩種狀態

  • 未付款、已付款、已收貨、已評價
  • 發起售後、售後稽核、售後處理、處理完成

電商系統設計之訂單

圖1展示了每個商品,包括子商品都可以單獨發起售後

電商系統設計之訂單

圖2是點選申請售後之後的頁面

電商系統設計之訂單

圖3是選擇退換貨的相關事項

當完成這些步驟後,就會開啟售後稽核,賣家稽核成功後方可進行下一步操作

售後申請表

CREATE TABLE `order_returns_apply` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '訂單單號',
  `order_detail_id` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '子訂單編碼',
  `return_no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '售後單號',
  `member_id` int(11) NOT NULL COMMENT '使用者編碼',
  `state` tinyint(4) NOT NULL COMMENT '型別 0 僅退款 1退貨退款',
  `product_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '貨物狀態 0:已收到貨 1:未收到貨',
  `why` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '退換貨原因',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '稽核狀態 -1 拒絕 0 未稽核 1稽核通過',
  `audit_time` int(11) NOT NULL DEFAULT '0' COMMENT '稽核時間',
  `audit_why` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '稽核原因',
  `note` text COLLATE utf8mb4_unicode_ci COMMENT '備註',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
複製程式碼

售後表

CREATE TABLE `order_returns` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `returns_no` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退貨編號 供客戶查詢',
  `order_id` int(11) NOT NULL COMMENT '訂單編號',
  `express_no` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '物流單號',
  `consignee_realname` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '收貨人姓名',
  `consignee_telphone` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '聯絡電話',
  `consignee_telphone2` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '備用聯絡電話',
  `consignee_address` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '收貨地址',
  `consignee_zip` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '郵政編碼',
  `logistics_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '物流方式',
  `logistics_fee` decimal(12,2) NOT NULL COMMENT '物流發貨運費',
  `order_logistics_status` int(11) DEFAULT NULL COMMENT '物流狀態',
  `logistics_settlement_status` int(11) DEFAULT NULL COMMENT '物流結算狀態',
  `logistics_result_last` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '物流最後狀態描述',
  `logistics_result` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '物流描述',
  `logistics_create_time` int(11) DEFAULT NULL COMMENT '發貨時間',
  `logistics_update_time` int(11) DEFAULT NULL COMMENT '物流更新時間',
  `logistics_settlement_time` int(11) DEFAULT NULL COMMENT '物流結算時間',
  `returns_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0全部退單 1部分退單',
  `handling_way` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'PUPAWAY:退貨入庫;REDELIVERY:重新發貨;RECLAIM-REDELIVERY:不要求歸還並重新發貨; REFUND:退款; COMPENSATION:不退貨並賠償',
  `returns_amount` decimal(8,2) NOT NULL COMMENT '退款金額',
  `return_submit_time` int(11) NOT NULL COMMENT '退貨申請時間',
  `handling_time` int(11) NOT NULL COMMENT '退貨處理時間',
  `remark` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '退貨原因',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
複製程式碼

評價

如果使用者收貨後直接評價了,那恭喜你,這筆訂單基本成交了。這個沒什麼可講的,一般小的電商也沒有刷評價的,類似淘寶的防止刷評價的做法太過於複雜,這裡也不過多講解(其實我也沒接觸過)。

評價資料表

CREATE TABLE `order_appraise` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `order_id` int(11) NOT NULL COMMENT '訂單編碼',
  `info` text COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '評論內容',
  `level` enum('-1','0','1') COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '級別 -1差評 0中評 1好評',
  `desc_star` tinyint(4) NOT NULL COMMENT '描述相符 1-5',
  `logistics_star` tinyint(4) NOT NULL COMMENT '物流服務 1-5',
  `attitude_star` tinyint(4) NOT NULL COMMENT '服務態度 1-5',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `order_appraise_order_id_index` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
複製程式碼

致謝

感謝你看到這裡,希望我的文章和程式碼可以幫助到你。如果有什麼疑問可以在評論區留言,謝謝

相關文章