You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
2.9 KiB
142 lines
2.9 KiB
|
1 year ago
|
package base
|
||
|
|
|
||
|
|
import (
|
||
|
|
"encoding/json"
|
||
|
|
"errors"
|
||
|
|
"fmt"
|
||
|
|
"net/http"
|
||
|
|
"net/url"
|
||
|
|
"reflect"
|
||
|
|
"server/modules/pay/values"
|
||
|
|
"server/pb"
|
||
|
|
"strings"
|
||
|
|
|
||
|
|
"github.com/gin-gonic/gin"
|
||
|
|
"github.com/gogo/protobuf/proto"
|
||
|
|
"github.com/liangdas/mqant/log"
|
||
|
|
)
|
||
|
|
|
||
|
|
type HttpType int
|
||
|
|
|
||
|
|
const (
|
||
|
|
HttpTypeInvalid = iota
|
||
|
|
HttpTypeJson
|
||
|
|
HttpTypeForm
|
||
|
|
HttpTypeAll
|
||
|
|
)
|
||
|
|
|
||
|
|
type Base struct {
|
||
|
|
Channel values.PayWay
|
||
|
|
PayReq *pb.InnerRechargeReq
|
||
|
|
WithdrawReq *pb.InnerWithdrawReq
|
||
|
|
SignKey string
|
||
|
|
ShouldSignUpper bool
|
||
|
|
HttpType HttpType
|
||
|
|
ReqURL string
|
||
|
|
Opt int // 1支付 2退出
|
||
|
|
Status int // 返回的状态
|
||
|
|
Resp interface{}
|
||
|
|
CallbackReq interface{}
|
||
|
|
CallbackResp CallbackResp
|
||
|
|
SignPassStr []string // 不参与签名的字段
|
||
|
|
WhiteIPs []string // ip白名单
|
||
|
|
Sub
|
||
|
|
C *gin.Context
|
||
|
|
}
|
||
|
|
|
||
|
|
type CallbackResp struct {
|
||
|
|
Msg string
|
||
|
|
OrderID string
|
||
|
|
APIOrderID string
|
||
|
|
FailMessage string
|
||
|
|
Success bool
|
||
|
|
}
|
||
|
|
|
||
|
|
type Sub interface {
|
||
|
|
PackHeader(header http.Header) // 生成请求头
|
||
|
|
PackReq() interface{} // 生成支付请求体
|
||
|
|
GetResp() (proto.Message, error) // 获取返回
|
||
|
|
CheckSign(str string) bool // 验签同时给callbackresp赋值
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewRechargeBase(req *pb.InnerRechargeReq) *Base {
|
||
|
|
values.PackPay(req)
|
||
|
|
base := &Base{
|
||
|
|
Channel: values.PayWay(req.Channel),
|
||
|
|
PayReq: req,
|
||
|
|
Opt: 1,
|
||
|
|
}
|
||
|
|
return base
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewWithdrawBase(req *pb.InnerWithdrawReq) *Base {
|
||
|
|
values.PackWithdraw(req)
|
||
|
|
base := &Base{
|
||
|
|
Channel: values.PayWay(req.Channel),
|
||
|
|
WithdrawReq: req,
|
||
|
|
Opt: 2,
|
||
|
|
}
|
||
|
|
return base
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewCallbackBase(opt int) *Base {
|
||
|
|
base := &Base{
|
||
|
|
Opt: opt,
|
||
|
|
}
|
||
|
|
return base
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *Base) PackHeader(header http.Header) {
|
||
|
|
switch b.HttpType {
|
||
|
|
case HttpTypeJson:
|
||
|
|
header.Set("Content-Type", "application/json")
|
||
|
|
case HttpTypeForm:
|
||
|
|
header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||
|
|
}
|
||
|
|
b.Sub.PackHeader(header)
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *Base) Req() ([]byte, error) {
|
||
|
|
send := b.Sub.PackReq()
|
||
|
|
reqData := b.PackReq(send)
|
||
|
|
log.Debug("Req to:%v,req:%v", b.ReqURL, reqData)
|
||
|
|
req, err := http.NewRequest("POST", b.ReqURL, strings.NewReader(reqData))
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return nil, errors.New("pay fail")
|
||
|
|
}
|
||
|
|
b.PackHeader(req.Header)
|
||
|
|
b.Status = values.Post(req, b.Resp)
|
||
|
|
ret, err := b.Sub.GetResp()
|
||
|
|
if err != nil {
|
||
|
|
log.Error("err:%v", err)
|
||
|
|
return nil, err
|
||
|
|
}
|
||
|
|
data, _ := proto.Marshal(ret)
|
||
|
|
return data, nil
|
||
|
|
}
|
||
|
|
|
||
|
|
func (b *Base) PackReq(send interface{}) string {
|
||
|
|
ref := reflect.ValueOf(send)
|
||
|
|
reft := reflect.TypeOf(send)
|
||
|
|
if ref.Kind() == reflect.Ptr {
|
||
|
|
ref = ref.Elem()
|
||
|
|
reft = reft.Elem()
|
||
|
|
}
|
||
|
|
switch b.HttpType {
|
||
|
|
case HttpTypeJson:
|
||
|
|
reqData, _ := json.Marshal(send)
|
||
|
|
return string(reqData)
|
||
|
|
case HttpTypeForm:
|
||
|
|
data := url.Values{}
|
||
|
|
for i := 0; i < ref.NumField(); i++ {
|
||
|
|
if ref.Field(i).IsZero() {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
data.Set(reft.Field(i).Tag.Get("json"), fmt.Sprintf("%v", ref.Field(i).Interface()))
|
||
|
|
}
|
||
|
|
return data.Encode()
|
||
|
|
}
|
||
|
|
return ""
|
||
|
|
}
|