Jerry 6 лет назад
Родитель
Сommit
c2f85a810f

+ 8 - 9
README.md

@@ -96,7 +96,8 @@
 * gopay.FormatAliPayPublicKey() => 格式化支付宝公钥
 * gopay.ParseAliPayNotifyResult() => 解析支付宝支付异步通知的参数到Struct
 * gopay.ParseAliPayNotifyResultToBodyMap() => 解析支付宝支付异步通知的参数到BodyMap
-* gopay.VerifyAliPaySign() => 支付宝同步返回参数验签或异步通知参数验签
+* gopay.VerifyAliPaySign() => 支付宝异步通知参数验签
+* gopay.VerifyAliPaySyncSign() => 支付宝同步返回参数验签
 * gopay.DecryptAliPayOpenDataToStruct() => 支付宝小程序敏感加密数据解析到结构体
 
 # 一、安装
@@ -395,22 +396,20 @@ return c.String(http.StatusOK, rsp.ToXmlString())   //此写法是 echo 框架
 
 * #### 支付宝
 
-支付宝的**同步返回**验签,参数请注意看注释
-
-APP支付: 暂不支持同步返回验签
+注意:APP支付、手机网站支付、电脑网站支付 暂不支持同步返回验签
 
 支付宝支付后的同步/异步通知验签文档:[支付结果通知](https://docs.open.alipay.com/200/106120)
 ```go
 //====同步返回参数验签Sign====
 aliRsp, err := client.AliPayTradePay(bm)
-//支付宝同步返回验签或异步通知验签
+//支付宝同步返回验签
 //    注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签
 //    aliPayPublicKey:支付宝公钥
-//    bean: 同步返回验签时,此参数为 aliRsp.SignData ;异步通知验签时,此参数为异步通知解析的结构体 notifyReq
-//    syncSign:同步返回验签时,此参数必传,即:aliRsp.Sign ;异步通知验签时,不要传此参数,否则会出错。
+//    signData:待验签参数,aliRsp.SignData
+//    sign:待验签sign,aliRsp.Sign
 //    返回参数ok:是否验签通过
 //    返回参数err:错误信息
-ok, err := gopay.VerifyAliPaySign(alipayPublicKey, aliRsp.SignData, aliRsp.Sign)
+ok, err := gopay.VerifyAliPaySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
 
 //====异步通知参数解析和验签Sign====
 //解析异步通知的参数
@@ -419,7 +418,7 @@ ok, err := gopay.VerifyAliPaySign(alipayPublicKey, aliRsp.SignData, aliRsp.Sign)
 //    返回参数 err:错误信息
 notifyReq, err = gopay.ParseAliPayNotifyResult(c.Request())     //c.Request()是 echo 框架的获取
 //验签操作
-ok, err = gopay.VerifyAliPaySign(alipayPublicKey, notifyReq)
+ok, err = gopay.VerifyAliPaySign(aliPayPublicKey, notifyReq)
 
 //==异步通知,返回支付宝平台的信息==
 //    文档:https://docs.open.alipay.com/203/105286

+ 31 - 14
alipay_client.go

@@ -12,18 +12,19 @@ import (
 )
 
 type AliPayClient struct {
-	AppId            string
-	PrivateKey       string
-	AlipayRootCertSN string
-	AppCertSN        string
-	ReturnUrl        string
-	NotifyUrl        string
-	Charset          string
-	SignType         string
-	AppAuthToken     string
-	AuthToken        string
-	IsProd           bool
-	mu               sync.Mutex
+	AppId              string
+	PrivateKey         string
+	AppCertSN          string
+	AliPayPublicCertSN string
+	AliPayRootCertSN   string
+	ReturnUrl          string
+	NotifyUrl          string
+	Charset            string
+	SignType           string
+	AppAuthToken       string
+	AuthToken          string
+	IsProd             bool
+	mu                 sync.RWMutex
 }
 
 // 初始化支付宝客户端
@@ -537,34 +538,50 @@ func (a *AliPayClient) doAliPay(body BodyMap, method string) (bytes []byte, err
 	pubBody.Set("method", method)
 	pubBody.Set("format", "JSON")
 	if a.AppCertSN != null {
+		a.mu.RLock()
 		pubBody.Set("app_cert_sn", a.AppCertSN)
+		a.mu.RUnlock()
 	}
-	if a.AlipayRootCertSN != null {
-		pubBody.Set("alipay_root_cert_sn", a.AlipayRootCertSN)
+	if a.AliPayRootCertSN != null {
+		a.mu.RLock()
+		pubBody.Set("alipay_root_cert_sn", a.AliPayRootCertSN)
+		a.mu.RUnlock()
 	}
 	if a.ReturnUrl != null {
+		a.mu.RLock()
 		pubBody.Set("return_url", a.ReturnUrl)
+		a.mu.RUnlock()
 	}
 	if a.Charset == null {
 		pubBody.Set("charset", "utf-8")
 	} else {
+		a.mu.RLock()
 		pubBody.Set("charset", a.Charset)
+		a.mu.RUnlock()
 	}
 	if a.SignType == null {
 		pubBody.Set("sign_type", "RSA2")
 	} else {
+		a.mu.RLock()
 		pubBody.Set("sign_type", a.SignType)
+		a.mu.RUnlock()
 	}
 	pubBody.Set("timestamp", time.Now().Format(TimeLayout))
 	pubBody.Set("version", "1.0")
 	if a.NotifyUrl != null {
+		a.mu.RLock()
 		pubBody.Set("notify_url", a.NotifyUrl)
+		a.mu.RUnlock()
 	}
 	if a.AppAuthToken != null {
+		a.mu.RLock()
 		pubBody.Set("app_auth_token", a.AppAuthToken)
+		a.mu.RUnlock()
 	}
 	if a.AuthToken != null {
+		a.mu.RLock()
 		pubBody.Set("auth_token", a.AuthToken)
+		a.mu.RUnlock()
 	}
 	if bodyStr != null {
 		pubBody.Set("biz_content", bodyStr)

+ 53 - 4
alipay_params.go

@@ -10,6 +10,7 @@ import (
 	"encoding/base64"
 	"encoding/pem"
 	"errors"
+	"fmt"
 	"hash"
 	"net/url"
 )
@@ -45,15 +46,63 @@ func (a *AliPayClient) SetAppCertSN(appCertSN string) (client *AliPayClient) {
 	return a
 }
 
-// 设置 支付宝证书SN
-//    alipayRootCertSN:支付宝根证书SN,通过 gopay.GetCertSN() 获取
-func (a *AliPayClient) SetAliPayRootCertSN(alipayRootCertSN string) (client *AliPayClient) {
+// 设置 支付宝公钥证书SN
+//    aliPayPublicCertSN:支付宝公钥证书SN,通过 gopay.GetCertSN() 获取
+func (a *AliPayClient) SetAliPayPublicCertSN(aliPayPublicCertSN string) (client *AliPayClient) {
 	a.mu.Lock()
-	a.AlipayRootCertSN = alipayRootCertSN
+	a.AliPayPublicCertSN = aliPayPublicCertSN
 	a.mu.Unlock()
 	return a
 }
 
+// 设置 支付宝CA根证书SN
+//    aliPayRootCertSN:支付宝CA根证书SN,通过 gopay.GetCertSN() 获取
+func (a *AliPayClient) SetAliPayRootCertSN(aliPayRootCertSN string) (client *AliPayClient) {
+	a.mu.Lock()
+	a.AliPayRootCertSN = aliPayRootCertSN
+	a.mu.Unlock()
+	return a
+}
+
+// 设置 应用公钥证书路径,并赋值 app_cert_sn
+//    appCertPath:应用公钥证书路径
+func (a *AliPayClient) SetAppCertPath(appCertPath string) (client *AliPayClient, err error) {
+	sn, err := GetCertSN(appCertPath)
+	if err != nil {
+		return a, fmt.Errorf("get app_cert_sn return err, but alse return alipay client. err: %v", err)
+	}
+	a.mu.Lock()
+	a.AppCertSN = sn
+	a.mu.Unlock()
+	return a, nil
+}
+
+// 设置 支付宝公钥证书文件路径,并赋值 alipay_cert_sn
+//    aliPayPublicCertPath:支付宝公钥证书文件路径
+func (a *AliPayClient) SetAliPayPublicCertPath(aliPayPublicCertPath string) (client *AliPayClient, err error) {
+	sn, err := GetCertSN(aliPayPublicCertPath)
+	if err != nil {
+		return a, fmt.Errorf("get alipay_cert_sn return err, but alse return alipay client. err: %v", err)
+	}
+	a.mu.Lock()
+	a.AliPayPublicCertSN = sn
+	a.mu.Unlock()
+	return a, nil
+}
+
+// 设置 支付宝CA根证书文件路径,并赋值 alipay_root_cert_sn
+//    aliPayRootCertPath:支付宝CA根证书文件路径
+func (a *AliPayClient) SetAliPayRootCertPath(aliPayRootCertPath string) (client *AliPayClient, err error) {
+	sn, err := GetCertSN(aliPayRootCertPath)
+	if err != nil {
+		return a, fmt.Errorf("get alipay_root_cert_sn return err, but alse return alipay client. err: %v", err)
+	}
+	a.mu.Lock()
+	a.AliPayRootCertSN = sn
+	a.mu.Unlock()
+	return a, nil
+}
+
 // 设置支付后的ReturnUrl
 func (a *AliPayClient) SetReturnUrl(url string) (client *AliPayClient) {
 	a.mu.Lock()

+ 55 - 41
alipay_rsp.go

@@ -226,9 +226,10 @@ type closeResponse struct {
 
 //===================================================
 type AliPayTradeCancelResponse struct {
-	Response *cancelResponse `json:"alipay_trade_cancel_response,omitempty"`
-	SignData string          `json:"-"`
-	Sign     string          `json:"sign"`
+	Response     *cancelResponse `json:"alipay_trade_cancel_response,omitempty"`
+	AliPayCertSn string          `json:"alipay_cert_sn,omitempty"`
+	SignData     string          `json:"-"`
+	Sign         string          `json:"sign"`
 }
 
 type cancelResponse struct {
@@ -253,8 +254,9 @@ type AliPaySystemOauthTokenResponse struct {
 		SubCode string `json:"sub_code,omitempty"`
 		SubMsg  string `json:"sub_msg,omitempty"`
 	} `json:"error_response,omitempty"`
-	SignData string `json:"-"`
-	Sign     string `json:"sign"`
+	AliPayCertSn string `json:"alipay_cert_sn,omitempty"`
+	SignData     string `json:"-"`
+	Sign         string `json:"sign"`
 }
 type oauthTokenInfo struct {
 	AccessToken  string `json:"access_token,omitempty"`
@@ -267,9 +269,10 @@ type oauthTokenInfo struct {
 
 //===================================================
 type AliPayUserInfoShareResponse struct {
-	Response *userInfoShare `json:"alipay_user_info_share_response,omitempty"`
-	SignData string         `json:"-"`
-	Sign     string         `json:"sign"`
+	Response     *userInfoShare `json:"alipay_user_info_share_response,omitempty"`
+	AliPayCertSn string         `json:"alipay_cert_sn,omitempty"`
+	SignData     string         `json:"-"`
+	Sign         string         `json:"sign"`
 }
 
 type userInfoShare struct {
@@ -291,9 +294,10 @@ type userInfoShare struct {
 
 //===================================================
 type AliPayTradeRefundResponse struct {
-	Response *refundResponse `json:"alipay_trade_refund_response,omitempty"`
-	SignData string          `json:"-"`
-	Sign     string          `json:"sign"`
+	Response     *refundResponse `json:"alipay_trade_refund_response,omitempty"`
+	AliPayCertSn string          `json:"alipay_cert_sn,omitempty"`
+	SignData     string          `json:"-"`
+	Sign         string          `json:"sign"`
 }
 
 type refundResponse struct {
@@ -331,9 +335,10 @@ type tradeFundBill struct {
 
 //===================================================
 type AliPayTradeFastpayRefundQueryResponse struct {
-	Response *refundQueryResponse `json:"alipay_trade_fastpay_refund_query_response,omitempty"`
-	SignData string               `json:"-"`
-	Sign     string               `json:"sign"`
+	Response     *refundQueryResponse `json:"alipay_trade_fastpay_refund_query_response,omitempty"`
+	AliPayCertSn string               `json:"alipay_cert_sn,omitempty"`
+	SignData     string               `json:"-"`
+	Sign         string               `json:"sign"`
 }
 
 type refundQueryResponse struct {
@@ -367,9 +372,10 @@ type refundQueryResponse struct {
 
 //===================================================
 type AliPayTradeOrderSettleResponse struct {
-	Response *orderSettleResponse `json:"alipay_trade_order_settle_response,omitempty"`
-	SignData string               `json:"-"`
-	Sign     string               `json:"sign"`
+	Response     *orderSettleResponse `json:"alipay_trade_order_settle_response,omitempty"`
+	AliPayCertSn string               `json:"alipay_cert_sn,omitempty"`
+	SignData     string               `json:"-"`
+	Sign         string               `json:"sign"`
 }
 type orderSettleResponse struct {
 	Code    string `json:"code,omitempty"`
@@ -381,9 +387,10 @@ type orderSettleResponse struct {
 
 //===================================================
 type AliPayTradePrecreateResponse struct {
-	Response *precreateResponse `json:"alipay_trade_precreate_response,omitempty"`
-	SignData string             `json:"-"`
-	Sign     string             `json:"sign"`
+	Response     *precreateResponse `json:"alipay_trade_precreate_response,omitempty"`
+	AliPayCertSn string             `json:"alipay_cert_sn,omitempty"`
+	SignData     string             `json:"-"`
+	Sign         string             `json:"sign"`
 }
 
 type precreateResponse struct {
@@ -397,9 +404,10 @@ type precreateResponse struct {
 
 //===================================================
 type AliPayTradePageRefundResponse struct {
-	Response *pageRefundResponse `json:"alipay_trade_page_refund_response,omitempty"`
-	SignData string              `json:"-"`
-	Sign     string              `json:"sign"`
+	Response     *pageRefundResponse `json:"alipay_trade_page_refund_response,omitempty"`
+	AliPayCertSn string              `json:"alipay_cert_sn,omitempty"`
+	SignData     string              `json:"-"`
+	Sign         string              `json:"sign"`
 }
 
 type pageRefundResponse struct {
@@ -415,9 +423,10 @@ type pageRefundResponse struct {
 
 //===================================================
 type AliPayFundTransToaccountTransferResponse struct {
-	Response *transToaccountTransferResponse `json:"alipay_fund_trans_toaccount_transfer_response,omitempty"`
-	SignData string                          `json:"-"`
-	Sign     string                          `json:"sign"`
+	Response     *transToaccountTransferResponse `json:"alipay_fund_trans_toaccount_transfer_response,omitempty"`
+	AliPayCertSn string                          `json:"alipay_cert_sn,omitempty"`
+	SignData     string                          `json:"-"`
+	Sign         string                          `json:"sign"`
 }
 
 type transToaccountTransferResponse struct {
@@ -432,9 +441,10 @@ type transToaccountTransferResponse struct {
 
 //===================================================
 type ZhimaCreditScoreGetResponse struct {
-	Response *scoreGetResponse `json:"zhima_credit_score_get_response,omitempty"`
-	SignData string            `json:"-"`
-	Sign     string            `json:"sign"`
+	Response     *scoreGetResponse `json:"zhima_credit_score_get_response,omitempty"`
+	AliPayCertSn string            `json:"alipay_cert_sn,omitempty"`
+	SignData     string            `json:"-"`
+	Sign         string            `json:"sign"`
 }
 
 type scoreGetResponse struct {
@@ -448,9 +458,10 @@ type scoreGetResponse struct {
 
 //===================================================
 type AliPayOpenAuthTokenAppResponse struct {
-	Response *authTokenAppResponse `json:"alipay_open_auth_token_app_response,omitempty"`
-	SignData string                `json:"-"`
-	Sign     string                `json:"sign"`
+	Response     *authTokenAppResponse `json:"alipay_open_auth_token_app_response,omitempty"`
+	AliPayCertSn string                `json:"alipay_cert_sn,omitempty"`
+	SignData     string                `json:"-"`
+	Sign         string                `json:"sign"`
 }
 
 type authTokenAppResponse struct {
@@ -476,9 +487,10 @@ type authTokenAppResponse struct {
 
 //===================================================
 type AliPayUserCertifyOpenInitResponse struct {
-	Response *userCertifyOpenInitResponse `json:"alipay_user_certify_open_initialize_response,omitempty"`
-	SignData string                       `json:"-"`
-	Sign     string                       `json:"sign"`
+	Response     *userCertifyOpenInitResponse `json:"alipay_user_certify_open_initialize_response,omitempty"`
+	AliPayCertSn string                       `json:"alipay_cert_sn,omitempty"`
+	SignData     string                       `json:"-"`
+	Sign         string                       `json:"sign"`
 }
 
 type userCertifyOpenInitResponse struct {
@@ -491,9 +503,10 @@ type userCertifyOpenInitResponse struct {
 
 //===================================================
 type AliPayUserCertifyOpenCertifyResponse struct {
-	Response *userCertifyOpenCertifyResponse `json:"alipay_user_certify_open_certify_response,omitempty"`
-	SignData string                          `json:"-"`
-	Sign     string                          `json:"sign"`
+	Response     *userCertifyOpenCertifyResponse `json:"alipay_user_certify_open_certify_response,omitempty"`
+	AliPayCertSn string                          `json:"alipay_cert_sn,omitempty"`
+	SignData     string                          `json:"-"`
+	Sign         string                          `json:"sign"`
 }
 
 type userCertifyOpenCertifyResponse struct {
@@ -505,9 +518,10 @@ type userCertifyOpenCertifyResponse struct {
 
 //===================================================
 type AliPayUserCertifyOpenQueryResponse struct {
-	Response *userCertifyOpenQueryResponse `json:"alipay_user_certify_open_query_response,omitempty"`
-	SignData string                        `json:"-"`
-	Sign     string                        `json:"sign"`
+	Response     *userCertifyOpenQueryResponse `json:"alipay_user_certify_open_query_response,omitempty"`
+	AliPayCertSn string                        `json:"alipay_cert_sn,omitempty"`
+	SignData     string                        `json:"-"`
+	Sign         string                        `json:"sign"`
 }
 
 type userCertifyOpenQueryResponse struct {

+ 25 - 17
alipay_service_api.go

@@ -134,33 +134,41 @@ A:开发者上传自己的应用公钥证书后,开放平台会为开发者
 基于该机制可实现支付宝公钥证书变更时开发者无感知,当前开放平台提供的SDK已基于该机制实现对应功能。若开发者未通过SDK接入,须自行实现该功能。
 */
 
-// VerifyAliPaySign 支付宝同步返回验签或异步通知验签
+// VerifyAliPaySyncSign 支付宝同步返回验签
 //    注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签
 //    aliPayPublicKey:支付宝公钥
-//    bean: 同步返回验签时,此参数为字符串 aliRsp.SignData ;异步通知验签时,此参数为异步通知解析的结构体或BodyMap:notifyReq 或 bm
-//    syncSign:同步返回验签时,此参数必传,即:aliRsp.Sign ;异步通知验签时,不传此参数,否则会出错。
+//    signData:待验签参数,aliRsp.SignData
+//    sign:待验签sign,aliRsp.Sign
 //    返回参数ok:是否验签通过
 //    返回参数err:错误信息
 //    验签文档:https://docs.open.alipay.com/200/106120
-func VerifyAliPaySign(aliPayPublicKey string, bean interface{}, syncSign ...string) (ok bool, err error) {
+func VerifyAliPaySyncSign(aliPayPublicKey, signData, sign string) (ok bool, err error) {
+
+	// 支付宝公钥验签
+	pKey := FormatAliPayPublicKey(aliPayPublicKey)
+	if err = verifyAliPaySign(signData, sign, "RSA2", pKey); err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+// VerifyAliPaySign 支付宝异步通知验签
+//    注意:APP支付,手机网站支付,电脑网站支付 暂不支持同步返回验签
+//    aliPayPublicKey:支付宝公钥
+//    bean:此参数为异步通知解析的结构体或BodyMap:notifyReq 或 bm
+//    返回参数ok:是否验签通过
+//    返回参数err:错误信息
+//    验签文档:https://docs.open.alipay.com/200/106120
+func VerifyAliPaySign(aliPayPublicKey string, bean interface{}) (ok bool, err error) {
 	if bean == nil {
 		return false, errors.New("bean is nil")
 	}
 	var (
 		bodySign     string
 		bodySignType string
-		pKey         string
 		signData     string
-		bm           BodyMap
-		bs           []byte
+		bm           = make(BodyMap)
 	)
-	if len(syncSign) > 0 {
-		bodySign = syncSign[0]
-		bodySignType = "RSA2"
-		signData = bean.(string)
-		goto Verify
-	}
-	bm = make(BodyMap)
 	if reflect.ValueOf(bean).Kind() == reflect.Map {
 		if bm, ok = bean.(BodyMap); ok {
 			bodySign = bm.Get("sign")
@@ -170,7 +178,8 @@ func VerifyAliPaySign(aliPayPublicKey string, bean interface{}, syncSign ...stri
 			signData = bm.EncodeAliPaySignParams()
 		}
 	} else {
-		if bs, err = json.Marshal(bean); err != nil {
+		bs, err := json.Marshal(bean)
+		if err != nil {
 			return false, fmt.Errorf("json.Marshal:%s", err.Error())
 		}
 		if err = json.Unmarshal(bs, &bm); err != nil {
@@ -182,8 +191,7 @@ func VerifyAliPaySign(aliPayPublicKey string, bean interface{}, syncSign ...stri
 		bm.Remove("sign_type")
 		signData = bm.EncodeAliPaySignParams()
 	}
-Verify:
-	pKey = FormatAliPayPublicKey(aliPayPublicKey)
+	pKey := FormatAliPayPublicKey(aliPayPublicKey)
 	if err = verifyAliPaySign(signData, bodySign, bodySignType, pKey); err != nil {
 		return false, err
 	}

+ 1 - 1
constant.go

@@ -4,7 +4,7 @@ const (
 	null       string = ""
 	TimeLayout string = "2006-01-02 15:04:05"
 	DateLayout string = "2006-01-02"
-	Version    string = "1.4.4"
+	Version    string = "1.4.5"
 	// 微信
 	// ===========================================================================================
 

+ 68 - 0
doc.go

@@ -0,0 +1,68 @@
+package gopay
+
+/*
+
+// Java SDK 获取Root证书SN
+public static String getRootCertSN(String rootCertContent){
+   String rootCertSN = null;
+   try {
+	   X509Certificate[] x509Certificates = readPemCertChain(rootCertContent);
+	   MessageDigest md = MessageDigest.getInstance("MD5");
+	   for (X509Certificate c : x509Certificates) {
+		   if(c.getSigAlgOID().startsWith("1.2.840.113549.1.1")){
+			   md.update((c.getIssuerX500Principal().getName() + c.getSerialNumber()).getBytes());
+			   String certSN = new BigInteger(1,md.digest()).toString(16);
+			   //BigInteger���0ʡ�Ե����貹ȫ��32λ
+			   certSN = fillMD5(certSN);
+			   if(StringUtils.isEmpty(rootCertSN)){
+				   rootCertSN = certSN;
+			   }else {
+				   rootCertSN = rootCertSN + "_" + certSN;
+			   }
+		   }
+
+	   }
+   }catch (Exception e){
+	   AlipayLogger.logBizError(("��ȡ��֤��ʧ��"));
+   }
+   return rootCertSN;
+}
+
+// Java SDK 获取证书
+private X509Certificate getCert(String  certPath) throws AlipayApiException{
+	InputStream inputStream = null;
+	try {
+		inputStream = new FileInputStream(certPath);
+		CertificateFactory cf = CertificateFactory.getInstance("X.509");
+		X509Certificate cert = (X509Certificate)cf.generateCertificate(inputStream);
+		return cert;
+
+	}catch (IOException e) {
+		throw new AlipayApiException(e);
+	}catch (CertificateException e){
+		throw new AlipayApiException(e);
+	}finally {
+		try {
+			if (inputStream != null) {
+				inputStream.close();
+			}
+		}catch (IOException e) {
+			throw new AlipayApiException(e);
+		}
+	}
+}
+
+// Java SDK 获取证书SN
+private String getCertSN(X509Certificate cf) throws AlipayApiException{
+	try {
+		MessageDigest md = MessageDigest.getInstance("MD5");
+		md.update((cf.getIssuerX500Principal().getName() + cf.getSerialNumber()).getBytes());
+		String certSN = new BigInteger(1,md.digest()).toString(16);
+		certSN = fillMD5(certSN);
+		return certSN;
+	}catch (NoSuchAlgorithmException e){
+		throw new AlipayApiException(e);
+	}
+}
+
+*/

+ 2 - 1
examples/alipay/alipay_AliPayTradePay.go

@@ -34,8 +34,9 @@ func AliPayTradePay() {
 		return
 	}
 	fmt.Println("aliRsp:", *aliRsp)
+	// 同步返回验签
 	alipayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp8gueNlkbiDidz6FBQEBpqoRgH8h7JtsPtYW0nzAqy1MME4mFnDSMfSKlreUomS3a55gmBopL1eF4/Km/dEnaL5tCY9+24SKn1D4iyls+lvz/ZjvUjVwxoUYBh8kkcxMZSDeDz8//o+9qZTrICVP2a4sBB8T0XmU4gxfw8FsmtoomBH1nLk3AO7wgRN2a3+SRSAmxrhIGDmF1lljSlhY32eJpJ2TZQKaWNW+7yDBU/0Wt3kQVY84vr14yYagnSCiIfqyVFqePayRtmVJDr5qvSXr51tdqs2zKZCu+26X7JAF4BSsaq4gmY5DmDTm4TohCnBduI1+bPGD+igVmtl05wIDAQAB"
-	ok, err := gopay.VerifyAliPaySign(alipayPublicKey, aliRsp.SignData, aliRsp.Sign)
+	ok, err := gopay.VerifyAliPaySyncSign(alipayPublicKey, aliRsp.SignData, aliRsp.Sign)
 	if err != nil {
 		fmt.Println("err:::", err)
 	}

+ 2 - 1
examples/alipay/alipay_AlipayUserInfoShare.go

@@ -26,7 +26,8 @@ func AliPayUserInfoShare() {
 		return
 	}
 	fmt.Println("aliRsp:", *aliRsp)
-	ok, err := gopay.VerifyAliPaySign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
+	// 同步返回验签
+	ok, err := gopay.VerifyAliPaySyncSign(aliPayPublicKey, aliRsp.SignData, aliRsp.Sign)
 	if err != nil {
 		fmt.Println("VerifyAliPaySign-err:", err)
 		return

+ 15 - 0
examples/alipay/alipay_ServiceApi.go

@@ -48,6 +48,19 @@ func DecryptAliPayOpenDataToStruct() {
 	fmt.Println("rsp.Mobile:", rsp.Mobile)
 }
 
+func VerifyAliPaySyncSign() {
+	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
+	signData := "aaaaaaaaaaaaaaaaaaaaaa"
+	sign := "asdkjsdhfgkjdshflksdjfl"
+
+	ok, err := gopay.VerifyAliPaySyncSign(aliPayPublicKey, signData, sign)
+	if err != nil {
+		fmt.Println("err:", err)
+		return
+	}
+	fmt.Println("ok:", ok)
+}
+
 func ParseAliPayNotifyResultAndVerifyAliPaySign(req *http.Request) {
 	aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB"
 
@@ -55,6 +68,7 @@ func ParseAliPayNotifyResultAndVerifyAliPaySign(req *http.Request) {
 	notifyReq, err := gopay.ParseAliPayNotifyResult(req)
 	if err != nil {
 		fmt.Println("err:", err)
+		return
 	}
 	fmt.Println("notifyReq:", *notifyReq)
 
@@ -62,6 +76,7 @@ func ParseAliPayNotifyResultAndVerifyAliPaySign(req *http.Request) {
 	ok, err := gopay.VerifyAliPaySign(aliPayPublicKey, notifyReq)
 	if err != nil {
 		fmt.Println("err:", err)
+		return
 	}
 	log.Println("支付宝验签是否通过:", ok)
 }

+ 11 - 0
release_note.txt

@@ -1,3 +1,14 @@
+版本号:Release 1.4.5
+发布时间:2019/12/06 15:56
+修改记录:
+   (1) 支付宝:修复 公钥证书模式 下,同步返回参数接收问题,返回接收结构体增加参数 alipay_cert_sn,同步返回证书模式验签,暂时未解决
+   (2) 支付宝:修改公共API方法:gopay.VerifyAliPaySign(),不再支持同步验签,只做异步通知验签
+   (3) 支付宝:新增公共API方法:gopay.VerifyAliPaySyncSign(),支付宝同步返回验签
+   (4) 支付宝:新增Client方法:client.SetAliPayPublicCertSN(),设置 支付宝公钥证书SN,通过 gopay.GetCertSN() 获取 alipay_cert_sn
+   (5) 支付宝:新增Client方法:client.SetAppCertPath(),设置应用公钥证书路径,并赋值 app_cert_sn
+   (6) 支付宝:新增Client方法:client.SetAliPayPublicCertPath(),设置支付宝公钥证书文件路径,并赋值 alipay_cert_sn
+   (7) 支付宝:新增Client方法:client.SetAliPayRootCertPath(),设置支付宝CA根证书文件路径,并赋值 alipay_root_cert_sn
+
 版本号:Release 1.4.4
 发布时间:2019/11/16 15:56
 修改记录:

+ 2 - 1
support_note.txt

@@ -3,4 +3,5 @@
 平台  ----    用户  ----    金额
 
 微信  ----    燃烧的发丝   ----    50
-微信  ----    三五五七ᴳᴼ  ----    100
+微信  ----    三五五七ᴳᴼ  ----    100
+微信  ----    沐修      ----    50

+ 3 - 1
wechat_client.go

@@ -20,7 +20,7 @@ type WeChatClient struct {
 	KeyFile    []byte
 	Pkcs12File []byte
 	IsProd     bool
-	mu         sync.Mutex
+	mu         sync.RWMutex
 }
 
 // 初始化微信客户端
@@ -321,7 +321,9 @@ GoRequest:
 		agent.TLSClientConfig(tlsConfig[0])
 	}
 	if w.BaseURL != null {
+		w.mu.RLock()
 		agent.Post(w.BaseURL + path)
+		w.mu.RUnlock()
 	} else {
 		agent.Post(wxBaseUrlCh + path)
 	}

+ 6 - 4
wechat_params.go

@@ -56,8 +56,6 @@ func (w *WeChatClient) AddCertFileByte(certFile, keyFile, pkcs12File []byte) {
 //    pkcs12FilePath:apiclient_cert.p12 路径
 //    返回err
 func (w *WeChatClient) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath string) (err error) {
-	w.mu.Lock()
-	defer w.mu.Unlock()
 	var (
 		cert, key, pkcs []byte
 	)
@@ -70,9 +68,11 @@ func (w *WeChatClient) AddCertFilePath(certFilePath, keyFilePath, pkcs12FilePath
 	if pkcs, err = ioutil.ReadFile(pkcs12FilePath); err != nil {
 		return
 	}
+	w.mu.Lock()
 	w.CertFile = cert
 	w.KeyFile = key
 	w.Pkcs12File = pkcs
+	w.mu.Unlock()
 	return
 }
 
@@ -96,9 +96,11 @@ func (w *WeChatClient) addCertConfig(certFilePath, keyFilePath, pkcs12FilePath s
 			InsecureSkipVerify: true}
 		return
 	}
-
+	w.mu.RLock()
 	pkcsPool.AppendCertsFromPEM(w.Pkcs12File)
-	if certificate, err = tls.X509KeyPair(w.CertFile, w.KeyFile); err != nil {
+	certificate, err = tls.X509KeyPair(w.CertFile, w.KeyFile)
+	w.mu.RUnlock()
+	if err != nil {
 		return nil, fmt.Errorf("tls.X509KeyPair:%s", err.Error())
 	}
 	tlsConfig = &tls.Config{