| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- package qiyuesuosdk
- import (
- "crypto/aes"
- "crypto/cipher"
- "crypto/sha256"
- "encoding/base64"
- "encoding/hex"
- "encoding/json"
- "fmt"
- )
- type callbackMeta struct {
- CallbackType string `json:"callbackType"`
- CallbackTime string `json:"callbackTime"`
- CallbackBizType string `json:"callbackBizType"`
- }
- // ParseCallback 解密、验签并解析契约锁回调。
- func (c *Client) ParseCallback(req CallbackRequest) (CallbackEvent, error) {
- plain, err := c.decryptCallback(req.Encrypted, c.cfg.CallbackToken, c.cfg.CallbackAESKey)
- if err != nil {
- return CallbackEvent{}, err
- }
- hash := sha256.Sum256([]byte(plain + req.Timestamp + req.Nonce + c.cfg.CallbackToken))
- if hex.EncodeToString(hash[:]) != req.Signature {
- return CallbackEvent{}, fmt.Errorf("qiyuesuo: callback signature mismatch")
- }
- return parseCallbackPayload(plain)
- }
- func parseCallbackPayload(plain string) (CallbackEvent, error) {
- raw := []byte(plain)
- var meta callbackMeta
- if err := json.Unmarshal(raw, &meta); err != nil {
- return CallbackEvent{}, err
- }
- switch EventType(meta.CallbackType) {
- case EventCompanyAuthSuccess:
- var data CompanyCertificationData
- if err := json.Unmarshal(raw, &data); err != nil {
- return CallbackEvent{}, err
- }
- data.CallbackTime = meta.CallbackTime
- return CallbackEvent{Type: EventCompanyAuthSuccess, Data: data}, nil
- case EventCompanySealAuthSuccess:
- var data CompanySealAuthData
- if err := json.Unmarshal(raw, &data); err != nil {
- return CallbackEvent{}, err
- }
- data.CallbackTime = meta.CallbackTime
- return CallbackEvent{Type: EventCompanySealAuthSuccess, Data: data}, nil
- case EventPersonalSealAuthSuccess:
- var data PersonalSealAuthData
- if err := json.Unmarshal(raw, &data); err != nil {
- return CallbackEvent{}, err
- }
- data.CallbackTime = meta.CallbackTime
- return CallbackEvent{Type: EventPersonalSealAuthSuccess, Data: data}, nil
- case EventCallbackCheck:
- return CallbackEvent{Type: EventCallbackCheck, Data: nil}, nil
- default:
- return CallbackEvent{}, fmt.Errorf("qiyuesuo: unknown callback type %q", meta.CallbackType)
- }
- }
- func (c *Client) decryptCallback(encrypted, token, aesKey string) (string, error) {
- ciphertext, err := base64.StdEncoding.DecodeString(encrypted)
- if err != nil {
- return "", fmt.Errorf("qiyuesuo: base64 decode: %w", err)
- }
- key := []byte(aesKey)
- if len(key) < 16 {
- return "", fmt.Errorf("qiyuesuo: aes key too short")
- }
- key = key[:16]
- block, err := aes.NewCipher(key)
- if err != nil {
- return "", err
- }
- ivHash := sha256.Sum256([]byte(token))
- iv := ivHash[:aes.BlockSize]
- if len(ciphertext)%aes.BlockSize != 0 {
- return "", fmt.Errorf("qiyuesuo: invalid ciphertext block size")
- }
- mode := cipher.NewCBCDecrypter(block, iv)
- plain := make([]byte, len(ciphertext))
- mode.CryptBlocks(plain, ciphertext)
- if len(plain) == 0 {
- return "", fmt.Errorf("qiyuesuo: empty plaintext")
- }
- padding := int(plain[len(plain)-1])
- if padding <= 0 || padding > len(plain) {
- return "", fmt.Errorf("qiyuesuo: invalid pkcs padding")
- }
- return string(plain[:len(plain)-padding]), nil
- }
|