From eb4a5e5de23048655aaa6ef8104df626bc575d80 Mon Sep 17 00:00:00 2001 From: Xi Sun Date: Fri, 3 Nov 2023 14:31:10 +0800 Subject: [PATCH 1/5] =?UTF-8?q?ADD:FormAliPayAPISelfV2=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//=20=E6=B3=A8=E6=84=8F=EF=BC=9A=E6=9C=80=E6=96=B0=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E7=9A=84=E6=94=AF=E4=BB=98=E5=AE=9D=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=EF=BC=8C=E5=AF=B9=E4=BA=8E=E6=96=87=E4=BB=B6=E7=9A=84=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E5=B7=B2=E7=BB=9F=E4=B8=80=E6=94=B9=E4=B8=BA=E9=80=9A?= =?UTF-8?q?=E8=BF=87formData=E4=B8=8A=E4=BC=A0=20//=20=E8=AF=B7=E6=B1=82fo?= =?UTF-8?q?rm=E6=A0=BC=E5=BC=8F=E5=A6=82=E4=B8=8B=EF=BC=9A=20{file:=20"fil?= =?UTF-8?q?eData",=20"data":=20BodyMap{"key":=20"value"}}=20//=20=E5=85=B6?= =?UTF-8?q?=E4=B8=ADfile=E4=B8=BAfile=E8=AF=B7=E6=B1=82=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=EF=BC=8Cdata=E4=B8=BA=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E8=AF=B7=E6=B1=82=E5=8F=82=E6=95=B0=EF=BC=88key=E4=B8=BA?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=90=8D=EF=BC=8Cvalue=E4=B8=BA=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=86=85=E5=AE=B9=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- alipay/request.go | 75 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/alipay/request.go b/alipay/request.go index a19b40f5..d26e1be4 100644 --- a/alipay/request.go +++ b/alipay/request.go @@ -37,6 +37,81 @@ 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 ( + aat string + ) + pubBody := make(gopay.BodyMap) + formData := make(gopay.BodyMap) + if bm != nil { + aat = bm.GetString("app_auth_token") + bm.Remove("app_auth_token") + for k, v := range bm { + if file, ok := v.(*util.File); ok { + bm.Remove(k) + formData.SetFormFile(k, file) + } else { + formData.Set(k, v) + } + } + } + pubBody.Set("app_id", a.AppId). + Set("method", method). + Set("format", "JSON"). + Set("charset", a.Charset). + Set("sign_type", a.SignType). + Set("version", "1.0"). + Set("scene", "SYNC_ORDER"). + Set("timestamp", time.Now().Format(util.TimeLayout)) + + if a.AppCertSN != util.NULL { + pubBody.Set("app_cert_sn", a.AppCertSN) + } + if a.AliPayRootCertSN != util.NULL { + pubBody.Set("alipay_root_cert_sn", a.AliPayRootCertSN) + } + if a.location != nil { + pubBody.Set("timestamp", time.Now().In(a.location).Format(util.TimeLayout)) + } + //fmt.Println("notify,", pubBody.JsonBody()) + if a.AppAuthToken != util.NULL { + pubBody.Set("app_auth_token", a.AppAuthToken) + } + if aat != util.NULL { + pubBody.Set("app_auth_token", aat) + } + sign, err := a.getRsaSign(pubBody, pubBody.GetString("sign_type")) + if err != nil { + return fmt.Errorf("GetRsaSign Error: %w", err) + } + pubBody.Set("sign", sign) + if a.DebugSwitch == gopay.DebugOn { + xlog.Debugf("Alipay_Request: %s", pubBody.JsonBody()) + } + param := pubBody.EncodeURLParams() + url := baseUrlUtf8 + "&" + param + bm.Reset() + res, bs, err := a.hc.Req(xhttp.TypeMultipartFormData).Post(url). + SendMultipartBodyMap(formData).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 ( From 32c18b9534d06e67325d51988312ec9f89e20d16 Mon Sep 17 00:00:00 2001 From: Xi Sun Date: Fri, 3 Nov 2023 15:55:48 +0800 Subject: [PATCH 2/5] fix form data type change error --- alipay/request.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/alipay/request.go b/alipay/request.go index d26e1be4..fca5d6f9 100644 --- a/alipay/request.go +++ b/alipay/request.go @@ -136,7 +136,7 @@ func (a *Client) doAliPaySelf(ctx context.Context, bm gopay.BodyMap, method stri } else { url = sandboxBaseUrlUtf8 } - res, bs, err := a.hc.Req(xhttp.TypeForm).Post(url).SendString(bm.EncodeURLParams()).EndBytes(ctx) + res, bs, err := a.hc.Req(xhttp.TypeFormData).Post(url).SendString(bm.EncodeURLParams()).EndBytes(ctx) if err != nil { return nil, err } @@ -191,7 +191,7 @@ func (a *Client) doAliPay(ctx context.Context, bm gopay.BodyMap, method string, if !a.IsProd { url = sandboxBaseUrlUtf8 } - res, bs, err := a.hc.Req(xhttp.TypeForm).Post(url).SendString(param).EndBytes(ctx) + res, bs, err := a.hc.Req(xhttp.TypeFormData).Post(url).SendString(param).EndBytes(ctx) if err != nil { return nil, err } @@ -247,7 +247,7 @@ func (a *Client) DoAliPay(ctx context.Context, bm gopay.BodyMap, method string, if !a.IsProd { url = sandboxBaseUrlUtf8 } - res, bs, err := a.hc.Req(xhttp.TypeForm).Post(url).SendString(param).EndBytes(ctx) + res, bs, err := a.hc.Req(xhttp.TypeFormData).Post(url).SendString(param).EndBytes(ctx) if err != nil { return nil, err } From a28ef2d1ef5fad4f948b2a13c780d4a92cf4c1b6 Mon Sep 17 00:00:00 2001 From: Xi Sun Date: Fri, 3 Nov 2023 16:01:19 +0800 Subject: [PATCH 3/5] fix form data type change error --- allinpay/client.go | 2 +- paypal/access_token.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/allinpay/client.go b/allinpay/client.go index 82a9e36e..31f1f108 100644 --- a/allinpay/client.go +++ b/allinpay/client.go @@ -127,7 +127,7 @@ func (c *Client) doPost(ctx context.Context, path string, bm gopay.BodyMap) (bs if !c.isProd { url = sandboxBaseUrl } - res, bs, err := c.hc.Req(xhttp.TypeForm).Post(url + path).SendString(param).EndBytes(ctx) + res, bs, err := c.hc.Req(xhttp.TypeFormData).Post(url + path).SendString(param).EndBytes(ctx) if err != nil { return nil, err } diff --git a/paypal/access_token.go b/paypal/access_token.go index 0243d0f1..d05e7d71 100644 --- a/paypal/access_token.go +++ b/paypal/access_token.go @@ -24,7 +24,7 @@ func (c *Client) GetAccessToken() (token *AccessToken, err error) { url = baseUrl + getAccessToken // Authorization authHeader := AuthorizationPrefixBasic + base64.StdEncoding.EncodeToString([]byte(c.Clientid+":"+c.Secret)) - req := c.hc.Req(xhttp.TypeForm) + req := c.hc.Req(xhttp.TypeFormData) req.Header.Add(HeaderAuthorization, authHeader) req.Header.Add("Accept", "*/*") // Body From dae181e5b05d39e552696622b8ce222adf7a2eb6 Mon Sep 17 00:00:00 2001 From: Xi Sun Date: Fri, 3 Nov 2023 16:59:34 +0800 Subject: [PATCH 4/5] fix sign err bug --- alipay/request.go | 70 ++++++++++++++++++----------------------------- alipay/sign.go | 30 ++++++++++++++++++++ 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/alipay/request.go b/alipay/request.go index fca5d6f9..236588e7 100644 --- a/alipay/request.go +++ b/alipay/request.go @@ -43,60 +43,44 @@ func (a *Client) PostAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, meth // 其中file为file请求字段名称,data为其他请求参数(key为文件名,value为文件内容) func (a *Client) PostFormAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, method string, aliRsp any) (err error) { var ( - aat string + url string + sign string ) - pubBody := make(gopay.BodyMap) - formData := make(gopay.BodyMap) if bm != nil { - aat = bm.GetString("app_auth_token") - bm.Remove("app_auth_token") for k, v := range bm { - if file, ok := v.(*util.File); ok { - bm.Remove(k) - formData.SetFormFile(k, file) + if _, ok := v.(*util.File); ok { + continue } else { - formData.Set(k, v) + // 对form内容字段进行加密 + str := bm.GetString(k) + bm.Remove(k) + if signedData, err := a.getStrRsaSign(str, bm.GetString("sign_type")); err == nil { + bm.Set(k, signedData) + } } } } - pubBody.Set("app_id", a.AppId). - Set("method", method). - Set("format", "JSON"). - Set("charset", a.Charset). - Set("sign_type", a.SignType). - Set("version", "1.0"). - Set("scene", "SYNC_ORDER"). - Set("timestamp", time.Now().Format(util.TimeLayout)) - - if a.AppCertSN != util.NULL { - pubBody.Set("app_cert_sn", a.AppCertSN) - } - if a.AliPayRootCertSN != util.NULL { - pubBody.Set("alipay_root_cert_sn", a.AliPayRootCertSN) - } - if a.location != nil { - pubBody.Set("timestamp", time.Now().In(a.location).Format(util.TimeLayout)) - } - //fmt.Println("notify,", pubBody.JsonBody()) - if a.AppAuthToken != util.NULL { - pubBody.Set("app_auth_token", a.AppAuthToken) - } - if aat != util.NULL { - pubBody.Set("app_auth_token", aat) - } - sign, err := a.getRsaSign(pubBody, pubBody.GetString("sign_type")) - if err != nil { - return fmt.Errorf("GetRsaSign Error: %w", err) + 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) } - pubBody.Set("sign", sign) if a.DebugSwitch == gopay.DebugOn { - xlog.Debugf("Alipay_Request: %s", pubBody.JsonBody()) + xlog.Debugf("Alipay_Request: %s", bm.JsonBody()) + } + if a.IsProd { + url = baseUrlUtf8 + } else { + url = sandboxBaseUrlUtf8 } - param := pubBody.EncodeURLParams() - url := baseUrlUtf8 + "&" + param - bm.Reset() res, bs, err := a.hc.Req(xhttp.TypeMultipartFormData).Post(url). - SendMultipartBodyMap(formData).EndBytes(ctx) + SendMultipartBodyMap(bm).EndBytes(ctx) if err != nil { return nil } 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 =============================== // 需注意的是,公钥签名模式和公钥证书签名模式的不同之处 From f47b778d42296b7f8336d5d8d2c467ba7f1cfda5 Mon Sep 17 00:00:00 2001 From: Xi Sun Date: Fri, 3 Nov 2023 17:19:13 +0800 Subject: [PATCH 5/5] fix sign error --- alipay/request.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/alipay/request.go b/alipay/request.go index 236588e7..82ebf80e 100644 --- a/alipay/request.go +++ b/alipay/request.go @@ -46,9 +46,12 @@ func (a *Client) PostFormAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, 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内容字段进行加密 @@ -63,7 +66,7 @@ func (a *Client) PostFormAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, bm.Set("method", method) // check public parameter a.checkPublicParam(bm) - // check sign + // check sign, 需要先移除文件字段 if bm.GetString("sign") == "" { sign, err = a.getRsaSign(bm, bm.GetString("sign_type")) if err != nil { @@ -71,6 +74,10 @@ func (a *Client) PostFormAliPayAPISelfV2(ctx context.Context, bm gopay.BodyMap, } 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()) }