Commit a218b29b authored by wangp's avatar wangp

notify回调签名验证成功

parent 4018801a
......@@ -34,8 +34,8 @@ WORKDIR /go/src/system_pay
COPY --from=0 /go/src/system_pay/server ./
# 拷贝配置文件到当前工作目录
#COPY --from=0 /go/src/system_pay/conf/dev ./conf
COPY --from=0 /go/src/system_pay/conf/prod ./conf
COPY --from=0 /go/src/system_pay/conf/consts.go ./conf
# 拷贝国际化文件夹到当前工作目录
COPY --from=0 /go/src/system_pay/i18n ./i18n
......@@ -43,5 +43,12 @@ COPY --from=0 /go/src/system_pay/i18n ./i18n
# 拷贝国际化文件夹到当前工作目录
COPY --from=0 /go/src/system_pay/docs ./docs
# 拷贝私钥、公钥和证书文件夹到当前工作目录
COPY --from=0 /go/src/system_pay/cert ./cert
COPY --from=0 /go/src/system_pay/cert/dev ./cert/dev
COPY --from=0 /go/src/system_pay/cert/prod ./cert/prod
COPY --from=0 /go/src/system_pay/cert/prod/bk ./cert/prod/bk
COPY --from=0 /go/src/system_pay/cert/prod/dbc ./cert/prod/dbc
# 运行打包好的二进制
ENTRYPOINT ./server
\ No newline at end of file
......@@ -87,20 +87,21 @@ lakala:
# appid名称: ''
# serial_no: '1689571807509'
#谛宝多多自营
#1.聚合收银台(微信H5、支付宝H5)
merchant_no1: '8222900701107M5'
merchant_no1: '8221000599501K9'
term_no1: ''
#2.聚合收银台(微信扫码、支付宝扫码)
merchant_no2: '8221210594300JY'
merchant_no2: '8221000599501K9'
term_no2: ''
#3.聚合主扫(微信JSAPI、微信小程序)
merchant_no3: '8222900581201QB'
term_no3: 'D0027598'
sub_appid3: 'wxc3e4d1682da3053c' #子商户公众账号ID
user_id3: 'oLvoQ5deygCMj2WrDjPVPvV1L1t8' #用户标识(sub_openid)
merchant_no3: '8221000599501K9'
term_no3: '688354520242'
# sub_appid3: 'wxc3e4d1682da3053c' #子商户公众账号ID
# user_id3: 'oLvoQ5deygCMj2WrDjPVPvV1L1t8' #用户标识(sub_openid)
#4.聚合被扫(扫码枪)
merchant_no4: '822290070111135' #结算商户号
term_no4: '29034705' #结算终端号
merchant_no4: '8221000599501K9' #结算商户号
term_no4: '677902880958' #结算终端号
#配置项
#谛宝多多自营
......
......@@ -3,16 +3,20 @@ package pay
import (
"crypto"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/x509"
"encoding/base64"
"encoding/json"
"encoding/pem"
"errors"
"fmt"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"io/ioutil"
"strings"
"system_pay/controller/base"
"system_pay/models"
"system_pay/repository/pay"
)
// 卡拉卡统一支付回调
......@@ -30,23 +34,10 @@ type NoticeController struct {
// @Success 200
// @router /api/v1/pay/wx_notice [post]
func (l *PayController) WxNotice(c *gin.Context) {
fmt.Println("拉卡拉微信回调start")
//ph2 := make(map[string]interface{}, 0)
////ph2 = new(interface{})
//err := c.ShouldBind(ph2)
//if err != nil {
// response := new(base.ResponseDataWxNotice)
// response.Code = "FAIL"
// response.Message = "执行失败1"
// base.ResponseWxNotice(c, response)
// return
//}
//fmt.Println(ph2)
//验证签名
err := test_ver2()
err := VerifySignCert(c)
if err != nil {
fmt.Println("verySignByPublicKey err: ", err)
response := new(base.ResponseDataWxNotice)
......@@ -55,160 +46,197 @@ func (l *PayController) WxNotice(c *gin.Context) {
base.ResponseWxNotice(c, response)
return
}
fmt.Println("test_ver ok")
//fmt.Println("验证签名成功...")
//response := new(base.ResponseDataWxNotice)
//response.Code = "SUCCESS"
//response.Message = "执行成功"
//base.ResponseWxNotice(c, response)
//return
fmt.Println("验证签名成功...")
ph := new(models.WxNoticeInput)
err = c.ShouldBindJSON(ph)
if err != nil {
response := new(base.ResponseDataWxNotice)
response.Code = "SUCCESS"
response.Message = "执行成功"
response.Code = "FAIL"
response.Message = "执行失败2"
base.ResponseWxNotice(c, response)
return
}
fmt.Println(ph)
//_, err = testCert(c)
//if err != nil {
// fmt.Println("verySignByPublicKey err: ", err)
// response := new(base.ResponseDataWxNotice)
// response.Code = "FAIL"
// response.Message = "验证签名失败"
// base.ResponseWxNotice(c, response)
// return
//}
//
//ph := new(models.WxNoticeInput)
//err := c.ShouldBindJSON(ph)
//if err != nil {
// response := new(base.ResponseDataWxNotice)
// response.Code = "FAIL"
// response.Message = "执行失败2"
// base.ResponseWxNotice(c, response)
// return
//}
//fmt.Println(ph)
//
//// 拉卡拉统一支付微信回调
//response, err := pay.WxNotice(ph)
//
//fmt.Println("拉卡拉微信回调end")
//base.ResponseWxNotice(c, response)
// 拉卡拉统一支付微信回调
response, err := pay.WxNotice(ph)
fmt.Println("拉卡拉微信回调end")
base.ResponseWxNotice(c, response)
}
func test_ver2() error {
// 1、读取公钥文件,获取公钥字节
//rootPEM, err := ioutil.ReadFile("./cert/prod/saas/api_cert.cer")
//certPEM, err := ioutil.ReadFile("./cert/prod/saas/lkl-apigw-v1.cer")
certPEM, err := ioutil.ReadFile("./cert/dev/lkl-apigw-v2.cer")
//读取证书文件,验证签名
func VerifySignCert(c *gin.Context) error {
// 1、读取证书文件,获取证书字节
certPEM, err := ioutil.ReadFile("./cert/dev/lkl-apigw-v2.cer") //测试
//certPEM, err := ioutil.ReadFile("./cert/prod/dbc/lkl-apigw-v1.cer") //正式
if err != nil {
fmt.Println("ioutil.ReadFile failed")
return err
}
block, _ := pem.Decode([]byte(certPEM))
if block == nil {
fmt.Println("failed to parse certificate PEM")
return errors.New("failed to parse certificate")
}
cert, err := x509.ParseCertificate(block.Bytes)
if err != nil {
fmt.Println("failed to parse certificate: " + err.Error())
return err
}
timestamp := "1630905585";
nonce := "9003323344";
signature := "tnjIAcEISq/ClrOppv/nojeZnE/pB1wNfQC/hMTME+rQMapWzvs9v1J68ueDpVzs1RW22dNotmUVy2sM6thNFRkaOx4qQGslX6kIttwvlsJsSEIR3qrjdPdUAkbP2KDRLujspxE9X0daJ6BU+rOoJ8p4c6y1/QSOMtDJoO3EABOF4O6RFHR3N7JW8o4qcf7lOOO7D4rlAB2vw6tV8WeG+OEyJ++Q0K3V1oM5uJEIPPuJkb2qlEqVYKiYLyvIdEJ1Z5qMbC9U7rKuHdeTQPl7last/h5nd6WauzDfYPKlAjZBEPYjiDqRv6Dm+4FeNtALoy6Mg7Ruxeq1pJudfj0iKg==";
reqBody := "{\"payOrderNo\":\"21090611012001970631000463034\",\"merchantOrderNo\":\"CH2021090613190866292\",\"orderInfo\":null,\"merchantNo\":\"822126090640003\",\"termId\":\"47781282\",\"tradeMerchantNo\":\"822126090640003\",\"tradeTermId\":\"47781282\",\"channelId\":\"10000038\",\"currency\":\"156\",\"amount\":1,\"tradeType\":\"PAY\",\"payStatus\":\"S\",\"notifyStatus\":0,\"orderCreateTime\":\"2021-09-06T05:19:43.000+00:00\",\"orderEfficientTime\":\"2021-09-06T05:19:43.000+00:00\",\"extendField\":null,\"payTime\":\"2021-09-06T05:19:43.000+00:00\",\"remark\":\"\",\"noticeNum\":1,\"sign\":null,\"notifyUrl\":null,\"notifyMode\":\"2\",\"payInfo\":\"1#1#ALIPAY#0#2021090622001432581427657317\",\"lklOrderNo\":\"2021090666210003610012\",\"crdFlg\":\"92\",\"payerId1\":\"2088702852632582\",\"payerId2\":\"rob***@126.com\",\"smCrdFlg\":\"01\",\"tradeTime\":\"20210906131943\",\"accountChannelOrderNo\":\"2021090622001432581427657317\",\"actualPayAmount\":1,\"logNo\":\"66210003610012\"}";
preSignData := timestamp +"\n" + nonce + "\n" +reqBody + "\n";
//fmt.Println("SignatureAlgorithm=")
//fmt.Println(cert.SignatureAlgorithm)
//sign := cert.Signature
//timestamp = c.GetHeader("Lklapi-Timestamp")
//nonce = c.GetHeader("Lklapi-Nonce")
//signature = c.GetHeader("Lklapi-Signature")
authorization := c.GetHeader("Authorization")
fmt.Println("wangpei test 验证签名0...")
fmt.Println("Authorization1="+authorization)
//err = cert.CheckSignature(cert.SignatureAlgorithm, []byte(preSignData), []byte(signature))
//if err != nil {
// fmt.Println("failed to CheckSignature: " + err.Error())
// return err
//}
authorization = strings.Replace(authorization, "LKLAPI-SHA256withRSA ", "", -1)
authorization = strings.Replace(authorization, ",","&", -1)
authorization = strings.Replace(authorization, "\"","", -1)
//证书 => 公钥
publicKey := cert.PublicKey.(*rsa.PublicKey)
//authorization = "timestamp=1689752771&nonce_str=5HO2w0AjbhJc&signature=VNk9oio0rUMOs1X2j37p9+6o2EyAL3SaLwq2riO0C2FIbTbCZaOrpLSHt6LmgWHHYf50GOQnjZb3oWiTW6LBhF/2ROisEtl78tef6HtMl4mrnDy8BkQGpJS3IL/du+t35OlxeKpBjrpr6ObdZlaA26OZf4uMXRnSv15tvntSi0zM0GA7+dcUCBd4sFPGRgU0qfABiqC7bzzOZFrUpEe7ZZRfXQ2PLkJO0uBQt7vUoqt0fVXsPR+FjR++e1JASg821Gf7+J+Tr73MoAVkRJ0HwJX72HbbffVMNAYF/5cc/sL50WtFJ8JrLj6WAJdesSmeFBrs+tOEMH62b+Wr/mPnXw=="
bytes, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
return err
auth_parts := strings.Split(authorization, "&")
params := make(map[string]string)
for _, param := range auth_parts {
item := strings.Split(param, "=")
params[item[0]] = item[1]
}
hashed := sha256.Sum256([]byte(preSignData))
err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], bytes)
if err != nil {
return err
}
//sign, err := base64.StdEncoding.DecodeString(signature)
//if err != nil {
// return err
//if params["signature"] != "" && len(params["signature"]) > 10 {
// //params["signature"] = substr($query, strrpos($query, 'signature=') + 10);
// params["signature"] = params["signature"][0:10]
//}
//hash := sha1.New()
//hash.Write([]byte(preSignData))
////err = RsaVerySignWithSha1Base64(originalData, signData, publicKey)
//err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA1, hash.Sum(nil), sign)
timestamp := params["timestamp"]
nonce := params["nonce_str"]
signature := params["signature"]
signature = signature + "=="
//signature = "VNk9oio0rUMOs1X2j37p9+6o2EyAL3SaLwq2riO0C2FIbTbCZaOrpLSHt6LmgWHHYf50GOQnjZb3oWiTW6LBhF/2ROisEtl78tef6HtMl4mrnDy8BkQGpJS3IL/du+t35OlxeKpBjrpr6ObdZlaA26OZf4uMXRnSv15tvntSi0zM0GA7+dcUCBd4sFPGRgU0qfABiqC7bzzOZFrUpEe7ZZRfXQ2PLkJO0uBQt7vUoqt0fVXsPR+FjR++e1JASg821Gf7+J+Tr73MoAVkRJ0HwJX72HbbffVMNAYF/5cc/sL50WtFJ8JrLj6WAJdesSmeFBrs+tOEMH62b+Wr/mPnXw=="
//b, err := c.GetRawData()
//if err != nil {
// fmt.Println("failed to VerifyPKCS1v15: " + err.Error())
// fmt.Println("failed to get request body: " + err.Error())
// return err
//}
//reqBody := string(b) //获取response body
//opts := x509.VerifyOptions{
// //DNSName: "mail.google.com",
// //Roots: roots,
//}
//
//if _, err := cert.Verify(opts); err != nil {
// fmt.Println("failed to verify certificate: " + err.Error())
//}
fmt.Println("wangpei test ok")
return nil
}
//(4)验签:对采用sha1算法进行签名后转base64格式的数据进行验签
func RsaVerySignWithSha1Base64(originalData, signData, pubKey string) error{
sign, err := base64.StdEncoding.DecodeString(signData)
if err != nil {
var body interface{}
if err = c.ShouldBindBodyWith(&body, binding.JSON); err != nil {
//log.Default().Error("should bind body error", zap.Error(err))
fmt.Println("should bind body error: " + err.Error())
return err
}
//public, _ := base64.StdEncoding.DecodeString(pubKey)
public := []byte(pubKey)
pub, err := x509.ParsePKIXPublicKey(public)
byteBody, err := json.Marshal(body)
if err != nil {
fmt.Println("json.Marshal error: " + err.Error())
return err
}
hash := sha1.New()
hash.Write([]byte(originalData))
return rsa.VerifyPKCS1v15(pub.(*rsa.PublicKey), crypto.SHA1, hash.Sum(nil), sign)
}
reqBody := string(byteBody)
func decodePublicKey(publicKey string) (*rsa.PublicKey, error) {
block, _ := pem.Decode([]byte(publicKey))
if block == nil {
return nil, errors.New("failed to decode PEM block containing private key")
}
pub,err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}
return pub.(*rsa.PublicKey), err
}
//reqBody, _ := json.MarshalToString(body)
// VerifyWithPublicKey 公钥验签
func VerifyWithPublicKey(signData string, srcData []byte, publicKey string) error {
//defer GetTimer("公钥验签")()
key, err := decodePublicKey(publicKey)
if err != nil {
return err
}
//JAVA demo
//timestamp = "1630905585";
//nonce = "9003323344";
//signature = "tnjIAcEISq/ClrOppv/nojeZnE/pB1wNfQC/hMTME+rQMapWzvs9v1J68ueDpVzs1RW22dNotmUVy2sM6thNFRkaOx4qQGslX6kIttwvlsJsSEIR3qrjdPdUAkbP2KDRLujspxE9X0daJ6BU+rOoJ8p4c6y1/QSOMtDJoO3EABOF4O6RFHR3N7JW8o4qcf7lOOO7D4rlAB2vw6tV8WeG+OEyJ++Q0K3V1oM5uJEIPPuJkb2qlEqVYKiYLyvIdEJ1Z5qMbC9U7rKuHdeTQPl7last/h5nd6WauzDfYPKlAjZBEPYjiDqRv6Dm+4FeNtALoy6Mg7Ruxeq1pJudfj0iKg==";
//reqBody = "{\"payOrderNo\":\"21090611012001970631000463034\",\"merchantOrderNo\":\"CH2021090613190866292\",\"orderInfo\":null,\"merchantNo\":\"822126090640003\",\"termId\":\"47781282\",\"tradeMerchantNo\":\"822126090640003\",\"tradeTermId\":\"47781282\",\"channelId\":\"10000038\",\"currency\":\"156\",\"amount\":1,\"tradeType\":\"PAY\",\"payStatus\":\"S\",\"notifyStatus\":0,\"orderCreateTime\":\"2021-09-06T05:19:43.000+00:00\",\"orderEfficientTime\":\"2021-09-06T05:19:43.000+00:00\",\"extendField\":null,\"payTime\":\"2021-09-06T05:19:43.000+00:00\",\"remark\":\"\",\"noticeNum\":1,\"sign\":null,\"notifyUrl\":null,\"notifyMode\":\"2\",\"payInfo\":\"1#1#ALIPAY#0#2021090622001432581427657317\",\"lklOrderNo\":\"2021090666210003610012\",\"crdFlg\":\"92\",\"payerId1\":\"2088702852632582\",\"payerId2\":\"rob***@126.com\",\"smCrdFlg\":\"01\",\"tradeTime\":\"20210906131943\",\"accountChannelOrderNo\":\"2021090622001432581427657317\",\"actualPayAmount\":1,\"logNo\":\"66210003610012\"}";
preSignData := timestamp +"\n" + nonce + "\n" +reqBody + "\n";
fmt.Println("wangpei test 验证签名1...")
fmt.Println("params=");fmt.Println(params)
fmt.Println("wangpei test 验证签名2...")
fmt.Println("signature="+signature)
fmt.Println("wangpei test 验证签名3...")
fmt.Println("Authorization2="+authorization)
fmt.Println("wangpei test 验证签名4...")
fmt.Println("preSignData=" + preSignData)
fmt.Println("wangpei test 验证签名5...")
//证书 => 公钥
publicKey := cert.PublicKey.(*rsa.PublicKey)
bytes, err := base64.StdEncoding.DecodeString(signData)
//验证签名
bytes, err := base64.StdEncoding.DecodeString(signature)
if err != nil {
fmt.Println("failed to base64.StdEncoding.DecodeString: " + err.Error())
return err
}
hashed := sha256.Sum256(srcData)
err = rsa.VerifyPKCS1v15(key, crypto.SHA256, hashed[:], bytes)
hashed := sha256.Sum256([]byte(preSignData))
err = rsa.VerifyPKCS1v15(publicKey, crypto.SHA256, hashed[:], bytes)
if err != nil {
fmt.Println("failed to VerifyPKCS1v15: " + err.Error())
return err
}
fmt.Println("wangpei test ok")
return nil
}
//
//// Strval 获取变量的字符串值
//// 浮点型 3.0将会转换成字符串3, "3"
//// 非数值或字符类型的变量将会被转换成JSON格式字符串
//func Strval(value interface{}) string {
// // interface 转 string
// var key string
// if value == nil {
// return key
// }
//
// 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
//}
\ No newline at end of file
......@@ -53,7 +53,6 @@ func WxNotice(input *models.WxNoticeInput) (*base.ResponseDataWxNotice, error) {
fmt.Println("222")
//if noticeRequest.ReturnCode == "SUCCESS" {
// 把订单状态置为 结算成功
err = BillPayStateSuccess(tx, billID)
if err != nil {
......
......@@ -80,8 +80,8 @@ func UnifiedOrder(input *models.PlaceAnOrderParamInput, ip string) (interface{},
merchant_no2 := setting.Conf.Lakala.MerchantNo2
merchant_no3 := setting.Conf.Lakala.MerchantNo3
term_no3 := setting.Conf.Lakala.TermNo3
sub_appid3 := setting.Conf.Lakala.SubAppid3
user_id3 := setting.Conf.Lakala.UserId3
//sub_appid3 := setting.Conf.Lakala.SubAppid3
//user_id3 := setting.Conf.Lakala.UserId3
merchant_no4 := setting.Conf.Lakala.MerchantNo4
term_no4 := setting.Conf.Lakala.TermNo4
......@@ -193,8 +193,8 @@ func UnifiedOrder(input *models.PlaceAnOrderParamInput, ip string) (interface{},
data4 := make(map[string]interface{})
//data4["open_id"] = input.OpenID //此参数 支付类型是 JS API 的时候 必传
data4["sub_appid"] = sub_appid3
data4["user_id"] = user_id3
data4["sub_appid"] = input.AppID //子商户公众账号ID
data4["user_id"] = input.OpenID //用户标识
data2["acc_busi_fields"] = make(map[string]interface{})
data2["acc_busi_fields"] = data4
......
......@@ -185,7 +185,7 @@ type Esign struct {
// Init 支持热修改的viper设置
func Init() error {
viper.SetConfigFile("conf/dev/config.yaml") // 指定配置文件路径
viper.SetConfigFile("conf/config.yaml") // 指定配置文件路径
err := viper.ReadInConfig() // 读取配置信息
if err != nil { // 读取配置信息失败
fmt.Printf("viper.ReadInConfig failed, new_error:%v\n", err)
......
......@@ -202,42 +202,42 @@ func RsaVerySignWithSha1Base64(originalData, signData, pubKey string) error{
//}
//func VerifyDerCert(der_cert []byte, der_signing_cert []byte) (bool, error) {
func VerifyDerCert(der_cert []byte, filename string) (bool, error) {
// 1、读取私钥文件,获取私钥字节
der_signing_cert, err := ioutil.ReadFile(filename)
if err != nil {
return false, err
}
roots := x509.NewCertPool()
opts := x509.VerifyOptions{
Roots: roots,
}
// Verify key
policy_cert, err := x509.ParseCertificate(der_signing_cert)
if err != nil {
return false, errors.New("Signing ParseCertificate fails")
}
roots.AddCert(policy_cert)
fmt.Printf("Root cert: %x\n", der_signing_cert)
// Verify key
cert, err := x509.ParseCertificate(der_cert)
if err != nil {
return false, errors.New("Cert ParseCertificate fails")
}
roots.AddCert(policy_cert)
opts.Roots = roots
chains, err := cert.Verify(opts)
if err != nil {
return false, errors.New("Verify fails")
}
if chains != nil {
return true, nil
} else {
return false, nil
}
}
\ No newline at end of file
//func VerifyDerCert(der_cert []byte, filename string) (bool, error) {
// // 1、读取私钥文件,获取私钥字节
// der_signing_cert, err := ioutil.ReadFile(filename)
// if err != nil {
// return false, err
// }
//
// roots := x509.NewCertPool()
// opts := x509.VerifyOptions{
// Roots: roots,
// }
//
// // Verify key
// policy_cert, err := x509.ParseCertificate(der_signing_cert)
// if err != nil {
// return false, errors.New("Signing ParseCertificate fails")
// }
// roots.AddCert(policy_cert)
// fmt.Printf("Root cert: %x\n", der_signing_cert)
//
// // Verify key
// cert, err := x509.ParseCertificate(der_cert)
// if err != nil {
// return false, errors.New("Cert ParseCertificate fails")
// }
//
// roots.AddCert(policy_cert)
// opts.Roots = roots
// chains, err := cert.Verify(opts)
// if err != nil {
// return false, errors.New("Verify fails")
// }
// if chains != nil {
// return true, nil
// } else {
// return false, nil
// }
//
//}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment