From 94c81f92f94a57430a3b1bf4cb4de5bd2ae559a4 Mon Sep 17 00:00:00 2001 From: charsunny Date: Mon, 6 Nov 2023 20:37:42 -0600 Subject: [PATCH] =?UTF-8?q?ADD:=20PostFormAliPayAPISelfV2=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=E7=94=A8=E4=BA=8E=E6=94=AF=E4=BB=98=E5=AE=9D=E5=B8=A6?= =?UTF-8?q?=E6=9C=89=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E7=9A=84=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=87=AA=E8=A1=8C=E5=AE=9E=E7=8E=B0=E6=96=B9=E6=B3=95?= =?UTF-8?q?=20(#363)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ADD:FormAliPayAPISelfV2 实现用于支付宝带有文件上传的接口自行实现方法 // 注意:最新版本的支付宝接口,对于文件的上传已统一改为通过formData上传 // 请求form格式如下: {file: "fileData", "data": BodyMap{"key": "value"}} // 其中file为file请求字段名称,data为其他请求参数(key为文件名,value为文件内容) Co-authored-by: Xi Sun --- alipay/request.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++ alipay/sign.go | 30 +++++++++++++++++++++ 2 files changed, 96 insertions(+) diff --git a/alipay/request.go b/alipay/request.go index e04a4e6c..82ebf80e 100644 --- a/alipay/request.go +++ b/alipay/request.go @@ -37,6 +37,72 @@ func (a *Client) PostAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, meth return nil } +// FormAliPayAPISelfV2 用于支付宝带有文件上传的接口自行实现方法 +// 注意:最新版本的支付宝接口,对于文件的上传已统一改为通过formData上传 +// 请求form格式如下: {file: "fileData", "data": BodyMap{"key": "value"}} +// 其中file为file请求字段名称,data为其他请求参数(key为文件名,value为文件内容) +func (a *Client) PostFormAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, method string, aliRsp any) (err error) { + var ( + url string + sign string + ) + fm := make(gopay.BodyMap) + if bm != nil { + for k, v := range bm { + if _, ok := v.(*util.File); ok { + fm.Set(k, v) + bm.Remove(k) + continue + } else { + // 对form内容字段进行加密 + str := bm.GetString(k) + bm.Remove(k) + if signedData, err := a.getStrRsaSign(str, bm.GetString("sign_type")); err == nil { + bm.Set(k, signedData) + } + } + } + } + bm.Set("method", method) + // check public parameter + a.checkPublicParam(bm) + // check sign, 需要先移除文件字段 + if bm.GetString("sign") == "" { + sign, err = a.getRsaSign(bm, bm.GetString("sign_type")) + if err != nil { + return fmt.Errorf("GetRsaSign Error: %w", err) + } + bm.Set("sign", sign) + } + // 增加文件字段 + for k, v := range fm { + bm.Set(k, v) + } + if a.DebugSwitch == gopay.DebugOn { + xlog.Debugf("Alipay_Request: %s", bm.JsonBody()) + } + if a.IsProd { + url = baseUrlUtf8 + } else { + url = sandboxBaseUrlUtf8 + } + res, bs, err := a.hc.Req(xhttp.TypeMultipartFormData).Post(url). + SendMultipartBodyMap(bm).EndBytes(ctx) + if err != nil { + return nil + } + if a.DebugSwitch == gopay.DebugOn { + xlog.Debugf("Alipay_Response: %s%d %s%s", xlog.Red, res.StatusCode, xlog.Reset, string(bs)) + } + if res.StatusCode != 200 { + return fmt.Errorf("HTTP Request Error, StatusCode = %d", res.StatusCode) + } + if err = json.Unmarshal(bs, aliRsp); err != nil { + return err + } + return nil +} + // 向支付宝发送自定义请求 func (a *Client) doAliPaySelf(ctx context.Context, bm gopay.BodyMap, method string) (bs []byte, err error) { var ( diff --git a/alipay/sign.go b/alipay/sign.go index a8dd3905..0dae68b1 100644 --- a/alipay/sign.go +++ b/alipay/sign.go @@ -205,6 +205,36 @@ func (a *Client) getRsaSign(bm gopay.BodyMap, signType string) (sign string, err return } +func (a *Client) getStrRsaSign(signParams string, signType string) (sign string, err error) { + var ( + h hash.Hash + hashs crypto.Hash + encryptedBytes []byte + ) + switch signType { + case RSA: + h = sha1.New() + hashs = crypto.SHA1 + case RSA2: + h = sha256.New() + hashs = crypto.SHA256 + default: + h = sha256.New() + hashs = crypto.SHA256 + } + if a.DebugSwitch == gopay.DebugOn { + xlog.Debugf("Alipay_Request_SignStr: %s", signParams) + } + if _, err = h.Write([]byte(signParams)); err != nil { + return + } + if encryptedBytes, err = rsa.SignPKCS1v15(rand.Reader, a.privateKey, hashs, h.Sum(nil)); err != nil { + return util.NULL, fmt.Errorf("[%w]: %+v", gopay.SignatureErr, err) + } + sign = base64.StdEncoding.EncodeToString(encryptedBytes) + return +} + // =============================== 获取SignData =============================== // 需注意的是,公钥签名模式和公钥证书签名模式的不同之处