diff --git a/gateway/controllers/gateway/payfor_controller_test.go b/gateway/controllers/gateway/payfor_controller_test.go new file mode 100644 index 0000000..92e2916 --- /dev/null +++ b/gateway/controllers/gateway/payfor_controller_test.go @@ -0,0 +1,74 @@ +package gateway + +import ( + "encoding/json" + "fmt" + "gateway/utils" + "io/ioutil" + "log" + "math/rand" + "net/http" + "testing" + "time" +) + +func TestPayFor(t *testing.T) { + u := "http://127.0.0.1:12309/gateway/payfor" + m := make(map[string]string) + m["merchantKey"] = "kkkkc254gk8isf001cqrj6p0" + m["realname"] = "11" + m["cardNo"] = "123" + m["accType"] = "private" + m["amount"] = "0.1" + merchantOrderId := GenerateOrderNo() + m["merchantOrderId"] = merchantOrderId + sec := "ssssc254gk8isf001cqrj6pg" + keys := utils.SortMap(m) + sign := utils.GetMD5Sign(m, keys, sec) + m["sign"] = sign + + m1 := make(map[string]interface{}) + marshal, _ := json.Marshal(m) + json.Unmarshal(marshal, &m1) + req := new(utils.Request) + req.SetParams(m1) + req.SetURL(u) + resp, err := req.GET() + if err != nil { + t.Fatal("err------>", err.Error()) + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + b, _ := ioutil.ReadAll(resp.Body) + + t.Fatal("返回的http状态码不是200,body:", string(b)) + } + b, _ := ioutil.ReadAll(resp.Body) + log.Println("result--------->", string(b)) + /** + result---------> { + "resultCode": "00", + "resultMsg": "银行处理中", + "settAmount": "0.1" + } + */ +} + +func GetTimeTick64() int64 { + return time.Now().UnixNano() / 1e6 +} + +func GetFormatTime(time time.Time) string { + return time.Format("20060102") +} + +// 基础做法 日期20191025时间戳1571987125435+3位随机数 +func GenerateOrderNo() string { + date := GetFormatTime(time.Now()) + r := rand.Intn(1000) + code := fmt.Sprintf("%s%d%03d", date, GetTimeTick64(), r) + return code +} +func TestGenerateCode(t *testing.T) { + GenerateOrderNo() +} diff --git a/gateway/go.mod b/gateway/go.mod index 3ceed71..d4d48ad 100644 --- a/gateway/go.mod +++ b/gateway/go.mod @@ -9,6 +9,5 @@ require ( github.com/go-sql-driver/mysql v1.5.0 github.com/go-stomp/stomp v2.1.4+incompatible github.com/rs/xid v1.3.0 - github.com/smartystreets/goconvey v1.6.4 github.com/widuu/gojson v0.0.0-20170212122013-7da9d2cd949b ) diff --git a/gateway/routers/router.go b/gateway/routers/router.go index ee878af..2ef8026 100644 --- a/gateway/routers/router.go +++ b/gateway/routers/router.go @@ -11,7 +11,7 @@ func init() { web.Router("/gateway/scan", &gateway.ScanController{}, "*:Scan") web.Router("/err/params", &gateway.ErrorGatewayController{}, "*:ErrorParams") //代付相关的接口 - web.Router("gateway/payfor", &gateway.PayForGateway{}, "*:PayFor") + web.Router("/gateway/payfor", &gateway.PayForGateway{}, "*:PayFor") web.Router("/gateway/payfor/query", &gateway.PayForGateway{}, "*:PayForQuery") web.Router("/gateway/balance", &gateway.PayForGateway{}, "*:Balance") // 接收银行回调 diff --git a/gateway/utils/http.go b/gateway/utils/http.go new file mode 100644 index 0000000..6536af6 --- /dev/null +++ b/gateway/utils/http.go @@ -0,0 +1,308 @@ +package utils + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "net/http" + "net/url" + "strings" + "time" +) + +// Request HTTP request +type Request struct { + customRequest func(req *http.Request, data *bytes.Buffer) // 用于定义HEADER, 如添加sign等 + url string + params map[string]interface{} // URL后的参数 + body string // Body数据 + bodyJSON interface{} // 可JSON Marshal 的Body的数据 + timeout time.Duration // Client timeout + headers map[string]string + + request *http.Request + response *Response + method string + err error +} + +// Response HTTP response +type Response struct { + *http.Response + err error +} + +// ==================================== Request ==================================== + +// Reset set all fields to default value, use at pool +func (req *Request) Reset() { + req.params = nil + req.body = "" + req.bodyJSON = nil + req.timeout = 0 + req.headers = nil + + req.request = nil + req.response = nil + req.method = "" + req.err = nil +} + +// SetURL 设置URL +func (req *Request) SetURL(path string) *Request { + req.url = path + return req +} + +// SetParams 设置URL后的参数 +func (req *Request) SetParams(params map[string]interface{}) *Request { + if req.params == nil { + req.params = params + } else { + for k, v := range params { + req.params[k] = v + } + } + return req +} + +// SetParam 设置URL后的参数 +func (req *Request) SetParam(k string, v interface{}) *Request { + if req.params == nil { + req.params = make(map[string]interface{}) + } + req.params[k] = v + return req +} + +// SetBody 设置Body数据 +func (req *Request) SetBody(body string) *Request { + req.body = body + return req +} + +// SetJSONBody 设置Body数据, JSON格式 +func (req *Request) SetJSONBody(body interface{}) *Request { + req.bodyJSON = body + return req +} + +// SetTimeout 超时时间 +func (req *Request) SetTimeout(t time.Duration) *Request { + req.timeout = t + return req +} + +// SetContentType 设置ContentType +func (req *Request) SetContentType(a string) *Request { + req.SetHeader("Content-Type", a) + return req +} + +// SetHeader 设置Request Header 的值 +func (req *Request) SetHeader(k, v string) *Request { + if req.headers == nil { + req.headers = make(map[string]string) + } + req.headers[k] = v + return req +} + +// CustomRequest 自定义Request +// 如添加sign, 设置header等 +func (req *Request) CustomRequest(f func(req *http.Request, data *bytes.Buffer)) *Request { + req.customRequest = f + return req +} + +// GET 发送GET请求 +func (req *Request) GET() (*Response, error) { + req.method = "GET" + return req.pull() +} + +// DELETE 发送DELETE请求 +func (req *Request) DELETE() (*Response, error) { + req.method = "DELETE" + return req.pull() +} + +// POST 发送POST请求 +func (req *Request) POST() (*Response, error) { + req.method = "POST" + return req.push() +} + +// PUT 发送PUT请求 +func (req *Request) PUT() (*Response, error) { + req.method = "PUT" + return req.push() +} + +// PATCH 发送PATCH请求 +func (req *Request) PATCH() (*Response, error) { + req.method = "PATCH" + return req.push() +} + +// Do a request +func (req *Request) Do(method string, data interface{}) (*Response, error) { + req.method = method + + switch method { + case "GET", "DELETE": + if data != nil { + if params, ok := data.(map[string]interface{}); ok { + req.SetParams(params) + } else { + req.err = errors.New("params is not a map[string]interface{}") + return nil, req.err + } + } + + return req.pull() + + case "POST", "PUT", "PATCH": + if data != nil { + req.SetJSONBody(data) + } + + return req.push() + } + + req.err = errors.New("unknow method " + method) + return nil, req.err +} + +func (req *Request) pull() (*Response, error) { + val := "" + if len(req.params) > 0 { + values := url.Values{} + for k, v := range req.params { + values.Add(k, fmt.Sprintf("%v", v)) + } + val += values.Encode() + } + + if val != "" { + if strings.Contains(req.url, "?") { + req.url += "&" + val + } else { + req.url += "?" + val + } + } + + var buf *bytes.Buffer + if req.customRequest != nil { + buf = bytes.NewBufferString(val) + } + + return req.send(nil, buf) +} + +func (req *Request) push() (*Response, error) { + var buf = new(bytes.Buffer) + + if req.bodyJSON != nil { + body, err := json.Marshal(req.bodyJSON) + if err != nil { + req.err = err + return nil, req.err + } + + buf = bytes.NewBuffer(body) + + } else { + buf = bytes.NewBufferString(req.body) + } + + return req.send(buf, buf) +} + +func (req *Request) send(body io.Reader, buf *bytes.Buffer) (*Response, error) { + req.request, req.err = http.NewRequest(req.method, req.url, body) + if req.err != nil { + return nil, req.err + } + + if req.customRequest != nil { + req.customRequest(req.request, buf) + } + + if req.headers != nil { + for k, v := range req.headers { + req.request.Header.Add(k, v) + } + } + + if req.timeout < 1 { + req.timeout = 1 * time.Minute + } + client := http.Client{Timeout: req.timeout} + + resp := new(Response) + resp.Response, resp.err = client.Do(req.request) + + req.response = resp + req.err = resp.err + + return resp, resp.err +} + +// Response return response +func (req *Request) Response() (*Response, error) { + if req.err != nil { + return nil, req.err + } + return req.response, req.response.Error() +} + +// ==================================== Response ==================================== + +// Error return err +func (resp *Response) Error() error { + return resp.err +} + +// BodyString 返回HttpResponse的body数据 +func (resp *Response) BodyString() (string, error) { + if resp.err != nil { + return "", resp.err + } + body, err := resp.ReadBody() + return string(body), err +} + +// ReadBody 返回HttpResponse的body数据 +func (resp *Response) ReadBody() ([]byte, error) { + if resp.err != nil { + return []byte{}, resp.err + } + + if resp.Response == nil { + return []byte{}, errors.New("nil") + } + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return []byte{}, err + } + + resp.Body = ioutil.NopCloser(bytes.NewBuffer(body)) + return body, nil +} + +// BindJSON parses the response's body as JSON +func (resp *Response) BindJSON(v interface{}) error { + if resp.err != nil { + return resp.err + } + body, err := resp.ReadBody() + if err != nil { + return err + } + return json.Unmarshal(body, v) +}