feat: payment pay
This commit is contained in:
@@ -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, ¬ify); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ¬ify, 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))
|
||||
}
|
||||
Reference in New Issue
Block a user