main
elf 6 months ago
parent 7eee3952d0
commit 744b92c086

@ -1,6 +1,7 @@
package h5
import (
"encoding/json"
"fmt"
"github.com/gin-gonic/gin"
"gold-shop/errors"
@ -8,8 +9,7 @@ import (
"gold-shop/request"
"gold-shop/service"
"gold-shop/utils/result"
"gold-shop/utils/tlpay"
"gold-shop/utils/tlpay/param"
"gold-shop/utils/tlpay/notify"
"gold-shop/utils/weixin"
"gorm.io/gorm"
"net/http"
@ -170,15 +170,53 @@ func PaymentNotify(c *gin.Context) {
}
fmt.Println("has-data")
fmt.Println(req)
service.PaymentService.AfterPaymentNotify(req)
c.String(http.StatusOK, "success")
return
}
func BindingPayNotify(c *gin.Context) {
var req notify.PayAgreeNotify
err := c.ShouldBind(&req)
if err != nil {
fmt.Println("error: " + err.Error())
c.String(http.StatusOK, "fail")
return
}
service.PaymentService.AfterPaymentNotify(req)
fmt.Println("has-data")
fmt.Println(req)
reqJson, err := json.Marshal(req)
fmt.Println(string(reqJson))
if err != nil {
c.String(http.StatusOK, "fail")
return
}
service.PaymentService.AfterBindingPayNotify(req)
c.String(http.StatusOK, "success")
return
}
func GatewayPayRet(c *gin.Context) {
var req notify.GatewayPayRet
err := c.ShouldBind(&req)
if err != nil {
fmt.Println("error: " + err.Error())
c.String(http.StatusOK, "fail")
return
}
fmt.Println("has-data")
fmt.Println(req)
reqJson, err := json.Marshal(req)
fmt.Println(string(reqJson))
if err != nil {
c.String(http.StatusOK, "fail")
return
}
c.Redirect(http.StatusMovedPermanently, "http://mall.wrtcjt.com/pages/knq-detail/index")
return
}
func TlBindingApply(c *gin.Context) (result.Data, error) {
var req request.TlBindingApplyRequest
err := c.ShouldBind(&req)
@ -206,7 +244,7 @@ func GetUserBankCard(c *gin.Context) (result.Data, error) {
if err != nil {
return nil, err
}
bankCard, err := service.UserService.GetBankCardByUserID(2)
bankCard, err := service.UserService.GetBankCardByUserID(user(c).ID)
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return result.Data{"bankCard": bankCard}, nil
}
@ -228,20 +266,46 @@ func BindingPayConfirm(c *gin.Context) (result.Data, error) {
return data, err
}
func TLPay(c *gin.Context) {
p := param.GatewayPayParam{}
p.OrderID = "22222222223323232"
p.PayType = "B2B"
p.TrxAmt = "1"
p.RetUrl = "https://www.baidu.com"
p.NotifyUrl = "https://www.baidu.com"
p.GoodsID = "1"
p.GoodsInf = "充值"
p.Charset = "UTF-8"
func BindingPaySms(c *gin.Context) (result.Data, error) {
var req request.BindingPaySmsRequest
err := c.ShouldBind(&req)
if err != nil {
return nil, err
}
data, err := service.PaymentService.SmsBindingPayment(req, user(c))
return data, err
}
func GatewayPayApply(c *gin.Context) (result.Data, error) {
var req request.PaymentRequest
err := c.ShouldBind(&req)
if err != nil {
return nil, err
}
req.PayType = "gateway"
return service.PaymentService.GatewayPayApply(user(c).ID, req)
}
str := tlpay.TLPay.GatewayPay(p)
fmt.Println(str)
func GatewayPay(c *gin.Context) {
c.Writer.Header().Set("content-type", "text/html")
c.Writer.WriteString(str)
token := c.DefaultQuery("token", "")
if token == "" {
c.Writer.WriteString("token empty")
return
}
body, err := service.PaymentService.GatewayPay(token)
if err != nil {
c.Writer.WriteString(err.Error())
return
}
c.Writer.WriteString(body)
return
}
func BankCardUnbind(c *gin.Context) (result.Data, error) {
err := service.UserService.BankCardUnbind(user(c))
if err != nil {
return nil, err
}
return nil, nil
}

@ -3,7 +3,6 @@ module gold-shop
go 1.21.1
require (
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
github.com/gin-contrib/cors v1.7.1
github.com/gin-gonic/gin v1.9.1
github.com/golang-jwt/jwt/v5 v5.2.1

@ -29,8 +29,6 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 h1:6VSn3hB5U5GeA6kQw4TwWIWbOhtvR2hmbBJnTOtqTWc=
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6/go.mod h1:YxOVT5+yHzKvwhsiSIWmbAYM3Dr9AEEbER2dVayfBkg=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gin-contrib/cors v1.7.1 h1:s9SIppU/rk8enVvkzwiC2VK3UZ/0NNGsWfUKvV55rqs=

Binary file not shown.

@ -10,12 +10,14 @@ import (
"gold-shop/request"
"gold-shop/route"
"gold-shop/utils"
"gold-shop/utils/tlpay"
"gold-shop/utils/tlpay/notify"
"net/url"
)
func main() {
initial()
//testPay()
//testVerify()
//runServer()
runServerInWindows()
}
@ -123,3 +125,14 @@ func payOrder3() {
fmt.Println(string(body))
utils.Post2("https://api.paypal.com/v2/checkout/orders", string(body), token)
}
func testVerify() {
str := "{\"cusid\":\"6603910521126XB\",\"appid\":\"00307595\",\"outTrxid\":\"2024051323201201\",\"trxcode\":\"VSP301\",\"trxid\":\"240513117804146702\",\"initamt\":\"10\",\"trxamt\":\"10\",\"trxdate\":\"20240513\",\"paytime\":\"20240513232054\",\"chnltrxid\":\"\",\"trxstatus\":\"0000\",\"termno\":\"\",\"termbatchid\":\"\",\"termtraceno\":\"0\",\"termauthno\":\"0513030178146702\",\"termrefnum\":\"2405132301010100017804146702\",\"trxreserved\":\"充值\",\"srctrxid\":\"\",\"cusorderid\":\"2024051323201201\",\"acct\":\"6226631705801444\",\"fee\":\"0\",\"cmid\":\"\",\"chnlid\":\"\",\"chnldata\":\"\",\"accttype\":\"00\",\"bankcode\":\"03030000\",\"logonid\":\"\",\"signtype\":\"RSA\",\"sign\":\"bQlu7ErUyYhmk5Atv7RWcqAnD1B7Ls0UwAaSJSXn7vJkTsl2C0NZ8pXYPpXeVxrZY7D+YWoUkHTSmtZH5V4qRtzlWDZSdOE8T3eeEs54tibr5ZUg6UuhbunUrznyTLRKsof+BvLjDp+4bYCG1+q/mesAXDOqA1fHXkc1jDvvGdQ=\"}"
req := notify.PayAgreeNotify{}
err := json.Unmarshal([]byte(str), &req)
fmt.Println("err1", err)
params, err := utils.StructToURLValues(req)
fmt.Println("err2", err)
err = tlpay.TLPay.Verify(params)
fmt.Println("err3", err)
}

@ -15,6 +15,7 @@ type Payment struct {
PayOrderID string
UserID int
Amount float64
Token string
User User `gorm:"foreignKey:UserID;references:ID"`
PayType string
OpenID string

@ -0,0 +1,7 @@
package request
type BindingPaySmsRequest struct {
PaymentNo string `json:"paymentNo" form:"paymentNo"`
ThpInfo string `json:"thpInfo" form:"thpInfo"`
AgreeID string `json:"agreeId" form:"agreeId"`
}

@ -15,7 +15,10 @@ func h5RouteInit(r *gin.Engine) {
h5Group.Match([]string{"GET", "OPTIONS"}, "/get-product-info", result.Json(h5.GetProductInfo))
h5Group.Match([]string{"POST", "OPTIONS"}, "/transfer-pay-notify", h5.TransferPayNotify)
h5Group.Match([]string{"POST", "OPTIONS"}, "/payment-notify", h5.PaymentNotify)
h5Group.Match([]string{"GET", "OPTIONS"}, "/tl-pay", h5.TLPay)
h5Group.Match([]string{"POST", "OPTIONS"}, "/binding-pay-notify", h5.BindingPayNotify)
h5Group.Match([]string{"GET", "OPTIONS"}, "/test-gateway-pay", h5.GatewayPay)
h5Group.Match([]string{"GET", "OPTIONS"}, "/gateway-pay", h5.GatewayPay)
h5Group.Match([]string{"POST", "GET", "OPTIONS"}, "/gateway-pay-ret", h5.GatewayPayRet)
authGroup := h5Group.Group("")
authGroup.Use(middleware.JwtMiddleware("user"))
@ -36,6 +39,8 @@ func h5RouteInit(r *gin.Engine) {
authGroup.Match([]string{"POST", "OPTIONS"}, "/tl-binding-confirm", result.Json(h5.TlBindingConfirm))
authGroup.Match([]string{"GET", "OPTIONS"}, "/get-user-bank-card", result.Json(h5.GetUserBankCard))
authGroup.Match([]string{"POST", "OPTIONS"}, "/binding-pay-confirm", result.Json(h5.BindingPayConfirm))
authGroup.Match([]string{"POST", "OPTIONS"}, "/binding-pay-sms", result.Json(h5.BindingPaySms))
authGroup.Match([]string{"POST", "OPTIONS"}, "/gateway-pay-apply", result.Json(h5.GatewayPayApply))
authGroup.Match([]string{"POST", "OPTIONS"}, "/bank-card-unbind", result.Json(h5.BankCardUnbind))
}
}

@ -15,6 +15,7 @@ import (
"gold-shop/utils/payment"
"gold-shop/utils/result"
"gold-shop/utils/tlpay"
"gold-shop/utils/tlpay/notify"
"gold-shop/utils/tlpay/param"
"gorm.io/gorm"
"strconv"
@ -48,6 +49,8 @@ func (s paymentService) Payment(userID int, paymentRequest request.PaymentReques
data, err = s.transferPayment(paymentRequest, p)
} else if paymentRequest.PayType == "binding" {
data, err = s.bindingPayment(paymentRequest, p)
} else if paymentRequest.PayType == "gateway" {
data, err = s.getGatewayPayUrl(p)
} else {
err = errors.NewBusinessError("payType参数错误")
}
@ -125,7 +128,7 @@ func (s paymentService) bindingPayment(paymentRequest request.PaymentRequest, p
payParam.Currency = "CNY"
payParam.Subject = "充值"
payParam.TrxReserve = "充值"
payParam.NotifyUrl = "http://api.wrtcjt.com/h5/payment-notify"
payParam.NotifyUrl = "http://api.wrtcjt.com/h5/binding-pay-notify"
res, err := tlpay.TLPay.PayApplyAgree(payParam)
if err != nil {
return nil, err
@ -175,7 +178,8 @@ func (s paymentService) ConfirmBindingPayment(req request.BindingPayConfirmReque
if res.RetCode != "SUCCESS" {
return nil, errors.NewBusinessError(res.RetMsg)
}
if res.TrxStatus != "1999" {
if res.TrxStatus != "0000" {
return nil, errors.NewBusinessError(res.ErrMsg)
}
@ -186,6 +190,38 @@ func (s paymentService) ConfirmBindingPayment(req request.BindingPayConfirmReque
return data, nil
}
func (s paymentService) SmsBindingPayment(req request.BindingPaySmsRequest, user *model.User) (result.Data, error) {
pm := &model.Payment{}
err := global.DB.Where("user_id", user.ID).Where("payment_no", req.PaymentNo).Where("status", 0).First(&pm).Error
if err != nil {
return nil, err
}
thpInfo, err := base64.StdEncoding.DecodeString(req.ThpInfo)
if err != nil {
return nil, err
}
smsParam := param.PaySmsAgreeParam{}
smsParam.AgreeID = req.AgreeID
smsParam.ThpInfo = string(thpInfo)
smsParam.OrderID = req.PaymentNo
res, err := tlpay.TLPay.PaySmsAgree(smsParam)
if err != nil {
return nil, err
}
if err != nil {
return nil, err
}
if res.RetCode != "SUCCESS" {
return nil, errors.NewBusinessError(res.RetMsg)
}
data := result.Data{
"paymentNo": pm.PaymentNo,
}
return data, nil
}
func (paymentService) createPayment(userID int, paymentRequest request.PaymentRequest) (*model.Payment, error) {
p := model.Payment{}
p.PaymentNo = utils.GenerateNo("payment")
@ -309,3 +345,70 @@ func (s paymentService) AfterPaymentNotify(req request.PaymentNotifyRequest) err
return err
}
func (s paymentService) AfterBindingPayNotify(req notify.PayAgreeNotify) error {
pm := &model.Payment{}
err := global.DB.Where("payment_no", req.CusOrderID).Where("status", 0).First(&pm).Error
if err != nil && e.Is(err, gorm.ErrRecordNotFound) {
return errors.NewBusinessError("记录不存在")
}
user := model.User{}
global.DB.Model(&model.User{}).Where("id", pm.UserID).Find(&user)
if req.TrxStatus == "0000" {
pm.Status = 1
global.DB.Model(&user).UpdateColumn("balance", gorm.Expr("balance + ?", pm.Amount))
} else {
pm.Status = 2
}
err = global.DB.Save(&pm).Error
return err
}
func (s paymentService) GatewayPay(token string) (string, error) {
pm := &model.Payment{}
err := global.DB.Where("token", token).Where("status", 0).First(&pm).Error
if err != nil {
return "", err
}
p := param.GatewayPayParam{}
p.OrderID = pm.PaymentNo
p.PayType = "B2B,B2C"
p.TrxAmt = strconv.FormatFloat(pm.Amount*100, 'f', 0, 64)
p.LimitPay = "no_credit"
p.RetUrl = "http://api.wrtcjt.com/h5/gateway-pay-ret"
p.NotifyUrl = "http://api.wrtcjt.com/h5/binding-pay-notify"
p.GoodsID = "1"
p.GoodsInf = "充值"
p.Charset = "UTF-8"
str := tlpay.TLPay.GatewayPay(p)
return str, nil
}
func (s paymentService) GatewayPayRet(ret notify.GatewayPayRet) (string, error) {
return "", nil
}
func (s paymentService) GatewayPayApply(userID int, paymentRequest request.PaymentRequest) (result.Data, error) {
pm, err := s.createPayment(userID, paymentRequest)
if err != nil {
return nil, err
}
return s.getGatewayPayUrl(pm)
}
func (s paymentService) getGatewayPayUrl(pm *model.Payment) (result.Data, error) {
token := utils.Md5(pm.PaymentNo + strconv.Itoa(pm.UserID) + "_gateway")
pm.Token = token
err := global.DB.Save(pm).Error
if err != nil {
return nil, err
}
data := result.Data{"url": "http://api.wrtcjt.com/h5/gateway-pay?token=" + token, "orderId": ""}
return data, nil
}

@ -181,7 +181,7 @@ func (s *userService) doTlBindingApply(req request.TlBindingApplyRequest, user *
func (userService) createBankCard(req request.TlBindingApplyRequest, user *model.User) (*model.UserBankCard, error) {
c := model.UserBankCard{}
err := global.DB.Where("user_id", user.ID).Where("account_no", req.AcctNo).Find(&c).Error
err := global.DB.Where("user_id", user.ID).Where("account_no", req.AcctNo).First(&c).Error
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
@ -203,7 +203,7 @@ func (userService) createBankCard(req request.TlBindingApplyRequest, user *model
func (s *userService) TlBindingConfirm(req request.TlBindingConfirmRequest, user *model.User) (result.Data, error) {
c := model.UserBankCard{}
err := global.DB.Where("user_id", user.ID).Where("account_no", req.AcctNo).Find(&c).Error
err := global.DB.Where("user_id", user.ID).Where("account_no", req.AcctNo).First(&c).Error
if err != nil {
return nil, err
}
@ -272,3 +272,35 @@ func (s *userService) GetBankCardByUserID(userID int) (*model.UserBankCard, erro
}
return &c, nil
}
func (s *userService) BankCardUnbind(user *model.User) error {
c := model.UserBankCard{}
err := global.DB.Where("user_id", user.ID).Where("status", 1).First(&c).Error
if err != nil && errors.Is(err, gorm.ErrRecordNotFound) {
return errors.NewBusinessError("银行卡不存在")
}
if err != nil {
return err
}
p := param.UnbindParam{}
p.AgreeID = c.AgreeID
p.ReqIp = "127.0.0.1"
p.Version = "11"
r, err := tlpay.TLPay.Unbind(p)
if err != nil {
return err
}
if r.RetCode != "SUCCESS" {
return errors.NewBusinessError(r.RetMsg)
}
c.Status = 3
err = global.DB.Save(&c).Error
if err != nil {
return errors.NewBusinessError("更新失败")
}
return nil
}

@ -64,6 +64,28 @@ func (api *tlPay) AgreeConfirm(p param.AgreeConfirmParam) (*result.AgreeConfirmR
return &r, nil
}
func (api *tlPay) Unbind(p param.UnbindParam) (*result.CommonResult, error) {
payConfig := global.Config.TlPay
data, err := utils.StructToURLValues(p)
data = api.SetCommonParams(data, true)
sign, err := api.sign(data)
if err != nil {
return nil, err
}
fmt.Println(sign)
data.Set("sign", sign)
res, err := api.post(payConfig.BaseUrl+"/apiweb/qpay/unbind", data)
if err != nil {
return nil, err
}
r := result.CommonResult{}
err = json.Unmarshal(res, &r)
if err != nil {
return nil, err
}
return &r, nil
}
func (api *tlPay) PayApplyAgree(p param.PayApplyAgreeParam) (*result.PayApplyAgreeResult, error) {
payConfig := global.Config.TlPay
data, err := utils.StructToURLValues(p)
@ -159,6 +181,26 @@ func (api *tlPay) sign(params url.Values) (string, error) {
return utils.RSASign([]byte(signStr), payConfig.PriPemFile)
}
func (api *tlPay) Verify(params url.Values) error {
payConfig := global.Config.TlPay
sign := params.Get("sign")
params.Del("sign")
for key, value := range params {
if len(value) == 0 || value[0] == "" {
params.Del(key)
}
}
//signStr, err := url.QueryUnescape(params.Encode())
//if err != nil {
// return err
//}
signStr := params.Encode()
fmt.Println("sign: ", sign)
fmt.Println("signStr: ", signStr)
return utils.RSAVerify([]byte(signStr), sign, payConfig.PriPemFile)
}
func (api *tlPay) post(url string, data url.Values) ([]byte, error) {
client := &http.Client{}
body := strings.NewReader(data.Encode())
@ -181,7 +223,7 @@ func (api *tlPay) post(url string, data url.Values) ([]byte, error) {
bodyBytes, err := io.ReadAll(response.Body)
fmt.Println(string(bodyBytes))
fmt.Println("res: ", string(bodyBytes))
if err != nil {
return nil, errors.NewBusinessError("返回内容错误")
@ -207,7 +249,7 @@ func (api *tlPay) BuildForm(data url.Values) string {
<meta charset="utf-8">
<script>
window.onload = function() {
//document.getElementById("auto-submit-form").submit();
document.getElementById("auto-submit-form").submit();
};
</script>
</head>
@ -228,7 +270,7 @@ func (api *tlPay) buildFormHtml(data url.Values) string {
formHtml += "<input type=\"hidden\" name=\"" + key + "\" value=\"" + value[0] + "\">"
}
formHtml += "<button type=\"submit\">提交</button>"
//formHtml += "<button type=\"submit\">提交</button>"
formHtml += "</form>"
return formHtml
}

@ -0,0 +1,16 @@
package notify
type GatewayPayRet struct {
CusID string `json:"cusid" form:"cusid"`
AppID string `json:"appid" form:"appid"`
TrxCode string `json:"trxcode" form:"trxcode"`
TrxID string `json:"trxid" form:"trxid"`
TrxAmt string `json:"trxamt" form:"trxamt"`
TrxDate string `json:"trxdate" form:"trxdate"`
PayTime string `json:"paytime" form:"paytime"`
TrxStatus string `json:"trxstatus" form:"trxstatus"`
TrxReserved string `json:"trxreserved" form:"trxreserved"`
CusOrderID string `json:"cusorderid" form:"cusorderid"`
SignType string `json:"signtype" form:"signtype"`
Sign string `json:"sign" form:"sign"`
}

@ -0,0 +1,36 @@
package notify
type PayAgreeNotify struct {
CusID string `json:"cusid" form:"cusid"`
AppID string `json:"appid" form:"appid"`
OutTrxID string `json:"outTrxid" form:"outtrxid"`
TrxCode string `json:"trxcode" form:"trxcode"`
TrxID string `json:"trxid" form:"trxid"`
InitAmt string `json:"initamt" form:"initamt"`
TrxAmt string `json:"trxamt" form:"trxamt"`
TrxDate string `json:"trxdate" form:"trxdate"`
PayTime string `json:"paytime" form:"paytime"`
ChannelTrxID string `json:"chnltrxid" form:"chnltrxid"`
TrxStatus string `json:"trxstatus" form:"trxstatus"`
TermNo string `json:"termno" form:"termno"`
TermBatchID string `json:"termbatchid" form:"termbatchid"`
TermTraceNo string `json:"termtraceno" form:"termtraceno"`
TermAuthNo string `json:"termauthno" form:"termauthno"`
TermRefNum string `json:"termrefnum" form:"termrefnum"`
TrxReserved string `json:"trxreserved" form:"trxreserved"`
SrcTrxID string `json:"srctrxid" form:"srctrxid"`
CusOrderID string `json:"cusorderid" form:"cusorderid"`
Acct string `json:"acct" form:"acct"`
Fee string `json:"fee" form:"fee"`
CmID string `json:"cmid" form:"cmid"`
ChannelID string `json:"chnlid" form:"chnlid"`
ChannelData string `json:"chnldata" form:"chnldata"`
AcctType string `json:"accttype" form:"accttype"`
BankCode string `json:"bankcode" form:"bankcode"`
LogOnID string `json:"logonid" form:"logonid"`
SignType string `json:"signtype" form:"signtype"`
Sign string `json:"sign" form:"sign"`
}

@ -0,0 +1,14 @@
package param
type UnbindParam struct {
CusID string `json:"cusid" form:"cusid"`
AppID string `json:"appid" form:"appid"`
ReqTime string `json:"reqtime" form:"reqtime"`
ReqIp string `json:"reqip" form:"reqip"`
Version string `json:"version" form:"version"`
RandomStr string `json:"randomstr" form:"randomstr"`
SignType string `json:"signtype" form:"signtype"`
Sign string `json:"sign" form:"sign"`
AgreeID string `json:"agreeid" form:"agreeid"`
}
Loading…
Cancel
Save