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.
141 lines
2.9 KiB
141 lines
2.9 KiB
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 "" |
|
}
|
|
|