parent
							
								
									f66e2f8891
								
							
						
					
					
						commit
						6406f023db
					
				| @ -0,0 +1,74 @@ | ||||
| package com.gitee.sop.storyweb.controller; | ||||
| 
 | ||||
| import com.alibaba.fastjson.JSON; | ||||
| import com.gitee.sop.servercommon.annotation.ApiMapping; | ||||
| import com.gitee.sop.servercommon.util.UploadUtil; | ||||
| import lombok.Data; | ||||
| import org.apache.commons.io.IOUtils; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| import org.springframework.web.multipart.MultipartFile; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import java.io.IOException; | ||||
| import java.nio.charset.StandardCharsets; | ||||
| import java.util.Collection; | ||||
| 
 | ||||
| /** | ||||
|  * @author tanghc | ||||
|  */ | ||||
| @RestController | ||||
| public class DemoOrderController { | ||||
| 
 | ||||
|     @Value("${server.port}") | ||||
|     private String port; | ||||
| 
 | ||||
|     @ApiMapping("member.info.get") | ||||
|     public Object member(MemberInfoGetParam param, HttpServletRequest request) { | ||||
|         if ("tom".equals(param.name)) { | ||||
|             throw new IllegalArgumentException("name参数错误"); | ||||
|         } | ||||
|         Collection<MultipartFile> uploadFiles = UploadUtil.getUploadFiles(request); | ||||
|         for (MultipartFile uploadFile : uploadFiles) { | ||||
|             try { | ||||
|                 System.out.println("文件名称:" + uploadFile.getOriginalFilename() | ||||
|                         + " 表单名称:" + uploadFile.getName() | ||||
|                         + " 文件内容:" + | ||||
|                         IOUtils.toString(uploadFile.getInputStream(), StandardCharsets.UTF_8)); | ||||
|             } catch (IOException e) { | ||||
|                 e.printStackTrace(); | ||||
|             } | ||||
|         } | ||||
|         System.out.println(param); | ||||
|         return JSON.parseObject("{\n" + | ||||
|                 "    \"id\": 123,\n" + | ||||
|                 "    \"name\": \"jim\",\n" + | ||||
|                 "    \"member_info\": {\n" + | ||||
|                 "        \"is_vip\": 1,\n" + | ||||
|                 "        \"vip_endtime\": \"2020-11-11 11:11:11\"\n" + | ||||
|                 "    }\n" + | ||||
|                 "}", MemberInfoGetResult.class); | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     @Data | ||||
|     public static class MemberInfoGetParam { | ||||
|         private String name; | ||||
|         private Integer age; | ||||
|         private String address; | ||||
|     } | ||||
| 
 | ||||
|     @Data | ||||
|     public static class MemberInfoGetResult { | ||||
|         private Integer id; | ||||
|         private String name; | ||||
|         private MemberInfoGetResultMemberInfo member_info; | ||||
|     } | ||||
| 
 | ||||
|     @Data | ||||
|     public static class MemberInfoGetResultMemberInfo { | ||||
|         private Byte is_vip; | ||||
|         private String vip_endtime; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,126 @@ | ||||
| package common | ||||
| 
 | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding/json" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
| 	"mime/multipart" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| type UploadFile struct { | ||||
| 	// 表单名称
 | ||||
| 	Name string | ||||
| 	Filepath string | ||||
| } | ||||
| 
 | ||||
| // 请求客户端
 | ||||
| var httpClient = &http.Client{} | ||||
| 
 | ||||
| func Get(reqUrl string, allParams map[string]string, headers map[string]string) string  { | ||||
| 	urlParams := url.Values{} | ||||
| 	Url, _ := url.Parse(reqUrl) | ||||
| 	for key, val := range allParams { | ||||
| 		urlParams.Set(key, val) | ||||
| 	} | ||||
| 
 | ||||
| 	//如果参数中有中文参数,这个方法会进行URLEncode
 | ||||
| 	Url.RawQuery = urlParams.Encode() | ||||
| 	// 得到完整的url,http://xx?query
 | ||||
| 	urlPath := Url.String() | ||||
| 
 | ||||
| 	httpRequest,_ := http.NewRequest("GET", urlPath, nil) | ||||
| 	// 添加请求头
 | ||||
| 	if headers != nil { | ||||
| 		for k, v := range headers { | ||||
| 			httpRequest.Header.Add(k,v) | ||||
| 		} | ||||
| 	} | ||||
| 	// 发送请求
 | ||||
| 	resp, err := httpClient.Do(httpRequest) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 	response, _ := ioutil.ReadAll(resp.Body) | ||||
| 	return string(response) | ||||
| } | ||||
| 
 | ||||
| func PostForm(reqUrl string, allParams map[string]string, headers map[string]string) string { | ||||
| 	return post(reqUrl, allParams, "application/x-www-form-urlencoded", nil, headers) | ||||
| } | ||||
| 
 | ||||
| func PostJson(reqUrl string, allParams map[string]string, headers map[string]string) string { | ||||
| 	return post(reqUrl, allParams, "application/json", nil, headers) | ||||
| } | ||||
| 
 | ||||
| func PostFile(reqUrl string, allParams map[string]string, files []UploadFile, headers map[string]string) string { | ||||
| 	return post(reqUrl, allParams, "multipart/form-data", files, headers) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| func post(reqUrl string, allParams map[string]string, contentType string, files []UploadFile, headers map[string]string) string  { | ||||
| 	requestBody, realContentType := getReader(allParams, contentType, files) | ||||
| 	httpRequest,_ := http.NewRequest("POST", reqUrl, requestBody) | ||||
| 	// 添加请求头
 | ||||
| 	httpRequest.Header.Add("Content-Type", realContentType) | ||||
| 	if headers != nil { | ||||
| 		for k, v := range headers { | ||||
| 			httpRequest.Header.Add(k,v) | ||||
| 		} | ||||
| 	} | ||||
| 	// 发送请求
 | ||||
| 	resp, err := httpClient.Do(httpRequest) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	defer resp.Body.Close() | ||||
| 	response, _ := ioutil.ReadAll(resp.Body) | ||||
| 	return string(response) | ||||
| } | ||||
| 
 | ||||
| func getReader(allParams map[string]string, contentType string, files []UploadFile) (io.Reader, string)  { | ||||
| 	if strings.Index(contentType, "json") > -1 { | ||||
| 		bytesData, _ := json.Marshal(allParams) | ||||
| 		return bytes.NewReader(bytesData), contentType | ||||
| 	} else if files != nil { | ||||
| 		body := &bytes.Buffer{} | ||||
| 		// 文件写入 body
 | ||||
| 		writer := multipart.NewWriter(body) | ||||
| 		for _, uploadFile := range files { | ||||
| 			file, err := os.Open(uploadFile.Filepath) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 			part, err := writer.CreateFormFile(uploadFile.Name, filepath.Base(uploadFile.Filepath)) | ||||
| 			if err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 			_, err = io.Copy(part, file) | ||||
| 			file.Close() | ||||
| 		} | ||||
| 		// 其他参数列表写入 body
 | ||||
| 		for k, v := range allParams { | ||||
| 			if err := writer.WriteField(k, v); err != nil { | ||||
| 				panic(err) | ||||
| 			} | ||||
| 		} | ||||
| 		if err := writer.Close(); err != nil { | ||||
| 			panic(err) | ||||
| 		} | ||||
| 		// 上传文件需要自己专用的contentType
 | ||||
| 		return body, writer.FormDataContentType() | ||||
| 	} else { | ||||
| 		urlValues := url.Values{} | ||||
| 		for key, val := range allParams { | ||||
| 			urlValues.Set(key, val) | ||||
| 		} | ||||
| 		reqBody:= urlValues.Encode() | ||||
| 		return strings.NewReader(reqBody), contentType | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,24 @@ | ||||
| package common | ||||
| 
 | ||||
| type RequestType string | ||||
| 
 | ||||
| const ( | ||||
| 	GET         RequestType = "GET" | ||||
| 	POST_JSON   RequestType = "POST_JSON" | ||||
| 	POST_FORM   RequestType = "POST_FORM" | ||||
| 	POST_UPLOAD RequestType = "POST_UPLOAD" | ||||
| ) | ||||
| 
 | ||||
| type Model struct { | ||||
| 	// 业务参数
 | ||||
| 	BizModel interface{} | ||||
| 	// 上传文件
 | ||||
| 	Files []UploadFile | ||||
| } | ||||
| 
 | ||||
| type IRequest interface { | ||||
| 	GetMethod() string | ||||
| 	GetVersion() string | ||||
| 	GetRequestType() RequestType | ||||
| 	GetModel() Model | ||||
| } | ||||
| @ -0,0 +1,108 @@ | ||||
| package common | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"errors" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| var headers = map[string]string{ | ||||
| 	"Accept-Encoding": "identity", | ||||
| } | ||||
| 
 | ||||
| type IClient interface { | ||||
| 	Execute() string | ||||
| } | ||||
| 
 | ||||
| type OpenClient struct { | ||||
| 	AppId      string | ||||
| 	PrivateKey string | ||||
| 	Url        string | ||||
| } | ||||
| 
 | ||||
| func (client OpenClient) ExecuteToken(iRequest IRequest, token string) []byte { | ||||
| 	model := iRequest.GetModel() | ||||
| 	bizModel := model.BizModel | ||||
| 	types := reflect.TypeOf(bizModel) | ||||
| 	values := reflect.ValueOf(bizModel) | ||||
| 	params := make(map[string]interface{}) | ||||
| 	//遍历结构体的所有字段
 | ||||
| 	for i := 0; i < values.NumField(); i++ { | ||||
| 		// 获取到struct标签,需要通过reflect.Type来获取tag标签的值
 | ||||
| 		fieldName := types.Field(i).Tag.Get("json") | ||||
| 		// 如果该字段有tag标签就显示,否则就不显示
 | ||||
| 		if fieldName != "" { | ||||
| 			params[fieldName] = values.Field(i).Interface() | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	requestType := iRequest.GetRequestType() | ||||
| 	var response string | ||||
| 	allParams := client.buildParams(iRequest, params, token) | ||||
| 	if model.Files != nil && len(model.Files) > 0 { | ||||
| 		response = PostFile(client.Url, allParams, model.Files, headers) | ||||
| 	} else { | ||||
| 		switch requestType { | ||||
| 		case GET: | ||||
| 			response = Get(client.Url, allParams, headers) | ||||
| 		case POST_FORM: | ||||
| 			response = PostForm(client.Url, allParams, headers) | ||||
| 		case POST_JSON: | ||||
| 			response = PostJson(client.Url, allParams, headers) | ||||
| 		case POST_UPLOAD: | ||||
| 			response = PostFile(client.Url, allParams, model.Files, headers) | ||||
| 		default: | ||||
| 			panic(errors.New("GetRequestType()返回错误")) | ||||
| 		} | ||||
| 	} | ||||
| 	return parseResponseResult(iRequest, response) | ||||
| } | ||||
| 
 | ||||
| func parseResponseResult(iRequest IRequest, response string) []byte { | ||||
| 	var responseRoot = map[string]interface{}{} | ||||
| 	var err = json.Unmarshal([]byte(response), &responseRoot) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	requestId := responseRoot["request_id"].(string) | ||||
| 	var responseDataMap = responseRoot["error_response"] | ||||
| 	if responseDataMap == nil { | ||||
| 		dataName := strings.ReplaceAll(iRequest.GetMethod(), ".", "_") + "_response" | ||||
| 		responseDataMap = responseRoot[dataName] | ||||
| 	} | ||||
| 	responseDataMap.(map[string]interface{})["request_id"] = requestId | ||||
| 	// json数据
 | ||||
| 	dataJsonBytes, _ := json.Marshal(responseDataMap) | ||||
| 	return dataJsonBytes | ||||
| } | ||||
| 
 | ||||
| func (client OpenClient) buildParams(iRequest IRequest, params map[string]interface{}, token string) map[string]string { | ||||
| 	allParams := map[string]string{ | ||||
| 		"app_id":    client.AppId, | ||||
| 		"method":    iRequest.GetMethod(), | ||||
| 		"charset":   "UTF-8", | ||||
| 		"sign_type":   "RSA2", | ||||
| 		"timestamp": time.Now().Format("2006-01-02 15:04:05"), | ||||
| 		"version":   iRequest.GetVersion(), | ||||
| 	} | ||||
| 
 | ||||
| 	if token != "" { | ||||
| 		allParams["access_token"] = token | ||||
| 	} | ||||
| 
 | ||||
| 	// 添加业务参数
 | ||||
| 	for k, v := range params { | ||||
| 		allParams[k] = ToString(v) | ||||
| 	} | ||||
| 
 | ||||
| 	// 构建sign
 | ||||
| 	sign := CreateSign(allParams, client.PrivateKey, "RSA2") | ||||
| 	allParams["sign"] = sign | ||||
| 	return allParams | ||||
| } | ||||
| 
 | ||||
| func (client OpenClient) Execute(iRequest IRequest) []byte { | ||||
| 	return client.ExecuteToken(iRequest, "") | ||||
| } | ||||
| @ -0,0 +1,99 @@ | ||||
| package common | ||||
| 
 | ||||
| import ( | ||||
| 	"crypto" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	"crypto/x509" | ||||
| 	"encoding/base64" | ||||
| 	"encoding/pem" | ||||
| 	"errors" | ||||
| 	"sort" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	PEM_BEGIN = "-----BEGIN RSA PRIVATE KEY-----\n" | ||||
| 	PEM_END = "\n-----END RSA PRIVATE KEY-----" | ||||
| ) | ||||
| 
 | ||||
| func CreateSign(allParams map[string]string, privateKey string, signType string) string { | ||||
| 	signContent := GetSignContent(allParams) | ||||
| 	return Sign(signContent, privateKey, signType) | ||||
| } | ||||
| 
 | ||||
| func Sign(signContent string, privateKey string, signType string) string  { | ||||
| 	if signType == "RSA" { | ||||
| 		return RsaSign(signContent, privateKey, crypto.SHA1) | ||||
| 	} else if signType == "RSA2"  { | ||||
| 		return RsaSign(signContent, privateKey, crypto.SHA256) | ||||
| 	} else { | ||||
| 		panic(errors.New("signType错误")) | ||||
| 	} 
 | ||||
| } | ||||
| 
 | ||||
| func RsaSign(signContent string, privateKey string, hash crypto.Hash) string { | ||||
| 	shaNew := hash.New() | ||||
| 	shaNew.Write([]byte(signContent)) | ||||
| 	hashed := shaNew.Sum(nil) | ||||
| 	priKey, err := ParsePrivateKey(privateKey) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 
 | ||||
| 	signature, err := rsa.SignPKCS1v15(rand.Reader, priKey, hash, hashed) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| 	return base64.StdEncoding.EncodeToString(signature) | ||||
| } | ||||
| 
 | ||||
| func ParsePrivateKey(privateKey string)(*rsa.PrivateKey, error) { | ||||
| 	privateKey = FormatPrivateKey(privateKey) | ||||
| 	// 2、解码私钥字节,生成加密对象
 | ||||
| 	block, _ := pem.Decode([]byte(privateKey)) | ||||
| 	if block == nil { | ||||
| 		return nil, errors.New("私钥信息错误!") | ||||
| 	} | ||||
| 	// 3、解析DER编码的私钥,生成私钥对象
 | ||||
| 	priKey, err := x509.ParsePKCS1PrivateKey(block.Bytes) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return priKey, nil | ||||
| } | ||||
| 
 | ||||
| func FormatPrivateKey(privateKey string) string  { | ||||
| 	if !strings.HasPrefix(privateKey, PEM_BEGIN) { | ||||
| 		privateKey = PEM_BEGIN + privateKey | ||||
| 	} | ||||
| 	if !strings.HasSuffix(privateKey, PEM_END) { | ||||
| 		privateKey = privateKey + PEM_END | ||||
| 	} | ||||
| 	return privateKey | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /** | ||||
| 1.筛选并排序 | ||||
| 获取所有请求参数,不包括字节类型参数,如文件、字节流,剔除sign字段,剔除值为空的参数,并按照参数名ASCII码递增排序(字母升序排序), | ||||
| 如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推。 | ||||
| 
 | ||||
| 2.拼接 | ||||
| 将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为待签名字符串。 | ||||
|  */ | ||||
| func GetSignContent(allParams map[string]string) string { | ||||
| 	keys := make([]string, 0, len(allParams)) | ||||
| 	var result []string | ||||
| 	for k := range allParams { | ||||
| 		keys = append(keys, k) | ||||
| 	} | ||||
| 	sort.Strings(keys) | ||||
| 	for _, key := range keys { | ||||
| 		val := allParams[key] | ||||
| 		if len(val) > 0 { | ||||
| 			result = append(result, key + "=" + val) | ||||
| 		} | ||||
| 	} | ||||
| 	return strings.Join(result, "&") | ||||
| } | ||||
| @ -0,0 +1,56 @@ | ||||
| package common | ||||
| 
 | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"strconv" | ||||
| ) | ||||
| 
 | ||||
| func ToString(value interface{}) string { | ||||
| 	var key string | ||||
| 	switch value.(type) { | ||||
| 	case float64: | ||||
| 		ft := value.(float64) | ||||
| 		key = strconv.FormatFloat(ft, 'f', -1, 64) | ||||
| 	case float32: | ||||
| 		ft := value.(float32) | ||||
| 		key = strconv.FormatFloat(float64(ft), 'f', -1, 64) | ||||
| 	case int: | ||||
| 		it := value.(int) | ||||
| 		key = strconv.Itoa(it) | ||||
| 	case uint: | ||||
| 		it := value.(uint) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case int8: | ||||
| 		it := value.(int8) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case uint8: | ||||
| 		it := value.(uint8) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case int16: | ||||
| 		it := value.(int16) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case uint16: | ||||
| 		it := value.(uint16) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case int32: | ||||
| 		it := value.(int32) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case uint32: | ||||
| 		it := value.(uint32) | ||||
| 		key = strconv.Itoa(int(it)) | ||||
| 	case int64: | ||||
| 		it := value.(int64) | ||||
| 		key = strconv.FormatInt(it, 10) | ||||
| 	case uint64: | ||||
| 		it := value.(uint64) | ||||
| 		key = strconv.FormatUint(it, 10) | ||||
| 	case string: | ||||
| 		key = value.(string) | ||||
| 	case []byte: | ||||
| 		key = string(value.([]byte)) | ||||
| 	default: | ||||
| 		newValue, _ := json.Marshal(value) | ||||
| 		key = string(newValue) | ||||
| 	} | ||||
| 	return key | ||||
| } | ||||
| @ -0,0 +1,7 @@ | ||||
| package model | ||||
| 
 | ||||
| type MemberInfoGetModel struct { | ||||
| 	Name string `json:"name"` | ||||
| 	Age uint32  `json:"age"` | ||||
| 	Address string  `json:"address"` | ||||
| } | ||||
| @ -0,0 +1,43 @@ | ||||
| # sdk-go | ||||
| 
 | ||||
| ```go | ||||
| 
 | ||||
| // 应用ID | ||||
| const appId string = "xx" | ||||
| // 应用私钥 | ||||
| const privateKey string = "xx" | ||||
| // 请求地址 | ||||
| const url string = "http://localhost:7071/prod/gw68uy85" | ||||
| 
 | ||||
| // 请求客户端 | ||||
| var openClient = common.OpenClient{AppId: appId, PrivateKey: privateKey, Url: url} | ||||
| 
 | ||||
| func main() { | ||||
| 	// 创建请求 | ||||
| 	memberInfoGetRequest := request.MemberInfoGetRequest{} | ||||
| 	// 请求参数 | ||||
| 	memberInfoGetRequest.BizModel = model.MemberInfoGetModel{Name: "jim", Age: 22, Address: "xx"} | ||||
| 	 | ||||
|     // 添加上传文件 | ||||
| 	//path, _ := os.Getwd() | ||||
| 	//files := []common.UploadFile{ | ||||
| 	//	{Name:"file1", Filepath:path + "/test/aa.txt"}, | ||||
| 	//	{Name:"file2", Filepath:path + "/test/bb.txt"}, | ||||
| 	//} | ||||
| 	//memberInfoGetRequest.Files = files | ||||
|      | ||||
|     // 发送请求,返回json bytes | ||||
| 	var jsonBytes = openClient.Execute(memberInfoGetRequest) | ||||
| 	fmt.Printf("data:%s\n", string(jsonBytes)) | ||||
| 	// 转换结果 | ||||
| 	var memberInfoGetResponse response.MemberInfoGetResponse | ||||
| 	response.ConvertResponse(jsonBytes, &memberInfoGetResponse) | ||||
| 
 | ||||
| 	if memberInfoGetResponse.IsSuccess() { | ||||
| 		fmt.Printf("is_vip:%d, vip_endtime:%s\n", memberInfoGetResponse.MemberInfo.IsVip, memberInfoGetResponse.MemberInfo.VipEndtime) | ||||
| 	} else { | ||||
| 		fmt.Printf("code:%s, msg:%s, subCode:%s, subMsg:%s\n", | ||||
| 			memberInfoGetResponse.Code, memberInfoGetResponse.Msg, memberInfoGetResponse.SubCode, memberInfoGetResponse.SubMsg) | ||||
| 	} | ||||
| } | ||||
| ``` | ||||
| @ -0,0 +1,23 @@ | ||||
| package request | ||||
| 
 | ||||
| import "../common" | ||||
| 
 | ||||
| type MemberInfoGetRequest struct { | ||||
| 	common.Model | ||||
| } | ||||
| 
 | ||||
| func (MemberInfoGetRequest) GetMethod() string { | ||||
| 	return "member.info.get" | ||||
| } | ||||
| 
 | ||||
| func (MemberInfoGetRequest) GetVersion() string { | ||||
| 	return "1.0" | ||||
| } | ||||
| 
 | ||||
| func (MemberInfoGetRequest) GetRequestType() common.RequestType { | ||||
| 	return common.GET | ||||
| } | ||||
| 
 | ||||
| func (req MemberInfoGetRequest) GetModel() common.Model { | ||||
| 	return req.Model | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| package response | ||||
| 
 | ||||
| import "encoding/json" | ||||
| 
 | ||||
| type IResponse interface { | ||||
| 	IsSuccess() bool | ||||
| } | ||||
| 
 | ||||
| type BaseResponse struct { | ||||
| 	RequestId string `json:"request_id"` | ||||
| 	Code      string `json:"code"` | ||||
| 	Msg       string `json:"msg"` | ||||
| 	SubCode   string `json:"sub_code"` | ||||
| 	SubMsg    string `json:"sub_msg"` | ||||
| } | ||||
| 
 | ||||
| func (resp BaseResponse) IsSuccess() bool { | ||||
| 	return len(resp.SubCode) == 0 | ||||
| } | ||||
| 
 | ||||
| func ConvertResponse(data []byte, ptr interface{})  { | ||||
| 	err := json.Unmarshal(data, ptr) | ||||
| 	if err != nil { | ||||
| 		panic(err) | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,14 @@ | ||||
| package response | ||||
| 
 | ||||
| type MemberInfoGetResponse struct { | ||||
| 	BaseResponse | ||||
| 
 | ||||
| 	Id         int32      `json:"id"` | ||||
| 	Name       string     `json:"name"` | ||||
| 	MemberInfo MemberInfo `json:"member_info"` | ||||
| } | ||||
| 
 | ||||
| type MemberInfo struct { | ||||
| 	IsVip      int32      `json:"is_vip"` | ||||
| 	VipEndtime string `json:"vip_endtime"` | ||||
| } | ||||
| @ -0,0 +1 @@ | ||||
| hello你好123 | ||||
| @ -0,0 +1 @@ | ||||
| 文件bb的内容 | ||||
| @ -0,0 +1,48 @@ | ||||
| package main | ||||
| 
 | ||||
| import ( | ||||
| 	"../common" | ||||
| 	"../model" | ||||
| 	"../request" | ||||
| 	"../response" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| // 应用ID
 | ||||
| const appId string = "201904035630907729292csharp" | ||||
| // 应用私钥
 | ||||
| const privateKey string = "MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr" | ||||
| // 请求路径
 | ||||
| const url string = "http://localhost:8081" | ||||
| 
 | ||||
| // 请求客户端
 | ||||
| var openClient = common.OpenClient{AppId: appId, PrivateKey: privateKey, Url: url} | ||||
| 
 | ||||
| func main() { | ||||
| 	// 创建请求
 | ||||
| 	memberInfoGetRequest := request.MemberInfoGetRequest{} | ||||
| 	// 设置请求参数
 | ||||
| 	memberInfoGetRequest.BizModel = model.MemberInfoGetModel{Name: "jim", Age: 22, Address: "xx"} | ||||
| 
 | ||||
| 	// 添加上传文件
 | ||||
| 	//path, _ := os.Getwd()
 | ||||
| 	//files := []common.UploadFile{
 | ||||
| 	//	{Name:"file1", Filepath:path + "/test/aa.txt"},
 | ||||
| 	//	{Name:"file2", Filepath:path + "/test/bb.txt"},
 | ||||
| 	//}
 | ||||
| 	//memberInfoGetRequest.Files = files
 | ||||
| 
 | ||||
| 	// 发送请求,返回json bytes
 | ||||
| 	var jsonBytes = openClient.Execute(memberInfoGetRequest) | ||||
| 	fmt.Printf("data:%s\n", string(jsonBytes)) | ||||
| 	// 转换结果
 | ||||
| 	var memberInfoGetResponse response.MemberInfoGetResponse | ||||
| 	response.ConvertResponse(jsonBytes, &memberInfoGetResponse) | ||||
| 
 | ||||
| 	if memberInfoGetResponse.IsSuccess() { | ||||
| 		fmt.Printf("is_vip:%d, vip_endtime:%s\n", memberInfoGetResponse.MemberInfo.IsVip, memberInfoGetResponse.MemberInfo.VipEndtime) | ||||
| 	} else { | ||||
| 		fmt.Printf("code:%s, msg:%s, subCode:%s, subMsg:%s\n", | ||||
| 			memberInfoGetResponse.Code, memberInfoGetResponse.Msg, memberInfoGetResponse.SubCode, memberInfoGetResponse.SubMsg) | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| /target/ | ||||
| /venv/ | ||||
| !.mvn/wrapper/maven-wrapper.jar | ||||
| 
 | ||||
| ### STS ### | ||||
| .apt_generated | ||||
| .classpath | ||||
| .factorypath | ||||
| .project | ||||
| .settings | ||||
| .springBeans | ||||
| .sts4-cache | ||||
| 
 | ||||
| ### IntelliJ IDEA ### | ||||
| .idea | ||||
| *.iws | ||||
| *.iml | ||||
| *.ipr | ||||
| 
 | ||||
| ### NetBeans ### | ||||
| /nbproject/private/ | ||||
| /nbbuild/ | ||||
| /dist/ | ||||
| /nbdist/ | ||||
| /.nb-gradle/ | ||||
| /build/ | ||||
| 
 | ||||
| @ -0,0 +1,21 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| 
 | ||||
| import json | ||||
| 
 | ||||
| 
 | ||||
| def to_json_string(obj): | ||||
|     """将对象转换成json字符串 | ||||
| 
 | ||||
|     :param obj: 对象 | ||||
|     :type obj: object | ||||
| 
 | ||||
|     :return: 返回json | ||||
|     :rtype: str | ||||
|     """ | ||||
|     if isinstance(obj, dict): | ||||
|         param = obj | ||||
|     else: | ||||
|         param = obj.__dict__ | ||||
|     return json.dumps(param, ensure_ascii=False) | ||||
| 
 | ||||
| @ -0,0 +1,122 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| 
 | ||||
| import json | ||||
| import time | ||||
| 
 | ||||
| import requests | ||||
| 
 | ||||
| from common import SignUtil, RequestTypes | ||||
| from common.RequestType import RequestType | ||||
| 
 | ||||
| _headers = {'Accept-Encoding': 'identity'} | ||||
| 
 | ||||
| 
 | ||||
| class OpenClient: | ||||
|     """调用客户端""" | ||||
|     __app_id = '' | ||||
|     __private_key = '' | ||||
|     __url = '' | ||||
| 
 | ||||
|     def __init__(self, app_id, private_key, url): | ||||
|         """客户端 | ||||
| 
 | ||||
|         :param app_id: 应用ID | ||||
|         :type app_id: str | ||||
| 
 | ||||
|         :param private_key: 应用私钥 | ||||
|         :type private_key: str | ||||
| 
 | ||||
|         :param url: 请求URL | ||||
|         :type url: str | ||||
|         """ | ||||
|         self.__app_id = app_id | ||||
|         self.__private_key = private_key | ||||
|         self.__url = url | ||||
| 
 | ||||
|     def execute(self, request, token=None): | ||||
|         """ | ||||
| 
 | ||||
|         :param request: 请求对象,BaseRequest的子类 | ||||
| 
 | ||||
|         :param token: (Optional) token | ||||
|         :type token: str | ||||
| 
 | ||||
|         :return: 返回请求结果 | ||||
|         :rtype: BaseResponse | ||||
|         """ | ||||
|         biz_model = request.biz_model | ||||
|         request_type = request.get_request_type() | ||||
|         if not isinstance(request_type, RequestType): | ||||
|             raise Exception('get_request_type返回错误类型,正确方式:RequestTypes.XX') | ||||
| 
 | ||||
|         params = biz_model.__dict__ | ||||
|         if request.files is not None: | ||||
|             response = self._post_file(request, params, token) | ||||
|         elif request_type == RequestTypes.GET: | ||||
|             response = self._get(request, params, token) | ||||
|         elif request_type == RequestTypes.POST_FORM: | ||||
|             response = self._post_form(request, params, token) | ||||
|         elif request_type == RequestTypes.POST_JSON: | ||||
|             response = self._post_json(request, params, token) | ||||
|         elif request_type == RequestTypes.POST_UPLOAD: | ||||
|             response = self._post_file(request, params, token) | ||||
|         else: | ||||
|             raise Exception('get_request_type设置错误') | ||||
| 
 | ||||
|         return self._parse_response(response, request) | ||||
| 
 | ||||
|     def _get(self, request, params, token): | ||||
|         all_params = self._build_params(request, params, token) | ||||
|         return requests.get(self.__url, all_params, headers=_headers).text | ||||
| 
 | ||||
|     def _post_form(self, request, params, token): | ||||
|         all_params = self._build_params(request, params, token) | ||||
|         return requests.post(self.__url, data=all_params, headers=_headers).text | ||||
| 
 | ||||
|     def _post_json(self, request, params, token): | ||||
|         all_params = self._build_params(request, params, token) | ||||
|         return requests.post(self.__url, json=all_params, headers=_headers).text | ||||
| 
 | ||||
|     def _post_file(self, request, params, token): | ||||
|         all_params = self._build_params(request, params, token) | ||||
|         return requests.request('POST', self.__url, data=all_params, files=request.files, headers=_headers).text | ||||
| 
 | ||||
|     def _build_params(self, request, params, token): | ||||
|         """构建所有的请求参数 | ||||
| 
 | ||||
|         :param request: 请求对象 | ||||
|         :type request: request.BaseRequest | ||||
| 
 | ||||
|         :param params: 业务请求参数 | ||||
|         :type params: dict | ||||
| 
 | ||||
|         :param token: token | ||||
|         :type token: str | ||||
| 
 | ||||
|         :return: 返回请求参数 | ||||
|         :rtype: str | ||||
|         """ | ||||
|         all_params = { | ||||
|             'app_id': self.__app_id, | ||||
|             'method': request.get_method(), | ||||
|             'charset': 'UTF-8', | ||||
|             'sign_type': 'RSA2', | ||||
|             'timestamp': time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), | ||||
|             'version': request.get_version() | ||||
|         } | ||||
| 
 | ||||
|         if token is not None: | ||||
|             all_params['access_token'] = token | ||||
| 
 | ||||
|         # 添加业务参数 | ||||
|         all_params.update(params) | ||||
| 
 | ||||
|         # 构建sign | ||||
|         sign = SignUtil.create_sign(all_params, self.__private_key, 'RSA2') | ||||
|         all_params['sign'] = sign | ||||
|         return all_params | ||||
| 
 | ||||
|     def _parse_response(self, resp, request): | ||||
|         response_dict = json.loads(resp) | ||||
|         return request.parse_response(response_dict) | ||||
| @ -0,0 +1,8 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| 
 | ||||
| 
 | ||||
| class RequestType: | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         pass | ||||
| @ -0,0 +1,6 @@ | ||||
| from common.RequestType import RequestType | ||||
| 
 | ||||
| GET = RequestType() | ||||
| POST_JSON = RequestType() | ||||
| POST_FORM = RequestType() | ||||
| POST_UPLOAD = RequestType() | ||||
| @ -0,0 +1,102 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| import rsa | ||||
| import base64 | ||||
| 
 | ||||
| __pem_begin = '-----BEGIN RSA PRIVATE KEY-----\n' | ||||
| __pem_end = '\n-----END RSA PRIVATE KEY-----' | ||||
| 
 | ||||
| 
 | ||||
| def create_sign(all_params, private_key, sign_type): | ||||
|     """创建签名 | ||||
| 
 | ||||
|     :param all_params: 参数 | ||||
|     :type all_params: dict | ||||
| 
 | ||||
|     :param private_key: 私钥字符串 | ||||
|     :type private_key: str | ||||
| 
 | ||||
|     :param sign_type: 签名类型,'RSA', 'RSA2'二选一 | ||||
|     :type sign_type: str | ||||
| 
 | ||||
|     :return: 返回签名内容 | ||||
|     :rtype: str | ||||
|     """ | ||||
|     sign_content = get_sign_content(all_params) | ||||
|     private_key = _format_private_key(private_key) | ||||
|     return sign(sign_content, private_key, sign_type) | ||||
| 
 | ||||
| 
 | ||||
| def _format_private_key(private_key): | ||||
|     if not private_key.startswith(__pem_begin): | ||||
|         private_key = __pem_begin + private_key | ||||
|     if not private_key.endswith(__pem_end): | ||||
|         private_key = private_key + __pem_end | ||||
|     return private_key | ||||
| 
 | ||||
| 
 | ||||
| def get_sign_content(params): | ||||
|     """构建签名内容 | ||||
| 
 | ||||
|     1.筛选并排序 | ||||
|     获取所有请求参数,不包括字节类型参数,如文件、字节流,剔除sign字段,剔除值为空的参数,并按照参数名ASCII码递增排序(字母升序排序), | ||||
|     如果遇到相同字符则按照第二个字符的键值ASCII码递增排序,以此类推。 | ||||
| 
 | ||||
|     2.拼接 | ||||
|     将排序后的参数与其对应值,组合成“参数=参数值”的格式,并且把这些参数用&字符连接起来,此时生成的字符串为待签名字符串。 | ||||
| 
 | ||||
|     :param params: 参数 | ||||
|     :type params: dict | ||||
| 
 | ||||
|     :return: 返回签名内容 | ||||
|     :rtype: str | ||||
|     """ | ||||
|     keys = params.keys() | ||||
|     keys.sort() | ||||
|     result = [] | ||||
|     for key in keys: | ||||
|         value = str(params.get(key)) | ||||
|         if len(value) > 0: | ||||
|             result.append(key + '=' + value) | ||||
| 
 | ||||
|     return '&'.join(result) | ||||
| 
 | ||||
| 
 | ||||
| def sign(content, private_key, sign_type): | ||||
|     """签名 | ||||
| 
 | ||||
|     :param content: 签名内容 | ||||
|     :type content: str | ||||
| 
 | ||||
|     :param private_key: 私钥字符串 | ||||
|     :type private_key: str | ||||
| 
 | ||||
|     :param sign_type: 签名类型,'RSA', 'RSA2'二选一 | ||||
|     :type sign_type: str | ||||
| 
 | ||||
|     :return: 返回签名内容 | ||||
|     :rtype: str | ||||
|     """ | ||||
|     if sign_type.upper() == 'RSA': | ||||
|         return rsa_sign(content, private_key, 'SHA-1') | ||||
|     elif sign_type.upper() == 'RSA2': | ||||
|         return rsa_sign(content, private_key, 'SHA-256') | ||||
|     else: | ||||
|         raise Exception('sign_type错误') | ||||
| 
 | ||||
| 
 | ||||
| def rsa_sign(content, private_key, hash): | ||||
|     """SHAWithRSA | ||||
| 
 | ||||
|     :param content: 签名内容 | ||||
|     :type content: str | ||||
| 
 | ||||
|     :param private_key: 私钥 | ||||
|     :type private_key: str | ||||
| 
 | ||||
|     :return: 签名内容 | ||||
|     :rtype: str | ||||
|     """ | ||||
|     pri_key = rsa.PrivateKey.load_pkcs1(private_key.encode('utf-8')) | ||||
|     sign_result = rsa.sign(content, pri_key, hash) | ||||
|     return base64.b64encode(sign_result) | ||||
| @ -0,0 +1,7 @@ | ||||
| 
 | ||||
| class MemberInfoGetModel: | ||||
|     """MemberInfoGetModel""" | ||||
| 
 | ||||
|     name = None | ||||
|     age = None | ||||
|     address = None | ||||
| @ -0,0 +1,56 @@ | ||||
| # sdk-python | ||||
| 
 | ||||
| 安装 | ||||
| 
 | ||||
| `pip install requests`  | ||||
| 
 | ||||
| `pip install rsa`  | ||||
| 
 | ||||
| - 调用方式 | ||||
| 
 | ||||
| ```python | ||||
|     # 创建请求 | ||||
|     request = MemberInfoGetRequest() | ||||
|     # 请求参数 | ||||
|     model = MemberInfoGetModel() | ||||
|     model.age = 22 | ||||
|     model.name = 'jim' | ||||
|     model.address = 'xx' | ||||
|     # 添加请求参数 | ||||
|     request.biz_model = model | ||||
| 
 | ||||
|     # 添加上传文件 | ||||
|     # files = { | ||||
|     #     'file1': open('aa.txt', 'rb'), | ||||
|     #     'file2': open('bb.txt', 'rb') | ||||
|     # } | ||||
|     # request.files = files | ||||
| 
 | ||||
|     # 调用请求 | ||||
|     response = self.client.execute(request) | ||||
| 
 | ||||
|     if response.is_success(): | ||||
|         print 'response: ', response | ||||
|         print 'is_vip:', response.get('member_info').get('is_vip', 0) | ||||
|     else: | ||||
|         print '请求失败,code:%s, msg:%s, sub_code:%s, sub_msg:%s' % \ | ||||
|               (response.code, response.msg, response.sub_code, response.sub_msg) | ||||
| ``` | ||||
| 
 | ||||
| 详见`test.py` | ||||
| 
 | ||||
| 代码规范: | ||||
| 
 | ||||
| | Type                       | Public             | Internal                                                          |  | ||||
| | -------------------------- | ------------------ | ----------------------------------------------------------------- |   | ||||
| | Modules                    | lower_with_under   | _lower_with_under                                                 |   | ||||
| | Packages                   | lower_with_under   |                                                                   |   | ||||
| | Classes                    | CapWords           | _CapWords                                                         |   | ||||
| | Exceptions                 | CapWords           |                                                                   |   | ||||
| | Functions                  | lower_with_under() | _lower_with_under()                                               |   | ||||
| | Global/Class Constants     | CAPS_WITH_UNDER    | _CAPS_WITH_UNDER                                                  |   | ||||
| | Global/Class Variables     | lower_with_under   | _lower_with_under                                                 |   | ||||
| | Instance Variables         | lower_with_under   | _lower_with_under (protected) or __lower_with_under (private)     |   | ||||
| | Method Names               | lower_with_under() | _lower_with_under() (protected) or __lower_with_under() (private) |   | ||||
| | Function/Method Parameters | lower_with_under   |                                                                   |   | ||||
| | Local Variables            | lower_with_under   |               | ||||
| @ -0,0 +1,59 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| from response.BaseResponse import BaseResponse | ||||
| 
 | ||||
| 
 | ||||
| class BaseRequest: | ||||
|     """请求类的父类""" | ||||
| 
 | ||||
|     biz_model = None | ||||
|     """请求参数""" | ||||
| 
 | ||||
|     files = None | ||||
|     """上传文件""" | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         pass | ||||
| 
 | ||||
|     def get_method(self): | ||||
|         """返回接口名 | ||||
| 
 | ||||
|         :return: 返回接口名 | ||||
|         :rtype: str | ||||
|         """ | ||||
|         raise Exception('未实现BaseRequest.get_method()方法') | ||||
| 
 | ||||
|     def get_version(self): | ||||
|         """返回接口版本号 | ||||
| 
 | ||||
|         :return: 返回版本号,如:1.0 | ||||
|         :rtype: str | ||||
|         """ | ||||
|         raise Exception('未实现BaseRequest.get_version()方法') | ||||
| 
 | ||||
|     def get_request_type(self): | ||||
|         """返回请求类型 | ||||
| 
 | ||||
|         :return: 返回RequestType类实例 | ||||
|         :rtype:  common.RequestType | ||||
|         """ | ||||
|         raise Exception('未实现BaseRequest.get_request_type()方法') | ||||
| 
 | ||||
|     def parse_response(self, response_dict): | ||||
|         response_data = response_dict.get('error_response') | ||||
|         if response_data is None: | ||||
|             data_name = self.get_method().replace('.', '_') + '_response' | ||||
|             response_data = response_dict.get(data_name) | ||||
|         base_response = BaseResponse(response_data) | ||||
|         base_response.request_id = response_dict.get('request_id') | ||||
|         base_response.code = response_data.get('code') | ||||
|         base_response.msg = response_data.get('msg') | ||||
|         base_response.sub_code = response_data.get('sub_code') | ||||
|         base_response.sub_msg = response_data.get('sub_msg') | ||||
|         return base_response | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| @ -0,0 +1,20 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| from common import RequestTypes | ||||
| from request.BaseRequest import BaseRequest | ||||
| 
 | ||||
| 
 | ||||
| class MemberInfoGetRequest(BaseRequest): | ||||
|     """获取会员信息请求""" | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         BaseRequest.__init__(self) | ||||
| 
 | ||||
|     def get_method(self): | ||||
|         return 'member.info.get' | ||||
| 
 | ||||
|     def get_version(self): | ||||
|         return '1.0' | ||||
| 
 | ||||
|     def get_request_type(self): | ||||
|         return RequestTypes.GET | ||||
| @ -0,0 +1,23 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| from UserDict import UserDict | ||||
| 
 | ||||
| 
 | ||||
| class BaseResponse(UserDict): | ||||
|     """返回类""" | ||||
|     request_id = None | ||||
|     code = None | ||||
|     msg = None | ||||
|     sub_code = None | ||||
|     sub_msg = None | ||||
| 
 | ||||
|     def __init__(self, _dict=None, **kwargs): | ||||
|         UserDict.__init__(self, _dict, **kwargs) | ||||
| 
 | ||||
|     def is_success(self): | ||||
|         """是否成功 | ||||
| 
 | ||||
|         :return: True,成功 | ||||
|         :rtype: bool | ||||
|         """ | ||||
|         return self.sub_code is None | ||||
| @ -0,0 +1 @@ | ||||
| hello你好123 | ||||
| @ -0,0 +1 @@ | ||||
| 文件bb的内容 | ||||
| @ -0,0 +1,68 @@ | ||||
| #!/usr/bin/python | ||||
| # -*- coding: UTF-8 -*- | ||||
| import unittest | ||||
| 
 | ||||
| from common import JsonUtil | ||||
| from model.MemberInfoGetModel import MemberInfoGetModel | ||||
| from request.MemberInfoGetRequest import MemberInfoGetRequest | ||||
| from common.OpenClient import OpenClient | ||||
| 
 | ||||
| import sys | ||||
| 
 | ||||
| reload(sys) | ||||
| sys.setdefaultencoding('utf8') | ||||
| 
 | ||||
| 
 | ||||
| class MyTestCase(unittest.TestCase): | ||||
|     # 应用id | ||||
|     app_id = '201904035630907729292csharp' | ||||
|     # 应用私钥 | ||||
|     private_key = 'MIIEowIBAAKCAQEA5+OvJxeSzf44NxQ/cl7Ii+BzPg2k6sRcvH4ffOtU5Dzq1/oEvg02nxIhmwOHBZmjbmuUu0aLsfglUTAwqfXftfAKZidshsgj9NNh0/kxk0avRZ1UoljWGz/FxVZA0ogbxxhohPZ9jWcD+eBQcIwF2DtHfAJqWWZrYFnCMeHD8mPzxo2kwXSvDzi0vf9I2tKiYvNG26a9FqeYtPOoi81sdS3+70HOMdxP8ejXtyfnKpKz7Dx506LCIRS5moWS3Q5eTLV3NGX/1CSJ8wpQA2DAQTjVhX5eVu7Yqz12t8W+sjWM/tHUR6cgwYYR10p7tSCeCPzkigjGxKm4cYXWtATQJQIDAQABAoIBAHFDsgrrJca+NKEan77ycwx3jnKx4WrWjOF4zVKL9AQjiSYDNgvKknJyPb3kpC/lEoHdxGERHSzJoxib7DkoIqRQYhPxj73pxj5QfYk3P7LLJNNg/LTrpXDb3nL8JV9wIflGf87qQvstZTDJEyFWE4jBs7Hr0BxovWvri8InnzkmERJ1cbGJgNHe1Y3Zo2tw0yaHxQCxLuajP+notRZhD9bEp7uKeI0w9AvlW6k8m/7y10F0BK/TlyW8rQiEC391yOiRYoMcUh4hd2Q9bMx3jngZgX8PXIvZZcup4/pvWlv1alwhB2tsnLdazP62r1MO80vLyLunzGO+7WwCjEYlVaECgYEA+lQRFmbhKaPuAuXMtY31Fbga8nedka5TjnEV7+/kX+yowE2OlNujF+ZG8UTddTxAGv56yVNi/mjRlgD74j8z0eOsgvOq9mwbCrgLhLo51H9O/wAxtb+hBKtC5l50pBr4gER6d8W6EQNTSGojnMIaLXTkAZ5Qf6Z8e2HFVdOn0X0CgYEA7SSrTokwzukt5KldNu5ukyyd+C3D1i6orbg6qD73EP9CfNMfGSBn7dDv9wMSJH01+Ty+RgTROgtjGRDbMJWnfbdt/61NePr9ar5sb6Nbsf7/I0w7cZF5dsaFYgzaOfQYquzXPbLQHkpMT64bqpv/Mwy4F2lFvaYWY5fA4pC2uckCgYEAg75Ym9ybJaoTqky8ttQ2Jy8UZ4VSVQhVC0My02sCWwWXLlXi8y7An+Rec73Ve0yxREOn5WrQT6pkmzh7V/ABWrYi5WxODpCIjtSbo0fLBa3Wqle00b0/hdCITetqIa/cFs1zUrOqICgK3bKWeXqiAkhhcwSZwwSgwOKM04Wn7ZUCgYBvhHX2mbdVJfyJ8kc+hMOE/E9RHRxiBVEXWHJlGi8PVCqNDq8qHr4g7Mdbzprig+s0yKblwHAvrpkseWvKHiZEjVTyDipHgShY4TGXEigVvUd37uppTrLi8xpYcJjS9gH/px7VCdiq1d+q/MJP6coJ1KphgATm2UrgDMYNBWaYWQKBgEHRxrmER7btUF60/YgcqPHFc8RpYQB2ZZE0kyKGDqk2Data1XYUY6vsPAU28yRLAaWr/D2H17iyLkxP80VLm6QhifxCadv90Q/Wl1DFfOJQMW6avyQ0so6G0wFq/LJxaFK4iLXQn1RJnmTp6BYiJMmK2BhFbRzw8ssMoF6ad2rr' | ||||
|     # 请求URL | ||||
|     url = 'http://localhost:8081' | ||||
|     # 创建请求客户端 | ||||
|     client = OpenClient(app_id, private_key, url) | ||||
| 
 | ||||
|     def test_api(self): | ||||
|         # 创建请求 | ||||
|         request = MemberInfoGetRequest() | ||||
|         # 请求参数 | ||||
|         model = MemberInfoGetModel() | ||||
|         model.age = 22 | ||||
|         model.name = 'jim' | ||||
|         model.address = 'xx' | ||||
|         # 添加请求参数 | ||||
|         request.biz_model = model | ||||
| 
 | ||||
|         # 添加上传文件 | ||||
|         # files = { | ||||
|         #     'file1': open('aa.txt', 'rb'), | ||||
|         #     'file2': open('bb.txt', 'rb') | ||||
|         # } | ||||
|         # request.files = files | ||||
| 
 | ||||
|         # 调用请求 | ||||
|         response = self.client.execute(request) | ||||
| 
 | ||||
|         # 关闭文件 | ||||
|         # for f in files.values(): | ||||
|         #     f.close() | ||||
| 
 | ||||
|         if response.is_success(): | ||||
|             print 'response: ', response | ||||
|             print 'is_vip:', response.get('member_info').get('is_vip', 0) | ||||
|         else: | ||||
|             print '请求失败,code:%s, msg:%s, sub_code:%s, sub_msg:%s' % \ | ||||
|                   (response.code, response.msg, response.sub_code, response.sub_msg) | ||||
| 
 | ||||
|     def test_to_json_string(self): | ||||
|         model = MemberInfoGetModel() | ||||
|         model.age = 1 | ||||
|         model.name = '张三' | ||||
|         model.address = 'xx' | ||||
|         json_string = JsonUtil.to_json_string(model) | ||||
|         print 'json:', json_string | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     unittest.main() | ||||
					Loading…
					
					
				
		Reference in new issue