簡(jiǎn)電云 | 充電平臺(tái)基于中電聯(lián)協(xié)議互聯(lián)互通的設(shè)計(jì)與實(shí)現(xiàn)-棚戶區(qū)嫖妓全部過(guò)程メイリン モデルコレクション メ_久久綜合伊人中文字幕
- 報(bào)價(jià)
- 請(qǐng)來(lái)電詢價(jià)
- 產(chǎn)品咨詢熱線
- 15920323068
- 微信號(hào)
- 15920323068
- 軟件開發(fā)
- 小程序+公眾號(hào)+APP定制開發(fā)
國(guó)內(nèi)充電運(yùn)營(yíng)平臺(tái)接入第三方聚合平臺(tái)、城市監(jiān)管平臺(tái)或其他運(yùn)營(yíng)商時(shí),常會(huì)采用中電聯(lián)充換電服務(wù)信息交換相關(guān)規(guī)范。它解決的不是充電樁與平臺(tái)之間的通信,而是平臺(tái)與平臺(tái)之間如何交換場(chǎng)站、設(shè)備、狀態(tài)和充電訂單等信息。
這類項(xiàng)目真正困難的部分通常不是發(fā)送一個(gè) HTTP請(qǐng)求,而是統(tǒng)一協(xié)議版本、處理加密簽名、建立可靠的業(yè)務(wù)狀態(tài)機(jī),并在雙方數(shù)據(jù)口徑不一致時(shí)保證訂單可追溯。本文從工程落地角度給出一套實(shí)現(xiàn)方案。文中的地址、運(yùn)營(yíng)商編號(hào)和業(yè)務(wù)數(shù)據(jù)均為演示內(nèi)容;不同標(biāo)準(zhǔn)版本、地方平臺(tái)和運(yùn)營(yíng)商可能存在擴(kuò)展,生產(chǎn)接入應(yīng)以雙方確認(rèn)的接口清單和聯(lián)調(diào)文檔為準(zhǔn)。
一套典型的充電業(yè)務(wù)會(huì)涉及三層通信:
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
充電樁 <--設(shè)備協(xié)議--> 運(yùn)營(yíng)商平臺(tái) <--中電聯(lián)信息交換協(xié)議--> 對(duì)接平臺(tái)
設(shè)備協(xié)議負(fù)責(zé)啟停充電、實(shí)時(shí)遙測(cè)和故障上報(bào);中電聯(lián)信息交換協(xié)議負(fù)責(zé)平臺(tái)間的數(shù)據(jù)共享與業(yè)務(wù)協(xié)同。對(duì)接平臺(tái)發(fā)起啟動(dòng)請(qǐng)求后,運(yùn)營(yíng)商平臺(tái)仍需把請(qǐng)求轉(zhuǎn)換成設(shè)備協(xié)議命令,再等待充電樁執(zhí)行。因此,“接口受理成功”和“充電已經(jīng)啟動(dòng)”是兩個(gè)不同狀態(tài)。
落地前應(yīng)由雙方凍結(jié)一份接入基線,至少包括:
項(xiàng)目
需要確認(rèn)的內(nèi)容
協(xié)議版本
標(biāo)準(zhǔn)版本、地方擴(kuò)展版本、修訂日期
運(yùn)營(yíng)商身份
OperatorID、平臺(tái)編碼及測(cè)試環(huán)境編碼
接口范圍
基礎(chǔ)信息、狀態(tài)、鑒權(quán)、啟停、訂單等
安全參數(shù)
簽名密鑰、數(shù)據(jù)密鑰、初始向量及換鑰方式
字段口徑
時(shí)間、金額、電量、槍口編號(hào)、狀態(tài)枚舉
回調(diào)策略
地址、超時(shí)、重試次數(shù)、冪等規(guī)則
不要只寫“按中電聯(lián)協(xié)議接入”。同一接口在不同項(xiàng)目中可能存在字段增減、路徑差異或枚舉擴(kuò)展,版本基線必須能夠落到具體文檔和聯(lián)調(diào)樣例。
建議在現(xiàn)有充電業(yè)務(wù)之外增加獨(dú)立的互聯(lián)互通網(wǎng)關(guān):
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
對(duì)接平臺(tái)
|
v
接入網(wǎng)關(guān):驗(yàn)簽、解密、限流、審計(jì)
|
v
協(xié)議適配層:字段轉(zhuǎn)換、版本適配、冪等控制
|
+--> 基礎(chǔ)數(shù)據(jù)服務(wù):場(chǎng)站、設(shè)備、價(jià)格
+--> 狀態(tài)服務(wù):空閑、充電、離線、故障
+--> 充電服務(wù):鑒權(quán)、啟動(dòng)、停止、訂單
+--> 回調(diào)任務(wù):結(jié)果通知、狀態(tài)通知、訂單通知
接入網(wǎng)關(guān)不直接操作充電樁。它先完成安全校驗(yàn),再把標(biāo)準(zhǔn)報(bào)文轉(zhuǎn)換成內(nèi)部命令。這樣既能隔離外部協(xié)議變化,也能避免在核心充電服務(wù)中散落大量外部字段判斷。
每個(gè)合作方應(yīng)維護(hù)獨(dú)立配置,包括協(xié)議版本、密鑰版本、回調(diào)地址、超時(shí)時(shí)間、啟用接口和擴(kuò)展字段。不要把合作方差異寫成遍布代碼的if/else。
常見協(xié)議實(shí)現(xiàn)會(huì)在 JSON 外層攜帶運(yùn)營(yíng)商標(biāo)識(shí)、加密數(shù)據(jù)、時(shí)間戳、序列號(hào)和簽名,結(jié)構(gòu)類似:
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
{
"OperatorID": "1000000001",
"Data": "Base64EncodedCipherText",
"TimeStamp": "20260923153045",
"Seq": "0001",
"Sig": "Re"}
其中 Data 是業(yè)務(wù) JSON 加密后的 Base64文本,Sig用于驗(yàn)證請(qǐng)求來(lái)源和報(bào)文完整性。工程上應(yīng)把處理順序固定下來(lái):
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
校驗(yàn)報(bào)文長(zhǎng)度和必填字段
-> 根據(jù) OperatorID 加載協(xié)議配置與密鑰版本
-> 校驗(yàn)時(shí)間窗口和 Seq
-> 按約定的原始字符串計(jì)算并校驗(yàn) Sig
-> Base64 解碼并解密 Data
-> 解析業(yè)務(wù) JSON
-> 執(zhí)行業(yè)務(wù)冪等檢查
簽名串的字段順序、字符編碼、大小寫以及加密算法參數(shù)必須嚴(yán)格按雙方采用的協(xié)議版本實(shí)現(xiàn)。常見項(xiàng)目會(huì)使用共享密鑰簽名以及對(duì)稱加密,但不能僅憑經(jīng)驗(yàn)猜測(cè)算法、填充方式或初始向量。
建議使用成熟密碼庫(kù),并注意以下細(xì)節(jié):
明確使用 UTF-8,禁止依賴操作系統(tǒng)默認(rèn)編碼;
簽名使用協(xié)議要求的原始值,不對(duì) Data 做二次 Base64 或格式化;
使用常量時(shí)間比較方法校驗(yàn)簽名,減少時(shí)序差異;
密鑰放入密鑰管理服務(wù)或受控配置中心,日志中不得輸出明文密鑰、解密后的用戶標(biāo)識(shí)或完整憑證;
支持密鑰版本和灰度換鑰,在約定窗口內(nèi)兼容新舊密鑰;
對(duì)時(shí)間戳設(shè)置合理窗口,并以 OperatorID + TimeStamp + Seq 等組合進(jìn)行防重放控制。
下面的 Java 偽代碼強(qiáng)調(diào)處理邊界,具體算法名稱和簽名拼接規(guī)則應(yīng)來(lái)自已確認(rèn)的協(xié)議版本:
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
publicuest decode(Envelope envelope) {
PartnerConfig config =uire(envelope.operatorId());
validateTimestamp(envelope.timeStamp(),config.allowedClockSkew());
replayGuard.check(envelope.operatorId(),envelope.timeStamp(),());
String signSource =config.signRule().build(envelope);
byte[] expected = signer.sign(signSource,config.signSecret());
if (!Mual(expected,decodeSignature(envelope.sig()))) {
throw newProtocolException("INVALID_SIGNATURE");
}
byte[] cipherText =Base64.getDecoder().decode(envelope.data());
byte[] plainText = cipher.decrypt(cipherText,config.dataKey(), config.iv());
return json.readValue(plainText,BusinessRe);
}
響應(yīng)也要經(jīng)過(guò)相同版本的封裝流程。即使業(yè)務(wù)失敗,也應(yīng)返回協(xié)議約定的結(jié)果碼和加密數(shù)據(jù),不能把內(nèi)部異常堆棧直接暴露給調(diào)用方。
互聯(lián)互通接口可以按數(shù)據(jù)變化頻率分成三組。
場(chǎng)站、充電設(shè)備、充電接口和計(jì)費(fèi)規(guī)則變化較慢,適合“全量初始化 + 增量更新+ 定期校準(zhǔn)”。首次接入先完成分頁(yè)全量同步,此后由變更通知驅(qū)動(dòng)更新,每天再執(zhí)行一次差異校準(zhǔn)。
核心關(guān)聯(lián)關(guān)系建議保留為:
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
運(yùn)營(yíng)商 OperatorID
-> 場(chǎng)站 StationID
-> 設(shè)備 E
-> 充電接口 ConnectorID
外部 ID 應(yīng)按字符串保存,不要轉(zhuǎn)換成整數(shù)。數(shù)據(jù)庫(kù)唯一鍵至少包含合作方和外部ID,例如 (partner_id, connector_id),因?yàn)椴煌脚_(tái)的編號(hào)空間未必全局唯一。
計(jì)費(fèi)規(guī)則應(yīng)按版本保存生效區(qū)間,不要覆蓋歷史記錄。一筆訂單Zui終使用哪個(gè)價(jià)格版本,應(yīng)由啟動(dòng)時(shí)間和雙方約定的計(jì)費(fèi)規(guī)則確定,以便后續(xù)賬單復(fù)核。
槍口狀態(tài)變化頻繁,通常采用主動(dòng)通知,查詢接口用于補(bǔ)償。平臺(tái)接到狀態(tài)通知后,應(yīng)比較事件時(shí)間或內(nèi)部版本號(hào),防止網(wǎng)絡(luò)延遲導(dǎo)致舊狀態(tài)覆蓋新狀態(tài)。
內(nèi)部狀態(tài)不要直接等同于某一家平臺(tái)的枚舉。可以先歸一化為:
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
UNKNOWN、OFFLINE、IDLE、OCCUPIED、CHARGING、FAULT、RESERVED
再通過(guò)版本適配器映射到對(duì)方協(xié)議值。對(duì)于無(wú)法jingque映射的狀態(tài),按雙方約定降級(jí),并保留原始狀態(tài)碼用于排查。
充電業(yè)務(wù)通常包含設(shè)備鑒權(quán)、啟動(dòng)充電、停止充電、啟動(dòng)結(jié)果通知、停止結(jié)果通知和訂單信息通知。它是異步流程,不適合用一次同步請(qǐng)求表達(dá)Zui終結(jié)果。
啟動(dòng)充電可以設(shè)計(jì)為以下狀態(tài)機(jī):
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
CREATED
-> ACCEPTED
-> COMMAND_SENT
-> STARTED
-> CHARGING
-> STOPPING
->FINISHED異常分支:REJECTED、START_FAILED、TIMEOUT、CANCELLED
對(duì)接平臺(tái)提交啟動(dòng)請(qǐng)求后,運(yùn)營(yíng)商平臺(tái)完成參數(shù)與冪等校驗(yàn),只返回“已受理”或“拒絕受理”。隨后平臺(tái)向設(shè)備下發(fā)啟動(dòng)命令,并通過(guò)結(jié)果通知告知Zui終啟動(dòng)結(jié)果。
一條請(qǐng)求至少應(yīng)保留這些關(guān)聯(lián)字段:
字段
用途
合作方請(qǐng)求號(hào)
接口冪等與問(wèn)題定位
運(yùn)營(yíng)商訂單號(hào)
運(yùn)營(yíng)商內(nèi)部業(yè)務(wù)主鍵
對(duì)接平臺(tái)訂單號(hào)
雙方訂單關(guān)聯(lián)
ConnectorID
目標(biāo)充電接口
設(shè)備交易號(hào)
關(guān)聯(lián)樁側(cè)交易
當(dāng)前狀態(tài)與版本
防止亂序更新
原始請(qǐng)求摘要
審計(jì)與重復(fù)請(qǐng)求比對(duì)
冪等不能只根據(jù)“接口在幾秒內(nèi)重復(fù)”判斷。相同業(yè)務(wù)請(qǐng)求號(hào)和相同業(yè)務(wù)內(nèi)容應(yīng)返回第一次處理結(jié)果;相同請(qǐng)求號(hào)但業(yè)務(wù)內(nèi)容不同,應(yīng)拒絕并記錄沖突?;卣{(diào)也要攜帶穩(wěn)定的事件ID 或由業(yè)務(wù)主鍵、事件類型和狀態(tài)版本生成冪等鍵。
生產(chǎn)環(huán)境中必須假設(shè)回調(diào)會(huì)超時(shí)、重復(fù)、亂序和短暫失敗??煽客ㄖ梢允褂檬聞?wù)消息表或Outbox 模式:業(yè)務(wù)狀態(tài)與待發(fā)送事件在同一數(shù)據(jù)庫(kù)事務(wù)中落庫(kù),再由獨(dú)立任務(wù)投遞。
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
CREATE TABLE interop_outbox (
id BIGINT PRIMARY KEY,
partner_id VARCHAR(32) NOTNULL,
event_type VARCHAR(48) NOTNULL,
business_key VARCHAR(96) NOT NULL,
state_version BIGINT NOT NULL,
payload_json TEXT NOT NULL,
status VARCHAR(16)NOT NULL,
retry_count INT NOT NULL,
next_retry_at TIMESTAMP NOT NULL,
created_at TIMESTAMP NOT NULL,
UNIQUE (partner_id, event_type, business_key,state_version)
);
僅在收到對(duì)方明確的成功響應(yīng)后,任務(wù)才進(jìn)入SUCCESS。網(wǎng)絡(luò)超時(shí)不能解釋成業(yè)務(wù)失敗,因?yàn)閷?duì)方可能已經(jīng)處理成功。重試采用指數(shù)退避并設(shè)置上限,超過(guò)上限進(jìn)入人工處理隊(duì)列;不能無(wú)限快速重試。
建議分別記錄三種時(shí)間:業(yè)務(wù)事件發(fā)生時(shí)間、平臺(tái)收到事件時(shí)間、通知成功時(shí)間。這樣才能識(shí)別設(shè)備延遲、內(nèi)部積壓和外部接口延遲。
訂單是雙方Zui容易產(chǎn)生分歧的數(shù)據(jù)。平臺(tái)應(yīng)同時(shí)保留原始訂單、歸一化訂單和計(jì)費(fèi)明細(xì),不要只保存一個(gè)Zui終金額。
金額優(yōu)先使用Zui小貨幣單位的整數(shù),電量使用BigDecimal 并明確精度和舍入規(guī)則。例如:
展開
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
record ChargeOrder(
String,
String connectorId,
Instant startTime,
Instant endTime,
BigDecimal totalPower,
long electricityFeeFen,
long serviceFeeFen,
long totalFeeFen
) {}
入庫(kù)前至少校驗(yàn):
結(jié)束時(shí)間不早于開始時(shí)間;
總電量不為負(fù)數(shù),并與分時(shí)電量之和在約定誤差內(nèi)一致;
總金額與電費(fèi)、服務(wù)費(fèi)及其他約定費(fèi)用之和一致;
訂單中的槍口、設(shè)備和場(chǎng)站關(guān)系能夠匹配;
同一訂單的后續(xù)版本只能按狀態(tài)機(jī)前進(jìn),不能覆蓋已經(jīng)確認(rèn)的終態(tài)。
若雙方因精度、計(jì)費(fèi)時(shí)點(diǎn)或價(jià)格版本產(chǎn)生差異,應(yīng)進(jìn)入對(duì)賬異常表,保留雙方原值和差異原因,不能直接修改原始報(bào)文“抹平”差額。
協(xié)議錯(cuò)誤和業(yè)務(wù)錯(cuò)誤應(yīng)分開處理。簽名錯(cuò)誤、解密失敗、JSON格式錯(cuò)誤屬于協(xié)議層錯(cuò)誤;槍口不存在、設(shè)備離線、訂單已結(jié)束屬于業(yè)務(wù)層錯(cuò)誤。內(nèi)部異常先映射成穩(wěn)定的對(duì)外錯(cuò)誤碼,再記錄內(nèi)部錯(cuò)誤詳情。
日志建議包含:
代碼語(yǔ)言:JavaScript
自動(dòng)換行
AI代碼解釋
traceId、partnerId、interfaceName、re、businessKey、
timestamp、duration、resultCode、retryCount、payloadHash
手機(jī)號(hào)、車牌、用戶令牌、密鑰和解密后的完整業(yè)務(wù)報(bào)文不應(yīng)寫入普通日志。確需保存原始報(bào)文時(shí),應(yīng)加密存儲(chǔ)、限制訪問(wèn)并設(shè)置保留期限。
監(jiān)控至少覆蓋接口成功率、簽名失敗數(shù)、解密失敗數(shù)、時(shí)間戳超限數(shù)、回調(diào)積壓量、重試次數(shù)、啟動(dòng)成功率、啟動(dòng)耗時(shí)、狀態(tài)延遲和訂單差異數(shù)。按合作方和接口分別統(tǒng)計(jì),整體平均值往往會(huì)掩蓋單一通道故障。
上線前建議按以下順序驗(yàn)證:
用雙方確認(rèn)的固定報(bào)文完成加密、解密和簽名互驗(yàn);
同步一個(gè)測(cè)試場(chǎng)站,核對(duì)場(chǎng)站、設(shè)備、槍口和價(jià)格層級(jí);
驗(yàn)證狀態(tài)通知的重復(fù)、亂序、離線恢復(fù)和補(bǔ)償查詢;
完成啟動(dòng)、啟動(dòng)失敗、主動(dòng)停止、設(shè)備停止和超時(shí)等完整流程;
核對(duì)跨時(shí)段計(jì)費(fèi)、零電量訂單、異常結(jié)束和重復(fù)訂單;
模擬回調(diào)超時(shí)、返回失敗和網(wǎng)絡(luò)恢復(fù),確認(rèn)重試不會(huì)制造重復(fù)業(yè)務(wù);
檢查日志脫敏、密鑰權(quán)限、限流和告警是否生效。
正式切換時(shí)可以先開放少量測(cè)試槍,再逐步擴(kuò)大場(chǎng)站范圍。雙方應(yīng)約定故障聯(lián)系人、問(wèn)題報(bào)文留存方式以及狀態(tài)和訂單的補(bǔ)償時(shí)間窗口。
中電聯(lián)協(xié)議的互聯(lián)互通實(shí)現(xiàn),本質(zhì)上是一個(gè)跨平臺(tái)的分布式業(yè)務(wù)系統(tǒng)。HTTP、JSON、加密和簽名只是入口,真正決定穩(wěn)定性的,是清晰的版本基線、可靠的異步狀態(tài)機(jī)、嚴(yán)格的冪等設(shè)計(jì)以及可復(fù)核的訂單數(shù)據(jù)。
一個(gè)可維護(hù)的實(shí)現(xiàn)應(yīng)把安全封裝、協(xié)議適配和內(nèi)部業(yè)務(wù)分層;基礎(chǔ)信息采用全量與增量結(jié)合,狀態(tài)通知配合查詢補(bǔ)償,啟停充電采用異步結(jié)果通知,訂單保留原文與版本。只有把超時(shí)、重復(fù)、亂序和差異對(duì)賬當(dāng)作正常情況設(shè)計(jì),平臺(tái)間互聯(lián)互通才能從“接口調(diào)通”走向長(zhǎng)期穩(wěn)定運(yùn)行。
說(shuō)明:本文用于介紹通用工程方法,不替代標(biāo)準(zhǔn)原文、雙方簽署的接口文檔及安全規(guī)范。示例標(biāo)識(shí)、地址和數(shù)據(jù)均為虛構(gòu)內(nèi)容。
共享充電樁軟件開發(fā),充電樁共享軟件開發(fā),智能充電樁系統(tǒng)開發(fā),充電樁軟件開發(fā)公司,充電樁app的開發(fā),共享充電樁app開發(fā),充電樁平臺(tái)開發(fā),充電樁app開發(fā)
公司介紹廣州優(yōu)匠科技有限公司成立于2017年,于2018年開始深耕充電樁運(yùn)營(yíng)平臺(tái),是國(guó)內(nèi)海外的共享充電運(yùn)營(yíng)平臺(tái)整體解決方案服務(wù)商,致力于推動(dòng)共享充電領(lǐng)域的標(biāo)準(zhǔn)化、產(chǎn)品化,為用戶提供簡(jiǎn)單便捷的充電體驗(yàn)、充電安全及幫助合作伙伴提供穩(wěn)定、高效的運(yùn)營(yíng)平臺(tái)。公司為全球運(yùn)營(yíng)商、充電樁廠家提供電動(dòng)自行車、新能源汽車運(yùn)營(yíng)平臺(tái)的Saas租賃服務(wù)、私有化部署、個(gè)性定制化開發(fā)服務(wù)。同時(shí)我們將為全球所有國(guó)家、地區(qū)等運(yùn)營(yíng)商提供運(yùn)營(yíng)平臺(tái)的Saas租賃服務(wù)、幫助中小...