mirror of
https://github.com/yangjian102621/geekai.git
synced 2025-11-09 02:33:42 +08:00
opt: verify the order in notify callback
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
||||
"chatplus/core/types"
|
||||
"chatplus/utils"
|
||||
"crypto/md5"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -17,14 +18,14 @@ import (
|
||||
type HuPiPayService struct {
|
||||
appId string
|
||||
appSecret string
|
||||
host string
|
||||
apiURL string
|
||||
}
|
||||
|
||||
func NewHuPiPay(config *types.AppConfig) *HuPiPayService {
|
||||
return &HuPiPayService{
|
||||
appId: config.HuPiPayConfig.AppId,
|
||||
appSecret: config.HuPiPayConfig.AppSecret,
|
||||
host: config.HuPiPayConfig.PayURL,
|
||||
apiURL: config.HuPiPayConfig.ApiURL,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,8 +43,16 @@ type HuPiPayReq struct {
|
||||
NonceStr string `json:"nonce_str"`
|
||||
}
|
||||
|
||||
type HuPiResp struct {
|
||||
Openid interface{} `json:"openid"`
|
||||
UrlQrcode string `json:"url_qrcode"`
|
||||
URL string `json:"url"`
|
||||
ErrCode int `json:"errcode"`
|
||||
ErrMsg string `json:"errmsg,omitempty"`
|
||||
}
|
||||
|
||||
// Pay 执行支付请求操作
|
||||
func (s *HuPiPayService) Pay(params HuPiPayReq) (string, error) {
|
||||
func (s *HuPiPayService) Pay(params HuPiPayReq) (HuPiResp, error) {
|
||||
data := url.Values{}
|
||||
simple := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
params.AppId = s.appId
|
||||
@@ -58,21 +67,34 @@ func (s *HuPiPayService) Pay(params HuPiPayReq) (string, error) {
|
||||
encode = utils.JsonEncode(params)
|
||||
m = make(map[string]string)
|
||||
_ = utils.JsonDecode(encode, &m)
|
||||
data.Add("hash", s.Sign(m))
|
||||
resp, err := http.PostForm(s.host, data)
|
||||
data.Add("hash", s.sign(m))
|
||||
apiURL := fmt.Sprintf("%s/payment/do.html", s.apiURL)
|
||||
logger.Info(apiURL)
|
||||
resp, err := http.PostForm(apiURL, data)
|
||||
if err != nil {
|
||||
return "error", err
|
||||
return HuPiResp{}, fmt.Errorf("error with requst api: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
all, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "error", err
|
||||
return HuPiResp{}, fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
return string(all), err
|
||||
|
||||
var res HuPiResp
|
||||
err = utils.JsonDecode(string(all), &res)
|
||||
if err != nil {
|
||||
return HuPiResp{}, fmt.Errorf("error with decode payment result: %v", err)
|
||||
}
|
||||
|
||||
if res.ErrCode != 0 {
|
||||
return HuPiResp{}, fmt.Errorf("error with generate pay url: %s", res.ErrMsg)
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Sign 签名方法
|
||||
func (s *HuPiPayService) Sign(params map[string]string) string {
|
||||
func (s *HuPiPayService) sign(params map[string]string) string {
|
||||
var data string
|
||||
keys := make([]string, 0, 0)
|
||||
for key := range params {
|
||||
@@ -90,3 +112,50 @@ func (s *HuPiPayService) Sign(params map[string]string) string {
|
||||
sign := fmt.Sprintf("%x", m.Sum(nil))
|
||||
return sign
|
||||
}
|
||||
|
||||
// Check 校验订单状态
|
||||
func (s *HuPiPayService) Check(tradeNo string) error {
|
||||
data := url.Values{}
|
||||
data.Add("appid", s.appId)
|
||||
data.Add("open_order_id", tradeNo)
|
||||
stamp := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
data.Add("time", stamp)
|
||||
data.Add("nonce_str", stamp)
|
||||
// 生成签名
|
||||
encode := utils.JsonEncode(data)
|
||||
m := make(map[string]string)
|
||||
err := utils.JsonDecode(encode, &m)
|
||||
data.Add("sign", s.sign(m))
|
||||
|
||||
apiURL := fmt.Sprintf("%s/payment/query.html", s.apiURL)
|
||||
resp, err := http.PostForm(apiURL, data)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with http reqeust: %v", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
|
||||
var r struct {
|
||||
ErrCode int `json:"errcode"`
|
||||
Data struct {
|
||||
Status string `json:"status"`
|
||||
OpenOrderId string `json:"open_order_id"`
|
||||
} `json:"data,omitempty"`
|
||||
ErrMsg string `json:"errmsg"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
err = utils.JsonDecode(string(body), &r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
|
||||
if r.ErrCode == 0 && r.Data.Status == "OD" {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("order not paid")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"chatplus/utils"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@@ -55,10 +56,11 @@ func (js *PayJS) Pay(param JPayReq) JPayReps {
|
||||
}
|
||||
p.Add("mchid", js.config.AppId)
|
||||
|
||||
p.Add("sign", sign(p, js.config.PrivateKey))
|
||||
p.Add("sign", js.sign(p))
|
||||
|
||||
cli := http.Client{}
|
||||
r, err := cli.PostForm(js.config.ApiURL, p)
|
||||
apiURL := fmt.Sprintf("%s/api/native", js.config.ApiURL)
|
||||
r, err := cli.PostForm(apiURL, p)
|
||||
if err != nil {
|
||||
return JPayReps{ReturnMsg: err.Error()}
|
||||
}
|
||||
@@ -76,7 +78,7 @@ func (js *PayJS) Pay(param JPayReq) JPayReps {
|
||||
return data
|
||||
}
|
||||
|
||||
func sign(params url.Values, priKey string) string {
|
||||
func (js *PayJS) sign(params url.Values) string {
|
||||
params.Del(`sign`)
|
||||
var keys = make([]string, 0, 0)
|
||||
for key := range params {
|
||||
@@ -94,9 +96,45 @@ func sign(params url.Values, priKey string) string {
|
||||
}
|
||||
}
|
||||
var src = strings.Join(pList, "&")
|
||||
src += "&key=" + priKey
|
||||
src += "&key=" + js.config.PrivateKey
|
||||
|
||||
md5bs := md5.Sum([]byte(src))
|
||||
md5res := hex.EncodeToString(md5bs[:])
|
||||
return strings.ToUpper(md5res)
|
||||
}
|
||||
|
||||
// Check 查询订单支付状态
|
||||
// @param tradeNo 支付平台交易 ID
|
||||
func (js *PayJS) Check(tradeNo string) error {
|
||||
apiURL := fmt.Sprintf("%s/api/check", js.config.ApiURL)
|
||||
params := url.Values{}
|
||||
params.Add("payjs_order_id", tradeNo)
|
||||
params.Add("sign", js.sign(params))
|
||||
data := strings.NewReader(params.Encode())
|
||||
resp, err := http.Post(apiURL, "application/x-www-form-urlencoded", data)
|
||||
defer resp.Body.Close()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with http reqeust: %v", err)
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with reading response: %v", err)
|
||||
}
|
||||
|
||||
var r struct {
|
||||
ReturnCode int `json:"return_code"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
err = utils.JsonDecode(string(body), &r)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error with decode response: %v", err)
|
||||
}
|
||||
|
||||
if r.ReturnCode == 1 && r.Status == 1 {
|
||||
return nil
|
||||
} else {
|
||||
return errors.New("order not paid")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user