190 lines
5.0 KiB
Go
190 lines
5.0 KiB
Go
package services
|
|
|
|
import (
|
|
"PaymentCenter/app/constants/common"
|
|
"PaymentCenter/app/constants/errorcode"
|
|
"PaymentCenter/app/http/entities"
|
|
"PaymentCenter/app/http/entities/backend"
|
|
"PaymentCenter/app/http/entities/front"
|
|
"PaymentCenter/app/models/ordersmodel"
|
|
"PaymentCenter/app/models/paychannelmodel"
|
|
"PaymentCenter/app/utils"
|
|
"PaymentCenter/config"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
"xorm.io/builder"
|
|
)
|
|
|
|
// 收银台支付渠道列表
|
|
func PayPageChannelList(reqParam front.PayChannelListRequest) (resultPayChannelList []paychannelmodel.PayChannel, code int) {
|
|
|
|
orderId, err := strconv.ParseInt(reqParam.OrderId, 10, 64)
|
|
if err != nil {
|
|
code = errorcode.ParamError
|
|
return
|
|
}
|
|
|
|
// 订单检查
|
|
orderInfo := &ordersmodel.Orders{Id: orderId}
|
|
orderInfo, code = OrderFindOne(orderInfo, builder.Eq{"id": orderId})
|
|
if code != errorcode.Success {
|
|
return
|
|
}
|
|
if !(orderInfo.Status == common.ORDER_STATUS_PAYING || orderInfo.Status == common.ORDER_STATUS_WAITPAY) {
|
|
code = errorcode.OrderStatusErr
|
|
return
|
|
}
|
|
|
|
// 商户拥有的支付渠道检查
|
|
req := backend.PayChannelListRequest{
|
|
MerchantId: orderInfo.MerchantId,
|
|
PageRequest: entities.PageRequest{},
|
|
}
|
|
payList := make([]paychannelmodel.PayChannel, 0)
|
|
payList, _, code = PayChannelList(req)
|
|
if code != errorcode.Success {
|
|
return
|
|
}
|
|
if len(payList) == 0 {
|
|
code = errorcode.PayChannelNotFound
|
|
return
|
|
}
|
|
merchantPayChannelMap := make(map[int]paychannelmodel.PayChannel, 0)
|
|
for _, pay := range payList {
|
|
merchantPayChannelMap[pay.ChannelType] = pay
|
|
}
|
|
|
|
// 客户端环境检查
|
|
openType := ClientEnvCheck(reqParam.UserAgent)
|
|
if channels, ok := common.OpenInPayChannelMap[openType]; !ok {
|
|
code = errorcode.ClientEnvErr
|
|
return
|
|
} else {
|
|
for _, channel := range channels {
|
|
if _, ok = merchantPayChannelMap[channel]; ok {
|
|
resultPayChannelList = append(resultPayChannelList, merchantPayChannelMap[channel])
|
|
}
|
|
}
|
|
}
|
|
|
|
return resultPayChannelList, code
|
|
}
|
|
|
|
// 客户端环境检查
|
|
func ClientEnvCheck(ua string) int {
|
|
if utils.IsWeChatClient(ua) {
|
|
return common.OpenInWeChat
|
|
} else if utils.IsPC(ua) {
|
|
return common.OpenInWindows
|
|
} else if utils.IsMobile(ua) {
|
|
return common.OpenInMobile
|
|
}
|
|
|
|
return common.OpenInUnknown
|
|
}
|
|
|
|
// 预支付
|
|
type payUrl struct {
|
|
ClientIp string
|
|
param front.PayReqsV2
|
|
app *AppCheck
|
|
result front.PayReqsV2Response
|
|
}
|
|
|
|
func NewPayUrl(param front.PayReqsV2) *payUrl {
|
|
return &payUrl{
|
|
param: param,
|
|
}
|
|
}
|
|
func (this *payUrl) WithApp(app *AppCheck) *payUrl {
|
|
this.app = app
|
|
return this
|
|
}
|
|
func (this *payUrl) WithClientIp(ip string) *payUrl {
|
|
this.ClientIp = ip
|
|
return this
|
|
}
|
|
|
|
// 订单存在
|
|
func (this *payUrl) orderExist() {
|
|
switch this.result.Order.Status {
|
|
case common.ORDER_STATUS_CLOSE:
|
|
this.result.PayCode = errorcode.OrderClosed
|
|
case common.ORDER_STATUS_PAYED:
|
|
this.result.PayCode = errorcode.OrderPayed
|
|
case common.ORDER_STATUS_FAILED:
|
|
this.result.PayCode = errorcode.OrderFailed
|
|
case common.ORDER_STATUS_WAITPAY, common.ORDER_STATUS_PAYING:
|
|
this.result.PayCode = errorcode.Success
|
|
default:
|
|
this.result.PayCode = errorcode.OrderStatusErr
|
|
}
|
|
}
|
|
|
|
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 = 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()))
|
|
}
|
|
return
|
|
}
|
|
|
|
// 商户是否有配置支付渠道
|
|
channelList, _, code = 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 = OrderFindOne(order, conn)
|
|
if code == errorcode.Success {
|
|
// 订单存在
|
|
this.result.Order = order
|
|
this.orderExist()
|
|
} 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 + "?id=" + strconv.FormatInt(this.result.Order.Id, 10)
|
|
}
|
|
|
|
return this.result, code
|
|
}
|