印度包网
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.

238 lines
5.4 KiB

1 year ago
package base
import (
"bytes"
1 year ago
"encoding/json"
"errors"
"fmt"
"io"
"mime/multipart"
1 year ago
"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
type OPTType int
1 year ago
const (
HttpTypeInvalid HttpType = iota
1 year ago
HttpTypeJson
HttpTypeForm
HttpTypeMultiPartForm
HttpTypeGet // get请求
1 year ago
HttpTypeAll
)
const (
OPTPay OPTType = iota + 1
OPTWithdraw
OPTPayCB
OPTWithdrawCB
OPTQueryWithdraw
OPTQueryPay
)
3 months ago
const (
QueryStatusFail = iota + 1 // 查询到订单失败了或者提交失败
QueryStatusSuccess // 查询到订单提交成功
QueryStatusUnknown // 查询失败,状态未知,需要重新查询
QueryStatusOrderSuccess // 查询到订单支付成功
)
type QueryReq struct {
Channel int
OrderID string
APIOrderID string
}
1 year ago
type Base struct {
Channel values.PayWay
PayReq *pb.InnerRechargeReq
WithdrawReq *pb.InnerWithdrawReq
SignKey string
ShouldSignUpper bool
HttpType HttpType
ReqURL string
Opt OPTType // 1支付 2退出 3支付回调 4退出回调 5退出查询 6支付查询
Status int // 返回的状态
GetResp url.Values
Resp interface{}
CallbackReq interface{}
CallbackResp CallbackResp
QueryWithdrawResp QueryResp
QueryPayResp QueryResp
1 year ago
Sub
SubReq func() ([]byte, error) // 特殊处理一些非常规请求
SubCallbackDecode func([]byte) (string, error) // 特殊处理回调解析的方法
SignPassStr []string // 不参与签名的字段
KeyName string // 有时候有些渠道签名字段不一样
C *gin.Context
1 year ago
ReqData interface{}
3 months ago
QueryWithdrawReq *QueryReq
QueryPayReq *QueryReq
1 year ago
}
type CallbackResp struct {
Msg string
OrderID string
APIOrderID string
FailMessage string
Success bool
}
type QueryResp struct {
Msg string
OrderID string
APIOrderID string
Status int // 1成功 2失败 3处理中
}
1 year ago
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: OPTPay,
SignPassStr: []string{"sign"},
1 year ago
}
return base
}
func NewWithdrawBase(req *pb.InnerWithdrawReq) *Base {
values.PackWithdraw(req)
base := &Base{
Channel: values.PayWay(req.Channel),
WithdrawReq: req,
Opt: OPTWithdraw,
}
return base
}
func NewQueryWithdrawBase(req *pb.InnerWithdrawReq) *Base {
base := &Base{
Channel: values.PayWay(req.Channel),
WithdrawReq: req,
Opt: OPTQueryWithdraw,
}
return base
}
func NewQueryPayBase(req *pb.InnerWithdrawReq) *Base {
base := &Base{
Channel: values.PayWay(req.Channel),
WithdrawReq: req,
Opt: OPTQueryPay,
1 year ago
}
return base
}
func NewCallbackBase(opt OPTType) *Base {
1 year ago
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) {
if b.SubReq != nil {
return b.SubReq()
}
1 year ago
send := b.Sub.PackReq()
if send == nil {
1 year ago
return nil, errors.New("pay fail")
}
var req *http.Request
var err error
if b.HttpType == HttpTypeGet {
req, _ = http.NewRequest("GET", b.ReqURL, nil)
} else {
reqData := b.PackReq(send)
req, err = http.NewRequest("POST", b.ReqURL, reqData)
if err != nil {
log.Error("err:%v", err)
return nil, errors.New("pay fail")
}
}
1 year ago
b.PackHeader(req.Header)
b.Status = Request(req, b.Resp)
1 year ago
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{}) io.Reader {
1 year ago
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)
log.Debug("post to:%v,req:%v", b.ReqURL, string(reqData))
return bytes.NewBuffer(reqData)
1 year ago
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()))
}
str := data.Encode()
log.Debug("post to:%v,req:%v", b.ReqURL, str)
return strings.NewReader(str)
case HttpTypeMultiPartForm:
data := &bytes.Buffer{}
writer := multipart.NewWriter(data)
for i := 0; i < ref.NumField(); i++ {
if ref.Field(i).IsZero() {
continue
}
writer.WriteField(reft.Field(i).Tag.Get("json"), fmt.Sprintf("%v", ref.Field(i).Interface()))
}
log.Debug("post to:%v,req:%v", b.ReqURL, data.String())
return data
1 year ago
}
return nil
1 year ago
}
3 months ago
func (b *Base) GetPayCallbackURL() string {
return values.GetPayCallback(b.Channel)
}
func (b *Base) GetWithdrawCallbackURL() string {
return values.GetWithdrawCallback(b.Channel)
}