票接口對(duì)接實(shí)戰(zhàn):從材料拆解到聯(lián)調(diào)排錯(cuò)全流程指南)
簡(jiǎn)介面向醫(yī)院信息系統(tǒng)與財(cái)務(wù)軟件開(kāi)發(fā)人員的博思開(kāi)票接口完整材料集中匯總新舊版本對(duì)接所需的Dll動(dòng)態(tài)庫(kù)、接口規(guī)范說(shuō)明和測(cè)試程序可幫助讀者快速理解開(kāi)票流程、數(shù)據(jù)交換格式及聯(lián)調(diào)方法尤其適合HIS廠商、集成商或負(fù)責(zé)開(kāi)票對(duì)接的工程技術(shù)人員。整個(gè)壓縮包共271個(gè)文件約16.94MB以Dll庫(kù)、exe測(cè)試工具、txt規(guī)范文檔和bmp界面素材為主同時(shí)包含PowerBuilder、Delphi、VB、Html等多語(yǔ)言示例源碼。其中bmp文件多為界面或流程截圖dat及txt樣例給出醫(yī)院軟件轉(zhuǎn)入開(kāi)票的數(shù)據(jù)格式pas、frm、pbl等源碼便于直接參考或二次開(kāi)發(fā)配套的博思開(kāi)票測(cè)試卡、Kp虛擬卡和開(kāi)票測(cè)試程序則支持在無(wú)真實(shí)設(shè)備環(huán)境中演練。資源整體結(jié)構(gòu)清晰覆蓋從接口規(guī)范、數(shù)據(jù)樣例到多語(yǔ)言調(diào)用示例的完整鏈路能顯著縮短對(duì)接過(guò)程中的摸索時(shí)間。已有1123人學(xué)習(xí)下載適合需要直接調(diào)用接口、快速完成開(kāi)票模塊接入的開(kāi)發(fā)者。 做企業(yè)系統(tǒng)集成最怕的就是對(duì)方甩過(guò)來(lái)一個(gè)壓縮包告訴你“接口材料都在里面了”。我剛拿到“博思開(kāi)票接口完整材料.zip”的時(shí)候心里其實(shí)很復(fù)雜——材料給得越“完整”意味著里面的文件和文檔越多越需要在短時(shí)間內(nèi)理清主線、找到真正干活需要的部分。這個(gè)壓縮包本質(zhì)上是開(kāi)票服務(wù)的接口對(duì)接資料包含接口文檔、示例代碼、證書(shū)密鑰和配置說(shuō)明。它解決的核心問(wèn)題就是把企業(yè)內(nèi)部業(yè)務(wù)系統(tǒng)中的單據(jù)數(shù)據(jù)安全、準(zhǔn)確地提交到開(kāi)票服務(wù)平臺(tái)從而自動(dòng)開(kāi)具發(fā)票、查詢狀態(tài)、處理紅沖和作廢。這篇文章適合正在做ERP、財(cái)務(wù)系統(tǒng)、電商后臺(tái)或者任何需要對(duì)接發(fā)票服務(wù)的開(kāi)發(fā)同學(xué)參考。我會(huì)從拿到壓縮包的第一反應(yīng)開(kāi)始講逐步拆解如何高效分析材料、完成接口聯(lián)調(diào)并分享一些常規(guī)文檔里不會(huì)寫(xiě)的實(shí)戰(zhàn)經(jīng)驗(yàn)。1. 材料包先拆成四類心里就有底了打開(kāi)“完整材料.zip”的一瞬間大多數(shù)人的第一反應(yīng)是文件這么多先看哪個(gè)我的做法是先在本地新建一個(gè)臨時(shí)目錄把所有文件解壓出來(lái)然后按類型歸類。這個(gè)動(dòng)作看起來(lái)簡(jiǎn)單卻是整個(gè)對(duì)接過(guò)程中最關(guān)鍵的一步——它決定了你后續(xù)是像無(wú)頭蒼蠅一樣亂翻還是能直接進(jìn)入有效工作狀態(tài)。1.1 接口文檔是主心骨別急著看代碼壓縮包里最值錢(qián)的永遠(yuǎn)不是代碼而是接口文檔。一份合格的開(kāi)票接口文檔至少應(yīng)該包含開(kāi)通流程說(shuō)明、接口清單、報(bào)文規(guī)范和錯(cuò)誤碼表。我習(xí)慣先把接口文檔通讀一遍重點(diǎn)記錄兩件事一是總共有多少接口、每個(gè)接口是干什么用的二是接口之間有沒(méi)有強(qiáng)制的調(diào)用順序。開(kāi)票接口的文檔尤其要注意區(qū)分“基礎(chǔ)信息接口”和“業(yè)務(wù)處理接口”——前者包括查詢稅盤(pán)信息、查詢發(fā)票庫(kù)存、獲取開(kāi)票配置等后者包括藍(lán)票開(kāi)具、紅字發(fā)票開(kāi)具、發(fā)票查詢、作廢申請(qǐng)等。這兩類接口的使用場(chǎng)景完全不一樣不能在聯(lián)調(diào)初期就把它們混在一起調(diào)試。千萬(wàn)不要一上來(lái)就打開(kāi)SDK示例代碼去讀邏輯。代碼只是文檔的某種實(shí)現(xiàn)形式而不同語(yǔ)言、不同版本的SDK細(xì)節(jié)會(huì)有差異如果以代碼為準(zhǔn)去反推接口語(yǔ)義很容易被無(wú)關(guān)的異常分支帶偏。正確順序是先把文檔中的接口清單和調(diào)用流程吃透再對(duì)照代碼驗(yàn)證自己的理解。1.2 SDK、證書(shū)、配置文件各歸其位材料包里除了文檔通常還包含SDK壓縮包、證書(shū)文件和配置文件模板。SDK按語(yǔ)言區(qū)分常見(jiàn)的可能是Java版、C#版也有Python版。證書(shū)文件往往是.pfx、.cer或.p12格式用于客戶端身份認(rèn)證和報(bào)文簽名。配置文件模板則是讓你快速生成聯(lián)調(diào)所需參數(shù)的起點(diǎn)比如應(yīng)用ID、密鑰、網(wǎng)關(guān)地址、回調(diào)地址等。我的建議是把這三類文件分開(kāi)存放并且養(yǎng)成“證書(shū)文件不放進(jìn)代碼倉(cāng)庫(kù)”的習(xí)慣。因?yàn)樽C書(shū)通常有有效期限制而且一旦泄露可能導(dǎo)致身份被冒用給企業(yè)帶來(lái)安全風(fēng)險(xiǎn)。很多團(tuán)隊(duì)在聯(lián)調(diào)階段圖省事把證書(shū)直接丟在項(xiàng)目源碼目錄里最后不得不做安全整改。從一開(kāi)始就規(guī)范處理能省掉后面不少麻煩。2. 開(kāi)票接口的通用業(yè)務(wù)鏈路發(fā)票開(kāi)具的核心流程是業(yè)務(wù)系統(tǒng)把單據(jù)信息傳給開(kāi)票平臺(tái)由平臺(tái)完成開(kāi)票并將發(fā)票數(shù)據(jù)進(jìn)行回寫(xiě)。這個(gè)過(guò)程中接口調(diào)用的先后順序、參數(shù)傳遞方式、異常處理機(jī)制都決定了整套系統(tǒng)的穩(wěn)定性。2.1 從訂單到發(fā)票接口調(diào)用順序不能亂以最常見(jiàn)的增值稅發(fā)票開(kāi)具場(chǎng)景為例完整的接口調(diào)用鏈路大致如下開(kāi)票前的準(zhǔn)備查詢稅盤(pán)狀態(tài)、發(fā)票庫(kù)存和開(kāi)票配置。提交開(kāi)票請(qǐng)求把購(gòu)買(mǎi)方信息、商品明細(xì)、金額和稅額等組成報(bào)文調(diào)用開(kāi)票接口。查詢開(kāi)票狀態(tài)因?yàn)殚_(kāi)票平臺(tái)可能是異步處理的提交后需要輪詢查詢接口確認(rèn)是否成功。處理后續(xù)動(dòng)作開(kāi)票失敗時(shí)修正數(shù)據(jù)重新提交開(kāi)票成功后如需作廢或紅沖再調(diào)用對(duì)應(yīng)接口。這個(gè)順序如果顛倒后面會(huì)出各種詭異的問(wèn)題。比如有些開(kāi)發(fā)同學(xué)上來(lái)就先調(diào)用開(kāi)票接口發(fā)現(xiàn)報(bào)錯(cuò)“無(wú)可用發(fā)票庫(kù)存”又去查庫(kù)存接口最后才發(fā)現(xiàn)第一步先調(diào)用的是稅盤(pán)信息查詢接口用來(lái)確認(rèn)開(kāi)票終端的初始化狀態(tài)。文檔里的調(diào)用流程圖和接口依賴說(shuō)明一定要仔細(xì)看這部分信息通常隱藏在接入指南的章節(jié)中。2.2 接口鑒權(quán)與簽名機(jī)制開(kāi)票接口涉及企業(yè)和稅務(wù)數(shù)據(jù)安全性要求非常高大多數(shù)情況下采用的是應(yīng)用認(rèn)證和報(bào)文簽名雙重機(jī)制。應(yīng)用認(rèn)證解決的是“你是誰(shuí)”的問(wèn)題——客戶端拿應(yīng)用ID和密鑰換取訪問(wèn)令牌后續(xù)請(qǐng)求攜帶令牌訪問(wèn)服務(wù)端。報(bào)文簽名解決的是“數(shù)據(jù)有沒(méi)有被篡改”的問(wèn)題——業(yè)務(wù)參數(shù)按一定規(guī)則排序和拼接后使用證書(shū)私鑰或密鑰對(duì)原文進(jìn)行簽名服務(wù)端用公鑰驗(yàn)簽。簽名的算法每個(gè)廠商各有不同但大體的步驟是一致的獲取所有業(yè)務(wù)請(qǐng)求參數(shù)剔除空值和非簽名參數(shù)字段。按參數(shù)名ASCII碼升序排列。拼接成“key1value1key2value2”形式的字符串。在字符串末尾拼接密鑰。對(duì)上述字符串做摘要或加密生成簽名。這個(gè)過(guò)程中最容易出錯(cuò)的不是算法本身而是參與簽名的參數(shù)范圍。某些字段比如“sign”“token”“file”是不參與簽名的但文檔里表述得不夠直白需要看示例代碼去核對(duì)。我踩過(guò)最深的坑是簽名時(shí)的拼接順序沒(méi)按字典序結(jié)果在測(cè)試環(huán)境調(diào)了一整天后來(lái)對(duì)照?qǐng)?bào)錯(cuò)日志里的“驗(yàn)簽失敗”才找回來(lái)。3. 聯(lián)調(diào)實(shí)操?gòu)沫h(huán)境準(zhǔn)備到第一次真實(shí)調(diào)用所有準(zhǔn)備工作都是為實(shí)際聯(lián)調(diào)服務(wù)的而聯(lián)調(diào)質(zhì)量的高低往往取決于準(zhǔn)備階段是否足夠?qū)I(yè)。我把整個(gè)聯(lián)調(diào)過(guò)程拆成了三塊工具準(zhǔn)備、報(bào)文構(gòu)造、冪等性設(shè)計(jì)。3.1 工具鏈配置Postman、Swagger、Apipost怎么配合聯(lián)調(diào)開(kāi)票接口一個(gè)靠譜的HTTP調(diào)試工具是必須的。我個(gè)人的組合是Postman和Apipost配合使用Postman負(fù)責(zé)日常調(diào)試和保存環(huán)境變量Apipost用于團(tuán)隊(duì)文檔共享和快速生成接口文檔。如果材料包里提供了Swagger的OpenAPI定義文件直接導(dǎo)入到工具里能自動(dòng)生成所有接口的請(qǐng)求模板連參數(shù)類型和必填項(xiàng)都一并帶出來(lái)省去手工錄入的大量時(shí)間。在工具里設(shè)置好環(huán)境變量至關(guān)重要。要拆分的變量至少包括BaseUrl網(wǎng)關(guān)地址、AppId、令牌、證書(shū)路徑或密鑰值。這樣在切換測(cè)試環(huán)境和生產(chǎn)環(huán)境時(shí)只需要更換環(huán)境配置不用逐一修改每個(gè)請(qǐng)求里的URL和鑒權(quán)參數(shù)。我還建議把簽名函數(shù)寫(xiě)成一個(gè)腳本片段掛在工具的“預(yù)請(qǐng)求腳本”里讓每次請(qǐng)求自動(dòng)計(jì)算簽名。否則每調(diào)試一個(gè)接口都要手工去生成一遍簽名效率極低也容易算錯(cuò)。3.2 開(kāi)票請(qǐng)求的報(bào)文結(jié)構(gòu)拆解開(kāi)票接口的請(qǐng)求體看起來(lái)字段很多但拆開(kāi)來(lái)看其實(shí)可以分四個(gè)區(qū)塊。第一個(gè)區(qū)塊是基礎(chǔ)信息包括交易流水號(hào)、業(yè)務(wù)單據(jù)編號(hào)、開(kāi)票類型、是否紅沖等第二個(gè)區(qū)塊是銷(xiāo)售方信息包括銷(xiāo)售方名稱、稅號(hào)等這些通常是在平臺(tái)配置好的請(qǐng)求體里不一定需要重復(fù)傳第三個(gè)區(qū)塊是購(gòu)買(mǎi)方信息名稱、納稅人識(shí)別號(hào)、地址電話、開(kāi)戶行及賬號(hào)每一項(xiàng)都有格式要求第四個(gè)區(qū)塊是商品明細(xì)是最容易出問(wèn)題的地方因?yàn)闋可娴矫骷?xì)行的數(shù)量、單價(jià)、金額、稅率和稅額。商品明細(xì)里的“金額不含稅”和“稅額”是服務(wù)端計(jì)算的客戶端提交時(shí)通常是提供數(shù)量和含稅單價(jià)或者提供不含稅金額和稅率具體要看接口傳參要求。這里有一個(gè)重要細(xì)節(jié)某些開(kāi)票接口對(duì)明細(xì)的行數(shù)字段精度有硬性校驗(yàn)比如金額保留兩位小數(shù)、數(shù)量最多四位小數(shù)、單價(jià)最多八位小數(shù)超過(guò)就會(huì)被拒絕。如果業(yè)務(wù)系統(tǒng)里的原始數(shù)據(jù)精度不一致對(duì)接層要做好舍入處理否則大概率會(huì)出現(xiàn)“金額校驗(yàn)不通過(guò)”或者“稅額比對(duì)不一致”的報(bào)錯(cuò)。3.3 冪等性設(shè)計(jì)防止一張票開(kāi)兩次接口冪等性是所有支付類、交易類接口的通用話題開(kāi)票接口尤其敏感。因?yàn)殚_(kāi)票涉及稅務(wù)數(shù)據(jù)一張發(fā)票被重復(fù)提交的后果非常嚴(yán)重。設(shè)計(jì)思路上我們通常借助“外部業(yè)務(wù)單據(jù)號(hào)”字段實(shí)現(xiàn)冪等控制??蛻舳嗽诎l(fā)起開(kāi)票請(qǐng)求時(shí)對(duì)同一筆業(yè)務(wù)必須使用同一個(gè)單據(jù)號(hào)服務(wù)端憑借這個(gè)單據(jù)號(hào)去重如果同一個(gè)單據(jù)號(hào)的請(qǐng)求已經(jīng)成功處理過(guò)就返回第一次的結(jié)果而不是重新開(kāi)一張票。我在對(duì)接過(guò)程中見(jiàn)過(guò)不止一次這樣的故障業(yè)務(wù)系統(tǒng)超時(shí)重試后沒(méi)有復(fù)用原始單據(jù)號(hào)而是重新生成了新單號(hào)同時(shí)服務(wù)端又因?yàn)榫W(wǎng)絡(luò)問(wèn)題返回了錯(cuò)誤導(dǎo)致兩邊數(shù)據(jù)對(duì)不上。最終的結(jié)果是票開(kāi)出來(lái)了但業(yè)務(wù)數(shù)據(jù)庫(kù)里沒(méi)有對(duì)應(yīng)記錄。所以對(duì)接層的重試邏輯必須嚴(yán)格遵守“同一業(yè)務(wù)請(qǐng)求復(fù)用同一單據(jù)號(hào)”原則同時(shí)要在業(yè)務(wù)數(shù)據(jù)表里保存完整的請(qǐng)求和響應(yīng)記錄以便出問(wèn)題時(shí)做對(duì)賬。4. 真實(shí)對(duì)接中踩過(guò)的坑任何一套接口聯(lián)調(diào)都不可能一路綠燈。這里把我實(shí)際在開(kāi)票接口對(duì)接中遇到的高頻問(wèn)題整理成速查表每條都是真金白銀換來(lái)的經(jīng)驗(yàn)。4.1 參數(shù)校驗(yàn)不過(guò)多半是金額和稅率的精度問(wèn)題這類報(bào)錯(cuò)通常表現(xiàn)為“請(qǐng)求參數(shù)校驗(yàn)失敗”或“金額與稅額不匹配”。排查時(shí)先看金額數(shù)據(jù)是后端自己計(jì)算還是前端傳遞。如果是前端傳遞的很可能是浮點(diǎn)數(shù)運(yùn)算導(dǎo)致的精度丟失。比如0.1加0.2的結(jié)果不是0.3而是0.30000000000000004JSON序列化之后就變成一串很長(zhǎng)的數(shù)位直接導(dǎo)致校驗(yàn)失敗。正確的做法是后端統(tǒng)一將金額字段定義為分單位的長(zhǎng)整型或者使用BigDecimal并且明確序列化格式里的小數(shù)位規(guī)則。稅率字段容易踩的坑是傳了小數(shù)形式的“0.13”而接口期望的是整數(shù)形式的“13”或者反過(guò)來(lái)。這類規(guī)則字段務(wù)必要看文檔里的取值說(shuō)明和示例值不要憑直覺(jué)去猜。4.2 簽名失敗先復(fù)查排序和編碼簽名驗(yàn)證失敗是聯(lián)調(diào)階段最常見(jiàn)的報(bào)錯(cuò)沒(méi)有之一。遇到這個(gè)問(wèn)題優(yōu)先級(jí)最高的是排查參與簽名的參數(shù)是否齊全、參數(shù)名是否按字典序排列、拼接的字符串是否多了或少了某個(gè)字段。其次要關(guān)注編碼中文的URL編碼方式標(biāo)準(zhǔn)是UTF-8但很多老系統(tǒng)用的是GBK編碼不一致會(huì)導(dǎo)致簽名原文和服務(wù)端驗(yàn)簽原文完全不一樣。這里分享一個(gè)排查技巧自己開(kāi)發(fā)環(huán)境下先打印出完整的待簽名串然后和服務(wù)端日志里提示的驗(yàn)簽串做逐字符比對(duì)。字符層面都一致但簽名值還對(duì)不上再去排查算法和密鑰是否匹配。這個(gè)對(duì)比動(dòng)作會(huì)快速縮小問(wèn)題范圍。4.3 測(cè)試環(huán)境切生產(chǎn)環(huán)境時(shí)的證書(shū)與地址測(cè)試環(huán)境聯(lián)調(diào)順利后很多團(tuán)隊(duì)以為切換生產(chǎn)環(huán)境只需要換個(gè)BaseUrl就行結(jié)果一調(diào)用就報(bào)“證書(shū)無(wú)效”或“認(rèn)證失敗”。原因是測(cè)試環(huán)境的證書(shū)、應(yīng)用ID、密鑰和生產(chǎn)環(huán)境完全獨(dú)立代碼里如果寫(xiě)死了測(cè)試環(huán)境的證書(shū)路徑或密鑰值換環(huán)境后必然失敗。正確的做法是把環(huán)境相關(guān)的配置全部抽到配置中心或環(huán)境變量里證書(shū)文件也不要與代碼綁定而是通過(guò)路徑配置動(dòng)態(tài)加載。還有一個(gè)隱蔽的坑是回調(diào)地址的域名白名單。生產(chǎn)環(huán)境的回調(diào)地址如果沒(méi)在平臺(tái)側(cè)登記平臺(tái)會(huì)拒絕回調(diào)通知。這通常不會(huì)在文檔里寫(xiě)得很明顯但聯(lián)調(diào)時(shí)一定要提前在平臺(tái)的商家配置里檢查回調(diào)地址是否填寫(xiě)正確。4.4 聯(lián)調(diào)排錯(cuò)的通用思路排錯(cuò)的核心是分層定位。先確認(rèn)網(wǎng)絡(luò)層是否通暢能否正常訪問(wèn)網(wǎng)關(guān)地址并拿到響應(yīng)再確認(rèn)應(yīng)用層鑒權(quán)是否通過(guò)是否報(bào)token失效或簽名錯(cuò)誤最后再查業(yè)務(wù)層參數(shù)是否有問(wèn)題。我在看問(wèn)題的時(shí)候最忌諱在沒(méi)有任何日志的情況下胡亂猜測(cè)原因。開(kāi)票接口聯(lián)調(diào)一定要在客戶端和服務(wù)端都開(kāi)啟完整日志日志里至少包含時(shí)間、請(qǐng)求報(bào)文、響應(yīng)報(bào)文、流水號(hào)和異常堆棧。這樣定位問(wèn)題的速度會(huì)快很多。5. 材料包沉淀與后續(xù)擴(kuò)展一套開(kāi)票接口對(duì)接完成并不代表這個(gè)壓縮包的價(jià)值就消耗完了。我自己習(xí)慣在做完聯(lián)調(diào)后把整個(gè)材料包進(jìn)行二次整理形成團(tuán)隊(duì)內(nèi)部的知識(shí)沉淀。整理方式是根據(jù)實(shí)際情況調(diào)整的但有幾個(gè)步驟通常比較重要。第一把原始材料包中所有涉及敏感信息的文件單獨(dú)剝離比如證書(shū)私鑰、密鑰、生產(chǎn)環(huán)境地址換成占位符后重新歸檔確保其他同事拿到這份材料也不會(huì)造成信息泄露。第二把聯(lián)調(diào)過(guò)程中遇到的錯(cuò)誤碼和解決方法整理成速查表附在文檔的附錄里。第三把請(qǐng)求報(bào)文的模板按業(yè)務(wù)場(chǎng)景整理成若干標(biāo)準(zhǔn)樣例比如普通藍(lán)票開(kāi)票、折扣票開(kāi)票、紅字發(fā)票開(kāi)具后續(xù)業(yè)務(wù)部門(mén)提新需求時(shí)能直接用這些樣例去改。這樣做的好處是顯而易見(jiàn)的。當(dāng)團(tuán)隊(duì)里換了新同學(xué)或者系統(tǒng)需要擴(kuò)展到新的業(yè)務(wù)渠道時(shí)直接使用整理后的文檔就能快速上手不需要再?gòu)脑級(jí)嚎s包里重新摸索一遍。而且整理過(guò)程本身也會(huì)逼迫你重新審視代碼和接口設(shè)計(jì)往往能發(fā)現(xiàn)一些隱蔽的bug或設(shè)計(jì)不合理之處。最后再分享幾個(gè)小經(jīng)驗(yàn)對(duì)接開(kāi)票接口這類涉及稅務(wù)數(shù)據(jù)的系統(tǒng)和普通業(yè)務(wù)接口最大的不同在于它出錯(cuò)之后的影響是連續(xù)的很難單獨(dú)一筆回滾。所以我對(duì)自己的要求是代碼寧可寫(xiě)慢一點(diǎn)也要把日志打全、報(bào)文記錄存好、回調(diào)處理做到冪等。具體來(lái)說(shuō)有三點(diǎn)值得注意。第一開(kāi)票請(qǐng)求和響應(yīng)報(bào)文一定要落庫(kù)原始報(bào)文就是事后的審計(jì)證據(jù)能讓你在出現(xiàn)稅務(wù)合規(guī)問(wèn)題時(shí)說(shuō)得清來(lái)龍去脈。第二重試邏輯永不改變?cè)紭I(yè)務(wù)單號(hào)并且要給重試設(shè)置次數(shù)上限和人工介入提醒防止無(wú)限重試把平臺(tái)打掛。第三聯(lián)調(diào)階段就養(yǎng)成和平臺(tái)技術(shù)支持保持順暢溝通的習(xí)慣遇到文檔不明確的地方主動(dòng)確認(rèn)不要自行腦補(bǔ)接口行為。從拿到“博思開(kāi)票接口完整材料.zip”到最后穩(wěn)定上線整個(gè)過(guò)程其實(shí)就是不斷把“不明白”變成“明白”的過(guò)程。壓縮包里的內(nèi)容是死的你怎么去解讀、怎么把零散的信息整合成可落地的代碼和流程才是決定對(duì)接成敗的關(guān)鍵。希望這篇拆解能讓你在面對(duì)類似的第一份開(kāi)票接口材料時(shí)心里更有底氣。本文還有配套的精品資源點(diǎn)擊獲取