From 514104a3917ddd26cd9db4fa5712501efa1a3220 Mon Sep 17 00:00:00 2001 From: wolter Date: Wed, 7 Aug 2024 10:49:06 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E5=AE=9A=E6=97=B6=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E9=80=80=E6=AC=BE=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/console/command.go | 144 +++++++++++++++++++++---------- app/console/kernel.go | 1 + app/constants/common/common.go | 3 +- app/models/ordersmodel/orders.go | 29 ++++--- 4 files changed, 114 insertions(+), 63 deletions(-) diff --git a/app/console/command.go b/app/console/command.go index de6eed2..47025ab 100644 --- a/app/console/command.go +++ b/app/console/command.go @@ -6,14 +6,13 @@ import ( "PaymentCenter/app/http/entities" "PaymentCenter/app/http/entities/backend" "PaymentCenter/app/models/ordersmodel" - "PaymentCenter/app/models/orderthirdpaylogmodel" + "PaymentCenter/app/services/thirdpay/notify" "PaymentCenter/app/third/paymentService" "PaymentCenter/app/third/paymentService/payCommon" "PaymentCenter/app/utils" "PaymentCenter/config" "context" "encoding/json" - "fmt" "github.com/qit-team/snow-core/command" "strconv" "sync" @@ -83,7 +82,7 @@ func closeOrder() { if response.Code == payCommon.PAY_SUCCESS_CODE { orderIds = append(orderIds, orderInfo.Id) } else { - utils.Log(nil, "关闭订单,上游支付失败", response) + utils.Log(nil, "关闭订单,上游失败", response) } } // 修改订单状态为关闭 @@ -172,64 +171,115 @@ func queryOrder() { // 成功 status = common.ORDER_STATUS_PAYED case "REFUND": - // 退款 - status = common.ORDER_STATUS_REFUND - + // 退款 订单支付完成才能退款,所以支付单的状态是支付完成 + status = common.ORDER_STATUS_PAYED case "NOTPAY": // 未支付 return case "CLOSED": // 关闭 status = common.ORDER_STATUS_CLOSE - } // 回调通知下游 todo + notifyResult := notify.NewOrderNotifyWithHandle(orderInfo.Id, status, int(result.Result.PayerTotal), "") + utils.Log(nil, "主动查询订单支付状态,回调下游", notifyResult) + } + }(orderInfo) + } + wg.Wait() + } +} - // 更新订单状态 todo - orderUpdate := ordersmodel.Orders{ - Id: orderInfo.Id, - Status: status, - PayerTotal: int(result.Result.PayerTotal), +// 主动查询退款订单状态 +func queryRefundOrder() { + var now = time.Now().Format(time.DateTime) + utils.Log(nil, "主动查询退款订单状态", now) + ctx := context.Background() + // 查询退款中的订单 + repo := data.NewOrderRepo(ordersmodel.GetInstance().GetDb()) + // 拼接条件 + cond := builder.NewCond() + cond = cond.And(builder.Eq{"status": common.ORDER_STATUS_PAYING}, builder.Gt{"orders.create_time": time.Now().Add(-time.Second * time.Duration(config.GetConf().CronConfig.QueryOrderTime))}) + cond = cond.And(builder.Eq{"order_type": common.ORDER_TYPE_REFUND}) + order := make([]ordersmodel.OrdersLeftPayChannelList, 0) + err := repo.OrdersLeftPayChannelList(cond, entities.PageRequest{}, &order) + if err != nil { + utils.Log(nil, "主动查询退款订单状态,查询退款中订单失败", err) + return + } else if len(order) > 0 { + ch := make(chan struct{}, config.GetConf().CronConfig.ConcurrentNumber) + wg := sync.WaitGroup{} + + for index := range order { + ch <- struct{}{} + wg.Add(1) + orderInfo := order[index] + + // 发起查询上游 + go func(orderInfo ordersmodel.OrdersLeftPayChannelList) { + defer func() { + <-ch + wg.Done() + }() + + query := paymentService.OrderRefundQueryRequest{ + RefundOrderId: orderInfo.Id, + OrderId: orderInfo.RefundOrderId, + } + switch utils.PayType(orderInfo.ChannelType) { + case common.PAY_CHANNLE_TYPE_WECHAT: + wx := backend.WechatPayChannel{} + _ = json.Unmarshal([]byte(orderInfo.ExtJson), &wx) + query.PayChannel = payCommon.PAY_CHANNLE_TYPE_WECHAT + query.Wx = paymentService.WxPay{ + AppId: orderInfo.AppId, + MchId: wx.MchId, + SerialNo: wx.SerialNo, + ApiV3Key: wx.ApiV3Key, + PrivateKey: wx.PrivateKey, } + case common.PAY_CHANNLE_TYPE_ZFB: + ali := backend.AliPayChannel{} + query.PayChannel = payCommon.PAY_CHANNLE_TYPE_ZFB + _ = json.Unmarshal([]byte(orderInfo.ExtJson), &ali) + query.Ali = paymentService.AliPay{ + AppId: orderInfo.AppId, + PrivateKey: ali.PrivateKey, + AppPublicCert: ali.AppPublicCert, + AlipayRootCert: ali.AlipayRootCert, + AlipayPublicCert: ali.AlipayPublicCert, + } + default: + utils.Log(nil, "查询订单,支付渠道不支持", orderInfo.ChannelType) + return + } - session := ordersmodel.GetInstance().GetDb().NewSession() - if err = session.Begin(); err != nil { - utils.Log(nil, "主动查询订单支付状态,更新订单状态失败", err) + // 发起查询 + result := paymentService.OrderRefundQuery(ctx, query) + utils.Log(nil, "主动查询退款订单状态,上游返回数据", result) + // 查询成功,校验状态 + var status int + if result.Code == payCommon.PAY_SUCCESS_CODE { + // 退款状态 0:未申请,1:退款中,2:退款成功,3:退款失败 + switch result.Result.RefundStatus { + case 0: + // 未申请 + utils.Log(nil, "主动查询退款订单状态,未申请", status) return - } - defer func() { - if err != nil { - session.Rollback() - } else { - err = session.Commit() - } - }() - orderLogRepo := data.NewOrderThirdPayLogRepo(session) - orderRepo := data.NewOrderRepo(session) - - conn := builder.NewCond() - conn = conn.And(builder.Eq{"id": orderInfo.Id}) - _, err = orderRepo.OrderUpdate(&orderUpdate, conn) - if err != nil { - utils.Log(nil, "主动查询订单支付状态,更新订单状态失败", err) + case 1: + // 退款中 + status = common.ORDER_STATUS_PAYING return + case 2: + // 退款成功 + status = common.ORDER_STATUS_PAYED + case 3: + // 退款失败 + status = common.ORDER_STATUS_FAILED } - - // 写入日志 - body, _ := json.Marshal(result) - log := orderthirdpaylogmodel.OrderThirdPayLog{ - OrderId: orderInfo.Id, - PayCallback: string(body), - Status: 0, - PayParam: fmt.Sprintf(`{"pay_channel_id":%d}`, orderInfo.PayChannelId), - Type: common.THIRD_ORDER_TYPE_ORDER_QUERY, - MerchantCallback: "{}", - } - _, err = orderLogRepo.OrderThirdPayLogInsertOne(&log) - if err != nil { - utils.Log(nil, "主动查询订单支付状态,写入支付日志失败", err) - } - + // 回调通知下游 todo + notifyResult := notify.NewOrderNotifyWithHandle(orderInfo.Id, status, int(result.Result.RefundFee), "") + utils.Log(nil, "主动查询退款订单状态,回调下游", notifyResult) } }(orderInfo) } diff --git a/app/console/kernel.go b/app/console/kernel.go index 88316d4..578f286 100644 --- a/app/console/kernel.go +++ b/app/console/kernel.go @@ -17,4 +17,5 @@ func RegisterSchedule(c *cron.Cron) { //c.AddFunc("@every 10s", test) c.AddFunc("@every 60s", closeOrder) c.AddFunc("@every 10s", queryOrder) + c.AddFunc("@every 60s", queryRefundOrder) } diff --git a/app/constants/common/common.go b/app/constants/common/common.go index f560214..0549e43 100644 --- a/app/constants/common/common.go +++ b/app/constants/common/common.go @@ -22,13 +22,12 @@ const ( ADMIN_USER_NAME = "User-Name" ADMIN_USER_INCLUDEUSERS = "Include-Users" - // '订单状态: 1待支付、2支付中、3支付成功、4支付失败、5订单关闭 6支付完成后退款, + // '订单状态: 1待支付、2支付中、3支付成功、4支付失败、5订单关闭 ORDER_STATUS_WAITPAY = 1 ORDER_STATUS_PAYING = 2 ORDER_STATUS_PAYED = 3 ORDER_STATUS_FAILED = 4 ORDER_STATUS_CLOSE = 5 - ORDER_STATUS_REFUND = 6 // 订单类型,1支付,2退款 ORDER_TYPE_PAY = 1 diff --git a/app/models/ordersmodel/orders.go b/app/models/ordersmodel/orders.go index ed8219a..e75a1a7 100644 --- a/app/models/ordersmodel/orders.go +++ b/app/models/ordersmodel/orders.go @@ -13,20 +13,21 @@ var ( // 实体 type Orders struct { - Id int64 - MerchantId int64 `xorm:"'merchant_id' bigint(20)"` - PayChannelId int64 `xorm:"'pay_channel_id' bigint(20)"` - AppId int64 `xorm:"'app_id' bigint(20)"` - OutTreadNo string `xorm:"'out_tread_no' varchar(50)"` - OrderType int `xorm:"'order_type' TINYINT"` - Amount int `xorm:"'amount' int(11)"` - PayerTotal int `xorm:"'payer_total' int(11)"` - ExtJson string `xorm:"'ext_json' varchar(1024)"` - 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"` - DeleteTime time.Time `xorm:"'delete_time' timestamp deleted"` + Id int64 + MerchantId int64 `xorm:"'merchant_id' bigint(20)"` + PayChannelId int64 `xorm:"'pay_channel_id' bigint(20)"` + AppId int64 `xorm:"'app_id' bigint(20)"` + OutTreadNo string `xorm:"'out_tread_no' varchar(50)"` + OrderType int `xorm:"'order_type' TINYINT"` + RefundOrderId int64 `xorm:"'refund_order_id' bigint(20)"` + Amount int `xorm:"'amount' int(11)"` + PayerTotal int `xorm:"'payer_total' int(11)"` + ExtJson string `xorm:"'ext_json' varchar(1024)"` + 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"` + DeleteTime time.Time `xorm:"'delete_time' timestamp deleted"` } type OrdersBackendList struct { From 0834171ea30efe87d9616b465c84780e8b85119b Mon Sep 17 00:00:00 2001 From: Rzy <465386466@qq.com> Date: Wed, 7 Aug 2024 11:12:06 +0800 Subject: [PATCH 2/5] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=9B=9E=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/constants/common/common.go | 7 +++++++ app/services/thirdpay/notify/notify.go | 13 +++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/constants/common/common.go b/app/constants/common/common.go index a738cc4..06a82c7 100644 --- a/app/constants/common/common.go +++ b/app/constants/common/common.go @@ -61,3 +61,10 @@ var OrderTypeList = map[int]string{ ORDER_TYPE_PAY: "付款", ORDER_TYPE_REFUND: "退款", } +var OrderStatusMap = map[int]string{ + ORDER_STATUS_WAITPAY: "等待执行", + ORDER_STATUS_PAYING: "执行中", + ORDER_STATUS_PAYED: "执行成功", + ORDER_STATUS_FAILED: "执行失败", + ORDER_STATUS_CLOSE: "订单关闭", +} diff --git a/app/services/thirdpay/notify/notify.go b/app/services/thirdpay/notify/notify.go index f1a92aa..2f4b7f7 100644 --- a/app/services/thirdpay/notify/notify.go +++ b/app/services/thirdpay/notify/notify.go @@ -37,6 +37,7 @@ type OrderNotifySendContent struct { OrderId int64 `json:"order_id"` OutTreadNo string `json:"out_tread_no"` CompleteTime time.Time `json:"complete_time"` + OrderType int `json:"order-type"` Status int `json:"status"` Msg string `json:"msg"` ErrCode int `json:"err_code"` @@ -85,7 +86,7 @@ func (o *OrderNotify) handle() (res *OrderNotifyResp) { return &OrderNotifyResp{ OrderId: o.OrderId, Send: true, - ErrCode: o.ErrCode, + ErrCode: o.code, Content: o, } } @@ -109,8 +110,9 @@ func (o *OrderNotify) setBody() *OrderNotifySendContent { OutTreadNo: o.order.OutTreadNo, CompleteTime: o.CompleteTime, Status: o.order.Status, + OrderType: o.order.OrderType, Msg: o.Msg, - ErrCode: o.ErrCode, + ErrCode: o.Status, AppId: o.order.AppId, ChannelId: o.order.PayChannelId, MerchantId: o.order.MerchantId, @@ -118,10 +120,9 @@ func (o *OrderNotify) setBody() *OrderNotifySendContent { } func (o *OrderNotify) updateOrder() { - if o.ErrCode != errorcode.Success { - o.order.Status = common.ORDER_STATUS_FAILED - } else { - o.order.Status = common.ORDER_STATUS_PAYED + if _, ok := common.OrderStatusMap[o.Status]; !ok { + o.code = errorcode.OrderStatusErr + return } o.code = services.OrderUpdate(o.order, "status") return From bf1bc4b1a20cef635d15ab2635b75e406ad3243c Mon Sep 17 00:00:00 2001 From: wolter Date: Wed, 7 Aug 2024 17:14:03 +0800 Subject: [PATCH 3/5] =?UTF-8?q?=E5=90=8E=E5=8F=B0=EF=BC=8C=E5=AF=86?= =?UTF-8?q?=E9=92=A5=E5=AF=B9=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/constants/errorcode/error_code.go | 4 ++++ app/http/controllers/backend/app.go | 19 ++++++++++++----- app/http/entities/backend/app.go | 2 +- app/utils/encrypt/rsa/rsa.go | 30 +++++++++++++++++++++++++++ app/utils/encrypt/rsa/rsa_test.go | 14 +++++++++++++ app/utils/encrypt/sm2/sm2_test.go | 15 +++++++++++++- 6 files changed, 77 insertions(+), 7 deletions(-) diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index 2f1a82c..c0057d6 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -47,6 +47,8 @@ const ( AppSM4DecryptFail = 1231 AppSM4EncryptKeyNotFound = 1232 AppSM4EncryptFail = 1233 + // 加密方式不存在 + EncryptTypeNotFound = 1240 //渠道 PayChannelNotFound = 1300 @@ -108,6 +110,8 @@ var MsgZH = map[int]string{ AppSM4EncryptKeyNotFound: "密匙缺失,无法进行sm4加密", AppSM4EncryptFail: "sm4加密失败", + EncryptTypeNotFound: "加密方式不存在", + PayChannelNotFound: "支付方式不存在", PayChannelNotBuild: "支付方式尚未开通", PayChannelExtJsonError: "支付方式扩展参数错误", diff --git a/app/http/controllers/backend/app.go b/app/http/controllers/backend/app.go index 1b170fd..6a66d5c 100644 --- a/app/http/controllers/backend/app.go +++ b/app/http/controllers/backend/app.go @@ -7,7 +7,9 @@ import ( "PaymentCenter/app/http/entities/backend" "PaymentCenter/app/models/appmodel" "PaymentCenter/app/services" + "PaymentCenter/app/utils/encrypt/rsa" "PaymentCenter/app/utils/encrypt/sm2" + "PaymentCenter/app/utils/encrypt/sm4" "github.com/ahmetb/go-linq/v3" "github.com/gin-gonic/gin" ) @@ -60,12 +62,19 @@ func GenerateDecrypt(c *gin.Context) { var publicKey, privateKey string var err error switch req.KeyType { - default: + case "sm2": publicKey, privateKey, err = sm2.GenerateSM2Key() - if err != nil { - controllers.Error(c, errorcode.SystemError, err.Error()) - return - } + case "rsa": + publicKey, privateKey, err = rsa.GenerateKey() + case "sm4": + privateKey, publicKey = sm4.GenerateKey() + default: + controllers.HandCodeRes(c, "", errorcode.EncryptTypeNotFound) + return + } + if err != nil { + controllers.Error(c, errorcode.SystemError, err.Error()) + return } controllers.HandCodeRes(c, map[string]string{ diff --git a/app/http/entities/backend/app.go b/app/http/entities/backend/app.go index 9956684..43b45f9 100644 --- a/app/http/entities/backend/app.go +++ b/app/http/entities/backend/app.go @@ -96,5 +96,5 @@ func (a *AppUpdateRequest) RequestToDb() (db appmodel.App) { } type GenerateDecryptKeyRequest struct { - KeyType int `json:"key_type" label:"密钥类型"` + KeyType string `json:"key_type" form:"key_type" label:"密钥类型"` } diff --git a/app/utils/encrypt/rsa/rsa.go b/app/utils/encrypt/rsa/rsa.go index f868e9d..f93101e 100644 --- a/app/utils/encrypt/rsa/rsa.go +++ b/app/utils/encrypt/rsa/rsa.go @@ -108,3 +108,33 @@ func Decrypt(privateKeyPEM string, encryptedDataBase64 string) ([]byte, error) { return decrypted, nil } + +// 生成密钥对 +func GenerateKey() (string, string, error) { + // 生成私钥 + privateKey, err := rsa.GenerateKey(rand.Reader, 2048) + if err != nil { + return "", "", err + } + // 导出私钥PKCS#1格式 + privKey := x509.MarshalPKCS1PrivateKey(privateKey) + // 将私钥转换为PEM编码 + var privBlock = &pem.Block{ + Type: "RSA PRIVATE KEY", + Bytes: privKey, + } + privPem := pem.EncodeToMemory(privBlock) + // 导出公钥 + pubKey := &privateKey.PublicKey + derPkix, err := x509.MarshalPKIXPublicKey(pubKey) + if err != nil { + return "", "", err + } + // 将公钥转换为PEM编码 + var pubBlock = &pem.Block{ + Type: "PUBLIC KEY", + Bytes: derPkix, + } + pubPem := pem.EncodeToMemory(pubBlock) + return string(pubPem), string(privPem), nil +} diff --git a/app/utils/encrypt/rsa/rsa_test.go b/app/utils/encrypt/rsa/rsa_test.go index b3547b8..bc4e64c 100644 --- a/app/utils/encrypt/rsa/rsa_test.go +++ b/app/utils/encrypt/rsa/rsa_test.go @@ -39,3 +39,17 @@ func encrypt() string { return base64.StdEncoding.EncodeToString(en) } + +// 测试生成密钥对 +func TestGenerateRSAKey(t *testing.T) { + pub, pri, err := GenerateKey() + 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) + en, err := Encrypt(pub, dataJson) + if err != nil { + panic(err) + } + content := base64.StdEncoding.EncodeToString(en) + res, err := Decrypt(pri, content) + fmt.Println("解密", string(res), err) +} diff --git a/app/utils/encrypt/sm2/sm2_test.go b/app/utils/encrypt/sm2/sm2_test.go index e82a6f2..5397fb1 100644 --- a/app/utils/encrypt/sm2/sm2_test.go +++ b/app/utils/encrypt/sm2/sm2_test.go @@ -17,7 +17,20 @@ func TestGenerateSM2KeyPair(t *testing.T) { // Print the private and public keys fmt.Printf("Private Key: %s\n", privateKey) - fmt.Printf("Public Key: %s", publicKey) + fmt.Printf("Public Key: %s\n", publicKey) + + data := "{\"name\":\"张三\",\"sex\":1,\"is_human\":true}" + en, err := SM2Encrypt(data, publicKey) + if err != nil { + panic(err) + } + + decrypt, err := SM2Decrypt(en, publicKey, privateKey) + if err != nil { + panic(err) + } + t.Log(decrypt) + } func TestSM2Encrypt(t *testing.T) { From f85d6cc410f2dda3f31fa3688445f31a5827eae5 Mon Sep 17 00:00:00 2001 From: Rzy <465386466@qq.com> Date: Wed, 7 Aug 2024 18:49:43 +0800 Subject: [PATCH 4/5] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E5=9B=9E=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/constants/errorcode/error_code.go | 8 ++ app/http/controllers/front/api.go | 46 ++++++--- app/http/entities/front/pay.go | 34 +------ app/http/middlewares/base.go | 10 +- app/http/requestmapping/front.go | 4 +- app/http/routes/route.go | 2 +- .../orderrequestlogmodel/order_request_log.go | 2 +- app/services/apicrypt/rsa.go | 9 +- app/services/apicrypt/sm2.go | 7 +- app/services/apicrypt/sm4.go | 5 +- app/services/apicrypt/types.go | 2 +- app/services/common.go | 5 + app/services/thirdpay/api/api_res_data.go | 47 ++++++++++ app/services/thirdpay/api/crypt.go | 52 +++++++++++ app/services/thirdpay/do/pay.go | 23 ++++- app/services/thirdpay/do/pay_check.go | 4 +- app/services/thirdpay/do/pay_way.go | 13 ++- app/services/thirdpay/notify/notify.go | 2 +- app/services/thirdpay/pay.go | 35 ++----- app/utils/encrypt/aes/aes.go | 93 +++++++++++++++++++ app/utils/encrypt/aes/aes_test.go | 34 +++++++ app/utils/encrypt/rsa/rsa_test.go | 34 ++++++- 22 files changed, 364 insertions(+), 107 deletions(-) create mode 100644 app/services/thirdpay/api/api_res_data.go create mode 100644 app/services/thirdpay/api/crypt.go create mode 100644 app/utils/encrypt/aes/aes.go create mode 100644 app/utils/encrypt/aes/aes_test.go diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index 2f1a82c..bfdab8a 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -47,6 +47,7 @@ const ( AppSM4DecryptFail = 1231 AppSM4EncryptKeyNotFound = 1232 AppSM4EncryptFail = 1233 + AppAesEncryptFail = 1240 //渠道 PayChannelNotFound = 1300 @@ -67,6 +68,9 @@ const ( //回调 NotifySendFail = 1600 + + //预支付 + PrePayFail = 1701 ) var MsgEN = map[int]string{ @@ -108,6 +112,8 @@ var MsgZH = map[int]string{ AppSM4EncryptKeyNotFound: "密匙缺失,无法进行sm4加密", AppSM4EncryptFail: "sm4加密失败", + AppAesEncryptFail: "aes 加密失败", + PayChannelNotFound: "支付方式不存在", PayChannelNotBuild: "支付方式尚未开通", PayChannelExtJsonError: "支付方式扩展参数错误", @@ -123,6 +129,8 @@ var MsgZH = map[int]string{ OrderStatusErr: "订单状态错误", NotifySendFail: "回调发送失败", + + PrePayFail: "预支付失败", } var MsgMap map[string]map[int]string = map[string]map[int]string{"en": MsgZH} diff --git a/app/http/controllers/front/api.go b/app/http/controllers/front/api.go index 006abbb..89c09b1 100644 --- a/app/http/controllers/front/api.go +++ b/app/http/controllers/front/api.go @@ -7,35 +7,47 @@ import ( "PaymentCenter/app/models/ordersmodel" "PaymentCenter/app/services" "PaymentCenter/app/services/thirdpay" + "PaymentCenter/app/services/thirdpay/api" "github.com/gin-gonic/gin" "xorm.io/builder" ) -func Pay(c *gin.Context) { +func PayUrl(c *gin.Context) { + var res front.PayUrlResp req := controllers.GetRequest(c).(*front.PayReqs) appCheckInfo := controllers.GetAppCheckInfo(c).(*services.AppCheck) - check := thirdpay.ThirdPayCheck(c.Request.Context(), req, appCheckInfo, c.ClientIP()) + check := thirdpay.ThirdPayInfoCheck(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) + check.CheckOrder() + if check.CheckCode != errorcode.Success { + controllers.ApiRes(c, nil, check.CheckCode) return } - controllers.ApiRes(c, thirdpay.PayCallBack(payInfo.Order, true), errorcode.Success) + pay := thirdpay.ThirdPayWeb(check) + if pay.PayCode != errorcode.Success { + controllers.ApiRes(c, nil, pay.PayCode) + return + } + data := api.NewOrdersResp(pay.Order) + encryptData, errCode := api.EnCrypt(appCheckInfo.App, data) + + if errCode != errorcode.Success { + controllers.ApiRes(c, nil, pay.PayCode) + return + } + res.Order = string(encryptData) + res.Url = pay.Url + controllers.ApiRes(c, res, pay.PayCode) return } // 查询订单 func QueryOrder(c *gin.Context) { req := controllers.GetRequest(c).(*front.QueryReqs) + appCheckInfo := controllers.GetAppCheckInfo(c).(*services.AppCheck) // 查询订单表 order := ordersmodel.Orders{ @@ -47,10 +59,14 @@ func QueryOrder(c *gin.Context) { cond = cond.And(builder.Eq{"out_tread_no": order.OutTreadNo}, builder.Eq{"app_id": order.AppId}) _, code := services.OrderFindOne(&order, cond) if code != errorcode.OrdersExist { - controllers.ApiRes(c, order, code) + controllers.ApiRes(c, nil, code) return } - data := front.OrdersResponse{} - data.ResponseFromDb(order) - controllers.ApiRes(c, data, errorcode.Success) + data := api.NewOrdersResp(&order) + encryptData, errCode := api.EnCrypt(appCheckInfo.App, data) + if errCode != errorcode.Success { + controllers.ApiRes(c, nil, errCode) + return + } + controllers.ApiRes(c, encryptData, errorcode.Success) } diff --git a/app/http/entities/front/pay.go b/app/http/entities/front/pay.go index cdaba6c..4413d58 100644 --- a/app/http/entities/front/pay.go +++ b/app/http/entities/front/pay.go @@ -1,7 +1,5 @@ package front -import "PaymentCenter/app/models/ordersmodel" - type ApiCommonBody struct { AppId int64 `json:"app_id" validate:"required"` Timestamp int64 `json:"timestamp" validate:"required"` @@ -11,6 +9,7 @@ type RequestBody struct { AppId int64 `json:"app_id" validate:"required"` Timestamp int64 `json:"timestamp" validate:"required"` Data string `json:"data" validate:"required"` + Key string `json:"key" validate:"max=32"` } type PayReqs struct { @@ -23,37 +22,12 @@ type PayReqs struct { Desc string `json:"desc" validate:"max=100" label:"商品描述"` } -type OrderApiResp struct { - Code int - Msg string - Data interface{} +type PayUrlResp struct { + Order string `json:"order"` + Url string `json:"url"` } type QueryReqs struct { ApiCommonBody OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"` } - -type OrdersResponse struct { - Id int64 `json:"id"` - 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"` - Amount int `json:"amount"` - PayerTotal int `json:"payer_total"` - CreateTime string `json:"create_time"` -} - -func (o *OrdersResponse) ResponseFromDb(db ordersmodel.Orders) { - o.Id = db.Id - o.PayChannelId = db.PayChannelId - o.AppId = db.AppId - o.OutTreadNo = db.OutTreadNo - o.Status = db.Status - o.OrderType = db.OrderType - o.Amount = db.Amount - o.PayerTotal = db.PayerTotal - o.CreateTime = db.CreateTime.Format("2006-01-02 15:04:05") -} diff --git a/app/http/middlewares/base.go b/app/http/middlewares/base.go index 0bdf33e..7f90056 100644 --- a/app/http/middlewares/base.go +++ b/app/http/middlewares/base.go @@ -7,7 +7,7 @@ import ( "PaymentCenter/app/http/entities/front" "PaymentCenter/app/http/requestmapping" "PaymentCenter/app/services" - "PaymentCenter/app/services/apicrypt" + "PaymentCenter/app/services/thirdpay/api" "PaymentCenter/app/utils" "PaymentCenter/config" "encoding/json" @@ -155,12 +155,8 @@ func ValidatePayRequest() gin.HandlerFunc { 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 { + dataByte, errCode := api.DeCrypt(appCheck.App, requestDataStruct.Data, requestDataStruct.Key) + if errCode != errorcode.Success { controllers.ApiRes(c, nil, errCode) return } diff --git a/app/http/requestmapping/front.go b/app/http/requestmapping/front.go index bf8173d..7548886 100644 --- a/app/http/requestmapping/front.go +++ b/app/http/requestmapping/front.go @@ -6,9 +6,9 @@ import ( ) var FrontRequestMap = map[string]func() interface{}{ - common.FRONT_V1 + "/pay/do": func() interface{} { return new(front.PayReqs) }, + common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.PayReqs) }, } var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{ - common.FRONT_V1 + "/pay/do": func() interface{} { return new(front.RequestBody) }, + common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.RequestBody) }, } diff --git a/app/http/routes/route.go b/app/http/routes/route.go index 8e684af..345e11a 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("/do", front.Pay) + pay.POST("/url", front.PayUrl) pay.POST("/query", front.QueryOrder) //查询订单 } } diff --git a/app/models/orderrequestlogmodel/order_request_log.go b/app/models/orderrequestlogmodel/order_request_log.go index 236c759..5254657 100644 --- a/app/models/orderrequestlogmodel/order_request_log.go +++ b/app/models/orderrequestlogmodel/order_request_log.go @@ -15,7 +15,7 @@ var ( type OrderRequestLog struct { Id int64 IpAddress string `xorm:"'ip_address' varchar(16)"` - URL string `xorm:"'url' varchar(20)"` + URL string `xorm:"'url' varchar(100)"` MerchantRequest string `xorm:"'merchant_request' JSON"` MerchantResponse string `xorm:"'merchant_response' JSON"` CreateTime time.Time `xorm:"'create_time' datetime created"` diff --git a/app/services/apicrypt/rsa.go b/app/services/apicrypt/rsa.go index 69012ac..0189620 100644 --- a/app/services/apicrypt/rsa.go +++ b/app/services/apicrypt/rsa.go @@ -4,6 +4,7 @@ import ( "PaymentCenter/app/constants/errorcode" "PaymentCenter/app/models/appmodel" "PaymentCenter/app/utils/encrypt/rsa" + "encoding/base64" ) func NewRsa(app *appmodel.App) ApiCrypt { @@ -12,23 +13,23 @@ func NewRsa(app *appmodel.App) ApiCrypt { } } -func (r *Rsa) Encrypt(decryptData string) (encryptData []byte, errCode int) { +func (r *Rsa) Encrypt(data []byte) (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)) + encryptByte, err := rsa.Encrypt(publicKeyPEM, data) if err != nil { return nil, errorcode.AppRsaEncryptFail } - + encryptData = []byte(base64.StdEncoding.EncodeToString(encryptByte)) return } func (r *Rsa) Decrypt(encryptData string) (decryptData []byte, errCode int) { - + if r.App.PrivateKey == "" { return nil, errorcode.AppRsaDecryptKeyNotFound } diff --git a/app/services/apicrypt/sm2.go b/app/services/apicrypt/sm2.go index 7aee726..6c89625 100644 --- a/app/services/apicrypt/sm2.go +++ b/app/services/apicrypt/sm2.go @@ -12,12 +12,13 @@ func NewSm2(app *appmodel.App) ApiCrypt { } } -func (r *SM2) Encrypt(decryptData string) (encryptData []byte, errCode int) { +func (r *SM2) Encrypt(data []byte) (encryptData []byte, errCode int) { + if r.App.MerchantPublicKey == "" { return nil, errorcode.AppSM2EncryptKeyNotFound } - // - encryptDataString, err := sm2.SM2Encrypt(decryptData, r.App.PrivateKey) + + encryptDataString, err := sm2.SM2Encrypt(string(data), r.App.PrivateKey) if err != nil { return nil, errorcode.AppSM2EncryptFail } diff --git a/app/services/apicrypt/sm4.go b/app/services/apicrypt/sm4.go index 9c8dcfe..9d69f40 100644 --- a/app/services/apicrypt/sm4.go +++ b/app/services/apicrypt/sm4.go @@ -13,12 +13,11 @@ func NewSm4(app *appmodel.App) ApiCrypt { } } -func (r *SM4) Encrypt(decryptData string) (encryptData []byte, errCode int) { +func (r *SM4) Encrypt(data []byte) (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) + encryptDataString, err := sm4.Sm4Encrypt(strconv.FormatInt(r.App.Id, 10), r.App.PrivateKey, r.App.MerchantPublicKey, string(data), "", true) if err != nil { return nil, errorcode.AppSM4EncryptFail } diff --git a/app/services/apicrypt/types.go b/app/services/apicrypt/types.go index 533de39..df21161 100644 --- a/app/services/apicrypt/types.go +++ b/app/services/apicrypt/types.go @@ -7,7 +7,7 @@ import ( type ( ApiCrypt interface { - Encrypt(decryptData string) (encryptData []byte, errCode int) + Encrypt(data []byte) (encryptData []byte, errCode int) Decrypt(encryptData string) (decryptData []byte, errCode int) } diff --git a/app/services/common.go b/app/services/common.go index ed282d7..1d9e945 100644 --- a/app/services/common.go +++ b/app/services/common.go @@ -2,6 +2,7 @@ package services import ( "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/models/appmodel" "PaymentCenter/app/utils" ) @@ -13,3 +14,7 @@ func handErr(err error) int { return errorcode.Success } } + +func EnCryptData(app *appmodel.App) { + +} diff --git a/app/services/thirdpay/api/api_res_data.go b/app/services/thirdpay/api/api_res_data.go new file mode 100644 index 0000000..cf09148 --- /dev/null +++ b/app/services/thirdpay/api/api_res_data.go @@ -0,0 +1,47 @@ +package api + +import ( + "PaymentCenter/app/models/ordersmodel" +) + +type OrdersResp struct { + OrderNo int64 `json:"order_no"` + OrderType int `json:"order_type"` + OutTreadNo string `json:"out_tread_no"` + Amount int `json:"amount"` + Desc string `json:"desc"` + + Status int `json:"status"` + CreateTime string `json:"create_time"` +} + +type OrdersWithUrl struct { + Order *OrdersResp + Url string +} + +func NewOrdersResp(db *ordersmodel.Orders) *OrdersResp { + return &OrdersResp{ + OrderNo: db.Id, + OutTreadNo: db.OutTreadNo, + Status: db.Status, + OrderType: db.OrderType, + Amount: db.Amount, + Desc: db.Desc, + CreateTime: db.CreateTime.Format("2006-01-02 15:04:05"), + } +} + +func (o *OrdersResp) WithUrl(url string) *OrdersWithUrl { + return &OrdersWithUrl{ + Order: o, + Url: url, + } +} + +func (o *OrdersResp) WithAes(url string) *OrdersWithUrl { + return &OrdersWithUrl{ + Order: o, + Url: url, + } +} diff --git a/app/services/thirdpay/api/crypt.go b/app/services/thirdpay/api/crypt.go new file mode 100644 index 0000000..26e250d --- /dev/null +++ b/app/services/thirdpay/api/crypt.go @@ -0,0 +1,52 @@ +package api + +import ( + "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/models/appmodel" + "PaymentCenter/app/services" + "PaymentCenter/app/services/apicrypt" + "encoding/json" +) + +func EnCrypt(app *appmodel.App, data interface{}) ([]byte, int) { + appCheck := services.NewAppCheck(app) + cryptFunc := appCheck.Crypt() + if cryptFunc == nil { + return nil, appCheck.Code + } + dataByte, err := json.Marshal(data) + if err != nil { + return nil, errorcode.AppAesEncryptFail + } + //aesKey, err := aes.GenerateRandomStringCrypto(16) + //if err != nil { + // return "", errorcode.AppAesEncryptFail + //} + //aesData, err := aes.Encrypt(dataByte, []byte(aesKey)) + //if err != nil { + // return "", errorcode.AppAesEncryptFail + //} + encryptData, errCode := cryptFunc(appCheck.App).Encrypt(dataByte) + if errCode != apicrypt.CryptNotError { + return nil, errCode + } + return encryptData, errorcode.Success +} + +func DeCrypt(app *appmodel.App, data string, aesKey string) ([]byte, int) { + appCheck := services.NewAppCheck(app) + cryptFunc := appCheck.Crypt() + if cryptFunc == nil { + return nil, appCheck.Code + } + dataByte, errCode := cryptFunc(app).Decrypt(data) + if errCode != apicrypt.CryptNotError { + return nil, errCode + } + //aesData, err := aes.Decrypt(dataByte, []byte(aesKey)) + //if err != nil { + // return nil, errorcode.AppAesEncryptFail + //} + + return dataByte, errorcode.Success +} diff --git a/app/services/thirdpay/do/pay.go b/app/services/thirdpay/do/pay.go index e07d841..72714d8 100644 --- a/app/services/thirdpay/do/pay.go +++ b/app/services/thirdpay/do/pay.go @@ -3,7 +3,9 @@ package do import ( "PaymentCenter/app/constants/common" "PaymentCenter/app/constants/errorcode" + "PaymentCenter/app/models/paychannelmodel" "PaymentCenter/app/services" + "PaymentCenter/app/third/paymentService/payCommon" "PaymentCenter/app/models/ordersmodel" "PaymentCenter/app/third/paymentService" @@ -13,6 +15,7 @@ type Pay struct { paycheck *PayCheck Order *ordersmodel.Orders PayCode int + Url string } func NewPay(paycheck *PayCheck) *Pay { @@ -37,9 +40,9 @@ func (w *Pay) CreateOrder() { ) } -func (w *Pay) Pay() { +func (w *Pay) PayUrl() (url string) { var ( - payFunc func(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error + payFunc func(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error ok bool ) thirdPay := &paymentService.PayOrderRequest{ @@ -54,13 +57,23 @@ func (w *Pay) Pay() { w.PayCode = errorcode.PayChannelNotBuild return } - err := payFunc(thirdPay, w.paycheck.Channel.ExtJson) + err := payFunc(thirdPay, w.paycheck.Channel) if err != nil { w.PayCode = errorcode.PayChannelExtJsonError return } res := paymentService.PaymentService(*w.paycheck.ctx, *thirdPay) - // payCommon.PAY_SUCCESS_CODE - w.PayCode = res.Code + + if res.Code == payCommon.PAY_SUCCESS_CODE { + w.Order.Status = common.ORDER_STATUS_PAYING + code := services.OrderUpdate(w.Order, "status") + if code != errorcode.Success { + w.PayCode = code + } + w.Url = res.Result + } else { + w.PayCode = errorcode.PrePayFail + } + return } diff --git a/app/services/thirdpay/do/pay_check.go b/app/services/thirdpay/do/pay_check.go index e3228e4..c3116a1 100644 --- a/app/services/thirdpay/do/pay_check.go +++ b/app/services/thirdpay/do/pay_check.go @@ -61,9 +61,9 @@ 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 + if code == errorcode.SystemError { w.CheckCode = code } + w.OldOrder = order return } diff --git a/app/services/thirdpay/do/pay_way.go b/app/services/thirdpay/do/pay_way.go index b367964..8d43ae9 100644 --- a/app/services/thirdpay/do/pay_way.go +++ b/app/services/thirdpay/do/pay_way.go @@ -2,27 +2,30 @@ package do import ( "PaymentCenter/app/constants/common" + "PaymentCenter/app/models/paychannelmodel" "PaymentCenter/app/third/paymentService" "github.com/bytedance/sonic" ) -var PayWayList = map[int]func(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error{ +var PayWayList = map[int]func(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) 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) +func WechatH5(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error { + err := sonic.Unmarshal([]byte(channel.ExtJson), &commonPayInfo.Wx) if err != nil { return err } + commonPayInfo.Wx.AppId = channel.AppId return nil } -func AlipayWeb(commonPayInfo *paymentService.PayOrderRequest, ExtJson string) error { - err := sonic.Unmarshal([]byte(ExtJson), &commonPayInfo.Ali) +func AlipayWeb(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error { + err := sonic.Unmarshal([]byte(channel.ExtJson), &commonPayInfo.Ali) if err != nil { return err } + commonPayInfo.Ali.AppId = channel.AppId return nil } diff --git a/app/services/thirdpay/notify/notify.go b/app/services/thirdpay/notify/notify.go index 2f4b7f7..2a2b949 100644 --- a/app/services/thirdpay/notify/notify.go +++ b/app/services/thirdpay/notify/notify.go @@ -94,7 +94,6 @@ func (o *OrderNotify) handle() (res *OrderNotifyResp) { 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) @@ -124,6 +123,7 @@ func (o *OrderNotify) updateOrder() { o.code = errorcode.OrderStatusErr return } + o.order.Status = o.Status o.code = services.OrderUpdate(o.order, "status") return } diff --git a/app/services/thirdpay/pay.go b/app/services/thirdpay/pay.go index 2396c00..12973b6 100644 --- a/app/services/thirdpay/pay.go +++ b/app/services/thirdpay/pay.go @@ -3,37 +3,35 @@ 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 + if &check.OldOrder != nil { + pay.CreateOrder() + if pay.PayCode != errorcode.Success { + return pay + } + } else { + pay.Order = check.OldOrder } // 支付 - pay.Pay() + pay.PayUrl() return pay } -func ThirdPayCheck(ctx context.Context, req *front.PayReqs, appCheck *services.AppCheck, ip string) (check *thirdpay.PayCheck) { +func ThirdPayInfoCheck(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 { @@ -47,16 +45,3 @@ func ThirdPayCheck(ctx context.Context, req *front.PayReqs, appCheck *services.A 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/utils/encrypt/aes/aes.go b/app/utils/encrypt/aes/aes.go new file mode 100644 index 0000000..24d2772 --- /dev/null +++ b/app/utils/encrypt/aes/aes.go @@ -0,0 +1,93 @@ +package aes + +import ( + "bytes" + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "fmt" + "io" + "math/big" +) + +const ( + TestKey = "ROK0nAaxcsI0KRCy8VJgLlnlfjWYAOHk" +) + +// 加密函数 +func Encrypt(plaintext, key []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + ciphertext := make([]byte, aes.BlockSize+len(plaintext)) + iv := ciphertext[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return nil, err + } + + mode := cipher.NewCBCEncrypter(block, iv) + mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) + + return iv, nil +} + +// 解密函数 +func Decrypt(ciphertext, key []byte) ([]byte, error) { + block, err := aes.NewCipher(key) + if err != nil { + return nil, err + } + + if len(ciphertext) < aes.BlockSize { + return nil, fmt.Errorf("ciphertext too short") + } + + // 提取iv + iv := ciphertext[:aes.BlockSize] + ciphertext = ciphertext[aes.BlockSize:] + + // 创建一个cipher.BlockMode + mode := cipher.NewCBCDecrypter(block, iv) + + // 解密 + mode.CryptBlocks(ciphertext, ciphertext) + + // 去除PKCS#7填充 + plaintext, err := pkcs7Unpadding(ciphertext, block.BlockSize()) + if err != nil { + return nil, err + } + + return plaintext, nil +} + +// PKCS#7填充 +func pkcs7Padding(ciphertext []byte, blockSize int) []byte { + padding := blockSize - len(ciphertext)%blockSize + padtext := bytes.Repeat([]byte{byte(padding)}, padding) + return append(ciphertext, padtext...) +} + +// 去除PKCS#7填充 +func pkcs7Unpadding(ciphertext []byte, blockSize int) ([]byte, error) { + length := len(ciphertext) + unpadding := int(ciphertext[length-1]) + if unpadding > blockSize || unpadding == 0 { + return nil, fmt.Errorf("invalid padding") + } + return ciphertext[:(length - unpadding)], nil +} + +func GenerateRandomStringCrypto(length int) (string, error) { + const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + var bytes = make([]byte, length) + for i := range bytes { + num, err := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) + if err != nil { + return "", err + } + bytes[i] = charset[num.Int64()] + } + return string(bytes), nil +} diff --git a/app/utils/encrypt/aes/aes_test.go b/app/utils/encrypt/aes/aes_test.go new file mode 100644 index 0000000..c9e4ef3 --- /dev/null +++ b/app/utils/encrypt/aes/aes_test.go @@ -0,0 +1,34 @@ +package aes + +import ( + "fmt" + "testing" +) + +func TestCreateKey(t *testing.T) { + key, _ := GenerateRandomStringCrypto(32) + fmt.Printf(key) +} + +func TestAesEncrypt(t *testing.T) { + + fmt.Printf("%s\n", encrypt()) +} + +func TestAesDecrypt(t *testing.T) { + data := "dk9trGQn2kZyE0rmfYglxwNmr7gc0DGFWvnPDVpLHfzwPiaWKkr+ZffKu0wj9/DQurIgjrQZIW8uV5/e+jxzBE6+5YZuKcT9+5xZSv6ieiXB7WUrKKnjxX/bHEaWgfoa0eDqEBhGth+mgql7qWFZLmuXpoKuAc0FPhdHTiynAttqjNMU4rMeXq52yJLuXrKHGlavhd9DETNDrhPFzyIAw7XjoMfGtBIFkXyDK5X+AKGkRvMJ8KfXR3lk9sSzTyGKRK/S" + + res, err := Decrypt([]byte(data), []byte(TestKey)) + fmt.Println(string(res), err) +} + +func encrypt() string { + data := "{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}" + + en, err := Encrypt([]byte(data), []byte(TestKey)) + if err != nil { + panic(err) + } + + return string(en) +} diff --git a/app/utils/encrypt/rsa/rsa_test.go b/app/utils/encrypt/rsa/rsa_test.go index b3547b8..6113d37 100644 --- a/app/utils/encrypt/rsa/rsa_test.go +++ b/app/utils/encrypt/rsa/rsa_test.go @@ -1,6 +1,7 @@ package rsa import ( + "PaymentCenter/app/utils/encrypt/aes" "encoding/base64" "fmt" "testing" @@ -13,7 +14,6 @@ const ( ) func TestRsaEncrypt(t *testing.T) { - fmt.Printf("%s\n", encrypt()) } @@ -27,7 +27,37 @@ func TestRsaDecrypt(t *testing.T) { } func encrypt() string { - data := "{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}" + data := "{\"order_no\":4323455642275676219,\"order_type\":1,\"out_tread_no\":\"asdadasdas\",\"amount\":1,\"desc\":\"abc\",\"status\":2,\"create_time\":\"2024-08-07 18:36:43\"}" + fmt.Println(len(data)) + dataJson := []byte(data) + pub := `-----BEGIN PUBLIC KEY----- +` + PUB + ` +-----END PUBLIC KEY-----` + en, err := Encrypt(pub, dataJson) + if err != nil { + panic(err) + } + + return base64.StdEncoding.EncodeToString(en) +} + +func TestRsaEncryptWithAes(t *testing.T) { + + fmt.Printf("%s\n", encryptWithAes()) +} + +func TestRsaDecryptWithAes(t *testing.T) { + data := "cGuoR6Bmmm9fZr/OAnM54eM6Z7M4ysnRr7TV64rIK6mAkGDzJROwSOY443e7UJmLpwIEn8G5jNk6j8K1scxvIMMdSJZ0QOJREjgzbZfNfuXV0LO1lVNu3uhwVQXN/zMZxBHGIcYQnPWSaOHhNy6yMRPLFNRuIb5FuTx7E6VI5UVZpHk9VLv63QX+6+hQMOiqoif/YyXkAqi2xG+unq4MVq9w5aYMOVzHX1eyMiTeRFRB4iKhf6bCJmVvLMmvjHYKQl3/225R4uXaI8nv7y4IHnK8KVYAnuJE6SvEPeJAjpINrY2CRoNqTYkt7DRS2uz5l7aE+KX8GShV2XlDoM8KZA==" + privateKeyPEM := `-----BEGIN RSA PRIVATE KEY----- +` + PRI + ` +-----END RSA PRIVATE KEY-----` + res, err := Decrypt(privateKeyPEM, data) + fmt.Println(string(res), err) +} + +func encryptWithAes() string { + data := "{\"pay_channel_id\":8935141660703064070,\"out_trade_no\":\"asdadasdas\",\"order_type\":1,\"amount\":1,\"desc\":\"abc\",\"ext_json\":\"\",\"app_id\":5476377146882523138,\"timestamp\":53612533412643}" + aes.Encrypt([]byte(data), []byte(aes.TestKey)) dataJson := []byte(data) pub := `-----BEGIN PUBLIC KEY----- ` + PUB + ` From f225fc0f8ce8d67b39409a144f5d5f200fae90e3 Mon Sep 17 00:00:00 2001 From: Rzy <465386466@qq.com> Date: Thu, 8 Aug 2024 09:30:02 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=94=AF=E4=BB=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/constants/errorcode/error_code.go | 10 +++++++--- app/services/thirdpay/do/pay_check.go | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/app/constants/errorcode/error_code.go b/app/constants/errorcode/error_code.go index bfdab8a..349d81b 100644 --- a/app/constants/errorcode/error_code.go +++ b/app/constants/errorcode/error_code.go @@ -60,7 +60,9 @@ const ( OrderTypeNotFount = 1403 OrderIsDelete = 1405 OrderStatusErr = 1406 - + OrderClosed = 1407 + OrderFailed = 1408 + OrderPayed = 1409 //请求日志 RequestLogErrors = 1500 RequestLogNotFound = 1501 @@ -127,8 +129,10 @@ var MsgZH = map[int]string{ OrderTypeNotFount: "未知的支付方式", OrderIsDelete: "订单已删除", OrderStatusErr: "订单状态错误", - - NotifySendFail: "回调发送失败", + OrderClosed: "订单已关闭,无法继续支付", + OrderFailed: "订单支付失败,请重新发起", + OrderPayed: "订单已支付成功,请勿重复支付", + NotifySendFail: "回调发送失败", PrePayFail: "预支付失败", } diff --git a/app/services/thirdpay/do/pay_check.go b/app/services/thirdpay/do/pay_check.go index c3116a1..d690c07 100644 --- a/app/services/thirdpay/do/pay_check.go +++ b/app/services/thirdpay/do/pay_check.go @@ -59,11 +59,23 @@ func (w *PayCheck) CheckMerchant() { 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}) + cond = cond.And(builder.Eq{"out_tread_no": w.WebPayReqs.OutTradeNo}, builder.Eq{"app_id": w.AppCheck.AppId}) order, code := services.OrderFindOne(&ordersmodel.Orders{}, cond) if code == errorcode.SystemError { w.CheckCode = code + return } - w.OldOrder = order + if code == errorcode.OrdersExist { + w.OldOrder = order + switch order.Status { + case common.ORDER_STATUS_CLOSE: + w.CheckCode = errorcode.OrderClosed + case common.ORDER_STATUS_FAILED: + w.CheckCode = errorcode.OrderFailed + case common.ORDER_STATUS_PAYED: + w.CheckCode = errorcode.OrderPayed + } + } + return }