From 943c3401c66913c63f92a57fb38610269745347c Mon Sep 17 00:00:00 2001 From: Rzy <465386466@qq.com> Date: Tue, 6 Aug 2024 16:53:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/console/command.go | 2 +- app/constants/errorcode/error_code.go | 11 +- app/http/controllers/api.go | 102 +++++++++++++++ app/http/controllers/base.go | 5 + app/http/controllers/front/api.go | 24 +++- app/http/entities/backend/order.go | 16 ++- app/http/entities/front/pay.go | 8 +- app/http/middlewares/base.go | 42 +++--- app/http/requestmapping/front.go | 8 +- app/http/routes/route.go | 2 +- .../orderrequestlogmodel/order_request_log.go | 4 +- app/models/ordersmodel/orders.go | 2 +- app/models/paychannelmodel/pay_channel.go | 2 +- app/services/api_request_valid.go | 2 +- app/services/app.go | 23 +++- app/services/merchant.go | 3 +- app/services/order.go | 8 +- app/services/pay.go | 45 ------- app/services/pay_channel.go | 6 +- app/services/request_log.go | 37 +++++- app/services/thirdpay/do/pay.go | 64 +++++++++ app/services/thirdpay/do/pay_check.go | 69 ++++++++++ app/services/thirdpay/do/pay_way.go | 28 ++++ app/services/thirdpay/pay.go | 62 +++++++++ app/services/thirdpay/types/callback.go | 10 ++ app/services/thirdpay/web_pay.go | 123 ------------------ app/third/paymentService/payment_service.go | 8 ++ app/utils/encrypt/rsa/rsa_test.go | 2 +- 28 files changed, 486 insertions(+), 232 deletions(-) create mode 100644 app/http/controllers/api.go delete mode 100644 app/services/pay.go create mode 100644 app/services/thirdpay/do/pay.go create mode 100644 app/services/thirdpay/do/pay_check.go create mode 100644 app/services/thirdpay/do/pay_way.go create mode 100644 app/services/thirdpay/pay.go create mode 100644 app/services/thirdpay/types/callback.go delete mode 100644 app/services/thirdpay/web_pay.go diff --git a/app/console/command.go b/app/console/command.go index fb8e8de..dd7a3e2 100644 --- a/app/console/command.go +++ b/app/console/command.go @@ -125,7 +125,7 @@ func queryOrder() { // 更新订单状态 todo orderUpdate := ordersmodel.Orders{ Id: orderInfo.Id, - Status: status, + Status: int32(status), } session := ordersmodel.GetInstance().GetDb().NewSession() diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index 5b248fd..d7b4235 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -56,8 +56,11 @@ const ( OrdersNotFound = 1401 OrdersExist = 1402 OrderTypeNotFount = 1403 - //网页支付 - RequestLogErrors = 1500 + + //请求日志 + RequestLogErrors = 1500 + RequestLogNotFound = 1501 + RequestResponseValid = 1502 ) var MsgEN = map[int]string{ @@ -101,7 +104,9 @@ var MsgZH = map[int]string{ PayChannelNotBuild: "支付方式尚未开通", PayChannelExtJsonError: "支付方式扩展参数错误", - RequestLogErrors: "请求日志错误", + RequestLogErrors: "请求日志错误", + RequestLogNotFound: "未找到日志信息", + RequestResponseValid: "上游返回格式无效", OrdersNotFound: "未找到订单", OrdersExist: "订单已存在", diff --git a/app/http/controllers/api.go b/app/http/controllers/api.go new file mode 100644 index 0000000..ec1e2eb --- /dev/null +++ b/app/http/controllers/api.go @@ -0,0 +1,102 @@ +package controllers + +import ( + "PaymentCenter/app/constants/common" + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/models/orderrequestlogmodel" + "PaymentCenter/app/services" + "PaymentCenter/app/utils" + "PaymentCenter/config" + "encoding/json" + "github.com/gin-gonic/gin" + "net/http" +) + +func ApiRes(c *gin.Context, data interface{}, code int, msg ...string) { + var log_id int64 + message := "" + if utils.IsNil(data) { + data = struct{}{} + } + if len(msg) > 0 { + message = msg[0] + } else { + message = errorcode.GetMsg(code, "") + } + log, exists := GetApiLogId(c) + if exists { + log_id = log.(int64) + dataByte, _ := json.Marshal(data) + status := common.STATUS_ENABLE + if code == errorcode.Success { + status = common.STATUS_DISABLED + } + services.RequestLogUpdate(&orderrequestlogmodel.OrderRequestLog{ + Id: log_id, + MerchantResponse: string(dataByte), + Status: status, + }) + } + + if code == errorcode.Success { + ApiSuccess(c, data, log_id, message) + } else { + ApiError(c, code, log_id, message) + } +} + +func ApiSuccess(c *gin.Context, data interface{}, log_id int64, messageSlice ...string) { + var message string + if len(messageSlice) > 0 { + message = messageSlice[0] + } + if message == "" { + message = errorcode.GetMsg(errorcode.Success, c.GetHeader("local")) + } + if config.GetConf().Env == "production" { + c.String(http.StatusOK, EncriptJson(gin.H{ + "code": errorcode.Success, + "message": message, + "data": data, + "trace_id": log_id, + })) + } else { + c.JSON(http.StatusOK, gin.H{ + "code": errorcode.Success, + "message": message, + "data": data, + "trace_id": log_id, + }) + } + + c.Abort() +} + +/** + * 失败时返回 + */ +func ApiError(c *gin.Context, code int, log_id int64, msg ...string) { + message := "" + if len(msg) > 0 { + message = msg[0] + } else { + message = errorcode.GetMsg(code, "") + } + if config.GetConf().Env == "production" { + c.String(http.StatusOK, EncriptJson(gin.H{ + "code": code, + "message": message, + "data": make(map[string]string), + "trace_id": log_id, + })) + } else { + c.JSON(http.StatusOK, gin.H{ + "code": code, + "message": message, + "data": make(map[string]string), + "trace_id": log_id, + }) + } + + c.Abort() +} diff --git a/app/http/controllers/base.go b/app/http/controllers/base.go index 03afeee..b42fd4d 100644 --- a/app/http/controllers/base.go +++ b/app/http/controllers/base.go @@ -200,6 +200,11 @@ func GetAppCheckInfo(c *gin.Context) interface{} { return request } +func GetApiLogId(c *gin.Context) (interface{}, bool) { + request, exists := c.Get("log") + return request, exists +} + func HandRes(c *gin.Context, data interface{}, err error) { if err == nil { Success(c, data, "") diff --git a/app/http/controllers/front/api.go b/app/http/controllers/front/api.go index b23b617..fd7f2da 100644 --- a/app/http/controllers/front/api.go +++ b/app/http/controllers/front/api.go @@ -1,16 +1,32 @@ package front import ( + "PaymentCenter/app/constants/errorcode" "PaymentCenter/app/http/controllers" "PaymentCenter/app/http/entities/front" "PaymentCenter/app/services" + "PaymentCenter/app/services/thirdpay" "github.com/gin-gonic/gin" ) -func WebPay(c *gin.Context) { - req := controllers.GetRequest(c).(*front.PayWebReqs) +func Pay(c *gin.Context) { + req := controllers.GetRequest(c).(*front.PayReqs) appCheckInfo := controllers.GetAppCheckInfo(c).(*services.AppCheck) - code := services.ThirdPayWeb(c.Request.Context(), req, appCheckInfo, c.ClientIP()) - controllers.ErrWithCode(c, code) + check := thirdpay.ThirdPayCheck(c.Request.Context(), req, appCheckInfo, c.ClientIP()) + if check.CheckCode != errorcode.Success { + if check.CheckCode == errorcode.OrdersExist { + //订单已存在,直接返回订单信息 + controllers.ApiRes(c, thirdpay.PayCallBack(check.OldOrder, false), errorcode.Success) + return + } + controllers.ApiRes(c, nil, check.CheckCode) + return + } + payInfo := thirdpay.ThirdPayWeb(check) + if payInfo.PayCode != errorcode.Success { + controllers.ApiRes(c, nil, payInfo.PayCode) + return + } + controllers.ApiRes(c, thirdpay.PayCallBack(payInfo.Order, true), errorcode.Success) return } diff --git a/app/http/entities/backend/order.go b/app/http/entities/backend/order.go index 8ff87bd..6e14a6f 100644 --- a/app/http/entities/backend/order.go +++ b/app/http/entities/backend/order.go @@ -70,8 +70,8 @@ type OrdersResponse struct { PayChannelId int64 `json:"pay_channel_id"` AppId int64 `json:"app_id"` OutTreadNo string `json:"out_tread_no"` - Status int `json:"status"` - OrderType int `json:"order_type"` + Status int32 `json:"status"` + OrderType int32 `json:"order_type"` Amount int `json:"amount"` IpAddress string `json:"ip_address"` MerchantRequest string `json:"merchant_request"` @@ -110,17 +110,18 @@ type OrderLogsListRequest struct { type OrderRequestLogResponse struct { Id int64 `json:"id"` IpAddress string `json:"ip_address"` - OrderId int64 `json:"order_id"` + Url string `json:"url"` MerchantRequest string `json:"merchant_request"` MerchantResponse string `json:"merchant_response"` CreateTime string `json:"create_time"` - Status int `json:"status"` + Status int32 `json:"status"` } func (o *OrderRequestLogResponse) ResponseFromDb(db orderrequestlogmodel.OrderRequestLog) { o.Id = db.Id - o.OrderId = db.OrderId + o.IpAddress = db.IpAddress + o.Url = db.URL o.Status = db.Status o.MerchantRequest = db.MerchantRequest o.MerchantResponse = db.MerchantResponse @@ -128,8 +129,9 @@ func (o *OrderRequestLogResponse) ResponseFromDb(db orderrequestlogmodel.OrderRe } type OrderThirdLogResponse struct { - Id int64 `json:"id"` - OrderId int64 `json:"order_id"` + Id int64 `json:"id"` + OrderId int64 `json:"order_id"` + CreateTime string `json:"create_time"` PayCallback string `json:"pay_callback"` Status int `json:"status"` diff --git a/app/http/entities/front/pay.go b/app/http/entities/front/pay.go index 56bbcb7..150f3ff 100644 --- a/app/http/entities/front/pay.go +++ b/app/http/entities/front/pay.go @@ -11,7 +11,7 @@ type RequestBody struct { Data string `json:"data" validate:"required"` } -type PayWebReqs struct { +type PayReqs struct { ApiCommonBody PayChannelId int64 `json:"pay_channel_id" validate:"required" label:"支付渠道"` OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"` @@ -20,3 +20,9 @@ type PayWebReqs struct { ExtJson string `json:"ext_json" label:"扩展参数"` Desc string `json:"desc" validate:"max=100" label:"商品描述"` } + +type OrderApiResp struct { + Code int + Msg string + Data interface{} +} diff --git a/app/http/middlewares/base.go b/app/http/middlewares/base.go index 220a59a..0bdf33e 100644 --- a/app/http/middlewares/base.go +++ b/app/http/middlewares/base.go @@ -10,6 +10,7 @@ import ( "PaymentCenter/app/services/apicrypt" "PaymentCenter/app/utils" "PaymentCenter/config" + "encoding/json" "github.com/gin-gonic/gin" "strings" ) @@ -104,10 +105,11 @@ func ValidateRequest() gin.HandlerFunc { return func(c *gin.Context) { var path = c.FullPath() var handler func() interface{} + if strings.Index(path, "admin") >= 0 { handler = requestmapping.BackendRequestMap[path] } else { - handler = requestmapping.FrontRequest() + handler = requestmapping.FrontRequestMapBeforeDecrypt[path] } if handler == nil { utils.Log(c, "path", path) @@ -133,40 +135,45 @@ func ValidatePayRequest() gin.HandlerFunc { var handler func() interface{} requestData, err := utils.SonicApiDataToStruct(controllers.GetRequest(c), &front.RequestBody{}) if err != nil { - controllers.ErrWithCode(c, errorcode.ParamError) + controllers.ApiRes(c, nil, errorcode.ParamError) return } requestDataStruct := requestData.(*front.RequestBody) + //判断时间 //now := time.Now().UnixNano() / 1000000 - //if comStruct.Timestamp > now || (config.GetConf().TimeOut != 0 && (now-comStruct.Timestamp) > config.GetConf().TimeOut) { - // controllers.ErrWithCode(c, errorcode.RequestTimeOut) + //if requestDataStruct.Timestamp > now || (config.GetConf().TimeOut != 0 && (now-requestDataStruct.Timestamp) > config.GetConf().TimeOut) { + // controllers.ApiRes(c, nil, errorcode.RequestTimeOut) // return //} //获取app信息 - appCheck := services.AppGetAndCheck(&services.AppCheck{ - AppId: requestDataStruct.AppId, - Ip: c.ClientIP(), - Code: errorcode.Success, - }) + appCheck := services.GetAppCheck(requestDataStruct.AppId, c.ClientIP()) + //存入请求记录 + if appCheck.Code != errorcode.Success { - controllers.ErrWithCode(c, appCheck.Code) + controllers.ApiRes(c, nil, appCheck.Code) return } //解密 cryptFunc := appCheck.Crypt() if cryptFunc == nil { - controllers.ErrWithCode(c, appCheck.GetCode()) + controllers.ApiRes(c, nil, appCheck.GetCode()) } dataByte, errCode := cryptFunc(appCheck.App).Decrypt(requestDataStruct.Data) if errCode != apicrypt.CryptNotError { - controllers.ErrWithCode(c, errCode) + controllers.ApiRes(c, nil, errCode) return } + //记录请求日志 + id, code := services.AddRequestLog(dataByte, c.ClientIP(), path) + if code != errorcode.Success { + controllers.ApiRes(c, nil, errCode) + } + c.Set("log", id) //检查解密后的数据是否与请求一致 reCheck := appCheck.ReCheckAfterDecrypt(dataByte, requestDataStruct) if !reCheck { - controllers.ErrWithCode(c, appCheck.GetCode()) + controllers.ApiRes(c, nil, appCheck.GetCode()) return } //表单验证 @@ -175,10 +182,15 @@ func ValidatePayRequest() gin.HandlerFunc { msg, err := controllers.ValidApiData(dataByte, v) if err != nil { utils.Log(c, "参数错误", "path=", path, "err=", err.Error(), "msg=", msg) - controllers.Error(c, errorcode.ParamError, msg...) + controllers.ApiRes(c, nil, errorcode.ParamError, msg...) c.Abort() } - c.Set("request", dataByte) + err = json.Unmarshal(dataByte, &v) + if err != nil { + controllers.ApiRes(c, nil, errorcode.Forbidden) + return + } + c.Set("request", v) c.Set("appCheckInfo", appCheck) c.Next() } diff --git a/app/http/requestmapping/front.go b/app/http/requestmapping/front.go index 79e6f2c..bf8173d 100644 --- a/app/http/requestmapping/front.go +++ b/app/http/requestmapping/front.go @@ -6,11 +6,9 @@ import ( ) var FrontRequestMap = map[string]func() interface{}{ - common.FRONT_V1 + "/pay/web": func() interface{} { return new(front.PayWebResp) }, + common.FRONT_V1 + "/pay/do": func() interface{} { return new(front.PayReqs) }, } -func FrontRequest() func() interface{} { - return func() interface{} { - return new(front.RequestBody) - } +var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{ + common.FRONT_V1 + "/pay/do": func() interface{} { return new(front.RequestBody) }, } diff --git a/app/http/routes/route.go b/app/http/routes/route.go index c1df4fa..65deec4 100644 --- a/app/http/routes/route.go +++ b/app/http/routes/route.go @@ -58,7 +58,7 @@ func RegisterRoute(router *gin.Engine) { pay := v1.Group("/pay", middlewares.ValidateRequest(), middlewares.ValidatePayRequest()) { - pay.POST("/web", front.WebPay) + pay.POST("/do", front.Pay) } } diff --git a/app/models/orderrequestlogmodel/order_request_log.go b/app/models/orderrequestlogmodel/order_request_log.go index 961b6e6..892fa44 100644 --- a/app/models/orderrequestlogmodel/order_request_log.go +++ b/app/models/orderrequestlogmodel/order_request_log.go @@ -15,12 +15,12 @@ var ( type OrderRequestLog struct { Id int64 IpAddress string `xorm:"'ip_address' varchar(16)"` - OrderId int64 `xorm:"'order_id' bigint(20)"` + URL string `xorm:"'url' varchar(20)"` MerchantRequest string `xorm:"'merchant_request' JSON"` MerchantResponse string `xorm:"'merchant_response' JSON"` CreateTime time.Time `xorm:"'create_time' datetime created"` UpdateTime time.Time `xorm:"'update_time' timestamp updated"` - Status int `xorm:"'status' TINYINT"` + Status int32 `xorm:"'status' TINYINT"` } // 表名 diff --git a/app/models/ordersmodel/orders.go b/app/models/ordersmodel/orders.go index f6dd2f2..ba3999a 100644 --- a/app/models/ordersmodel/orders.go +++ b/app/models/ordersmodel/orders.go @@ -24,7 +24,7 @@ type Orders struct { Desc string `xorm:"'desc' varchar(100)"` CreateTime time.Time `xorm:"'create_time' datetime created"` UpdateTime time.Time `xorm:"'update_time' timestamp updated"` - Status int `xorm:"'status' TINYINT"` + Status int32 `xorm:"'status' TINYINT"` DeleteTime time.Time `xorm:"'delete_time' timestamp deleted"` } diff --git a/app/models/paychannelmodel/pay_channel.go b/app/models/paychannelmodel/pay_channel.go index 7b65f10..c99448b 100644 --- a/app/models/paychannelmodel/pay_channel.go +++ b/app/models/paychannelmodel/pay_channel.go @@ -16,7 +16,7 @@ type PayChannel struct { Id int64 PayName string `xorm:"'pay_name' varchar(128)"` MerchantId int64 `xorm:"'merchant_id' bigint(20)"` - ChannelType int `xorm:"'channel_type' int(11)"` + ChannelType int `xorm:"'channel_type' tinyint(2)"` AppId string `xorm:"'app_id' varchar(255)"` ExtJson string `xorm:"'ext_json' JSON"` ExpireTime time.Time `xorm:"'expire_time' datetime"` diff --git a/app/services/api_request_valid.go b/app/services/api_request_valid.go index ccdbbb8..ca007ce 100644 --- a/app/services/api_request_valid.go +++ b/app/services/api_request_valid.go @@ -42,7 +42,7 @@ func (a *AppCheck) Check() *AppCheck { a.Code = errorcode.AppDisabled return a } - if a.App.DeleteTime.Location() == nil { + if !a.App.DeleteTime.IsZero() { a.Code = errorcode.AppNotFound return a } diff --git a/app/services/app.go b/app/services/app.go index 88ce3d3..371ecce 100644 --- a/app/services/app.go +++ b/app/services/app.go @@ -100,22 +100,31 @@ func AppFindOne(req entities.IdRequest, col ...string) (row *appmodel.App, code return row, errorcode.Success } -func AppGetAndCheck(appCheckIn *AppCheck) (appCheckOut *AppCheck) { +func CheckApp(appCheckIn *AppCheck) { errCode := errorcode.Success - appCheckOut.App, errCode = AppFindOne(entities.IdRequest{Id: appCheckIn.AppId}) + appCheckIn.App, errCode = AppFindOne(entities.IdRequest{Id: appCheckIn.AppId}) if errCode != errorcode.Success { - appCheckOut.Code = errCode - return + appCheckIn.Code = errCode } //检查app可用性 - appCheckOut = appCheckIn.Check() - if appCheckOut.GetCode() != errorcode.Success { + appCheckIn.Check() + if appCheckIn.GetCode() != errorcode.Success { return } //检查白名单 - if appCheckIn.Ip != "" && !appCheckOut.IpCheck(appCheckIn.Ip) { + if appCheckIn.Ip != "" && !appCheckIn.IpCheck(appCheckIn.Ip) { return } return } + +func GetAppCheck(appId int64, ip string) *AppCheck { + appCheck := &AppCheck{ + AppId: appId, + Ip: ip, + Code: errorcode.Success, + } + CheckApp(appCheck) + return appCheck +} diff --git a/app/services/merchant.go b/app/services/merchant.go index 386d965..abba737 100644 --- a/app/services/merchant.go +++ b/app/services/merchant.go @@ -86,7 +86,8 @@ func GetAndCheckMerchant(merchant *merchantmodel.Merchant, conn builder.Cond, co if code != errorcode.Success { return nil, code } - if merchantInfo.DeleteTime.Location() != nil { + + if !merchantInfo.DeleteTime.IsZero() { return nil, errorcode.MerchantNotFound } return diff --git a/app/services/order.go b/app/services/order.go index 76fdc91..7e62603 100644 --- a/app/services/order.go +++ b/app/services/order.go @@ -1,7 +1,6 @@ package services import ( - "PaymentCenter/app/constants/common" "PaymentCenter/app/constants/errorcode" "PaymentCenter/app/data" "PaymentCenter/app/http/entities/backend" @@ -78,8 +77,7 @@ func OrderLogsList(req backend.OrderLogsListRequest) (requestLog []orderrequestl func OrderCreate(orderIn *ordersmodel.Orders) (orderOut *ordersmodel.Orders, code int) { repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb()) - orderId, err := repo.OrderInsertOne(orderIn) - orderIn.Id = orderId + _, err := repo.OrderInsertOne(orderIn) code = handErr(err) return orderIn, code } @@ -97,9 +95,7 @@ func OrderFindOne(order *ordersmodel.Orders, conn builder.Cond, col ...string) ( return orderInfo, errorcode.OrdersExist } -func HadSameValueOrder(order *ordersmodel.Orders) (exist bool, code int) { - conn := builder.NewCond() - conn = conn.And(builder.Neq{"Status": common.ORDER_STATUS_CLOSE}) +func PayOrderCheckRepeat(order *ordersmodel.Orders, conn builder.Cond) (exist bool, code int) { _, code = OrderFindOne(order, conn) if code != errorcode.OrdersNotFound { return false, errorcode.Success diff --git a/app/services/pay.go b/app/services/pay.go deleted file mode 100644 index 79b1a6d..0000000 --- a/app/services/pay.go +++ /dev/null @@ -1,45 +0,0 @@ -package services - -import ( - "PaymentCenter/app/constants/errorcode" - "PaymentCenter/app/http/entities/front" - "PaymentCenter/app/services/thirdpay" - "context" -) - -func ThirdPayWeb(ctx context.Context, req *front.PayWebReqs, appCheck *AppCheck, ip string) (code int) { - pay := thirdpay.NewWebPay(&ctx, req, appCheck, ip) - // 校验表单 - pay.CheckForm() - if pay.PayCode != errorcode.Success { - code = pay.PayCode - return - } - // 校验商户 - pay.CheckMerchant() - if pay.PayCode != errorcode.Success { - code = pay.PayCode - return - } - // 校验支付通道 - pay.CheckPayChannel() - if pay.PayCode != errorcode.Success { - code = pay.PayCode - return - } - // 校验订单 - pay.CheckOrder() - if pay.PayCode != errorcode.Success { - code = pay.PayCode - return - } - // 创建订单 - pay.CreateOrder() - if pay.PayCode != errorcode.Success { - code = pay.PayCode - return - } - // 支付 - pay.Pay() - return -} diff --git a/app/services/pay_channel.go b/app/services/pay_channel.go index 26d47bd..fd88eb6 100644 --- a/app/services/pay_channel.go +++ b/app/services/pay_channel.go @@ -107,12 +107,12 @@ func PayChannelFindOne(channel *paychannelmodel.PayChannel, conn builder.Cond, c return channelInfo, errorcode.Success } -func GetAndCheckPayChannel(channel *paychannelmodel.PayChannel, conn builder.Cond, col ...string) (merchantInfo *paychannelmodel.PayChannel, code int) { - merchantInfo, code = PayChannelFindOne(channel, conn, col...) +func GetAndCheckPayChannel(channel *paychannelmodel.PayChannel, conn builder.Cond, col ...string) (channelInfo *paychannelmodel.PayChannel, code int) { + channelInfo, code = PayChannelFindOne(channel, conn, col...) if code != errorcode.Success { return nil, code } - if merchantInfo.DeleteTime.Location() != nil { + if !channelInfo.DeleteTime.IsZero() { return nil, errorcode.PayChannelNotFound } return diff --git a/app/services/request_log.go b/app/services/request_log.go index 8f3f122..f84bdda 100644 --- a/app/services/request_log.go +++ b/app/services/request_log.go @@ -1,14 +1,43 @@ package services import ( + "PaymentCenter/app/constants/common" "PaymentCenter/app/data" "PaymentCenter/app/models/orderrequestlogmodel" + "xorm.io/builder" ) -func RequestLogCreate(log *orderrequestlogmodel.OrderRequestLog) (code int) { +func RequestLogCreate(log *orderrequestlogmodel.OrderRequestLog) (*orderrequestlogmodel.OrderRequestLog, int) { db := orderrequestlogmodel.GetInstance().GetDb() repo := data.NewOrderRequestLogRepo(db) - _, err := repo.OrderRequestLogInsertOne(log) - code = handErr(err) - return + id, err := repo.OrderRequestLogInsertOne(log) + code := handErr(err) + if err != nil { + log.Id = id + } + return log, code +} + +func RequestLogUpdate(log *orderrequestlogmodel.OrderRequestLog) (logOut *orderrequestlogmodel.OrderRequestLog, code int) { + db := orderrequestlogmodel.GetInstance().GetDb() + repo := data.NewOrderRequestLogRepo(db) + conn := builder.NewCond() + conn = conn.And(builder.Eq{"Id": log.Id}) + id, err := repo.OrderRequestLogUpdate(log, conn) + code = handErr(err) + if err != nil { + log.Id = id + } + return log, code +} + +func AddRequestLog(requestDataByte []byte, ip string, url string) (int64, int) { + requestLog, checkCode := RequestLogCreate(&orderrequestlogmodel.OrderRequestLog{ + IpAddress: ip, + MerchantRequest: string(requestDataByte), + URL: url, + MerchantResponse: "{}", + Status: common.STATUS_ENABLE, + }) + return requestLog.Id, checkCode } diff --git a/app/services/thirdpay/do/pay.go b/app/services/thirdpay/do/pay.go new file mode 100644 index 0000000..184a946 --- /dev/null +++ b/app/services/thirdpay/do/pay.go @@ -0,0 +1,64 @@ +package do + +import ( + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/services" + + "PaymentCenter/app/models/ordersmodel" + "PaymentCenter/app/third/paymentService" +) + +type Pay struct { + paycheck *PayCheck + Order *ordersmodel.Orders + PayCode int +} + +func NewPay(paycheck *PayCheck) *Pay { + return &Pay{ + paycheck: paycheck, + PayCode: errorcode.Success, + } +} + +func (w *Pay) CreateOrder() { + w.Order, w.PayCode = services.OrderCreate(&ordersmodel.Orders{ + MerchantId: w.paycheck.Merchant.Id, + PayChannelId: w.paycheck.Channel.Id, + AppId: w.paycheck.Channel.Id, + OutTreadNo: w.paycheck.WebPayReqs.OutTradeNo, + OrderType: w.paycheck.WebPayReqs.OrderType, + Amount: w.paycheck.WebPayReqs.Amount, + ExtJson: w.paycheck.WebPayReqs.ExtJson, + Desc: w.paycheck.WebPayReqs.Desc, + }, + ) +} + +func (w *Pay) Pay() { + var ( + payFunc func(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error + ok bool + ) + thirdPay := &paymentService.PayOrderRequest{ + PayChannelId: w.paycheck.WebPayReqs.PayChannelId, + OrderId: w.Order.Id, + ChannelType: w.paycheck.Channel.ChannelType, + Description: w.Order.Desc, + Amount: w.Order.Amount, + PayerClientIp: w.paycheck.AppCheck.Ip, + } + if payFunc, ok = PayWayList[w.paycheck.Channel.ChannelType]; !ok { + w.PayCode = errorcode.PayChannelNotBuild + return + } + err := payFunc(thirdPay, w.paycheck.Channel.ExtJson) + if err != nil { + w.PayCode = errorcode.PayChannelExtJsonError + return + } + res := paymentService.PaymentService(*w.paycheck.ctx, *thirdPay) + + w.PayCode = res.Code + return +} diff --git a/app/services/thirdpay/do/pay_check.go b/app/services/thirdpay/do/pay_check.go new file mode 100644 index 0000000..e3228e4 --- /dev/null +++ b/app/services/thirdpay/do/pay_check.go @@ -0,0 +1,69 @@ +package do + +import ( + "PaymentCenter/app/constants/common" + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/services" + "xorm.io/builder" + + "PaymentCenter/app/http/entities/front" + "PaymentCenter/app/models/merchantmodel" + "PaymentCenter/app/models/orderrequestlogmodel" + "PaymentCenter/app/models/ordersmodel" + "PaymentCenter/app/models/paychannelmodel" + "context" +) + +type PayCheck struct { + ctx *context.Context + WebPayReqs *front.PayReqs + AppCheck *services.AppCheck + RequestLog *orderrequestlogmodel.OrderRequestLog + Channel *paychannelmodel.PayChannel + Merchant *merchantmodel.Merchant + OldOrder *ordersmodel.Orders + CheckCode int +} + +func NewPayCheck(ctx *context.Context, reqs *front.PayReqs, appCheck *services.AppCheck, ip string) *PayCheck { + if appCheck == nil { + appCheck = services.GetAppCheck(reqs.AppId, ip) + } + return &PayCheck{ + ctx: ctx, + WebPayReqs: reqs, + AppCheck: appCheck, + CheckCode: appCheck.Code, + } +} + +func (w *PayCheck) CheckForm() { + if _, ok := common.OrderTypeList[w.WebPayReqs.OrderType]; !ok { //判断是否是支持的支付渠道 + w.CheckCode = errorcode.PayChannelNotFound + return + } + +} + +func (w *PayCheck) CheckPayChannel() { + conn := builder.NewCond() + conn = conn.And(builder.Eq{"id": w.WebPayReqs.PayChannelId}) + w.Channel, w.CheckCode = services.GetAndCheckPayChannel(&paychannelmodel.PayChannel{}, conn) +} + +func (w *PayCheck) CheckMerchant() { + conn := builder.NewCond() + conn = conn.And(builder.Eq{"id": w.AppCheck.App.MerchantId}) + w.Merchant, w.CheckCode = services.GetAndCheckMerchant(&merchantmodel.Merchant{}, conn) +} + +func (w *PayCheck) CheckOrder() { + cond := builder.NewCond() + cond = cond.And(builder.Eq{"out_tread_no": w.WebPayReqs.OutTradeNo}, builder.Eq{"app_id": w.AppCheck.AppId}, builder.Neq{"status": common.ORDER_STATUS_CLOSE}) + order, code := services.OrderFindOne(&ordersmodel.Orders{}, cond) + if code == errorcode.OrdersExist { + w.OldOrder = order + w.CheckCode = code + } + return +} diff --git a/app/services/thirdpay/do/pay_way.go b/app/services/thirdpay/do/pay_way.go new file mode 100644 index 0000000..b367964 --- /dev/null +++ b/app/services/thirdpay/do/pay_way.go @@ -0,0 +1,28 @@ +package do + +import ( + "PaymentCenter/app/constants/common" + "PaymentCenter/app/third/paymentService" + "github.com/bytedance/sonic" +) + +var PayWayList = map[int]func(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error{ + common.PAY_CHANNEL_WECHAT_H5: WechatH5, + common.PAY_CHANNEL_ALIPAY_WEB: AlipayWeb, +} + +func WechatH5(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error { + err := sonic.Unmarshal([]byte(ExtJson), &commonPayInfo.Wx) + if err != nil { + return err + } + return nil +} + +func AlipayWeb(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error { + err := sonic.Unmarshal([]byte(ExtJson), &commonPayInfo.Ali) + if err != nil { + return err + } + return nil +} diff --git a/app/services/thirdpay/pay.go b/app/services/thirdpay/pay.go new file mode 100644 index 0000000..2396c00 --- /dev/null +++ b/app/services/thirdpay/pay.go @@ -0,0 +1,62 @@ +package thirdpay + +import ( + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/http/entities/front" + "PaymentCenter/app/models/ordersmodel" + "PaymentCenter/app/services" + thirdpay "PaymentCenter/app/services/thirdpay/do" + "PaymentCenter/app/services/thirdpay/types" + "context" +) + +func ThirdPayWeb(check *thirdpay.PayCheck) *thirdpay.Pay { + pay := thirdpay.NewPay(check) + // 创建订单 + pay.CreateOrder() + if pay.PayCode != errorcode.Success { + return pay + } + // 支付 + pay.Pay() + return pay +} + +func ThirdPayCheck(ctx context.Context, req *front.PayReqs, appCheck *services.AppCheck, ip string) (check *thirdpay.PayCheck) { + check = thirdpay.NewPayCheck(&ctx, req, appCheck, ip) + // 校验表单 + check.CheckForm() + if check.CheckCode != errorcode.Success { + return + } + // 校验订单 + check.CheckOrder() + if check.CheckCode != errorcode.Success { + return + } + // 校验商户 + check.CheckMerchant() + if check.CheckCode != errorcode.Success { + return + } + // 校验支付通道 + check.CheckPayChannel() + if check.CheckCode != errorcode.Success { + return + } + + return +} + +func PayCallBack(order *ordersmodel.Orders, isNew bool) *types.PayResp { + res := &types.PayResp{ + OrderNo: order.Id, + OrderType: order.OrderType, + Amount: order.Amount, + Desc: order.Desc, + IsNewCreate: isNew, + Status: order.Status, + } + + return res +} diff --git a/app/services/thirdpay/types/callback.go b/app/services/thirdpay/types/callback.go new file mode 100644 index 0000000..b36419d --- /dev/null +++ b/app/services/thirdpay/types/callback.go @@ -0,0 +1,10 @@ +package types + +type PayResp struct { + OrderNo int64 `json:"order_no"` + OrderType int32 `json:"out_trade_no"` + Amount int `json:"order_type"` + Desc string `json:"amount"` + IsNewCreate bool `json:"is_new_create"` + Status int32 `json:"status"` +} diff --git a/app/services/thirdpay/web_pay.go b/app/services/thirdpay/web_pay.go deleted file mode 100644 index 406e060..0000000 --- a/app/services/thirdpay/web_pay.go +++ /dev/null @@ -1,123 +0,0 @@ -package thirdpay - -import ( - "PaymentCenter/app/constants/common" - "PaymentCenter/app/constants/errorcode" - "PaymentCenter/app/services" - - "PaymentCenter/app/http/entities/front" - "PaymentCenter/app/models/merchantmodel" - "PaymentCenter/app/models/orderrequestlogmodel" - "PaymentCenter/app/models/ordersmodel" - "PaymentCenter/app/models/paychannelmodel" - "PaymentCenter/app/third/paymentService" - "context" - "github.com/bytedance/sonic" -) - -type WebPay struct { - ctx *context.Context - WebPayReqs *front.PayWebReqs - AppCheck *services.AppCheck - Order *ordersmodel.Orders - Channel *paychannelmodel.PayChannel - Merchant *merchantmodel.Merchant - PayCode int -} - -func NewWebPay(ctx *context.Context, reqs *front.PayWebReqs, appCheck *services.AppCheck, ip string) *WebPay { - if appCheck == nil { - appCheck = services.AppGetAndCheck(&services.AppCheck{ - AppId: reqs.AppId, - Ip: ip, - Code: errorcode.Success, - }) - } - return &WebPay{ - ctx: ctx, - WebPayReqs: reqs, - AppCheck: appCheck, - PayCode: appCheck.Code, - } -} - -func (w *WebPay) CheckForm() { - if _, ok := common.OrderTypeList[w.WebPayReqs.OrderType]; !ok { //判断是否是支持的支付渠道 - w.PayCode = errorcode.PayChannelNotFound - return - } - -} - -func (w *WebPay) AddPayLog() { - requestJson, err := sonic.Marshal(w.WebPayReqs) - if err != nil { - w.PayCode = errorcode.RequestLogErrors - return - } - code := services.RequestLogCreate(&orderrequestlogmodel.OrderRequestLog{ - IpAddress: w.AppCheck.Ip, - MerchantRequest: string(requestJson), - }) - w.PayCode = code - return -} - -func (w *WebPay) CheckPayChannel() { - w.Channel, w.PayCode = services.GetAndCheckPayChannel(&paychannelmodel.PayChannel{Id: w.WebPayReqs.PayChannelId}, nil) -} - -func (w *WebPay) CheckMerchant() { - w.Merchant, w.PayCode = services.GetAndCheckMerchant(&merchantmodel.Merchant{Id: w.AppCheck.App.MerchantId}, nil) -} - -func (w *WebPay) CheckOrder() { - exist, code := services.HadSameValueOrder(&ordersmodel.Orders{OutTreadNo: w.WebPayReqs.OutTradeNo}) - if exist { - w.PayCode = code - } -} - -func (w *WebPay) CreateOrder() { - w.Order, w.PayCode = services.OrderCreate(&ordersmodel.Orders{ - MerchantId: w.Merchant.Id, - PayChannelId: w.Channel.Id, - AppId: w.Channel.Id, - OutTreadNo: w.WebPayReqs.OutTradeNo, - OrderType: w.WebPayReqs.OrderType, - Amount: w.WebPayReqs.Amount, - ExtJson: w.WebPayReqs.ExtJson, - Desc: w.WebPayReqs.Desc, - }, - ) -} - -func (w *WebPay) Pay() { - thirdPay := &paymentService.PayOrderRequest{ - PayChannelId: w.WebPayReqs.PayChannelId, - OrderId: w.Order.Id, - ChannelType: w.Channel.ChannelType, - Description: w.Order.Desc, - Amount: w.Order.Amount, - PayerClientIp: w.AppCheck.Ip, - } - //{"api_v_3_key": "131231231", "app_id": "123", "mch_id": "123123", "private_key": "2131312", "serial_no": "123213213"} - switch w.WebPayReqs.OrderType { - case common.PAY_CHANNEL_WECHAT_H5: - var wx paymentService.WxPay - err := sonic.Unmarshal([]byte(w.Channel.ExtJson), &wx) - if err != nil { - w.PayCode = errorcode.PayChannelExtJsonError - return - } - wx.AppId = w.Channel.AppId - case common.PAY_CHANNEL_ALIPAY_WEB: - //{"ali_public_key": "123", "private_key_path": "123", "sign_type": "123"} - //thirdPay.Ali = &paymentService.AliPay{} - default: - w.PayCode = errorcode.PayChannelNotBuild - return - } - _ = paymentService.PaymentService(*w.ctx, *thirdPay) - return -} diff --git a/app/third/paymentService/payment_service.go b/app/third/paymentService/payment_service.go index 6f5e00b..8ee1499 100644 --- a/app/third/paymentService/payment_service.go +++ b/app/third/paymentService/payment_service.go @@ -34,6 +34,14 @@ type AliPay struct { AlipayPublicCert []byte `json:"alipay_public_cert"` // 支付宝公钥 } +type AliPayA struct { + AppId string `json:"app_id"` // 应用ID + PrivateKey string `json:"private_key"` // 应用私钥 + AppPublicCert string `json:"app_public_cert"` // 应用公钥 + AlipayRootCert string `json:"alipay_root_cert"` // 支付宝根证书 + AlipayPublicCert string `json:"alipay_public_cert"` // 支付宝公钥 +} + type PayOrderResponse struct { Code int `json:"code"` ErrorMsg string `json:"error_msg"` diff --git a/app/utils/encrypt/rsa/rsa_test.go b/app/utils/encrypt/rsa/rsa_test.go index 628568e..b3547b8 100644 --- a/app/utils/encrypt/rsa/rsa_test.go +++ b/app/utils/encrypt/rsa/rsa_test.go @@ -27,7 +27,7 @@ func TestRsaDecrypt(t *testing.T) { } func encrypt() string { - data := "{\"app_id\":5476377146882523138,\"name\":\"张三\",\"sex\":1,\"is_human\":true,\"timestamp\":53612533412643}" + data := "{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}" dataJson := []byte(data) pub := `-----BEGIN PUBLIC KEY----- ` + PUB + `