|
@@ -3,11 +3,32 @@
|
|
|
package unionpay
|
|
|
|
|
|
import (
|
|
|
+ "bytes"
|
|
|
+ "crypto/rsa"
|
|
|
+ "crypto/sha256"
|
|
|
+ "crypto/x509"
|
|
|
"encoding/base64"
|
|
|
+ "encoding/hex"
|
|
|
+ "encoding/json"
|
|
|
+ "fmt"
|
|
|
+ "net/url"
|
|
|
+ "sort"
|
|
|
+
|
|
|
+ "git.chuangxin1.com/cx/util/binding"
|
|
|
+
|
|
|
+ "git.chuangxin1.com/cx/util"
|
|
|
)
|
|
|
|
|
|
+
|
|
|
+type MerchantInfo struct {
|
|
|
+ MerID string
|
|
|
+ OrderID string
|
|
|
+ TxnTime string
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
type CustomerInfo struct {
|
|
|
+ CardNo string `form:"cardNo" json:"cardNo" xml:"cardNo"`
|
|
|
Phone string `form:"phone" json:"phone" xml:"phone"`
|
|
|
CertifTp string `form:"certifTp" json:"certifTp" xml:"certifTp"`
|
|
|
CertifID string `form:"certifId" json:"certifId" xml:"certifId"`
|
|
@@ -16,42 +37,175 @@ type CustomerInfo struct {
|
|
|
Expired string `form:"expired" json:"expired" xml:"expired"`
|
|
|
}
|
|
|
|
|
|
-func sign() {
|
|
|
+
|
|
|
+type ReqRes struct {
|
|
|
+ TxnType string `form:"txnType" json:"txnType" xml:"txnType"`
|
|
|
+ RespCode string `form:"respCode" json:"respCode" xml:"respCode"`
|
|
|
+ ChannelType string `form:"channelType" json:"channelType" xml:"channelType"`
|
|
|
+ MerID string `form:"merId" json:"merId" xml:"merId"`
|
|
|
+
|
|
|
+ TxnSubType string `form:"txnSubType" json:"txnSubType" xml:"txnSubType"`
|
|
|
+ CustomerInfo string `form:"customerInfo" json:"customerInfo" xml:"customerInfo"`
|
|
|
+ Version string `form:"version" json:"version" xml:"version"`
|
|
|
+ SignPubKeyCert string `form:"signPubKeyCert" json:"signPubKeyCert" xml:"signPubKeyCert"`
|
|
|
|
|
|
+ SignMethod string `form:"signMethod" json:"signMethod" xml:"signMethod"`
|
|
|
+ AccNo string `form:"accNo" json:"accNo" xml:"accNo"`
|
|
|
+ CertID string `form:"certId" json:"certId" xml:"certId"`
|
|
|
+ Encoding string `form:"encoding" json:"encoding" xml:"encoding"`
|
|
|
+
|
|
|
+ RespMsg string `form:"respMsg" json:"respMsg" xml:"respMsg"`
|
|
|
+ BizType string `form:"bizType" json:"bizType" xml:"bizType"`
|
|
|
+ EncryptCertID string `form:"encryptCertId" json:"encryptCertId" xml:"encryptCertId"`
|
|
|
+ Signature string `form:"signature" json:"signature" xml:"signature"`
|
|
|
+
|
|
|
+ OrderID string `form:"orderId" json:"orderId" xml:"orderId"`
|
|
|
+ TxnTime string `form:"txnTime" json:"txnTime" xml:"txnTime"`
|
|
|
+ AccessType int `form:"accessType" json:"accessType" xml:"accessType"`
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-func s(filename string, cardNo string, customerInfo CustomerInfo) {
|
|
|
- cert, data, e := GetCertificate(filename)
|
|
|
- if e != nil {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+func Sign(encryptCert, signCert string, mi MerchantInfo, ci CustomerInfo) (err error) {
|
|
|
+ var (
|
|
|
+ cert = &x509.Certificate{}
|
|
|
+ priveKey = &rsa.PrivateKey{}
|
|
|
+ accNo []byte
|
|
|
+ )
|
|
|
+ cert, _, err = GetCertificate(encryptCert)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ priveKey, err = GetPrivateKey(signCert)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ args := url.Values{}
|
|
|
+
|
|
|
+ args.Add("version", "5.1.0")
|
|
|
+ args.Add("encoding", "utf-8")
|
|
|
+ args.Add("signMethod", "01")
|
|
|
+ args.Add("txnType", "72")
|
|
|
+ args.Add("txnSubType", "11")
|
|
|
+ args.Add("bizType", "000501")
|
|
|
+ args.Add("accessType", "0")
|
|
|
+ args.Add("channelType", "07")
|
|
|
+ args.Add("certId", cert.SerialNumber.String())
|
|
|
+ args.Add("encryptCertId", cert.SerialNumber.String())
|
|
|
+
|
|
|
+ args.Add("merId", mi.MerID)
|
|
|
+ args.Add("orderId", mi.OrderID)
|
|
|
+ args.Add("txnTime", mi.TxnTime)
|
|
|
+
|
|
|
+ publickey := cert.PublicKey.(*rsa.PublicKey)
|
|
|
+ accNo, err = RSAEncrypt(publickey, []byte(ci.CardNo))
|
|
|
+ if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- var args = make(map[string]interface{})
|
|
|
+ args.Add("accNo", base64.StdEncoding.EncodeToString(accNo))
|
|
|
|
|
|
- args["version"] = "5.1.0"
|
|
|
- args["encoding"] = "utf-8"
|
|
|
- args["signMethod"] = "01"
|
|
|
- args["txnType"] = "72"
|
|
|
- args["txnSubType"] = "11"
|
|
|
- args["bizType"] = "000501"
|
|
|
- args["accessType"] = "0"
|
|
|
- args["channelType"] = "07"
|
|
|
- args["encryptCertId"] = cert.SerialNumber.String()
|
|
|
+ fmt.Println("CardNo", ci.CardNo)
|
|
|
|
|
|
- args["merId"] = ""
|
|
|
- args["orderId"] = ""
|
|
|
- args["txnTime"] = ""
|
|
|
+ var cardNo []byte
|
|
|
+ cardNo, err = RSADecrypt(priveKey, accNo)
|
|
|
+ fmt.Println("CardNo", ci.CardNo)
|
|
|
+ fmt.Println("De CardNo", string(cardNo))
|
|
|
|
|
|
- accNo, err := RSAEncrypt(data, []byte(cardNo))
|
|
|
+
|
|
|
+ var phone []byte
|
|
|
+ phone, err = RSAEncrypt(publickey, []byte(ci.Phone))
|
|
|
if err != nil {
|
|
|
return
|
|
|
}
|
|
|
- args["accNo"] = string(accNo)
|
|
|
+ encryptedInfo := `phone=` + base64.StdEncoding.EncodeToString(phone)
|
|
|
+ if len(ci.Cvn2) > 0 {
|
|
|
+ var cvn2 []byte
|
|
|
+ cvn2, err = RSAEncrypt(publickey, []byte(ci.Cvn2))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ encryptedInfo += `cvn2=` + base64.StdEncoding.EncodeToString(cvn2)
|
|
|
+ }
|
|
|
+ if len(ci.Expired) > 0 {
|
|
|
+ var expired []byte
|
|
|
+ expired, err = RSAEncrypt(publickey, []byte(ci.Cvn2))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ encryptedInfo += `expired=` + base64.StdEncoding.EncodeToString(expired)
|
|
|
+ }
|
|
|
|
|
|
- kvs := `phone=` + customerInfo.Phone
|
|
|
- kvs += `&certifTp=` + customerInfo.CertifTp
|
|
|
- kvs += `&certifId=` + customerInfo.CertifID
|
|
|
- kvs += `&customerNm=` + customerInfo.CustomerName
|
|
|
+ kvs := `encryptedInfo=` + encryptedInfo
|
|
|
+ kvs += `&certifTp=` + ci.CertifTp
|
|
|
+ kvs += `&certifId=` + ci.CertifID
|
|
|
+ kvs += `&customerNm=` + ci.CustomerName
|
|
|
info := `{` + kvs + `}`
|
|
|
- args["customerInfo"] = base64.StdEncoding.EncodeToString([]byte(info))
|
|
|
+ args.Add("customerInfo", base64.StdEncoding.EncodeToString([]byte(info)))
|
|
|
+
|
|
|
+ keys := make([]string, 0)
|
|
|
+
|
|
|
+ for k := range args {
|
|
|
+ keys = append(keys, k)
|
|
|
+ }
|
|
|
+
|
|
|
+ sort.Strings(keys)
|
|
|
+
|
|
|
+ var s string
|
|
|
+ for _, k := range keys {
|
|
|
+ for _, value := range args[k] {
|
|
|
+ if value != "" {
|
|
|
+ s = s + "&" + k + "=" + value
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ fmt.Println(s[1:])
|
|
|
+ hash := sha256.New()
|
|
|
+ hash.Write([]byte(s[1:]))
|
|
|
+ fmt.Println("sha1", hex.EncodeToString(hash.Sum(nil)))
|
|
|
+
|
|
|
+ var signature []byte
|
|
|
+ signature, err = RSASign256(priveKey, hash.Sum(nil))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ s = base64.StdEncoding.EncodeToString(signature)
|
|
|
+ fmt.Println("signature", s)
|
|
|
+ args.Add("signature", s)
|
|
|
+ fmt.Println(args.Encode())
|
|
|
+
|
|
|
+ headers := make(map[string]string)
|
|
|
+
|
|
|
+ headers["Accept"] = "text/html; charset=UTF-8"
|
|
|
+ headers["Accept-Encoding"] = "gzip, deflate, br"
|
|
|
+ headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"
|
|
|
+ var msg util.Message
|
|
|
+ msg, err = util.Post(BaseURL+ReqBackTrans, "", "", headers, bytes.NewReader([]byte(args.Encode())))
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ fmt.Println("*************************************")
|
|
|
+ fmt.Println(BaseURL + ReqBackTrans)
|
|
|
+ fmt.Println(msg.StatusCode)
|
|
|
+ fmt.Println(msg.Header)
|
|
|
+ fmt.Println(string(msg.Body))
|
|
|
+ fmt.Println("*************************************")
|
|
|
+ var (
|
|
|
+ res ReqRes
|
|
|
+ values url.Values
|
|
|
+ )
|
|
|
+ values, err = url.ParseQuery(string(msg.Body))
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ err = binding.MapForm(&res, values)
|
|
|
+ fmt.Println(err)
|
|
|
+ if err == nil {
|
|
|
+ bs, _ := json.Marshal(&res)
|
|
|
+ fmt.Println(string(bs))
|
|
|
+ }
|
|
|
+ return
|
|
|
}
|