PaymentCenter/app/services/thirdpay/pay_page.go

233 lines
6.5 KiB
Go

package thirdpay
import (
"PaymentCenter/app/constants/common"
"PaymentCenter/app/constants/errorcode"
"PaymentCenter/app/http/entities/backend"
"PaymentCenter/app/http/entities/front"
"PaymentCenter/app/models/orderrequestlogmodel"
"PaymentCenter/app/models/ordersmodel"
"PaymentCenter/app/models/paychannelmodel"
"PaymentCenter/app/services"
"PaymentCenter/app/services/thirdpay/do"
"PaymentCenter/app/third/paymentService"
"PaymentCenter/app/third/paymentService/payCommon"
"PaymentCenter/app/utils"
"PaymentCenter/config"
"context"
"encoding/json"
"fmt"
"strconv"
"time"
"xorm.io/builder"
)
// 收银台获取付款链接
func GetPayLinkService(req front.GetPayLinkRequest) (result, message string, code int) {
defer func() {
if err := recover(); err != nil {
utils.Log(nil, "", "GetPayLinkService,获取支付链接失败", fmt.Sprintf("错误原因:%s", err))
code = errorcode.SystemError
}
}()
var (
payChannel = &paychannelmodel.PayChannel{}
order = &ordersmodel.Orders{}
orderPayRequest front.PayReqsV2
)
// 支付方式校验
payChannel, code = services.PayChannelFindOne(payChannel, builder.Eq{"id": req.PayChannelId})
if code != errorcode.Success {
return
}
if !payChannel.ExpireTime.IsZero() && payChannel.ExpireTime.Unix() < time.Now().Unix() {
code = errorcode.PayChannelExpired
return
}
// 订单校验
order, code = services.OrderFindOne(order, builder.Eq{"id": req.OrderId})
if code != errorcode.Success {
return
}
// 订单状态校验
code = services.OrderStatusCheck(*order)
if code != errorcode.Success {
return
}
// 订单的支付方式是否一致, 不一致则更新
if order.PayChannelId != payChannel.Id {
order.PayChannelId = payChannel.Id
code = services.OrderUpdate(order)
if code != errorcode.Success {
return
}
}
// 获取订单的请求参数
orderRequestLog := orderrequestlogmodel.OrderRequestLog{
OutTradeNo: order.OutTradeNo,
AppId: order.AppId,
}
has, err := services.OrderRequestLogs(&orderRequestLog)
if err != nil {
code = handErr(err)
return
}
if !has {
code = errorcode.OrderPayRequestLogNotExist
return
}
err = json.Unmarshal([]byte(orderRequestLog.MerchantRequest), &orderPayRequest)
if err != nil {
code = handErr(err)
return
}
// 支付方式需要用户授权
if payChannel.ChannelType == common.PAY_CHANNEL_WECHAT_JSAPI && orderPayRequest.OpenId == "" {
result, code = do.GetWxAuthUrl(payChannel.AppId, order.Id)
return
}
// 请求第三方支付获取付款链接
payParam := paymentService.PayOrderRequest{
PayChannelId: payChannel.Id,
OrderId: order.Id,
ChannelType: payChannel.ChannelType,
Description: orderPayRequest.Desc,
Amount: orderPayRequest.Amount,
PayerClientIp: req.ClientIp,
ReturnUrl: orderPayRequest.ReturnUrl,
OpenId: orderPayRequest.OpenId,
}
// 判断是否是支持的支付渠道,找到对应的配置
var payFunc func(commonPayInfo *paymentService.PayOrderRequest, channel *paychannelmodel.PayChannel) error
var ok bool
if payFunc, ok = do.PayWayList[payChannel.ChannelType]; !ok {
code = errorcode.PayChannelNotBuild
return
}
err = payFunc(&payParam, payChannel)
if err != nil {
code = errorcode.PayChannelExtJsonError
return
}
res := paymentService.PaymentService(context.Background(), payParam)
// 下单失败
if res.Code != payCommon.PAY_SUCCESS_CODE {
code = errorcode.PrePayFail
message = res.ErrorMsg
return
}
// 更新订单状态
order.Status = common.ORDER_STATUS_PAYING
code = services.OrderUpdate(order, "status")
if code != errorcode.Success {
utils.Log(nil, "成功下单,更新订单状态失败", order)
}
result = res.Result
code = res.Code
return
}
// 预支付
type payUrl struct {
ClientIp string
param front.PayReqsV2
app *services.AppCheck
result front.PayReqsV2Response
}
func NewPayUrl(param front.PayReqsV2) *payUrl {
return &payUrl{
param: param,
}
}
func (this *payUrl) WithApp(app *services.AppCheck) *payUrl {
this.app = app
return this
}
func (this *payUrl) WithClientIp(ip string) *payUrl {
this.ClientIp = ip
return this
}
func (this *payUrl) saveOrder() {
order := &ordersmodel.Orders{
MerchantId: this.app.App.MerchantId,
//PayChannelId: w.PayParam.Channel.Id,
AppId: this.app.App.Id,
OutTradeNo: this.param.OutTradeNo,
OrderType: common.ORDER_TYPE_PAY,
Amount: this.param.Amount,
ExtJson: this.param.ExtJson,
Desc: this.param.Desc,
Status: common.ORDER_STATUS_WAITPAY,
}
this.result.Order, this.result.PayCode = services.OrderCreate(order)
}
func (this *payUrl) PayUrlV2Service() (result front.PayReqsV2Response, code int) {
var (
channelList []paychannelmodel.PayChannel
order = new(ordersmodel.Orders)
)
// redis 分布式锁 订单号幂等
key := utils.GetRealKey("payUrl:" + this.param.OutTradeNo)
lockValue := fmt.Sprintf("%d", time.Now().UnixNano())
ok, err := utils.AcquireLock(key, lockValue, time.Second*time.Duration(3))
if ok {
defer utils.ReleaseLock(key, lockValue)
} else {
if err != nil {
utils.Log(nil, "", "PayUrlV2Service,获取分布式锁失败", fmt.Sprintf("错误原因:%s", err.Error()))
code = errorcode.SystemError
} else {
code = errorcode.OrderPayRequestAcquireLock
}
return
}
// 商户是否有配置支付渠道
channelList, _, code = services.PayChannelList(backend.PayChannelListRequest{MerchantId: this.app.App.MerchantId})
if code != errorcode.Success {
return
}
if len(channelList) == 0 {
code = errorcode.PayChannelNotFound
return
}
// 订单是否存在
conn := builder.NewCond()
conn = conn.And(builder.Eq{"out_trade_no": this.param.OutTradeNo})
conn = conn.And(builder.Eq{"app_id": this.param.AppId})
order, code = services.OrderFindOne(order, conn)
if code == errorcode.Success {
// 订单存在
this.result.Order = order
this.result.PayCode = services.OrderStatusCheck(*order)
} else if code == errorcode.OrdersNotFound {
// 订单不存在
this.saveOrder()
} else {
return
}
code = this.result.PayCode
if code == errorcode.Success {
this.result.Url = config.GetConf().PayService.Host + common.PayPageAddress + "?no=" + strconv.FormatInt(this.result.Order.Id, 10)
}
return this.result, code
}
func PayPageCheckOrder(orderId string) (order ordersmodel.Orders, code int) {
orderInfo := &ordersmodel.Orders{}
orderInfo, code = services.OrderFindOne(&ordersmodel.Orders{}, builder.Eq{"id": orderId})
if code != errorcode.Success {
return
}
code = services.OrderStatusCheck(*orderInfo)
return *orderInfo, code
}