Merge remote-tracking branch 'origin/feature/rzy/api_1.0' into feature_413_cjh
This commit is contained in:
commit
75d68a3032
|
@ -60,7 +60,8 @@ func closeOrder() {
|
||||||
PrivateKey: wx.PrivateKey,
|
PrivateKey: wx.PrivateKey,
|
||||||
}
|
}
|
||||||
case common.PAY_CHANNLE_TYPE_ZFB:
|
case common.PAY_CHANNLE_TYPE_ZFB:
|
||||||
ali := backend.AliPayChannel{}
|
var ali backend.AliPayChannel
|
||||||
|
|
||||||
req.PayChannel = payCommon.PAY_CHANNLE_TYPE_ZFB
|
req.PayChannel = payCommon.PAY_CHANNLE_TYPE_ZFB
|
||||||
_ = json.Unmarshal([]byte(orderInfo.ExtJson), &ali)
|
_ = json.Unmarshal([]byte(orderInfo.ExtJson), &ali)
|
||||||
req.Ali = paymentService.AliPay{
|
req.Ali = paymentService.AliPay{
|
||||||
|
|
|
@ -29,6 +29,12 @@ const (
|
||||||
ORDER_STATUS_FAILED = 4
|
ORDER_STATUS_FAILED = 4
|
||||||
ORDER_STATUS_CLOSE = 5
|
ORDER_STATUS_CLOSE = 5
|
||||||
|
|
||||||
|
STATUS_ENABLE = 1
|
||||||
|
STATUS_DISABLED = 2
|
||||||
|
|
||||||
|
ORDER_TYPE_PAY = 1
|
||||||
|
ORDER_TYPE_REFUND = 2
|
||||||
|
|
||||||
PAY_CHANNLE_TYPE_WECHAT = 1 // 支付类型: 微信
|
PAY_CHANNLE_TYPE_WECHAT = 1 // 支付类型: 微信
|
||||||
PAY_CHANNLE_TYPE_ZFB = 2 // 支付类型:支付宝
|
PAY_CHANNLE_TYPE_ZFB = 2 // 支付类型:支付宝
|
||||||
|
|
||||||
|
@ -39,3 +45,19 @@ const (
|
||||||
THIRD_ORDER_TYPE_CLOSE = 5 // 关闭订单
|
THIRD_ORDER_TYPE_CLOSE = 5 // 关闭订单
|
||||||
THIRD_ORDER_TYPE_CALL_BACK = 6 // 支付回调
|
THIRD_ORDER_TYPE_CALL_BACK = 6 // 支付回调
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var PayChannelList = map[int]string{
|
||||||
|
PAY_CHANNEL_WECHAT_JSAPI: "微信JSAPI",
|
||||||
|
PAY_CHANNEL_WECHAT_H5: "微信H5",
|
||||||
|
PAY_CHANNEL_WECHAT_APP: "微信app",
|
||||||
|
PAY_CHANNEL_WECHAT_NATIVE: "微信Native",
|
||||||
|
PAY_CHANNEL_WECHAT_MINI: "微信小程序",
|
||||||
|
PAY_CHANNEL_ALIPAY_WEB: "支付宝网页&移动应用",
|
||||||
|
PAY_CHANNEL_ALIPAY_MINI: "支付宝小程序",
|
||||||
|
PAY_CHANNEL_ALIPAY_JSAPI: "支付宝JSAPI",
|
||||||
|
}
|
||||||
|
|
||||||
|
var OrderTypeList = map[int]string{
|
||||||
|
ORDER_TYPE_PAY: "付款",
|
||||||
|
ORDER_TYPE_REFUND: "退款",
|
||||||
|
}
|
||||||
|
|
|
@ -29,12 +29,44 @@ const (
|
||||||
MerchantNotFound = 1100
|
MerchantNotFound = 1100
|
||||||
|
|
||||||
// app
|
// app
|
||||||
AppNotFound = 1200
|
|
||||||
AppDisabled = 1201
|
AppNotFound = 1200
|
||||||
AppIpNotAllow = 1202
|
AppDisabled = 1201
|
||||||
|
AppIpNotAllow = 1202
|
||||||
|
AppRsaDecryptKeyNotFound = 1203
|
||||||
|
AppDecryptDataDiscrepancy = 1204
|
||||||
|
AppNotifyUrlNotFound = 1205
|
||||||
|
AppRsaDecryptFail = 1210
|
||||||
|
AppRsaEncryptKeyNotFound = 1211
|
||||||
|
AppRsaEncryptFail = 1212
|
||||||
|
AppSM2DecryptKeyNotFound = 1220
|
||||||
|
AppSM2DecryptFail = 1221
|
||||||
|
AppSM2EncryptKeyNotFound = 1222
|
||||||
|
AppSM2EncryptFail = 1223
|
||||||
|
AppSM4DecryptKeyNotFound = 1230
|
||||||
|
AppSM4DecryptFail = 1231
|
||||||
|
AppSM4EncryptKeyNotFound = 1232
|
||||||
|
AppSM4EncryptFail = 1233
|
||||||
|
|
||||||
//渠道
|
//渠道
|
||||||
PayChannelNotFound = 1300
|
PayChannelNotFound = 1300
|
||||||
|
PayChannelNotBuild = 1301
|
||||||
|
PayChannelExtJsonError = 1302
|
||||||
|
|
||||||
|
//订单
|
||||||
|
OrdersNotFound = 1401
|
||||||
|
OrdersExist = 1402
|
||||||
|
OrderTypeNotFount = 1403
|
||||||
|
OrderIsDelete = 1405
|
||||||
|
OrderStatusErr = 1406
|
||||||
|
|
||||||
|
//请求日志
|
||||||
|
RequestLogErrors = 1500
|
||||||
|
RequestLogNotFound = 1501
|
||||||
|
RequestResponseValid = 1502
|
||||||
|
|
||||||
|
//回调
|
||||||
|
NotifySendFail = 1600
|
||||||
)
|
)
|
||||||
|
|
||||||
var MsgEN = map[int]string{
|
var MsgEN = map[int]string{
|
||||||
|
@ -47,18 +79,50 @@ var MsgEN = map[int]string{
|
||||||
}
|
}
|
||||||
|
|
||||||
var MsgZH = map[int]string{
|
var MsgZH = map[int]string{
|
||||||
Success: "请求成功",
|
Success: "请求成功",
|
||||||
ParamError: "参数错误",
|
ParamError: "参数错误",
|
||||||
NotFound: "数据不存在",
|
NotFound: "数据不存在",
|
||||||
NotAuth: "未经授权",
|
NotAuth: "未经授权",
|
||||||
NotLogin: "未登录",
|
NotLogin: "未登录",
|
||||||
RequestTimeOut: "请求超时",
|
RequestTimeOut: "请求超时",
|
||||||
MerchantNotFound: "商户不存在",
|
MerchantNotFound: "商户不存在",
|
||||||
AppNotFound: "app_id未找到",
|
AppNotFound: "app_id未找到",
|
||||||
AppDisabled: "app通道关闭",
|
AppDisabled: "app通道关闭",
|
||||||
AppIpNotAllow: "ip不在白名单内",
|
AppIpNotAllow: "ip不在白名单内",
|
||||||
SystemError: "系统错误",
|
AppDecryptDataDiscrepancy: "解密数据不一致",
|
||||||
PayChannelNotFound: "支付方式不存在",
|
SystemError: "系统错误",
|
||||||
|
AppNotifyUrlNotFound: "未设置回调地址",
|
||||||
|
|
||||||
|
AppRsaDecryptKeyNotFound: "密匙缺失,无法进行Rsa解密",
|
||||||
|
AppRsaDecryptFail: "Rsa解密失败",
|
||||||
|
AppRsaEncryptKeyNotFound: "密匙缺失,无法进行Rsa加密",
|
||||||
|
AppRsaEncryptFail: "Rsa加密失败",
|
||||||
|
|
||||||
|
AppSM2DecryptKeyNotFound: "密匙缺失,无法进行sm2解密",
|
||||||
|
AppSM2DecryptFail: "sm2解密失败",
|
||||||
|
AppSM2EncryptKeyNotFound: "密匙缺失,无法进行sm2加密",
|
||||||
|
AppSM2EncryptFail: "sm2加密失败",
|
||||||
|
|
||||||
|
AppSM4DecryptKeyNotFound: "密匙缺失,无法进行sm4解密",
|
||||||
|
AppSM4DecryptFail: "sm4解密失败",
|
||||||
|
AppSM4EncryptKeyNotFound: "密匙缺失,无法进行sm4加密",
|
||||||
|
AppSM4EncryptFail: "sm4加密失败",
|
||||||
|
|
||||||
|
PayChannelNotFound: "支付方式不存在",
|
||||||
|
PayChannelNotBuild: "支付方式尚未开通",
|
||||||
|
PayChannelExtJsonError: "支付方式扩展参数错误",
|
||||||
|
|
||||||
|
RequestLogErrors: "请求日志错误",
|
||||||
|
RequestLogNotFound: "未找到日志信息",
|
||||||
|
RequestResponseValid: "上游返回格式无效",
|
||||||
|
|
||||||
|
OrdersNotFound: "未找到订单",
|
||||||
|
OrdersExist: "订单已存在",
|
||||||
|
OrderTypeNotFount: "未知的支付方式",
|
||||||
|
OrderIsDelete: "订单已删除",
|
||||||
|
OrderStatusErr: "订单状态错误",
|
||||||
|
|
||||||
|
NotifySendFail: "回调发送失败",
|
||||||
}
|
}
|
||||||
var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
|
var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package pojo
|
package pojo
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Rsa int32 = iota + 1
|
RSA int32 = iota + 1
|
||||||
Sm2
|
SM2
|
||||||
Sm4
|
SM4
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
package pojo
|
|
||||||
|
|
||||||
const (
|
|
||||||
STATUS_ENABLE int32 = 1
|
|
||||||
STATUS_DISABLED int32 = 2
|
|
||||||
)
|
|
|
@ -45,5 +45,4 @@ func (m *AppRepo) AppFindOne(app *appmodel.App, conn builder.Cond, columns ...st
|
||||||
return nil, sql.ErrNoRows
|
return nil, sql.ErrNoRows
|
||||||
}
|
}
|
||||||
return app, err
|
return app, err
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package data
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/http/entities"
|
"PaymentCenter/app/http/entities"
|
||||||
"PaymentCenter/app/models/merchantmodel"
|
"PaymentCenter/app/models/merchantmodel"
|
||||||
|
"database/sql"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
@ -41,3 +42,11 @@ func (m *MerchantRepo) MerchantUpdate(merchant *merchantmodel.Merchant, conn bui
|
||||||
func (m *MerchantRepo) MerchantDetail(merchant *merchantmodel.Merchant, conn builder.Cond) (bool, error) {
|
func (m *MerchantRepo) MerchantDetail(merchant *merchantmodel.Merchant, conn builder.Cond) (bool, error) {
|
||||||
return m.repo.Where(conn).Get(merchant)
|
return m.repo.Where(conn).Get(merchant)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MerchantRepo) MerchantFindOne(merchant *merchantmodel.Merchant, conn builder.Cond, columns ...string) (*merchantmodel.Merchant, error) {
|
||||||
|
has, err := m.repo.Where(conn).Get(merchant)
|
||||||
|
if !has {
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
return merchant, err
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package data
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/http/entities"
|
"PaymentCenter/app/http/entities"
|
||||||
"PaymentCenter/app/models/ordersmodel"
|
"PaymentCenter/app/models/ordersmodel"
|
||||||
|
"database/sql"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
@ -59,3 +60,11 @@ func (m *OrderRepo) OrdersLeftPayChannelList(conn builder.Cond, pageFilter entit
|
||||||
repo = repo.Join("left", "pay_channel", "pay_channel.id = orders.pay_channel_id")
|
repo = repo.Join("left", "pay_channel", "pay_channel.id = orders.pay_channel_id")
|
||||||
return repo.Find(orderList)
|
return repo.Find(orderList)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *OrderRepo) OrderFindOne(order *ordersmodel.Orders, conn builder.Cond, columns ...string) (*ordersmodel.Orders, error) {
|
||||||
|
has, err := m.repo.Where(conn).Get(order)
|
||||||
|
if !has {
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
return order, err
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@ package data
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/http/entities"
|
"PaymentCenter/app/http/entities"
|
||||||
"PaymentCenter/app/models/paychannelmodel"
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
|
"database/sql"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
@ -41,3 +42,11 @@ func (m *PayChannelRepo) PayChannelUpdate(payChannel *paychannelmodel.PayChannel
|
||||||
func (m *PayChannelRepo) PayChannelGet(payChannel *paychannelmodel.PayChannel, conn builder.Cond) (bool, error) {
|
func (m *PayChannelRepo) PayChannelGet(payChannel *paychannelmodel.PayChannel, conn builder.Cond) (bool, error) {
|
||||||
return m.repo.Where(conn).Get(payChannel)
|
return m.repo.Where(conn).Get(payChannel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PayChannelRepo) PayChannelFindOne(payChannel *paychannelmodel.PayChannel, conn builder.Cond, columns ...string) (*paychannelmodel.PayChannel, error) {
|
||||||
|
has, err := m.repo.Where(conn).Get(payChannel)
|
||||||
|
if !has {
|
||||||
|
return nil, sql.ErrNoRows
|
||||||
|
}
|
||||||
|
return payChannel, err
|
||||||
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
|
@ -149,6 +149,34 @@ func GenRequest(c *gin.Context, request interface{}) (msgs []string, err error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ValidApiData(dataByte []byte, validStruct interface{}) (msgs []string, err error) {
|
||||||
|
validate := validator.New()
|
||||||
|
err = json.Unmarshal(dataByte, validStruct)
|
||||||
|
if err != nil {
|
||||||
|
err = errors.New(errorcode.GetMsg(errorcode.ParamError, ""))
|
||||||
|
}
|
||||||
|
zh_ch := zh.New()
|
||||||
|
uni := ut.New(zh_ch)
|
||||||
|
trans, _ := uni.GetTranslator("zh")
|
||||||
|
//注册一个函数,获取struct tag里自定义的label作为字段名
|
||||||
|
validate.RegisterTagNameFunc(func(fld reflect.StructField) string {
|
||||||
|
name := fld.Tag.Get("label")
|
||||||
|
return name
|
||||||
|
})
|
||||||
|
//验证器注册翻译器
|
||||||
|
_ = zh_translations.RegisterDefaultTranslations(validate, trans)
|
||||||
|
errValidate := validate.Struct(validStruct)
|
||||||
|
if errValidate != nil {
|
||||||
|
// 如果有错误,打印出来
|
||||||
|
for _, v := range errValidate.(validator.ValidationErrors) {
|
||||||
|
msgs = append(msgs, v.Translate(trans))
|
||||||
|
}
|
||||||
|
err = errors.New(errorcode.GetMsg(errorcode.ParamError, ""))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// 重复读取body
|
// 重复读取body
|
||||||
func ReadBody(c *gin.Context) (body []byte, err error) {
|
func ReadBody(c *gin.Context) (body []byte, err error) {
|
||||||
body, err = ioutil.ReadAll(c.Request.Body)
|
body, err = ioutil.ReadAll(c.Request.Body)
|
||||||
|
@ -164,6 +192,19 @@ func GetRequest(c *gin.Context) interface{} {
|
||||||
return request
|
return request
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetAppCheckInfo(c *gin.Context) interface{} {
|
||||||
|
request, exists := c.Get("appCheckInfo")
|
||||||
|
if !exists {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
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) {
|
func HandRes(c *gin.Context, data interface{}, err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
Success(c, data, "")
|
Success(c, data, "")
|
||||||
|
|
|
@ -0,0 +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 Pay(c *gin.Context) {
|
||||||
|
req := controllers.GetRequest(c).(*front.PayReqs)
|
||||||
|
appCheckInfo := controllers.GetAppCheckInfo(c).(*services.AppCheck)
|
||||||
|
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
|
||||||
|
}
|
|
@ -108,7 +108,7 @@ type OrderLogsListRequest struct {
|
||||||
type OrderRequestLogResponse struct {
|
type OrderRequestLogResponse struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
IpAddress string `json:"ip_address"`
|
IpAddress string `json:"ip_address"`
|
||||||
OrderId int64 `json:"order_id"`
|
Url string `json:"url"`
|
||||||
MerchantRequest string `json:"merchant_request"`
|
MerchantRequest string `json:"merchant_request"`
|
||||||
MerchantResponse string `json:"merchant_response"`
|
MerchantResponse string `json:"merchant_response"`
|
||||||
CreateTime string `json:"create_time"`
|
CreateTime string `json:"create_time"`
|
||||||
|
@ -117,8 +117,9 @@ type OrderRequestLogResponse struct {
|
||||||
|
|
||||||
func (o *OrderRequestLogResponse) ResponseFromDb(db orderrequestlogmodel.OrderRequestLog) {
|
func (o *OrderRequestLogResponse) ResponseFromDb(db orderrequestlogmodel.OrderRequestLog) {
|
||||||
o.Id = db.Id
|
o.Id = db.Id
|
||||||
o.OrderId = db.OrderId
|
|
||||||
o.IpAddress = db.IpAddress
|
o.IpAddress = db.IpAddress
|
||||||
|
o.Url = db.URL
|
||||||
o.Status = db.Status
|
o.Status = db.Status
|
||||||
o.MerchantRequest = db.MerchantRequest
|
o.MerchantRequest = db.MerchantRequest
|
||||||
o.MerchantResponse = db.MerchantResponse
|
o.MerchantResponse = db.MerchantResponse
|
||||||
|
@ -126,12 +127,13 @@ func (o *OrderRequestLogResponse) ResponseFromDb(db orderrequestlogmodel.OrderRe
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrderThirdLogResponse struct {
|
type OrderThirdLogResponse struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
OrderId int64 `json:"order_id"`
|
OrderId int64 `json:"order_id"`
|
||||||
|
|
||||||
CreateTime string `json:"create_time"`
|
CreateTime string `json:"create_time"`
|
||||||
PayCallback string `json:"pay_callback"`
|
PayCallback string `json:"pay_callback"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
MerchantParam string `json:"merchant_param"`
|
PayParam string `json:"pay_param"`
|
||||||
MerchantCallback string `json:"merchant_callback"`
|
MerchantCallback string `json:"merchant_callback"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +142,7 @@ func (o *OrderThirdLogResponse) ResponseFromDb(db orderthirdpaylogmodel.OrderThi
|
||||||
o.OrderId = db.OrderId
|
o.OrderId = db.OrderId
|
||||||
o.PayCallback = db.PayCallback
|
o.PayCallback = db.PayCallback
|
||||||
o.Status = db.Status
|
o.Status = db.Status
|
||||||
o.MerchantParam = db.PayParam
|
o.PayParam = db.PayParam
|
||||||
o.MerchantCallback = db.MerchantCallback
|
o.MerchantCallback = db.MerchantCallback
|
||||||
o.CreateTime = db.CreateTime.Format("2006-01-02 15:04:05")
|
o.CreateTime = db.CreateTime.Format("2006-01-02 15:04:05")
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,28 @@
|
||||||
package front
|
package front
|
||||||
|
|
||||||
type PayCommonBody struct {
|
type ApiCommonBody struct {
|
||||||
AppId int64 `json:"app_id" validate:"required"`
|
AppId int64 `json:"app_id" validate:"required"`
|
||||||
Timestamp int64 `json:"timestamp" validate:"required"`
|
Timestamp int64 `json:"timestamp" validate:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PayWeb struct {
|
type RequestBody struct {
|
||||||
PayCommonBody
|
AppId int64 `json:"app_id" validate:"required"`
|
||||||
PayChannel int64 `json:"private_key_path"`
|
Timestamp int64 `json:"timestamp" validate:"required"`
|
||||||
Delay int64 `json:"delay"` //延时时间
|
Data string `json:"data" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PayReqs struct {
|
||||||
|
ApiCommonBody
|
||||||
|
PayChannelId int64 `json:"pay_channel_id" validate:"required" label:"支付渠道"`
|
||||||
|
OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"`
|
||||||
|
OrderType int `json:"order_type" validate:"required" label:"订单类型,支付,退款"`
|
||||||
|
Amount int `json:"amount" validate:"required" label:"支付金额,单位分"`
|
||||||
|
ExtJson string `json:"ext_json" label:"扩展参数"`
|
||||||
|
Desc string `json:"desc" validate:"max=100" label:"商品描述"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderApiResp struct {
|
||||||
|
Code int
|
||||||
|
Msg string
|
||||||
|
Data interface{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,13 @@ import (
|
||||||
"PaymentCenter/app/constants/common"
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/constants/errorcode"
|
"PaymentCenter/app/constants/errorcode"
|
||||||
"PaymentCenter/app/http/controllers"
|
"PaymentCenter/app/http/controllers"
|
||||||
"PaymentCenter/app/http/entities"
|
|
||||||
"PaymentCenter/app/http/entities/front"
|
"PaymentCenter/app/http/entities/front"
|
||||||
"PaymentCenter/app/http/requestmapping"
|
"PaymentCenter/app/http/requestmapping"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
|
"PaymentCenter/app/services/apicrypt"
|
||||||
"PaymentCenter/app/utils"
|
"PaymentCenter/app/utils"
|
||||||
"PaymentCenter/config"
|
"PaymentCenter/config"
|
||||||
|
"encoding/json"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -104,10 +105,11 @@ func ValidateRequest() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
var path = c.FullPath()
|
var path = c.FullPath()
|
||||||
var handler func() interface{}
|
var handler func() interface{}
|
||||||
|
|
||||||
if strings.Index(path, "admin") >= 0 {
|
if strings.Index(path, "admin") >= 0 {
|
||||||
handler = requestmapping.BackendRequestMap[path]
|
handler = requestmapping.BackendRequestMap[path]
|
||||||
} else {
|
} else {
|
||||||
handler = requestmapping.FrontRequestMap[path]
|
handler = requestmapping.FrontRequestMapBeforeDecrypt[path]
|
||||||
}
|
}
|
||||||
if handler == nil {
|
if handler == nil {
|
||||||
utils.Log(c, "path", path)
|
utils.Log(c, "path", path)
|
||||||
|
@ -129,35 +131,67 @@ func ValidateRequest() gin.HandlerFunc {
|
||||||
|
|
||||||
func ValidatePayRequest() gin.HandlerFunc {
|
func ValidatePayRequest() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
com, err := utils.SonicApiDataToStruct(controllers.GetRequest(c), &front.PayCommonBody{})
|
var path = c.FullPath()
|
||||||
|
var handler func() interface{}
|
||||||
|
requestData, err := utils.SonicApiDataToStruct(controllers.GetRequest(c), &front.RequestBody{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
controllers.ErrWithCode(c, errorcode.ParamError)
|
controllers.ApiRes(c, nil, errorcode.ParamError)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
comStruct := com.(*front.PayCommonBody)
|
requestDataStruct := requestData.(*front.RequestBody)
|
||||||
|
|
||||||
//判断时间
|
//判断时间
|
||||||
//now := time.Now().UnixNano() / 1000000
|
//now := time.Now().UnixNano() / 1000000
|
||||||
//if comStruct.Timestamp > now || (config.GetConf().TimeOut != 0 && (now-comStruct.Timestamp) > config.GetConf().TimeOut) {
|
//if requestDataStruct.Timestamp > now || (config.GetConf().TimeOut != 0 && (now-requestDataStruct.Timestamp) > config.GetConf().TimeOut) {
|
||||||
// controllers.ErrWithCode(c, errorcode.RequestTimeOut)
|
// controllers.ApiRes(c, nil, errorcode.RequestTimeOut)
|
||||||
// return
|
// return
|
||||||
//}
|
//}
|
||||||
//获取app信息
|
//获取app信息
|
||||||
app, errCode := services.AppFindOne(entities.IdRequest{Id: comStruct.AppId})
|
appCheck := services.GetAppCheck(requestDataStruct.AppId, c.ClientIP())
|
||||||
if errCode != errorcode.Success {
|
//存入请求记录
|
||||||
controllers.ErrWithCode(c, errCode)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//检查app可用性
|
|
||||||
appCheck := services.NewAppCheck(app).Check()
|
|
||||||
if appCheck.GetCode() != errorcode.Success {
|
|
||||||
controllers.ErrWithCode(c, appCheck.GetCode())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//检查白名单
|
|
||||||
if !appCheck.IpCheck(c.ClientIP()) {
|
|
||||||
controllers.ErrWithCode(c, appCheck.GetCode())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if appCheck.Code != errorcode.Success {
|
||||||
|
controllers.ApiRes(c, nil, appCheck.Code)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//解密
|
||||||
|
cryptFunc := appCheck.Crypt()
|
||||||
|
if cryptFunc == nil {
|
||||||
|
controllers.ApiRes(c, nil, appCheck.GetCode())
|
||||||
|
}
|
||||||
|
dataByte, errCode := cryptFunc(appCheck.App).Decrypt(requestDataStruct.Data)
|
||||||
|
if errCode != apicrypt.CryptNotError {
|
||||||
|
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.ApiRes(c, nil, appCheck.GetCode())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//表单验证
|
||||||
|
handler = requestmapping.FrontRequestMap[path]
|
||||||
|
v := handler()
|
||||||
|
msg, err := controllers.ValidApiData(dataByte, v)
|
||||||
|
if err != nil {
|
||||||
|
utils.Log(c, "参数错误", "path=", path, "err=", err.Error(), "msg=", msg)
|
||||||
|
controllers.ApiRes(c, nil, errorcode.ParamError, msg...)
|
||||||
|
c.Abort()
|
||||||
|
}
|
||||||
|
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()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var FrontRequestMap = map[string]func() interface{}{
|
var FrontRequestMap = map[string]func() interface{}{
|
||||||
common.FRONT_V1 + "/pay/web": func() interface{} { return new(front.PayWeb) },
|
common.FRONT_V1 + "/pay/do": func() interface{} { return new(front.PayReqs) },
|
||||||
|
}
|
||||||
|
|
||||||
|
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
||||||
|
common.FRONT_V1 + "/pay/do": func() interface{} { return new(front.RequestBody) },
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ package routes
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/constants/common"
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/http/controllers"
|
"PaymentCenter/app/http/controllers"
|
||||||
"PaymentCenter/app/http/controllers/backend"
|
|
||||||
"PaymentCenter/app/http/controllers/front"
|
"PaymentCenter/app/http/controllers/front"
|
||||||
"PaymentCenter/app/http/middlewares"
|
"PaymentCenter/app/http/middlewares"
|
||||||
"PaymentCenter/app/http/trace"
|
"PaymentCenter/app/http/trace"
|
||||||
|
@ -56,9 +55,13 @@ func RegisterRoute(router *gin.Engine) {
|
||||||
notify.POST("/wx/:payChannelId", front.WxCallback)
|
notify.POST("/wx/:payChannelId", front.WxCallback)
|
||||||
notify.POST("/ali/:payChannelId", front.AliCallback)
|
notify.POST("/ali/:payChannelId", front.AliCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pay := v1.Group("/pay", middlewares.ValidateRequest(), middlewares.ValidatePayRequest())
|
||||||
|
{
|
||||||
|
pay.POST("/do", front.Pay)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||||
pay := v1.Group("pay", middlewares.ValidatePayRequest())
|
|
||||||
pay.POST("web", backend.MerchantList) // 商户列表
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ var (
|
||||||
type OrderRequestLog struct {
|
type OrderRequestLog struct {
|
||||||
Id int64
|
Id int64
|
||||||
IpAddress string `xorm:"'ip_address' varchar(16)"`
|
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"`
|
MerchantRequest string `xorm:"'merchant_request' JSON"`
|
||||||
MerchantResponse string `xorm:"'merchant_response' JSON"`
|
MerchantResponse string `xorm:"'merchant_response' JSON"`
|
||||||
CreateTime time.Time `xorm:"'create_time' datetime created"`
|
CreateTime time.Time `xorm:"'create_time' datetime created"`
|
||||||
|
|
|
@ -22,6 +22,7 @@ type Orders struct {
|
||||||
Amount int `xorm:"'amount' int(11)"`
|
Amount int `xorm:"'amount' int(11)"`
|
||||||
PayerTotal int `xorm:"'payer_total' int(11)"`
|
PayerTotal int `xorm:"'payer_total' int(11)"`
|
||||||
ExtJson string `xorm:"'ext_json' varchar(1024)"`
|
ExtJson string `xorm:"'ext_json' varchar(1024)"`
|
||||||
|
Desc string `xorm:"'desc' varchar(100)"`
|
||||||
CreateTime time.Time `xorm:"'create_time' datetime created"`
|
CreateTime time.Time `xorm:"'create_time' datetime created"`
|
||||||
UpdateTime time.Time `xorm:"'update_time' timestamp updated"`
|
UpdateTime time.Time `xorm:"'update_time' timestamp updated"`
|
||||||
Status int `xorm:"'status' TINYINT"`
|
Status int `xorm:"'status' TINYINT"`
|
||||||
|
|
|
@ -16,7 +16,7 @@ type PayChannel struct {
|
||||||
Id int64
|
Id int64
|
||||||
PayName string `xorm:"'pay_name' varchar(128)"`
|
PayName string `xorm:"'pay_name' varchar(128)"`
|
||||||
MerchantId int64 `xorm:"'merchant_id' bigint(20)"`
|
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)"`
|
AppId string `xorm:"'app_id' varchar(255)"`
|
||||||
ExtJson string `xorm:"'ext_json' JSON"`
|
ExtJson string `xorm:"'ext_json' JSON"`
|
||||||
ExpireTime time.Time `xorm:"'expire_time' datetime"`
|
ExpireTime time.Time `xorm:"'expire_time' datetime"`
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/constants/errorcode"
|
"PaymentCenter/app/constants/errorcode"
|
||||||
"PaymentCenter/app/constants/pojo"
|
"PaymentCenter/app/http/entities/front"
|
||||||
"PaymentCenter/app/models/appmodel"
|
"PaymentCenter/app/models/appmodel"
|
||||||
|
"PaymentCenter/app/services/apicrypt"
|
||||||
"PaymentCenter/app/utils"
|
"PaymentCenter/app/utils"
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AppCheck struct {
|
type AppCheck struct {
|
||||||
App *appmodel.App
|
AppId int64
|
||||||
Code int
|
Ip string
|
||||||
|
App *appmodel.App
|
||||||
|
Code int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAppCheck(app *appmodel.App) *AppCheck {
|
func NewAppCheck(app *appmodel.App) *AppCheck {
|
||||||
|
@ -33,11 +38,13 @@ func (a *AppCheck) IpCheck(ip string) bool {
|
||||||
|
|
||||||
func (a *AppCheck) Check() *AppCheck {
|
func (a *AppCheck) Check() *AppCheck {
|
||||||
|
|
||||||
if a.App.Status == pojo.STATUS_DISABLED {
|
if a.App.Status == common.STATUS_DISABLED {
|
||||||
a.Code = errorcode.AppDisabled
|
a.Code = errorcode.AppDisabled
|
||||||
|
return a
|
||||||
}
|
}
|
||||||
if a.App.DeleteTime.Location() == nil {
|
if !a.App.DeleteTime.IsZero() {
|
||||||
a.Code = errorcode.AppNotFound
|
a.Code = errorcode.AppNotFound
|
||||||
|
return a
|
||||||
}
|
}
|
||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
|
@ -45,3 +52,27 @@ func (a *AppCheck) Check() *AppCheck {
|
||||||
func (a *AppCheck) GetCode() int {
|
func (a *AppCheck) GetCode() int {
|
||||||
return a.Code
|
return a.Code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *AppCheck) Crypt() (cryptFunc func(app *appmodel.App) apicrypt.ApiCrypt) {
|
||||||
|
var (
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
if cryptFunc, ok = apicrypt.ApiCryptMap[a.App.KeyType]; !ok {
|
||||||
|
a.Code = errorcode.AppNotFound
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return cryptFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AppCheck) ReCheckAfterDecrypt(data []byte, requestData *front.RequestBody) bool {
|
||||||
|
var requestCommonData front.ApiCommonBody
|
||||||
|
if err := sonic.Unmarshal(data, &requestCommonData); err != nil {
|
||||||
|
a.Code = errorcode.ParamError
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if requestCommonData.AppId != requestData.AppId || requestCommonData.Timestamp != requestData.Timestamp {
|
||||||
|
a.Code = errorcode.AppDecryptDataDiscrepancy
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -1,17 +1,43 @@
|
||||||
package apicrypt
|
package apicrypt
|
||||||
|
|
||||||
import "PaymentCenter/app/models/appmodel"
|
import (
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/models/appmodel"
|
||||||
|
"PaymentCenter/app/utils/encrypt/rsa"
|
||||||
|
)
|
||||||
|
|
||||||
func NewRsa(app *appmodel.App) ApiDecrypt {
|
func NewRsa(app *appmodel.App) ApiCrypt {
|
||||||
return &Rsa{
|
return &Rsa{
|
||||||
App: app,
|
App: app,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rsa) Encrypt(decryptData interface{}) (encryptData string, err error) {
|
func (r *Rsa) Encrypt(decryptData string) (encryptData []byte, errCode int) {
|
||||||
|
if r.App.PublicKey == "" {
|
||||||
|
return nil, errorcode.AppRsaEncryptKeyNotFound
|
||||||
|
}
|
||||||
|
publicKeyPEM := `-----BEGIN PUBLIC KEY-----
|
||||||
|
` + r.App.PublicKey + `
|
||||||
|
-----END PUBLIC KEY-----`
|
||||||
|
encryptData, err := rsa.Encrypt(publicKeyPEM, []byte(decryptData))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorcode.AppRsaEncryptFail
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rsa) Decrypt(encryptData string) (decryptData map[string]interface{}, err error) {
|
func (r *Rsa) Decrypt(encryptData string) (decryptData []byte, errCode int) {
|
||||||
|
|
||||||
|
if r.App.PrivateKey == "" {
|
||||||
|
return nil, errorcode.AppRsaDecryptKeyNotFound
|
||||||
|
}
|
||||||
|
privateKeyPEM := `-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
` + r.App.PrivateKey + `
|
||||||
|
-----END RSA PRIVATE KEY-----`
|
||||||
|
decryptData, err := rsa.Decrypt(privateKeyPEM, encryptData)
|
||||||
|
if err != nil || decryptData == nil {
|
||||||
|
return nil, errorcode.AppRsaDecryptFail
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,39 @@
|
||||||
package apicrypt
|
package apicrypt
|
||||||
|
|
||||||
func (r *SM2) Encrypt(decryptData interface{}) (encryptData string, err error) {
|
import (
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/models/appmodel"
|
||||||
|
"PaymentCenter/app/utils/encrypt/sm2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewSm2(app *appmodel.App) ApiCrypt {
|
||||||
|
return &SM2{
|
||||||
|
App: app,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SM2) Encrypt(decryptData string) (encryptData []byte, errCode int) {
|
||||||
|
if r.App.MerchantPublicKey == "" {
|
||||||
|
return nil, errorcode.AppSM2EncryptKeyNotFound
|
||||||
|
}
|
||||||
|
//
|
||||||
|
encryptDataString, err := sm2.SM2Encrypt(decryptData, r.App.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorcode.AppSM2EncryptFail
|
||||||
|
}
|
||||||
|
encryptData = []byte(encryptDataString)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SM2) Decrypt(encryptData string) (decryptData map[string]interface{}, err error) {
|
func (r *SM2) Decrypt(encryptData string) (decryptData []byte, errCode int) {
|
||||||
|
if r.App.PrivateKey == "" || r.App.PublicKey == "" {
|
||||||
|
return nil, errorcode.AppSM2DecryptKeyNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptDataString, err := sm2.SM2Decrypt(encryptData, r.App.PublicKey, r.App.PrivateKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorcode.AppSM2DecryptFail
|
||||||
|
}
|
||||||
|
decryptData = []byte(decryptDataString)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,41 @@
|
||||||
package apicrypt
|
package apicrypt
|
||||||
|
|
||||||
func (r *SM4) Encrypt(decryptData interface{}) (encryptData string, err error) {
|
import (
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/models/appmodel"
|
||||||
|
"PaymentCenter/app/utils/encrypt/sm4"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewSm4(app *appmodel.App) ApiCrypt {
|
||||||
|
return &SM4{
|
||||||
|
App: app,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *SM4) Encrypt(decryptData string) (encryptData []byte, errCode int) {
|
||||||
|
if r.App.MerchantPublicKey == "" || r.App.PrivateKey == "" {
|
||||||
|
return nil, errorcode.AppSM4DecryptKeyNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
encryptDataString, err := sm4.Sm4Encrypt(strconv.FormatInt(r.App.Id, 10), r.App.PrivateKey, r.App.MerchantPublicKey, decryptData, "", true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorcode.AppSM4EncryptFail
|
||||||
|
}
|
||||||
|
encryptData = []byte(encryptDataString)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *SM4) Decrypt(encryptData string) (decryptData map[string]interface{}, err error) {
|
func (r *SM4) Decrypt(encryptData string) (decryptData []byte, errCode int) {
|
||||||
|
if r.App.PrivateKey == "" || r.App.MerchantPublicKey == "" {
|
||||||
|
return nil, errorcode.AppSM4DecryptKeyNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
decryptDataString, err := sm4.Sm4Decrypt(strconv.FormatInt(r.App.Id, 10), r.App.PrivateKey, r.App.MerchantPublicKey, encryptData, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errorcode.AppSM4DecryptFail
|
||||||
|
}
|
||||||
|
decryptData = []byte(decryptDataString)
|
||||||
return
|
return
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package apicrypt
|
package apicrypt
|
||||||
|
|
||||||
import "PaymentCenter/app/models/appmodel"
|
import (
|
||||||
|
"PaymentCenter/app/constants/pojo"
|
||||||
|
"PaymentCenter/app/models/appmodel"
|
||||||
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
ApiDecrypt interface {
|
ApiCrypt interface {
|
||||||
Encrypt(decryptData interface{}) (encryptData string, err error)
|
Encrypt(decryptData string) (encryptData []byte, errCode int)
|
||||||
Decrypt(encryptData string) (decryptData map[string]interface{}, err error)
|
Decrypt(encryptData string) (decryptData []byte, errCode int)
|
||||||
}
|
}
|
||||||
|
|
||||||
Rsa struct {
|
Rsa struct {
|
||||||
|
@ -20,3 +23,11 @@ type (
|
||||||
App *appmodel.App
|
App *appmodel.App
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ApiCryptMap = map[int32]func(app *appmodel.App) ApiCrypt{
|
||||||
|
pojo.RSA: NewRsa,
|
||||||
|
pojo.SM2: NewSm2,
|
||||||
|
pojo.SM4: NewSm4,
|
||||||
|
}
|
||||||
|
|
||||||
|
const CryptNotError = 0
|
||||||
|
|
|
@ -65,7 +65,7 @@ func AppUpdate(app *appmodel.App) (code int) {
|
||||||
} else {
|
} else {
|
||||||
_, err = repo.AppUpdate(app, conn)
|
_, err = repo.AppUpdate(app, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
code = handErr(err)
|
code = handErr(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -99,3 +99,32 @@ func AppFindOne(req entities.IdRequest, col ...string) (row *appmodel.App, code
|
||||||
}
|
}
|
||||||
return row, errorcode.Success
|
return row, errorcode.Success
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CheckApp(appCheckIn *AppCheck) {
|
||||||
|
errCode := errorcode.Success
|
||||||
|
appCheckIn.App, errCode = AppFindOne(entities.IdRequest{Id: appCheckIn.AppId})
|
||||||
|
if errCode != errorcode.Success {
|
||||||
|
appCheckIn.Code = errCode
|
||||||
|
}
|
||||||
|
//检查app可用性
|
||||||
|
appCheckIn.Check()
|
||||||
|
if appCheckIn.GetCode() != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//检查白名单
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
"PaymentCenter/app/data"
|
"PaymentCenter/app/data"
|
||||||
"PaymentCenter/app/http/entities"
|
"PaymentCenter/app/http/entities"
|
||||||
"PaymentCenter/app/http/entities/backend"
|
"PaymentCenter/app/http/entities/backend"
|
||||||
"PaymentCenter/app/models/merchantmodel"
|
"PaymentCenter/app/models/merchantmodel"
|
||||||
|
"database/sql"
|
||||||
"strings"
|
"strings"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
@ -65,3 +67,28 @@ func MerchantDelete(req entities.IdRequest) (code int) {
|
||||||
code = handErr(err)
|
code = handErr(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MerchantFindOne(merchant *merchantmodel.Merchant, conn builder.Cond, col ...string) (merchantInfo *merchantmodel.Merchant, code int) {
|
||||||
|
repo := data.NewMerchantRepo(merchantmodel.GetInstance().GetDb())
|
||||||
|
// 拼接查询条件
|
||||||
|
merchantInfo, err := repo.MerchantFindOne(merchant, conn, col...)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errorcode.MerchantNotFound
|
||||||
|
}
|
||||||
|
return nil, errorcode.SystemError
|
||||||
|
}
|
||||||
|
return merchantInfo, errorcode.Success
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAndCheckMerchant(merchant *merchantmodel.Merchant, conn builder.Cond, col ...string) (merchantInfo *merchantmodel.Merchant, code int) {
|
||||||
|
merchantInfo, code = MerchantFindOne(merchant, conn, col...)
|
||||||
|
if code != errorcode.Success {
|
||||||
|
return nil, code
|
||||||
|
}
|
||||||
|
|
||||||
|
if !merchantInfo.DeleteTime.IsZero() {
|
||||||
|
return nil, errorcode.MerchantNotFound
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
"PaymentCenter/app/data"
|
"PaymentCenter/app/data"
|
||||||
"PaymentCenter/app/http/entities/backend"
|
"PaymentCenter/app/http/entities/backend"
|
||||||
"PaymentCenter/app/models/orderrequestlogmodel"
|
"PaymentCenter/app/models/orderrequestlogmodel"
|
||||||
"PaymentCenter/app/models/ordersmodel"
|
"PaymentCenter/app/models/ordersmodel"
|
||||||
"PaymentCenter/app/models/orderthirdpaylogmodel"
|
"PaymentCenter/app/models/orderthirdpaylogmodel"
|
||||||
"PaymentCenter/app/models/paychannelmodel"
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
|
"database/sql"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -72,3 +74,42 @@ func OrderLogsList(req backend.OrderLogsListRequest) (requestLog []orderrequestl
|
||||||
|
|
||||||
return orderLogList, thirdLogList, code
|
return orderLogList, thirdLogList, code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func OrderCreate(orderIn *ordersmodel.Orders) (orderOut *ordersmodel.Orders, code int) {
|
||||||
|
repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb())
|
||||||
|
_, err := repo.OrderInsertOne(orderIn)
|
||||||
|
code = handErr(err)
|
||||||
|
return orderIn, code
|
||||||
|
}
|
||||||
|
|
||||||
|
func OrderUpdate(order *ordersmodel.Orders, col ...string) (code int) {
|
||||||
|
repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb())
|
||||||
|
// 拼接查询条件
|
||||||
|
conn := builder.NewCond()
|
||||||
|
conn = conn.And(builder.Eq{"Id": order.Id})
|
||||||
|
_, err := repo.OrderUpdate(order, conn, col...)
|
||||||
|
|
||||||
|
code = handErr(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func OrderFindOne(order *ordersmodel.Orders, conn builder.Cond, col ...string) (merchantInfo *ordersmodel.Orders, code int) {
|
||||||
|
repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb())
|
||||||
|
// 拼接查询条件
|
||||||
|
orderInfo, err := repo.OrderFindOne(order, conn, col...)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errorcode.OrdersNotFound
|
||||||
|
}
|
||||||
|
return nil, errorcode.SystemError
|
||||||
|
}
|
||||||
|
return orderInfo, errorcode.OrdersExist
|
||||||
|
}
|
||||||
|
|
||||||
|
func PayOrderCheckRepeat(order *ordersmodel.Orders, conn builder.Cond) (exist bool, code int) {
|
||||||
|
_, code = OrderFindOne(order, conn)
|
||||||
|
if code != errorcode.OrdersNotFound {
|
||||||
|
return false, errorcode.Success
|
||||||
|
}
|
||||||
|
return true, code
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"PaymentCenter/app/http/entities/backend"
|
"PaymentCenter/app/http/entities/backend"
|
||||||
"PaymentCenter/app/models/merchantmodel"
|
"PaymentCenter/app/models/merchantmodel"
|
||||||
"PaymentCenter/app/models/paychannelmodel"
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
|
"database/sql"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -92,3 +93,27 @@ func PayChannelGet(payChannel *paychannelmodel.PayChannel) (code int) {
|
||||||
code = errorcode.Success
|
code = errorcode.Success
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PayChannelFindOne(channel *paychannelmodel.PayChannel, conn builder.Cond, col ...string) (merchantInfo *paychannelmodel.PayChannel, code int) {
|
||||||
|
repo := data.NewPayChannelRepo(paychannelmodel.GetInstance().GetDb())
|
||||||
|
// 拼接查询条件
|
||||||
|
channelInfo, err := repo.PayChannelFindOne(channel, conn, col...)
|
||||||
|
if err != nil {
|
||||||
|
if err == sql.ErrNoRows {
|
||||||
|
return nil, errorcode.MerchantNotFound
|
||||||
|
}
|
||||||
|
return nil, errorcode.SystemError
|
||||||
|
}
|
||||||
|
return channelInfo, errorcode.Success
|
||||||
|
}
|
||||||
|
|
||||||
|
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 !channelInfo.DeleteTime.IsZero() {
|
||||||
|
return nil, errorcode.PayChannelNotFound
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
package services
|
||||||
|
|
||||||
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
|
"PaymentCenter/app/data"
|
||||||
|
"PaymentCenter/app/models/orderrequestlogmodel"
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RequestLogCreate(log *orderrequestlogmodel.OrderRequestLog) (*orderrequestlogmodel.OrderRequestLog, int) {
|
||||||
|
db := orderrequestlogmodel.GetInstance().GetDb()
|
||||||
|
repo := data.NewOrderRequestLogRepo(db)
|
||||||
|
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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,164 @@
|
||||||
|
package notify
|
||||||
|
|
||||||
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/http/entities"
|
||||||
|
"PaymentCenter/app/models/appmodel"
|
||||||
|
"PaymentCenter/app/models/ordersmodel"
|
||||||
|
"PaymentCenter/app/services"
|
||||||
|
"PaymentCenter/app/utils/httpclient"
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
|
"time"
|
||||||
|
"xorm.io/builder"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OrderNotify struct {
|
||||||
|
order *ordersmodel.Orders
|
||||||
|
code int
|
||||||
|
app *appmodel.App
|
||||||
|
|
||||||
|
OrderId int64
|
||||||
|
ErrCode int
|
||||||
|
ActualAmount int
|
||||||
|
Msg string
|
||||||
|
CompleteTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderNotifyResp struct {
|
||||||
|
OrderId int64
|
||||||
|
Send bool
|
||||||
|
ErrCode int
|
||||||
|
SendTime time.Time
|
||||||
|
Content *OrderNotify
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderNotifySendContent struct {
|
||||||
|
OrderId int64 `json:"order_id"`
|
||||||
|
OutTreadNo string `json:"out_tread_no"`
|
||||||
|
CompleteTime time.Time `json:"complete_time"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
|
ErrCode int `json:"err_code"`
|
||||||
|
AppId int64 `json:"app_id"`
|
||||||
|
ChannelId int64 `json:"channel_id"`
|
||||||
|
MerchantId int64 `json:"merchant_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOrderNotifyWithHandle(orderId int64, errCode int, actualAmount int, msg string) *OrderNotifyResp {
|
||||||
|
orderNotify := &OrderNotify{
|
||||||
|
OrderId: orderId,
|
||||||
|
ErrCode: errCode,
|
||||||
|
ActualAmount: actualAmount,
|
||||||
|
Msg: msg,
|
||||||
|
code: errorcode.Success,
|
||||||
|
}
|
||||||
|
return orderNotify.handle()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) NotifyRespFail(errorCode int) *OrderNotifyResp {
|
||||||
|
return &OrderNotifyResp{
|
||||||
|
OrderId: o.OrderId,
|
||||||
|
Send: false,
|
||||||
|
ErrCode: errorCode,
|
||||||
|
Content: o,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) handle() (res *OrderNotifyResp) {
|
||||||
|
o.checkOrder()
|
||||||
|
if o.code != errorcode.Success {
|
||||||
|
return o.NotifyRespFail(o.code)
|
||||||
|
}
|
||||||
|
o.checkApp()
|
||||||
|
if o.code != errorcode.Success {
|
||||||
|
return o.NotifyRespFail(o.code)
|
||||||
|
}
|
||||||
|
o.updateOrder()
|
||||||
|
if o.code != errorcode.Success {
|
||||||
|
return o.NotifyRespFail(o.code)
|
||||||
|
}
|
||||||
|
o.sendNotify(o.setBody())
|
||||||
|
if o.code != errorcode.Success {
|
||||||
|
return o.NotifyRespFail(o.code)
|
||||||
|
}
|
||||||
|
return &OrderNotifyResp{
|
||||||
|
OrderId: o.OrderId,
|
||||||
|
Send: true,
|
||||||
|
ErrCode: o.ErrCode,
|
||||||
|
Content: o,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) sendNotify(body *OrderNotifySendContent) {
|
||||||
|
|
||||||
|
bodyByte, _ := sonic.Marshal(&body)
|
||||||
|
|
||||||
|
headers := make(map[string]string, 1)
|
||||||
|
headers["Content-Type"] = "application/json"
|
||||||
|
resByte, err := httpclient.FastHttpPost(o.app.NotifyUrl, headers, bodyByte, 0)
|
||||||
|
if err != nil || string(resByte) != "success" {
|
||||||
|
o.code = errorcode.NotifySendFail
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) setBody() *OrderNotifySendContent {
|
||||||
|
return &OrderNotifySendContent{
|
||||||
|
OrderId: o.OrderId,
|
||||||
|
OutTreadNo: o.order.OutTreadNo,
|
||||||
|
CompleteTime: o.CompleteTime,
|
||||||
|
Status: o.order.Status,
|
||||||
|
Msg: o.Msg,
|
||||||
|
ErrCode: o.ErrCode,
|
||||||
|
AppId: o.order.AppId,
|
||||||
|
ChannelId: o.order.PayChannelId,
|
||||||
|
MerchantId: o.order.MerchantId,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) updateOrder() {
|
||||||
|
if o.ErrCode == errorcode.Success {
|
||||||
|
o.order.Status = common.ORDER_STATUS_FAILED
|
||||||
|
} else {
|
||||||
|
o.order.Status = common.ORDER_STATUS_PAYED
|
||||||
|
}
|
||||||
|
o.code = services.OrderUpdate(o.order, "status")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) checkApp() {
|
||||||
|
o.app, o.code = services.AppFindOne(entities.IdRequest{Id: o.order.AppId})
|
||||||
|
if o.code != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if o.app.DeleteTime.IsZero() {
|
||||||
|
o.code = errorcode.AppDisabled
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if o.app.NotifyUrl == "" {
|
||||||
|
o.code = errorcode.AppNotifyUrlNotFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o *OrderNotify) checkOrder() {
|
||||||
|
cond := builder.NewCond()
|
||||||
|
cond = cond.And(builder.Eq{"id": o.OrderId})
|
||||||
|
|
||||||
|
o.order, o.code = services.OrderFindOne(&ordersmodel.Orders{}, cond)
|
||||||
|
if o.code != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if o.order.DeleteTime.IsZero() {
|
||||||
|
o.code = errorcode.OrderIsDelete
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if o.order.Status != common.ORDER_STATUS_PAYING {
|
||||||
|
o.code = errorcode.OrderStatusErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
|
@ -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
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
type PayResp struct {
|
||||||
|
OrderNo int64 `json:"order_no"`
|
||||||
|
OrderType int `json:"out_trade_no"`
|
||||||
|
Amount int `json:"order_type"`
|
||||||
|
Desc string `json:"amount"`
|
||||||
|
IsNewCreate bool `json:"is_new_create"`
|
||||||
|
Status int `json:"status"`
|
||||||
|
}
|
|
@ -39,6 +39,14 @@ type AliPay struct {
|
||||||
AlipayPublicCert string `json:"alipay_public_cert"` // 支付宝公钥
|
AlipayPublicCert string `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 {
|
type PayOrderResponse struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
ErrorMsg string `json:"error_msg"`
|
ErrorMsg string `json:"error_msg"`
|
||||||
|
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -14,8 +13,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRsaEncrypt(t *testing.T) {
|
func TestRsaEncrypt(t *testing.T) {
|
||||||
fmt.Println(time.Now().UnixNano() / (1000000))
|
|
||||||
//fmt.Printf("%s\n", encrypt())
|
fmt.Printf("%s\n", encrypt())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRsaDecrypt(t *testing.T) {
|
func TestRsaDecrypt(t *testing.T) {
|
||||||
|
@ -28,7 +27,7 @@ func TestRsaDecrypt(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func encrypt() string {
|
func encrypt() string {
|
||||||
data := "{\"name\":\"张三\",\"sex\":1,\"is_human\":true}"
|
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)
|
dataJson := []byte(data)
|
||||||
pub := `-----BEGIN PUBLIC KEY-----
|
pub := `-----BEGIN PUBLIC KEY-----
|
||||||
` + PUB + `
|
` + PUB + `
|
||||||
|
|
Loading…
Reference in New Issue