feat: payment pay

This commit is contained in:
zzw
2026-09-11 16:08:17 +08:00
parent f8c7419964
commit d9529a219d
33 changed files with 3108 additions and 89 deletions
+109
View File
@@ -0,0 +1,109 @@
package pay
import (
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"net/http"
)
type NotifyRequest struct {
ID string `json:"id"`
CreateTime string `json:"create_time"`
EventType string `json:"event_type"`
ResourceType string `json:"resource_type"`
Summary string `json:"summary"`
Resource NotifyResource `json:"resource"`
}
type NotifyResource struct {
Algorithm string `json:"algorithm"`
Ciphertext string `json:"ciphertext"`
AssociatedData string `json:"associated_data"`
Nonce string `json:"nonce"`
OriginalType string `json:"original_type"`
}
type TransactionNotify struct {
AppID string `json:"appid"`
MchID string `json:"mchid"`
OutTradeNo string `json:"out_trade_no"`
TransactionID string `json:"transaction_id"`
TradeType string `json:"trade_type"`
TradeState string `json:"trade_state"`
TradeStateDesc string `json:"trade_state_desc"`
BankType string `json:"bank_type"`
Attach string `json:"attach"`
SuccessTime string `json:"success_time"`
Payer struct {
OpenID string `json:"openid"`
} `json:"payer"`
Amount struct {
Total int64 `json:"total"`
PayerTotal int64 `json:"payer_total"`
Currency string `json:"currency"`
PayerCurrency string `json:"payer_currency"`
} `json:"amount"`
}
func (c *Client) ParseNotify(r *http.Request) (*NotifyRequest, error) {
body, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
if err := c.validateResponse(r.Header, body); err != nil {
return nil, err
}
var notify NotifyRequest
if err := json.Unmarshal(body, &notify); err != nil {
return nil, err
}
return &notify, nil
}
func (c *Client) DecryptNotify(notify *NotifyRequest) (*TransactionNotify, error) {
if c.APIv3Key == "" {
return nil, fmt.Errorf("apiv3 key is required for notify decryption")
}
plaintext, err := decryptAES256GCM(
c.APIv3Key,
notify.Resource.AssociatedData,
notify.Resource.Nonce,
notify.Resource.Ciphertext,
)
if err != nil {
return nil, err
}
var tx TransactionNotify
if err := json.Unmarshal(plaintext, &tx); err != nil {
return nil, err
}
return &tx, nil
}
func decryptAES256GCM(apiV3Key, associatedData, nonce, ciphertext string) ([]byte, error) {
key := []byte(apiV3Key)
cipherBytes, err := base64.StdEncoding.DecodeString(ciphertext)
if err != nil {
return nil, err
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
gcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}
return gcm.Open(nil, []byte(nonce), cipherBytes, []byte(associatedData))
}