123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- // 委托
- 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"
- )
- // MerchantInfo 商家信息
- type MerchantInfo struct {
- MerID string // 商户代码
- OrderID string // 商户订单号,8-32位数字字母,不能含“-”或“_”
- TxnTime string // 订单发送时间,格式为YYYYMMDDhhmmss,取北京时间
- }
- // CustomerInfo 客户信息
- 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"` // 证件类型, 01 - 身份证
- CertifID string `form:"certifId" json:"certifId" xml:"certifId"` // 证件号,15位身份证不校验尾号,18位会校验尾号
- CustomerName string `form:"customerNm" json:"customerNm" xml:"customerNm"` // 姓名
- Cvn2 string `form:"cvn2" json:"cvn2" xml:"cvn2"` // 信用卡安全码
- Expired string `form:"expired" json:"expired" xml:"expired"` // 有效期,YYMM格式,持卡人卡面印的是MMYY的,请注意代码设置倒一下
- }
- // ReqRes 请求返回
- 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"`
- }
- // Sign 签名
- // encryptCert 公钥证书路径
- // signCert 签名证书路径
- 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) // 商户订单号,8-32位数字字母,不能含“-”或“_”
- args.Add("txnTime", mi.TxnTime) // 订单发送时间,格式为YYYYMMDDhhmmss,取北京时间
- publickey := cert.PublicKey.(*rsa.PublicKey)
- accNo, err = RSAEncrypt(publickey, []byte(ci.CardNo))
- if err != nil {
- return
- }
- args.Add("accNo", base64.StdEncoding.EncodeToString(accNo)) // 卡号,敏感信息加密方式
- fmt.Println("CardNo", ci.CardNo)
- var cardNo []byte
- cardNo, err = RSADecrypt(priveKey, accNo)
- fmt.Println("CardNo", ci.CardNo)
- fmt.Println("De CardNo", string(cardNo))
- // 持卡人身份信息,敏感信息加密方式
- var phone []byte
- phone, err = RSAEncrypt(publickey, []byte(ci.Phone))
- if err != nil {
- return
- }
- 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 := `encryptedInfo=` + encryptedInfo
- kvs += `&certifTp=` + ci.CertifTp
- kvs += `&certifId=` + ci.CertifID
- kvs += `&customerNm=` + ci.CustomerName // `&cvn2=&=expired`
- info := `{` + kvs + `}`
- 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
- }
|