Compare commits
22 Commits
f225fc0f8c
...
ee912a204d
Author | SHA1 | Date |
---|---|---|
|
ee912a204d | |
|
aa43040aa2 | |
|
cb14c35aa9 | |
|
ebea5c52e0 | |
|
40dfffe31a | |
|
58f8cedb85 | |
|
d6bf4dd952 | |
|
7ed1ca131b | |
|
30b83b3645 | |
|
62d050c02f | |
|
3061987dae | |
|
3d5e33fed0 | |
|
bf1bc4b1a2 | |
|
514104a391 | |
|
ad56b5f0e5 | |
|
82ef285e7d | |
|
ca42c43bd2 | |
|
6ab982e874 | |
|
c79e316233 | |
|
75d68a3032 | |
|
e261a39cf5 | |
|
68b9e16864 |
|
@ -6,14 +6,13 @@ import (
|
||||||
"PaymentCenter/app/http/entities"
|
"PaymentCenter/app/http/entities"
|
||||||
"PaymentCenter/app/http/entities/backend"
|
"PaymentCenter/app/http/entities/backend"
|
||||||
"PaymentCenter/app/models/ordersmodel"
|
"PaymentCenter/app/models/ordersmodel"
|
||||||
"PaymentCenter/app/models/orderthirdpaylogmodel"
|
"PaymentCenter/app/services/thirdpay/thirdpay_notify"
|
||||||
"PaymentCenter/app/third/paymentService"
|
"PaymentCenter/app/third/paymentService"
|
||||||
"PaymentCenter/app/third/paymentService/payCommon"
|
"PaymentCenter/app/third/paymentService/payCommon"
|
||||||
"PaymentCenter/app/utils"
|
"PaymentCenter/app/utils"
|
||||||
"PaymentCenter/config"
|
"PaymentCenter/config"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
|
||||||
"github.com/qit-team/snow-core/command"
|
"github.com/qit-team/snow-core/command"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -83,7 +82,7 @@ func closeOrder() {
|
||||||
if response.Code == payCommon.PAY_SUCCESS_CODE {
|
if response.Code == payCommon.PAY_SUCCESS_CODE {
|
||||||
orderIds = append(orderIds, orderInfo.Id)
|
orderIds = append(orderIds, orderInfo.Id)
|
||||||
} else {
|
} else {
|
||||||
utils.Log(nil, "关闭订单,上游支付失败", response)
|
utils.Log(nil, "关闭订单,上游失败", response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 修改订单状态为关闭
|
// 修改订单状态为关闭
|
||||||
|
@ -172,64 +171,115 @@ func queryOrder() {
|
||||||
// 成功
|
// 成功
|
||||||
status = common.ORDER_STATUS_PAYED
|
status = common.ORDER_STATUS_PAYED
|
||||||
case "REFUND":
|
case "REFUND":
|
||||||
// 退款
|
// 退款 订单支付完成才能退款,所以支付单的状态是支付完成
|
||||||
status = common.ORDER_STATUS_REFUND
|
status = common.ORDER_STATUS_PAYED
|
||||||
|
|
||||||
case "NOTPAY":
|
case "NOTPAY":
|
||||||
// 未支付
|
// 未支付
|
||||||
return
|
return
|
||||||
case "CLOSED":
|
case "CLOSED":
|
||||||
// 关闭
|
// 关闭
|
||||||
status = common.ORDER_STATUS_CLOSE
|
status = common.ORDER_STATUS_CLOSE
|
||||||
|
|
||||||
}
|
}
|
||||||
// 回调通知下游 todo
|
// 回调通知下游 todo
|
||||||
|
notifyResult := thirdpay_notify.NewOrderNotifyWithHandle(orderInfo.Id, status, int(result.Result.PayerTotal), "")
|
||||||
|
utils.Log(nil, "主动查询订单支付状态,回调下游", notifyResult)
|
||||||
|
}
|
||||||
|
}(orderInfo)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 更新订单状态 todo
|
// 主动查询退款订单状态
|
||||||
orderUpdate := ordersmodel.Orders{
|
func queryRefundOrder() {
|
||||||
Id: orderInfo.Id,
|
var now = time.Now().Format(time.DateTime)
|
||||||
Status: status,
|
utils.Log(nil, "主动查询退款订单状态", now)
|
||||||
PayerTotal: int(result.Result.PayerTotal),
|
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 {
|
result := paymentService.OrderRefundQuery(ctx, query)
|
||||||
utils.Log(nil, "主动查询订单支付状态,更新订单状态失败", err)
|
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
|
return
|
||||||
}
|
case 1:
|
||||||
defer func() {
|
// 退款中
|
||||||
if err != nil {
|
status = common.ORDER_STATUS_PAYING
|
||||||
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)
|
|
||||||
return
|
return
|
||||||
|
case 2:
|
||||||
|
// 退款成功
|
||||||
|
status = common.ORDER_STATUS_PAYED
|
||||||
|
case 3:
|
||||||
|
// 退款失败
|
||||||
|
status = common.ORDER_STATUS_FAILED
|
||||||
}
|
}
|
||||||
|
// 回调通知下游 todo
|
||||||
// 写入日志
|
notifyResult := thirdpay_notify.NewOrderNotifyWithHandle(orderInfo.Id, status, int(result.Result.RefundFee), "")
|
||||||
body, _ := json.Marshal(result)
|
utils.Log(nil, "主动查询退款订单状态,回调下游", notifyResult)
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}(orderInfo)
|
}(orderInfo)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,4 +17,5 @@ func RegisterSchedule(c *cron.Cron) {
|
||||||
//c.AddFunc("@every 10s", test)
|
//c.AddFunc("@every 10s", test)
|
||||||
c.AddFunc("@every 60s", closeOrder)
|
c.AddFunc("@every 60s", closeOrder)
|
||||||
c.AddFunc("@every 10s", queryOrder)
|
c.AddFunc("@every 10s", queryOrder)
|
||||||
|
c.AddFunc("@every 60s", queryRefundOrder)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,12 @@ const (
|
||||||
ADMIN_USER_NAME = "User-Name"
|
ADMIN_USER_NAME = "User-Name"
|
||||||
ADMIN_USER_INCLUDEUSERS = "Include-Users"
|
ADMIN_USER_INCLUDEUSERS = "Include-Users"
|
||||||
|
|
||||||
// '订单状态: 1待支付、2支付中、3支付成功、4支付失败、5订单关闭 6支付完成后退款,
|
// '订单状态: 1待支付、2支付中、3支付成功、4支付失败、5订单关闭
|
||||||
ORDER_STATUS_WAITPAY = 1
|
ORDER_STATUS_WAITPAY = 1
|
||||||
ORDER_STATUS_PAYING = 2
|
ORDER_STATUS_PAYING = 2
|
||||||
ORDER_STATUS_PAYED = 3
|
ORDER_STATUS_PAYED = 3
|
||||||
ORDER_STATUS_FAILED = 4
|
ORDER_STATUS_FAILED = 4
|
||||||
ORDER_STATUS_CLOSE = 5
|
ORDER_STATUS_CLOSE = 5
|
||||||
ORDER_STATUS_REFUND = 6
|
|
||||||
|
|
||||||
// 订单类型,1支付,2退款
|
// 订单类型,1支付,2退款
|
||||||
ORDER_TYPE_PAY = 1
|
ORDER_TYPE_PAY = 1
|
||||||
|
|
|
@ -47,7 +47,9 @@ const (
|
||||||
AppSM4DecryptFail = 1231
|
AppSM4DecryptFail = 1231
|
||||||
AppSM4EncryptKeyNotFound = 1232
|
AppSM4EncryptKeyNotFound = 1232
|
||||||
AppSM4EncryptFail = 1233
|
AppSM4EncryptFail = 1233
|
||||||
AppAesEncryptFail = 1240
|
AppAesEncryptFail = 1234
|
||||||
|
// 加密方式不存在
|
||||||
|
EncryptTypeNotFound = 1241
|
||||||
|
|
||||||
//渠道
|
//渠道
|
||||||
PayChannelNotFound = 1300
|
PayChannelNotFound = 1300
|
||||||
|
@ -71,8 +73,9 @@ const (
|
||||||
//回调
|
//回调
|
||||||
NotifySendFail = 1600
|
NotifySendFail = 1600
|
||||||
|
|
||||||
//预支付
|
//订单结果
|
||||||
PrePayFail = 1701
|
PrePayFail = 1701
|
||||||
|
PreRefundFail = 1702
|
||||||
)
|
)
|
||||||
|
|
||||||
var MsgEN = map[int]string{
|
var MsgEN = map[int]string{
|
||||||
|
@ -116,6 +119,8 @@ var MsgZH = map[int]string{
|
||||||
|
|
||||||
AppAesEncryptFail: "aes 加密失败",
|
AppAesEncryptFail: "aes 加密失败",
|
||||||
|
|
||||||
|
EncryptTypeNotFound: "加密方式不存在",
|
||||||
|
|
||||||
PayChannelNotFound: "支付方式不存在",
|
PayChannelNotFound: "支付方式不存在",
|
||||||
PayChannelNotBuild: "支付方式尚未开通",
|
PayChannelNotBuild: "支付方式尚未开通",
|
||||||
PayChannelExtJsonError: "支付方式扩展参数错误",
|
PayChannelExtJsonError: "支付方式扩展参数错误",
|
||||||
|
|
|
@ -7,7 +7,9 @@ import (
|
||||||
"PaymentCenter/app/http/entities/backend"
|
"PaymentCenter/app/http/entities/backend"
|
||||||
"PaymentCenter/app/models/appmodel"
|
"PaymentCenter/app/models/appmodel"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
|
"PaymentCenter/app/utils/encrypt/rsa"
|
||||||
"PaymentCenter/app/utils/encrypt/sm2"
|
"PaymentCenter/app/utils/encrypt/sm2"
|
||||||
|
"PaymentCenter/app/utils/encrypt/sm4"
|
||||||
"github.com/ahmetb/go-linq/v3"
|
"github.com/ahmetb/go-linq/v3"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
@ -60,12 +62,19 @@ func GenerateDecrypt(c *gin.Context) {
|
||||||
var publicKey, privateKey string
|
var publicKey, privateKey string
|
||||||
var err error
|
var err error
|
||||||
switch req.KeyType {
|
switch req.KeyType {
|
||||||
default:
|
case "sm2":
|
||||||
publicKey, privateKey, err = sm2.GenerateSM2Key()
|
publicKey, privateKey, err = sm2.GenerateSM2Key()
|
||||||
if err != nil {
|
case "rsa":
|
||||||
controllers.Error(c, errorcode.SystemError, err.Error())
|
publicKey, privateKey, err = rsa.GenerateKey()
|
||||||
return
|
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{
|
controllers.HandCodeRes(c, map[string]string{
|
||||||
|
|
|
@ -21,17 +21,17 @@ func PayUrl(c *gin.Context) {
|
||||||
controllers.ApiRes(c, nil, check.CheckCode)
|
controllers.ApiRes(c, nil, check.CheckCode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
check.CheckOrder()
|
check.CheckOrderPay()
|
||||||
if check.CheckCode != errorcode.Success {
|
if check.CheckCode != errorcode.Success {
|
||||||
controllers.ApiRes(c, nil, check.CheckCode)
|
controllers.ApiRes(c, nil, check.CheckCode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pay := thirdpay.ThirdPayWeb(check)
|
pay := thirdpay.ThirdPayUrl(check)
|
||||||
if pay.PayCode != errorcode.Success {
|
if pay.PayCode != errorcode.Success {
|
||||||
controllers.ApiRes(c, nil, pay.PayCode)
|
controllers.ApiRes(c, nil, pay.PayCode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data := api.NewOrdersResp(pay.Order)
|
data := thirdpay.NewOrdersResp(pay.Order)
|
||||||
encryptData, errCode := api.EnCrypt(appCheckInfo.App, data)
|
encryptData, errCode := api.EnCrypt(appCheckInfo.App, data)
|
||||||
|
|
||||||
if errCode != errorcode.Success {
|
if errCode != errorcode.Success {
|
||||||
|
@ -44,6 +44,24 @@ func PayUrl(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Refund(c *gin.Context) {
|
||||||
|
req := controllers.GetRequest(c).(*front.RefundReqs)
|
||||||
|
appCheckInfo := controllers.GetAppCheckInfo(c).(*services.AppCheck)
|
||||||
|
refund := thirdpay.ThirdPayRefund(c.Request.Context(), req, appCheckInfo, c.ClientIP())
|
||||||
|
if refund.PayCode != errorcode.Success {
|
||||||
|
controllers.ApiRes(c, nil, refund.PayCode)
|
||||||
|
}
|
||||||
|
data := thirdpay.NewOrdersResp(refund.Order)
|
||||||
|
encryptData, errCode := api.EnCrypt(appCheckInfo.App, data)
|
||||||
|
if errCode != errorcode.Success {
|
||||||
|
controllers.ApiRes(c, nil, refund.PayCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
controllers.ApiRes(c, encryptData, refund.PayCode)
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// 查询订单
|
// 查询订单
|
||||||
func QueryOrder(c *gin.Context) {
|
func QueryOrder(c *gin.Context) {
|
||||||
req := controllers.GetRequest(c).(*front.QueryReqs)
|
req := controllers.GetRequest(c).(*front.QueryReqs)
|
||||||
|
@ -62,7 +80,7 @@ func QueryOrder(c *gin.Context) {
|
||||||
controllers.ApiRes(c, nil, code)
|
controllers.ApiRes(c, nil, code)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data := api.NewOrdersResp(&order)
|
data := thirdpay.NewOrdersResp(&order)
|
||||||
encryptData, errCode := api.EnCrypt(appCheckInfo.App, data)
|
encryptData, errCode := api.EnCrypt(appCheckInfo.App, data)
|
||||||
if errCode != errorcode.Success {
|
if errCode != errorcode.Success {
|
||||||
controllers.ApiRes(c, nil, errCode)
|
controllers.ApiRes(c, nil, errCode)
|
||||||
|
|
|
@ -65,6 +65,8 @@ func WxCallback(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifyReqJson, _ := json.Marshal(notifyReq)
|
||||||
|
logger.Info(c, "WxCallback-解析微信回调请求的参数到 V3NotifyReq 结构体", string(notifyReqJson))
|
||||||
err = paymentService.WxPayCallBack(notifyReq, wxConfig)
|
err = paymentService.WxPayCallBack(notifyReq, wxConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(c, "WxCallback-回调执行失败,失败原因:", err.Error())
|
logger.Error(c, "WxCallback-回调执行失败,失败原因:", err.Error())
|
||||||
|
@ -72,9 +74,6 @@ func WxCallback(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ====↓↓↓====异步通知应答====↓↓↓====
|
|
||||||
// 退款通知http应答码为200且返回状态码为SUCCESS才会当做商户接收成功,否则会重试。
|
|
||||||
// 注意:重试过多会导致微信支付端积压过多通知而堵塞,影响其他正常通知。
|
|
||||||
c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})
|
c.JSON(http.StatusOK, &wechat.V3NotifyRsp{Code: gopay.SUCCESS, Message: "成功"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -105,34 +104,27 @@ func AliCallback(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var aliConfig paymentService.AliPay
|
var aliConfig paymentService.AliPay
|
||||||
var aliConfigModel struct {
|
err := json.Unmarshal([]byte(payChannelModel.ExtJson), &aliConfig)
|
||||||
PrivateKey string `json:"private_key"` // 应用私钥
|
|
||||||
AppPublicCert string `json:"app_public_cert"` // 应用公钥
|
|
||||||
AlipayRootCert string `json:"alipay_root_cert"` // 支付宝根证书
|
|
||||||
AlipayPublicCert string `json:"alipay_public_cert"` // 支付宝公钥
|
|
||||||
}
|
|
||||||
err := json.Unmarshal([]byte(payChannelModel.ExtJson), &aliConfigModel)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(c, "AliCallback-回调数据解析支付配置错误", fmt.Sprintf("错误原因:%s", err.Error()))
|
logger.Error(c, "AliCallback-回调数据解析支付配置错误", fmt.Sprintf("错误原因:%s", err.Error()))
|
||||||
c.String(http.StatusBadRequest, "%s", "fail")
|
c.String(http.StatusBadRequest, "%s", "fail")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if aliConfigModel.AlipayPublicCert == "" || aliConfigModel.PrivateKey == "" || aliConfigModel.AppPublicCert == "" || aliConfigModel.AlipayRootCert == "" {
|
if aliConfig.AlipayPublicCert == "" || aliConfig.PrivateKey == "" || aliConfig.AppPublicCert == "" || aliConfig.AlipayRootCert == "" {
|
||||||
logger.Error(c, "AliCallback-回调数据解析支付配置错误,解析出来的信息为空")
|
logger.Error(c, "AliCallback-回调数据解析支付配置错误,解析出来的信息为空")
|
||||||
c.String(http.StatusBadRequest, "%s", "fail")
|
c.String(http.StatusBadRequest, "%s", "fail")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
aliConfig.AppId = payChannelModel.AppId
|
aliConfig.AppId = payChannelModel.AppId
|
||||||
aliConfig.PrivateKey = aliConfigModel.PrivateKey
|
|
||||||
aliConfig.AppPublicCert = aliConfigModel.AppPublicCert
|
|
||||||
aliConfig.AlipayRootCert = aliConfigModel.AlipayRootCert
|
|
||||||
aliConfig.AlipayPublicCert = aliConfigModel.AlipayPublicCert
|
|
||||||
|
|
||||||
notifyReq, err := alipay.ParseNotifyToBodyMap(c.Request) // c.Request 是 gin 框架的写法
|
notifyReq, err := alipay.ParseNotifyToBodyMap(c.Request) // c.Request 是 gin 框架的写法
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(http.StatusBadRequest, "%s", "fail")
|
c.String(http.StatusBadRequest, "%s", "fail")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
notifyReqJson, _ := json.Marshal(notifyReq)
|
||||||
|
logger.Info(c, "AliCallback-解析支付宝支付异步通知的参数到BodyMap", string(notifyReqJson))
|
||||||
err = paymentService.ALiCallBack(notifyReq, aliConfig)
|
err = paymentService.ALiCallBack(notifyReq, aliConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error(c, "AliCallback-回调执行失败,失败原因:", err.Error())
|
logger.Error(c, "AliCallback-回调执行失败,失败原因:", err.Error())
|
||||||
|
|
|
@ -96,5 +96,5 @@ func (a *AppUpdateRequest) RequestToDb() (db appmodel.App) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type GenerateDecryptKeyRequest struct {
|
type GenerateDecryptKeyRequest struct {
|
||||||
KeyType int `json:"key_type" label:"密钥类型"`
|
KeyType string `json:"key_type" form:"key_type" label:"密钥类型"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,16 +12,25 @@ type RequestBody struct {
|
||||||
Key string `json:"key" validate:"max=32"`
|
Key string `json:"key" validate:"max=32"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PayReqs struct {
|
type PayCommonReqBody struct {
|
||||||
ApiCommonBody
|
ApiCommonBody
|
||||||
PayChannelId int64 `json:"pay_channel_id" validate:"required" label:"支付渠道"`
|
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:"支付金额,单位分"`
|
Amount int `json:"amount" validate:"required" label:"支付金额,单位分"`
|
||||||
ExtJson string `json:"ext_json" label:"扩展参数"`
|
ExtJson string `json:"ext_json" label:"扩展参数"`
|
||||||
Desc string `json:"desc" validate:"max=100" label:"商品描述"`
|
Desc string `json:"desc" validate:"max=100" label:"商品描述"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PayReqs struct {
|
||||||
|
PayCommonReqBody
|
||||||
|
OutTradeNo string `json:"out_trade_no" validate:"required" label:"外侧商户订单号"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RefundReqs struct {
|
||||||
|
PayCommonReqBody
|
||||||
|
OutTradeNo string `json:"out_trade_no" label:"外侧商户订单号"`
|
||||||
|
OrderId string `json:"order_id" label:"平台订单号"`
|
||||||
|
}
|
||||||
|
|
||||||
type PayUrlResp struct {
|
type PayUrlResp struct {
|
||||||
Order string `json:"order"`
|
Order string `json:"order"`
|
||||||
Url string `json:"url"`
|
Url string `json:"url"`
|
||||||
|
|
|
@ -149,7 +149,6 @@ func ValidatePayRequest() gin.HandlerFunc {
|
||||||
//获取app信息
|
//获取app信息
|
||||||
appCheck := services.GetAppCheck(requestDataStruct.AppId, c.ClientIP())
|
appCheck := services.GetAppCheck(requestDataStruct.AppId, c.ClientIP())
|
||||||
//存入请求记录
|
//存入请求记录
|
||||||
|
|
||||||
if appCheck.Code != errorcode.Success {
|
if appCheck.Code != errorcode.Success {
|
||||||
controllers.ApiRes(c, nil, appCheck.Code)
|
controllers.ApiRes(c, nil, appCheck.Code)
|
||||||
return
|
return
|
||||||
|
|
|
@ -6,7 +6,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var FrontRequestMap = map[string]func() interface{}{
|
var FrontRequestMap = map[string]func() interface{}{
|
||||||
common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.PayReqs) },
|
common.FRONT_V1 + "/pay/url": func() interface{} { return new(front.PayReqs) },
|
||||||
|
common.FRONT_V1 + "/pay/refund": func() interface{} { return new(front.RefundReqs) },
|
||||||
}
|
}
|
||||||
|
|
||||||
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
var FrontRequestMapBeforeDecrypt = map[string]func() interface{}{
|
||||||
|
|
|
@ -60,6 +60,7 @@ func RegisterRoute(router *gin.Engine) {
|
||||||
{
|
{
|
||||||
pay.POST("/url", front.PayUrl)
|
pay.POST("/url", front.PayUrl)
|
||||||
pay.POST("/query", front.QueryOrder) //查询订单
|
pay.POST("/query", front.QueryOrder) //查询订单
|
||||||
|
pay.POST("/refund", front.Refund)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,21 @@ var (
|
||||||
|
|
||||||
// 实体
|
// 实体
|
||||||
type Orders struct {
|
type Orders struct {
|
||||||
Id int64
|
Id int64
|
||||||
MerchantId int64 `xorm:"'merchant_id' bigint(20)"`
|
MerchantId int64 `xorm:"'merchant_id' bigint(20)"`
|
||||||
PayChannelId int64 `xorm:"'pay_channel_id' bigint(20)"`
|
PayChannelId int64 `xorm:"'pay_channel_id' bigint(20)"`
|
||||||
AppId int64 `xorm:"'app_id' bigint(20)"`
|
AppId int64 `xorm:"'app_id' bigint(20)"`
|
||||||
OutTreadNo string `xorm:"'out_tread_no' varchar(50)"`
|
OutTreadNo string `xorm:"'out_tread_no' varchar(50)"`
|
||||||
OrderType int `xorm:"'order_type' TINYINT"`
|
OrderType int `xorm:"'order_type' TINYINT"`
|
||||||
Amount int `xorm:"'amount' int(11)"`
|
RefundOrderId int64 `xorm:"'refund_order_id' bigint(20)"`
|
||||||
PayerTotal int `xorm:"'payer_total' int(11)"`
|
Amount int `xorm:"'amount' int(11)"`
|
||||||
ExtJson string `xorm:"'ext_json' varchar(1024)"`
|
PayerTotal int `xorm:"'payer_total' int(11)"`
|
||||||
Desc string `xorm:"'desc' varchar(100)"`
|
ExtJson string `xorm:"'ext_json' varchar(1024)"`
|
||||||
CreateTime time.Time `xorm:"'create_time' datetime created"`
|
Desc string `xorm:"'desc' varchar(100)"`
|
||||||
UpdateTime time.Time `xorm:"'update_time' timestamp updated"`
|
CreateTime time.Time `xorm:"'create_time' datetime created"`
|
||||||
Status int `xorm:"'status' TINYINT"`
|
UpdateTime time.Time `xorm:"'update_time' timestamp updated"`
|
||||||
DeleteTime time.Time `xorm:"'delete_time' timestamp deleted"`
|
Status int `xorm:"'status' TINYINT"`
|
||||||
|
DeleteTime time.Time `xorm:"'delete_time' timestamp deleted"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OrdersBackendList struct {
|
type OrdersBackendList struct {
|
||||||
|
|
|
@ -18,7 +18,7 @@ func (r *SM2) Encrypt(data []byte) (encryptData []byte, errCode int) {
|
||||||
return nil, errorcode.AppSM2EncryptKeyNotFound
|
return nil, errorcode.AppSM2EncryptKeyNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptDataString, err := sm2.SM2Encrypt(string(data), r.App.PrivateKey)
|
encryptDataString, err := sm2.SM2Encrypt(string(data), r.App.MerchantPublicKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errorcode.AppSM2EncryptFail
|
return nil, errorcode.AppSM2EncryptFail
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,6 +105,7 @@ func CheckApp(appCheckIn *AppCheck) {
|
||||||
appCheckIn.App, errCode = AppFindOne(entities.IdRequest{Id: appCheckIn.AppId})
|
appCheckIn.App, errCode = AppFindOne(entities.IdRequest{Id: appCheckIn.AppId})
|
||||||
if errCode != errorcode.Success {
|
if errCode != errorcode.Success {
|
||||||
appCheckIn.Code = errCode
|
appCheckIn.Code = errCode
|
||||||
|
return
|
||||||
}
|
}
|
||||||
//检查app可用性
|
//检查app可用性
|
||||||
appCheckIn.Check()
|
appCheckIn.Check()
|
||||||
|
|
|
@ -100,7 +100,7 @@ func PayChannelFindOne(channel *paychannelmodel.PayChannel, conn builder.Cond, c
|
||||||
channelInfo, err := repo.PayChannelFindOne(channel, conn, col...)
|
channelInfo, err := repo.PayChannelFindOne(channel, conn, col...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
return nil, errorcode.MerchantNotFound
|
return nil, errorcode.PayChannelNotFound
|
||||||
}
|
}
|
||||||
return nil, errorcode.SystemError
|
return nil, errorcode.SystemError
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
|
||||||
"PaymentCenter/app/models/ordersmodel"
|
|
||||||
)
|
|
||||||
|
|
||||||
type OrdersResp struct {
|
type OrdersResp struct {
|
||||||
OrderNo int64 `json:"order_no"`
|
OrderNo int64 `json:"order_no"`
|
||||||
OrderType int `json:"order_type"`
|
OrderType int `json:"order_type"`
|
||||||
|
@ -20,18 +16,6 @@ type OrdersWithUrl struct {
|
||||||
Url string
|
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 {
|
func (o *OrdersResp) WithUrl(url string) *OrdersWithUrl {
|
||||||
return &OrdersWithUrl{
|
return &OrdersWithUrl{
|
||||||
Order: o,
|
Order: o,
|
||||||
|
|
|
@ -3,6 +3,7 @@ package do
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/constants/common"
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/constants/errorcode"
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/models/merchantmodel"
|
||||||
"PaymentCenter/app/models/paychannelmodel"
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
"PaymentCenter/app/third/paymentService/payCommon"
|
"PaymentCenter/app/third/paymentService/payCommon"
|
||||||
|
@ -12,6 +13,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Pay struct {
|
type Pay struct {
|
||||||
|
Merchant *merchantmodel.Merchant
|
||||||
|
Channel *paychannelmodel.PayChannel
|
||||||
|
|
||||||
paycheck *PayCheck
|
paycheck *PayCheck
|
||||||
Order *ordersmodel.Orders
|
Order *ordersmodel.Orders
|
||||||
PayCode int
|
PayCode int
|
||||||
|
@ -25,16 +29,20 @@ func NewPay(paycheck *PayCheck) *Pay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *Pay) CreateOrder() {
|
func (w *Pay) CreateOrder(order_type int) {
|
||||||
|
if _, ok := common.OrderTypeList[order_type]; !ok { //判断是否是支持的支付渠道
|
||||||
|
w.PayCode = errorcode.PayChannelNotFound
|
||||||
|
return
|
||||||
|
}
|
||||||
w.Order, w.PayCode = services.OrderCreate(&ordersmodel.Orders{
|
w.Order, w.PayCode = services.OrderCreate(&ordersmodel.Orders{
|
||||||
MerchantId: w.paycheck.Merchant.Id,
|
MerchantId: w.paycheck.Merchant.Id,
|
||||||
PayChannelId: w.paycheck.Channel.Id,
|
PayChannelId: w.paycheck.Channel.Id,
|
||||||
AppId: w.paycheck.Channel.Id,
|
AppId: w.paycheck.Channel.Id,
|
||||||
OutTreadNo: w.paycheck.WebPayReqs.OutTradeNo,
|
OutTreadNo: w.paycheck.Reqs.OutTradeNo,
|
||||||
OrderType: w.paycheck.WebPayReqs.OrderType,
|
OrderType: order_type,
|
||||||
Amount: w.paycheck.WebPayReqs.Amount,
|
Amount: w.paycheck.Reqs.Amount,
|
||||||
ExtJson: w.paycheck.WebPayReqs.ExtJson,
|
ExtJson: w.paycheck.Reqs.ExtJson,
|
||||||
Desc: w.paycheck.WebPayReqs.Desc,
|
Desc: w.paycheck.Reqs.Desc,
|
||||||
Status: common.ORDER_STATUS_WAITPAY,
|
Status: common.ORDER_STATUS_WAITPAY,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -46,7 +54,7 @@ func (w *Pay) PayUrl() (url string) {
|
||||||
ok bool
|
ok bool
|
||||||
)
|
)
|
||||||
thirdPay := &paymentService.PayOrderRequest{
|
thirdPay := &paymentService.PayOrderRequest{
|
||||||
PayChannelId: w.paycheck.WebPayReqs.PayChannelId,
|
PayChannelId: w.paycheck.Reqs.PayChannelId,
|
||||||
OrderId: w.Order.Id,
|
OrderId: w.Order.Id,
|
||||||
ChannelType: w.paycheck.Channel.ChannelType,
|
ChannelType: w.paycheck.Channel.ChannelType,
|
||||||
Description: w.Order.Desc,
|
Description: w.Order.Desc,
|
||||||
|
@ -77,3 +85,37 @@ func (w *Pay) PayUrl() (url string) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Pay) Refund() {
|
||||||
|
var (
|
||||||
|
refundFunc func(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error
|
||||||
|
ok bool
|
||||||
|
)
|
||||||
|
thirdPayRefund := &paymentService.OrderRefundRequest{
|
||||||
|
OrderId: w.Order.Id,
|
||||||
|
RefundOrderId: w.paycheck.OldOrder.Id,
|
||||||
|
RefundReason: w.paycheck.Reqs.Desc,
|
||||||
|
RefundAmount: int64(w.paycheck.Reqs.Amount),
|
||||||
|
PayChannel: w.paycheck.Channel.ChannelType,
|
||||||
|
}
|
||||||
|
if refundFunc, ok = RefundWayList[w.paycheck.Channel.ChannelType]; !ok {
|
||||||
|
w.PayCode = errorcode.PayChannelNotBuild
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := refundFunc(thirdPayRefund, w.paycheck.Channel)
|
||||||
|
if err != nil {
|
||||||
|
w.PayCode = errorcode.PayChannelExtJsonError
|
||||||
|
return
|
||||||
|
}
|
||||||
|
res := paymentService.OrderRefund(*w.paycheck.ctx, *thirdPayRefund)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
w.PayCode = errorcode.PreRefundFail
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"PaymentCenter/app/constants/common"
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/constants/errorcode"
|
"PaymentCenter/app/constants/errorcode"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
|
"PaymentCenter/app/services/thirdpay/types"
|
||||||
"xorm.io/builder"
|
"xorm.io/builder"
|
||||||
|
|
||||||
"PaymentCenter/app/http/entities/front"
|
|
||||||
"PaymentCenter/app/models/merchantmodel"
|
"PaymentCenter/app/models/merchantmodel"
|
||||||
"PaymentCenter/app/models/orderrequestlogmodel"
|
"PaymentCenter/app/models/orderrequestlogmodel"
|
||||||
"PaymentCenter/app/models/ordersmodel"
|
"PaymentCenter/app/models/ordersmodel"
|
||||||
|
@ -16,7 +16,7 @@ import (
|
||||||
|
|
||||||
type PayCheck struct {
|
type PayCheck struct {
|
||||||
ctx *context.Context
|
ctx *context.Context
|
||||||
WebPayReqs *front.PayReqs
|
Reqs *types.Reqs
|
||||||
AppCheck *services.AppCheck
|
AppCheck *services.AppCheck
|
||||||
RequestLog *orderrequestlogmodel.OrderRequestLog
|
RequestLog *orderrequestlogmodel.OrderRequestLog
|
||||||
Channel *paychannelmodel.PayChannel
|
Channel *paychannelmodel.PayChannel
|
||||||
|
@ -25,29 +25,32 @@ type PayCheck struct {
|
||||||
CheckCode int
|
CheckCode int
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPayCheck(ctx *context.Context, reqs *front.PayReqs, appCheck *services.AppCheck, ip string) *PayCheck {
|
func NewPayCheck(ctx *context.Context, reqs *types.Reqs, appCheck *services.AppCheck, ip string) *PayCheck {
|
||||||
if appCheck == nil {
|
if appCheck == nil {
|
||||||
appCheck = services.GetAppCheck(reqs.AppId, ip)
|
appCheck = services.GetAppCheck(reqs.AppId, ip)
|
||||||
}
|
}
|
||||||
return &PayCheck{
|
return &PayCheck{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
WebPayReqs: reqs,
|
Reqs: reqs,
|
||||||
AppCheck: appCheck,
|
AppCheck: appCheck,
|
||||||
CheckCode: appCheck.Code,
|
CheckCode: appCheck.Code,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PayCheck) CheckForm() {
|
func (w *PayCheck) CheckPayInfo() {
|
||||||
if _, ok := common.OrderTypeList[w.WebPayReqs.OrderType]; !ok { //判断是否是支持的支付渠道
|
w.CheckMerchant()
|
||||||
w.CheckCode = errorcode.PayChannelNotFound
|
if w.CheckCode != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.CheckPayChannel()
|
||||||
|
if w.CheckCode != errorcode.Success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PayCheck) CheckPayChannel() {
|
func (w *PayCheck) CheckPayChannel() {
|
||||||
conn := builder.NewCond()
|
conn := builder.NewCond()
|
||||||
conn = conn.And(builder.Eq{"id": w.WebPayReqs.PayChannelId})
|
conn = conn.And(builder.Eq{"id": w.Reqs.PayChannelId})
|
||||||
w.Channel, w.CheckCode = services.GetAndCheckPayChannel(&paychannelmodel.PayChannel{}, conn)
|
w.Channel, w.CheckCode = services.GetAndCheckPayChannel(&paychannelmodel.PayChannel{}, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,9 +60,45 @@ func (w *PayCheck) CheckMerchant() {
|
||||||
w.Merchant, w.CheckCode = services.GetAndCheckMerchant(&merchantmodel.Merchant{}, conn)
|
w.Merchant, w.CheckCode = services.GetAndCheckMerchant(&merchantmodel.Merchant{}, conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *PayCheck) CheckOrder() {
|
func (w *PayCheck) CheckOrderPay() {
|
||||||
|
w.GetOrder()
|
||||||
|
if w.OldOrder != nil {
|
||||||
|
switch w.OldOrder.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
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PayCheck) CheckOrderRefund() {
|
||||||
|
w.GetOrder()
|
||||||
|
if w.OldOrder == nil {
|
||||||
|
w.CheckCode = errorcode.OrdersNotFound
|
||||||
|
}
|
||||||
|
switch w.OldOrder.Status {
|
||||||
|
case common.ORDER_STATUS_CLOSE:
|
||||||
|
w.CheckCode = errorcode.OrderClosed
|
||||||
|
case common.ORDER_STATUS_FAILED:
|
||||||
|
w.CheckCode = errorcode.OrderFailed
|
||||||
|
case common.ORDER_STATUS_WAITPAY:
|
||||||
|
w.CheckCode = errorcode.OrderStatusErr
|
||||||
|
case common.ORDER_STATUS_PAYING:
|
||||||
|
w.CheckCode = errorcode.OrderStatusErr
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *PayCheck) GetOrder() {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
cond = cond.And(builder.Eq{"out_tread_no": w.WebPayReqs.OutTradeNo}, builder.Eq{"app_id": w.AppCheck.AppId})
|
cond = cond.And(builder.Eq{"out_tread_no": w.Reqs.OutTradeNo}, builder.Eq{"app_id": w.AppCheck.AppId})
|
||||||
order, code := services.OrderFindOne(&ordersmodel.Orders{}, cond)
|
order, code := services.OrderFindOne(&ordersmodel.Orders{}, cond)
|
||||||
if code == errorcode.SystemError {
|
if code == errorcode.SystemError {
|
||||||
w.CheckCode = code
|
w.CheckCode = code
|
||||||
|
@ -67,15 +106,6 @@ func (w *PayCheck) CheckOrder() {
|
||||||
}
|
}
|
||||||
if code == errorcode.OrdersExist {
|
if code == errorcode.OrdersExist {
|
||||||
w.OldOrder = order
|
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
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package do
|
||||||
|
|
||||||
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
|
"PaymentCenter/app/models/paychannelmodel"
|
||||||
|
"PaymentCenter/app/third/paymentService"
|
||||||
|
"github.com/bytedance/sonic"
|
||||||
|
)
|
||||||
|
|
||||||
|
var RefundWayList = map[int]func(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error{
|
||||||
|
common.PAY_CHANNEL_WECHAT_H5: WechatH5Refund,
|
||||||
|
common.PAY_CHANNEL_ALIPAY_WEB: AlipayWebRefund,
|
||||||
|
}
|
||||||
|
|
||||||
|
func WechatH5Refund(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error {
|
||||||
|
err := sonic.Unmarshal([]byte(channel.ExtJson), &commonRefundInfo.Wx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
commonRefundInfo.Wx.AppId = channel.AppId
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AlipayWebRefund(commonRefundInfo *paymentService.OrderRefundRequest, channel *paychannelmodel.PayChannel) error {
|
||||||
|
err := sonic.Unmarshal([]byte(channel.ExtJson), &commonRefundInfo.Ali)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
commonRefundInfo.Ali.AppId = channel.AppId
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,47 +1,79 @@
|
||||||
package thirdpay
|
package thirdpay
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
"PaymentCenter/app/constants/errorcode"
|
"PaymentCenter/app/constants/errorcode"
|
||||||
"PaymentCenter/app/http/entities/front"
|
"PaymentCenter/app/http/entities/front"
|
||||||
|
"PaymentCenter/app/models/ordersmodel"
|
||||||
"PaymentCenter/app/services"
|
"PaymentCenter/app/services"
|
||||||
|
"PaymentCenter/app/services/thirdpay/api"
|
||||||
thirdpay "PaymentCenter/app/services/thirdpay/do"
|
thirdpay "PaymentCenter/app/services/thirdpay/do"
|
||||||
|
"PaymentCenter/app/services/thirdpay/types"
|
||||||
"context"
|
"context"
|
||||||
|
"github.com/jinzhu/copier"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ThirdPayWeb(check *thirdpay.PayCheck) *thirdpay.Pay {
|
func ThirdPayUrl(check *thirdpay.PayCheck) *thirdpay.Pay {
|
||||||
pay := thirdpay.NewPay(check)
|
pay := ThirdPay(check)
|
||||||
// 创建订单
|
|
||||||
if &check.OldOrder != nil {
|
|
||||||
pay.CreateOrder()
|
|
||||||
if pay.PayCode != errorcode.Success {
|
|
||||||
return pay
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
pay.Order = check.OldOrder
|
|
||||||
}
|
|
||||||
// 支付
|
// 支付
|
||||||
pay.PayUrl()
|
pay.PayUrl()
|
||||||
return pay
|
return pay
|
||||||
}
|
}
|
||||||
|
|
||||||
func ThirdPayInfoCheck(ctx context.Context, req *front.PayReqs, appCheck *services.AppCheck, ip string) (check *thirdpay.PayCheck) {
|
func NewOrdersResp(db *ordersmodel.Orders) *api.OrdersResp {
|
||||||
check = thirdpay.NewPayCheck(&ctx, req, appCheck, ip)
|
return &api.OrdersResp{
|
||||||
// 校验表单
|
OrderNo: db.Id,
|
||||||
check.CheckForm()
|
OutTreadNo: db.OutTreadNo,
|
||||||
if check.CheckCode != errorcode.Success {
|
Status: db.Status,
|
||||||
return
|
OrderType: db.OrderType,
|
||||||
|
Amount: db.Amount,
|
||||||
|
Desc: db.Desc,
|
||||||
|
CreateTime: db.CreateTime.Format("2006-01-02 15:04:05"),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 校验商户
|
func ThirdPayInfoCheck(ctx context.Context, payReq *front.PayReqs, appCheck *services.AppCheck, ip string) (check *thirdpay.PayCheck) {
|
||||||
check.CheckMerchant()
|
var req types.Reqs
|
||||||
if check.CheckCode != errorcode.Success {
|
copier.Copy(&req, payReq)
|
||||||
return
|
check = thirdpay.NewPayCheck(&ctx, &req, appCheck, ip)
|
||||||
}
|
// 校验表单
|
||||||
// 校验支付通道
|
check.CheckPayInfo()
|
||||||
check.CheckPayChannel()
|
|
||||||
if check.CheckCode != errorcode.Success {
|
if check.CheckCode != errorcode.Success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ThirdPayRefund(ctx context.Context, refundReq *front.RefundReqs, appCheck *services.AppCheck, ip string) (refund *thirdpay.Pay) {
|
||||||
|
var req types.Reqs
|
||||||
|
copier.Copy(req, refundReq)
|
||||||
|
check := thirdpay.NewPayCheck(&ctx, &req, appCheck, ip)
|
||||||
|
// 校验表单
|
||||||
|
check.CheckPayInfo()
|
||||||
|
if check.CheckCode != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
check.CheckOrderRefund()
|
||||||
|
if check.CheckCode != errorcode.Success {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
refund = thirdpay.NewPay(check)
|
||||||
|
refund.CreateOrder(common.ORDER_TYPE_REFUND)
|
||||||
|
refund.Refund()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ThirdPay(check *thirdpay.PayCheck) (pay *thirdpay.Pay) {
|
||||||
|
pay = thirdpay.NewPay(check)
|
||||||
|
// 创建订单
|
||||||
|
if &check.OldOrder != nil {
|
||||||
|
pay.CreateOrder(common.ORDER_TYPE_PAY)
|
||||||
|
if pay.PayCode != errorcode.Success {
|
||||||
|
return pay
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pay.Order = check.OldOrder
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package notify
|
package thirdpay_notify
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"PaymentCenter/app/constants/common"
|
"PaymentCenter/app/constants/common"
|
||||||
|
@ -15,7 +15,7 @@ import (
|
||||||
|
|
||||||
type OrderNotify struct {
|
type OrderNotify struct {
|
||||||
order *ordersmodel.Orders
|
order *ordersmodel.Orders
|
||||||
code int
|
Code int
|
||||||
app *appmodel.App
|
app *appmodel.App
|
||||||
|
|
||||||
OrderId int64
|
OrderId int64
|
||||||
|
@ -52,9 +52,9 @@ func NewOrderNotifyWithHandle(orderId int64, Status int, actualAmount int, msg s
|
||||||
Status: Status,
|
Status: Status,
|
||||||
ActualAmount: actualAmount,
|
ActualAmount: actualAmount,
|
||||||
Msg: msg,
|
Msg: msg,
|
||||||
code: errorcode.Success,
|
Code: errorcode.Success,
|
||||||
}
|
}
|
||||||
return orderNotify.handle()
|
return orderNotify.Handle()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OrderNotify) NotifyRespFail(errorCode int) *OrderNotifyResp {
|
func (o *OrderNotify) NotifyRespFail(errorCode int) *OrderNotifyResp {
|
||||||
|
@ -66,27 +66,27 @@ func (o *OrderNotify) NotifyRespFail(errorCode int) *OrderNotifyResp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OrderNotify) handle() (res *OrderNotifyResp) {
|
func (o *OrderNotify) Handle() (res *OrderNotifyResp) {
|
||||||
o.checkOrder()
|
o.checkOrder()
|
||||||
if o.code != errorcode.Success {
|
if o.Code != errorcode.Success {
|
||||||
return o.NotifyRespFail(o.code)
|
return o.NotifyRespFail(o.Code)
|
||||||
}
|
}
|
||||||
o.checkApp()
|
o.checkApp()
|
||||||
if o.code != errorcode.Success {
|
if o.Code != errorcode.Success {
|
||||||
return o.NotifyRespFail(o.code)
|
return o.NotifyRespFail(o.Code)
|
||||||
}
|
}
|
||||||
o.updateOrder()
|
o.updateOrder()
|
||||||
if o.code != errorcode.Success {
|
if o.Code != errorcode.Success {
|
||||||
return o.NotifyRespFail(o.code)
|
return o.NotifyRespFail(o.Code)
|
||||||
}
|
}
|
||||||
o.sendNotify(o.setBody())
|
o.sendNotify(o.setBody())
|
||||||
if o.code != errorcode.Success {
|
if o.Code != errorcode.Success {
|
||||||
return o.NotifyRespFail(o.code)
|
return o.NotifyRespFail(o.Code)
|
||||||
}
|
}
|
||||||
return &OrderNotifyResp{
|
return &OrderNotifyResp{
|
||||||
OrderId: o.OrderId,
|
OrderId: o.OrderId,
|
||||||
Send: true,
|
Send: true,
|
||||||
ErrCode: o.code,
|
ErrCode: o.Code,
|
||||||
Content: o,
|
Content: o,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +98,7 @@ func (o *OrderNotify) sendNotify(body *OrderNotifySendContent) {
|
||||||
headers["Content-Type"] = "application/json"
|
headers["Content-Type"] = "application/json"
|
||||||
resByte, err := httpclient.FastHttpPost(o.app.NotifyUrl, headers, bodyByte, 0)
|
resByte, err := httpclient.FastHttpPost(o.app.NotifyUrl, headers, bodyByte, 0)
|
||||||
if err != nil || string(resByte) != "success" {
|
if err != nil || string(resByte) != "success" {
|
||||||
o.code = errorcode.NotifySendFail
|
o.Code = errorcode.NotifySendFail
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -120,25 +120,25 @@ func (o *OrderNotify) setBody() *OrderNotifySendContent {
|
||||||
|
|
||||||
func (o *OrderNotify) updateOrder() {
|
func (o *OrderNotify) updateOrder() {
|
||||||
if _, ok := common.OrderStatusMap[o.Status]; !ok {
|
if _, ok := common.OrderStatusMap[o.Status]; !ok {
|
||||||
o.code = errorcode.OrderStatusErr
|
o.Code = errorcode.OrderStatusErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
o.order.Status = o.Status
|
o.order.Status = o.Status
|
||||||
o.code = services.OrderUpdate(o.order, "status")
|
o.Code = services.OrderUpdate(o.order, "status")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *OrderNotify) checkApp() {
|
func (o *OrderNotify) checkApp() {
|
||||||
o.app, o.code = services.AppFindOne(entities.IdRequest{Id: o.order.AppId})
|
o.app, o.Code = services.AppFindOne(entities.IdRequest{Id: o.order.AppId})
|
||||||
if o.code != errorcode.Success {
|
if o.Code != errorcode.Success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if o.app.DeleteTime.IsZero() {
|
if o.app.DeleteTime.IsZero() {
|
||||||
o.code = errorcode.AppDisabled
|
o.Code = errorcode.AppDisabled
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if o.app.NotifyUrl == "" {
|
if o.app.NotifyUrl == "" {
|
||||||
o.code = errorcode.AppNotifyUrlNotFound
|
o.Code = errorcode.AppNotifyUrlNotFound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,16 +149,16 @@ func (o *OrderNotify) checkOrder() {
|
||||||
cond := builder.NewCond()
|
cond := builder.NewCond()
|
||||||
cond = cond.And(builder.Eq{"id": o.OrderId})
|
cond = cond.And(builder.Eq{"id": o.OrderId})
|
||||||
|
|
||||||
o.order, o.code = services.OrderFindOne(&ordersmodel.Orders{}, cond)
|
o.order, o.Code = services.OrderFindOne(&ordersmodel.Orders{}, cond)
|
||||||
if o.code != errorcode.Success {
|
if o.Code != errorcode.Success {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if o.order.DeleteTime.IsZero() {
|
if o.order.DeleteTime.IsZero() {
|
||||||
o.code = errorcode.OrderIsDelete
|
o.Code = errorcode.OrderIsDelete
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if o.order.Status != common.ORDER_STATUS_PAYING {
|
if o.order.Status != common.ORDER_STATUS_PAYING {
|
||||||
o.code = errorcode.OrderStatusErr
|
o.Code = errorcode.OrderStatusErr
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
return
|
return
|
|
@ -1,10 +0,0 @@
|
||||||
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"`
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "PaymentCenter/app/http/entities/front"
|
||||||
|
|
||||||
|
type Reqs struct {
|
||||||
|
front.PayCommonReqBody
|
||||||
|
OutTradeNo string `json:"out_trade_no"`
|
||||||
|
}
|
|
@ -1,164 +0,0 @@
|
||||||
package openapiService
|
|
||||||
|
|
||||||
import (
|
|
||||||
"PaymentCenter/app/models/orderdetailsmodel"
|
|
||||||
"PaymentCenter/app/models/ordersmodel"
|
|
||||||
"PaymentCenter/app/models/usercouponmodel"
|
|
||||||
"PaymentCenter/app/utils"
|
|
||||||
"PaymentCenter/config"
|
|
||||||
"context"
|
|
||||||
"crypto/aes"
|
|
||||||
"encoding/base64"
|
|
||||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk/api"
|
|
||||||
"gitee.com/chengdu_blue_brothers/openapi-go-sdk/notify"
|
|
||||||
"net/http"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreatClient() (client *api.Client, err error) {
|
|
||||||
merchantId := config.GetConf().OpenApi.MerchantId
|
|
||||||
secretKey := config.GetConf().OpenApi.SecretKey
|
|
||||||
isProd := config.GetConf().OpenApi.IsProd
|
|
||||||
timeout := 10 * time.Second // 请求超时时间
|
|
||||||
|
|
||||||
client, err = api.NewClient(merchantId, secretKey, isProd, timeout)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return client, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type RechargeOrderReq struct {
|
|
||||||
OutTradeNo string
|
|
||||||
ProductId int
|
|
||||||
RechargeAccount string
|
|
||||||
AccountType int
|
|
||||||
Number int
|
|
||||||
}
|
|
||||||
|
|
||||||
func RechargeOrder(rechargeOrderReq RechargeOrderReq) (result *api.RechargeOrderResp, err error) {
|
|
||||||
req := &api.RechargeOrderReq{
|
|
||||||
OutTradeNo: rechargeOrderReq.OutTradeNo,
|
|
||||||
ProductId: rechargeOrderReq.ProductId,
|
|
||||||
RechargeAccount: rechargeOrderReq.RechargeAccount,
|
|
||||||
AccountType: 0,
|
|
||||||
Number: 1,
|
|
||||||
NotifyUrl: config.GetConf().OpenApi.NotifyUrl,
|
|
||||||
}
|
|
||||||
client, err := CreatClient()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result, err = client.RechargeOrder(context.Background(), req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if result.Code != api.CodeCreateOrderSuccess {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReCardOrder(CardOrderReq api.CardOrderReq) (result *api.CardOrderResp, err error) {
|
|
||||||
req := &api.CardOrderReq{
|
|
||||||
OutTradeNo: CardOrderReq.OutTradeNo,
|
|
||||||
ProductId: CardOrderReq.ProductId,
|
|
||||||
AccountType: 0,
|
|
||||||
Number: 1,
|
|
||||||
NotifyUrl: config.GetConf().OpenApi.NotifyUrl,
|
|
||||||
}
|
|
||||||
client, err := CreatClient()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
result, err = client.CardOrder(context.Background(), req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if result.Code != api.CodeCreateOrderSuccess {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func DecryptCard(encCode string) (decode string, err error) {
|
|
||||||
defer func() error {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
utils.Log(nil, "解密错误", err)
|
|
||||||
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}()
|
|
||||||
client, err := CreatClient()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
decryptedCode, err := decryptAES(encCode, client.GetSecretKey())
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return decryptedCode, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AES 解密
|
|
||||||
func decryptAES(encryptedData string, secretKey string) (string, error) {
|
|
||||||
// 第一步:对加密的卡密做base64 decode
|
|
||||||
encryptedBytes, err := base64.StdEncoding.DecodeString(encryptedData)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 第二步:使用aes-256-ecb解密
|
|
||||||
cipher, _ := aes.NewCipher([]byte(secretKey))
|
|
||||||
decrypted := make([]byte, len(encryptedBytes))
|
|
||||||
size := 16
|
|
||||||
for bs, be := 0, size; bs < len(encryptedBytes); bs, be = bs+size, be+size {
|
|
||||||
cipher.Decrypt(decrypted[bs:be], encryptedBytes[bs:be])
|
|
||||||
}
|
|
||||||
paddingSize := int(decrypted[len(decrypted)-1])
|
|
||||||
return string(decrypted[0 : len(decrypted)-paddingSize]), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ParseAndVerify(request *http.Request) (req *notify.OrderReq, err error) {
|
|
||||||
// 第一步:初使化client实例
|
|
||||||
merchantId := config.GetConf().OpenApi.MerchantId
|
|
||||||
secretKey := config.GetConf().OpenApi.SecretKey
|
|
||||||
client := notify.NewNotify(merchantId, secretKey)
|
|
||||||
|
|
||||||
// 第二步:验签并解析结果
|
|
||||||
req, err = client.ParseAndVerify(request)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// NotifyOperation /**
|
|
||||||
func NotifyOperation(order ordersmodel.Orders, req *notify.OrderReq) (err error) {
|
|
||||||
var session = ordersmodel.GetInstance().GetDb().NewSession()
|
|
||||||
session.Begin()
|
|
||||||
updateOrder := ordersmodel.Orders{Status: 3}
|
|
||||||
_, err = session.Where("Id = ?", order.Id).Update(&updateOrder)
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//卡密
|
|
||||||
if req.CardCode != "" {
|
|
||||||
//订单详情
|
|
||||||
updateOrderDetail := orderdetailsmodel.OrderDetails{Url: req.CardCode.Value()}
|
|
||||||
_, err = session.Where("OrderId = ?", order.Id).Update(&updateOrderDetail)
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userCouponDetail := usercouponmodel.UserCoupon{OrderInfo: req.CardCode.Value()}
|
|
||||||
_, err = session.Where("OrderId = ?", order.Id).Update(&userCouponDetail)
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
session.Commit()
|
|
||||||
return
|
|
||||||
}
|
|
|
@ -1,9 +1,13 @@
|
||||||
package paymentService
|
package paymentService
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/services/thirdpay/thirdpay_notify"
|
||||||
"PaymentCenter/app/third/paymentService/payCommon"
|
"PaymentCenter/app/third/paymentService/payCommon"
|
||||||
"PaymentCenter/config"
|
"PaymentCenter/config"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-pay/gopay"
|
"github.com/go-pay/gopay"
|
||||||
|
@ -99,7 +103,43 @@ func ALiCallBack(notifyReq gopay.BodyMap, aliConfig AliPay) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo 拼装数据触发下游回调,数据待定
|
// 拼装数据触发下游回调,触发下游回调
|
||||||
|
orderId, _ := strconv.Atoi(notifyReq.Get("out_trade_no"))
|
||||||
|
payerTotal, _ := strconv.Atoi(notifyReq.Get("buyer_pay_amount"))
|
||||||
|
// 订单状态
|
||||||
|
tradeStatus := notifyReq.Get("trade_status")
|
||||||
|
errCode := 0
|
||||||
|
msg := ""
|
||||||
|
switch tradeStatus {
|
||||||
|
case "TRADE_CLOSED":
|
||||||
|
errCode = errorcode.ParamError
|
||||||
|
msg = "未付款交易超时关闭,或支付完成后全额退款。"
|
||||||
|
case "TRADE_SUCCESS":
|
||||||
|
errCode = errorcode.Success
|
||||||
|
msg = "交易支付成功。"
|
||||||
|
case "TRADE_FINISHED":
|
||||||
|
errCode = errorcode.Success
|
||||||
|
msg = "交易结束,不可退款。"
|
||||||
|
}
|
||||||
|
if errCode == 0 {
|
||||||
|
// 等待买家付款,不走后续回调
|
||||||
|
return errors.New("订单状态异常,无法进行后续回调")
|
||||||
|
}
|
||||||
|
|
||||||
|
res := thirdpay_notify.NewOrderNotifyWithHandle(int64(orderId), errCode, payerTotal, msg)
|
||||||
|
merchantCallback, _ := json.Marshal(res)
|
||||||
|
// 记录日志
|
||||||
|
go func() {
|
||||||
|
payCallback, _ := json.Marshal(notifyReq)
|
||||||
|
payParam := ""
|
||||||
|
saveLog(int64(orderId), common.THIRD_ORDER_TYPE_CALL_BACK, string(payCallback), payParam, string(merchantCallback))
|
||||||
|
}()
|
||||||
|
|
||||||
|
if res.ErrCode != errorcode.Success {
|
||||||
|
logger.Error(context.Background(), "ALiCallBack 发生错误", fmt.Sprintf("回调时,下游处理订单失败,返回数据为:%s", string(merchantCallback)))
|
||||||
|
return errors.New("回调时,下游处理订单失败")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +167,7 @@ func ALiOrderQuery(ctx context.Context, aliConfig AliPay, OrderNo string) (PayOr
|
||||||
return PayOrderQueryInfo{}, err
|
return PayOrderQueryInfo{}, err
|
||||||
}
|
}
|
||||||
// 同步返回验签
|
// 同步返回验签
|
||||||
ok, err := alipay.VerifySyncSignWithCert(aliConfig.AlipayPublicCert, aliRsp.SignData, aliRsp.Sign)
|
ok, err := alipay.VerifySyncSignWithCert([]byte(aliConfig.AlipayPublicCert), aliRsp.SignData, aliRsp.Sign)
|
||||||
if err != nil || !ok {
|
if err != nil || !ok {
|
||||||
return PayOrderQueryInfo{}, errors.New(fmt.Sprintf("验签失败,失败原因:%s", err.Error()))
|
return PayOrderQueryInfo{}, errors.New(fmt.Sprintf("验签失败,失败原因:%s", err.Error()))
|
||||||
}
|
}
|
||||||
|
@ -141,6 +181,7 @@ func ALiOrderQuery(ctx context.Context, aliConfig AliPay, OrderNo string) (PayOr
|
||||||
tradeStateDesc = "交易支付成功"
|
tradeStateDesc = "交易支付成功"
|
||||||
case "REFUND":
|
case "REFUND":
|
||||||
tradeState = "REFUND"
|
tradeState = "REFUND"
|
||||||
|
tradeStateDesc = "转入退款"
|
||||||
case "WAIT_BUYER_PAY":
|
case "WAIT_BUYER_PAY":
|
||||||
tradeState = "NOTPAY"
|
tradeState = "NOTPAY"
|
||||||
tradeStateDesc = "交易创建,等待买家付款"
|
tradeStateDesc = "交易创建,等待买家付款"
|
||||||
|
|
|
@ -39,14 +39,6 @@ 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"`
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,9 +1,13 @@
|
||||||
package paymentService
|
package paymentService
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"PaymentCenter/app/constants/common"
|
||||||
|
"PaymentCenter/app/constants/errorcode"
|
||||||
|
"PaymentCenter/app/services/thirdpay/thirdpay_notify"
|
||||||
"PaymentCenter/app/third/paymentService/payCommon"
|
"PaymentCenter/app/third/paymentService/payCommon"
|
||||||
"PaymentCenter/config"
|
"PaymentCenter/config"
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/go-pay/gopay"
|
"github.com/go-pay/gopay"
|
||||||
|
@ -135,7 +139,40 @@ func WxPayCallBack(notifyReq *wechat.V3NotifyReq, wxConfig WxPay) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// todo 返回触发下游回调的格式
|
|
||||||
|
errCode := 0
|
||||||
|
msg := ""
|
||||||
|
// 订单状态
|
||||||
|
switch CallBackInfo.TradeState {
|
||||||
|
case "SUCCESS":
|
||||||
|
errCode = errorcode.Success
|
||||||
|
msg = "支付成功"
|
||||||
|
case "CLOSED":
|
||||||
|
errCode = errorcode.ParamError
|
||||||
|
msg = "已关闭"
|
||||||
|
case "REVOKED":
|
||||||
|
errCode = errorcode.ParamError
|
||||||
|
msg = "已撤销(付款码支付)"
|
||||||
|
case "PAYERROR":
|
||||||
|
errCode = errorcode.ParamError
|
||||||
|
msg = "支付失败(其他原因,如银行返回失败)"
|
||||||
|
}
|
||||||
|
|
||||||
|
// 触发下游回调的格式
|
||||||
|
orderId, _ := strconv.Atoi(CallBackInfo.OutTradeNo)
|
||||||
|
res := thirdpay_notify.NewOrderNotifyWithHandle(int64(orderId), errCode, int(CallBackInfo.Amount.PayerTotal), msg)
|
||||||
|
merchantCallback, _ := json.Marshal(res)
|
||||||
|
// 记录日志
|
||||||
|
go func() {
|
||||||
|
payCallback, _ := json.Marshal(CallBackInfo)
|
||||||
|
payParam := ""
|
||||||
|
saveLog(int64(orderId), common.THIRD_ORDER_TYPE_CALL_BACK, string(payCallback), payParam, string(merchantCallback))
|
||||||
|
}()
|
||||||
|
|
||||||
|
if res.ErrCode != errorcode.Success {
|
||||||
|
logger.Error(context.Background(), "WxPayCallBack 发生错误", fmt.Sprintf("回调时,下游处理订单失败,返回数据为:%s", string(merchantCallback)))
|
||||||
|
return errors.New("回调时,下游处理订单失败")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,3 +108,33 @@ func Decrypt(privateKeyPEM string, encryptedDataBase64 string) ([]byte, error) {
|
||||||
|
|
||||||
return decrypted, nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -41,20 +41,6 @@ func encrypt() string {
|
||||||
return base64.StdEncoding.EncodeToString(en)
|
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 {
|
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}"
|
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))
|
aes.Encrypt([]byte(data), []byte(aes.TestKey))
|
||||||
|
@ -69,3 +55,17 @@ func encryptWithAes() string {
|
||||||
|
|
||||||
return base64.StdEncoding.EncodeToString(en)
|
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)
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SELF_PRI = "EA7CB6F907A96264D6763F8C46AB96B476538D2ABC880A459E10BE5A1C30013D"
|
SELF_PRI = "BD13D44C74422F80ADDF54AD2DE2888C4092AF6F61E41FABADA6C47F17574A41"
|
||||||
|
|
||||||
SELF_PUB = "04363DF574D4FE34EE58FB8A3F7CB08E6CA5EBB3B7335CBAE10A2900551F6450AB3AD25DBC0A76EFA9E6D44D2C51E3027483F7BFD09996457888BAFD1AF673817F"
|
SELF_PUB = "04363DF574D4FE34EE58FB8A3F7CB08E6CA5EBB3B7335CBAE10A2900551F6450AB3AD25DBC0A76EFA9E6D44D2C51E3027483F7BFD09996457888BAFD1AF673817F"
|
||||||
)
|
)
|
||||||
|
@ -17,7 +17,20 @@ func TestGenerateSM2KeyPair(t *testing.T) {
|
||||||
|
|
||||||
// Print the private and public keys
|
// Print the private and public keys
|
||||||
fmt.Printf("Private Key: %s\n", privateKey)
|
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) {
|
func TestSM2Encrypt(t *testing.T) {
|
||||||
|
@ -34,7 +47,7 @@ func TestSM2Decrypt(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func encrypt() string {
|
func encrypt() string {
|
||||||
data := "{\"name\":\"张三\",\"sex\":1,\"is_human\":true}"
|
data := "{\"order_no\":5476377146882523228,\"order_type\":1,\"out_tread_no\":\"asdadasdas\",\"amount\":1,\"desc\":\"abc\",\"status\":2,\"create_time\":\"2024-08-08 14:47:35\"}"
|
||||||
en, err := SM2Encrypt(data, SELF_PUB)
|
en, err := SM2Encrypt(data, SELF_PUB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -82,6 +82,7 @@ require (
|
||||||
github.com/hetiansu5/accesslog v1.0.0 // indirect
|
github.com/hetiansu5/accesslog v1.0.0 // indirect
|
||||||
github.com/hetiansu5/cores v1.0.0 // indirect
|
github.com/hetiansu5/cores v1.0.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
github.com/inconshreveable/mousetrap v1.0.0 // indirect
|
||||||
|
github.com/jinzhu/copier v0.4.0 // indirect
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -443,6 +443,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f
|
||||||
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
|
||||||
|
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||||
|
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
|
|
Loading…
Reference in New Issue