alipay_server_api.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. //==================================
  2. // * Name:Jerry
  3. // * DateTime:2019/6/18 19:24
  4. // * Desc:
  5. //==================================
  6. package gopay
  7. import (
  8. "bytes"
  9. "crypto"
  10. "crypto/aes"
  11. "crypto/cipher"
  12. "crypto/rsa"
  13. "crypto/x509"
  14. "encoding/base64"
  15. "encoding/json"
  16. "encoding/pem"
  17. "errors"
  18. "fmt"
  19. "hash"
  20. "log"
  21. "net/http"
  22. "reflect"
  23. "time"
  24. )
  25. //解析支付宝支付完成后的Notify信息
  26. func ParseAliPayNotifyResult(req *http.Request) (notifyRsp *AliPayNotifyRequest, err error) {
  27. notifyRsp = new(AliPayNotifyRequest)
  28. notifyRsp.NotifyTime = req.FormValue("notify_time")
  29. notifyRsp.NotifyType = req.FormValue("notify_type")
  30. notifyRsp.NotifyId = req.FormValue("notify_id")
  31. notifyRsp.AppId = req.FormValue("app_id")
  32. notifyRsp.Charset = req.FormValue("charset")
  33. notifyRsp.Version = req.FormValue("version")
  34. notifyRsp.SignType = req.FormValue("sign_type")
  35. notifyRsp.Sign = req.FormValue("sign")
  36. notifyRsp.AuthAppId = req.FormValue("auth_app_id")
  37. notifyRsp.TradeNo = req.FormValue("trade_no")
  38. notifyRsp.OutTradeNo = req.FormValue("out_trade_no")
  39. notifyRsp.OutBizNo = req.FormValue("out_biz_no")
  40. notifyRsp.BuyerId = req.FormValue("buyer_id")
  41. notifyRsp.BuyerLogonId = req.FormValue("buyer_logon_id")
  42. notifyRsp.SellerId = req.FormValue("seller_id")
  43. notifyRsp.SellerEmail = req.FormValue("seller_email")
  44. notifyRsp.TradeStatus = req.FormValue("trade_status")
  45. notifyRsp.TotalAmount = req.FormValue("total_amount")
  46. notifyRsp.ReceiptAmount = req.FormValue("receipt_amount")
  47. notifyRsp.InvoiceAmount = req.FormValue("invoice_amount")
  48. notifyRsp.BuyerPayAmount = req.FormValue("buyer_pay_amount")
  49. notifyRsp.PointAmount = req.FormValue("point_amount")
  50. notifyRsp.RefundFee = req.FormValue("refund_fee")
  51. notifyRsp.Subject = req.FormValue("subject")
  52. notifyRsp.Body = req.FormValue("body")
  53. notifyRsp.GmtCreate = req.FormValue("gmt_create")
  54. notifyRsp.GmtPayment = req.FormValue("gmt_payment")
  55. notifyRsp.GmtRefund = req.FormValue("gmt_refund")
  56. notifyRsp.GmtClose = req.FormValue("gmt_close")
  57. billList := req.FormValue("fund_bill_list")
  58. //log.Println("billList:", billList)
  59. if billList != null {
  60. bills := make([]fundBillListInfo, 0)
  61. err = json.Unmarshal([]byte(billList), &bills)
  62. if err != nil {
  63. return nil, err
  64. }
  65. notifyRsp.FundBillList = bills
  66. } else {
  67. notifyRsp.FundBillList = nil
  68. }
  69. notifyRsp.PassbackParams = req.FormValue("passback_params")
  70. detailList := req.FormValue("voucher_detail_list")
  71. //log.Println("detailList:", detailList)
  72. if detailList != null {
  73. details := make([]voucherDetailListInfo, 0)
  74. err = json.Unmarshal([]byte(detailList), &details)
  75. if err != nil {
  76. return nil, err
  77. }
  78. notifyRsp.VoucherDetailList = details
  79. } else {
  80. notifyRsp.VoucherDetailList = nil
  81. }
  82. return notifyRsp, err
  83. }
  84. //解密支付宝开放数据
  85. // encryptedData:包括敏感数据在内的完整用户信息的加密数据
  86. // sessionKey:会话密钥
  87. // beanPtr:需要解析到的结构体指针
  88. func DecryptAliPayOpenDataToStruct(encryptedData, secretKey string, beanPtr interface{}) (err error) {
  89. //验证参数类型
  90. beanValue := reflect.ValueOf(beanPtr)
  91. if beanValue.Kind() != reflect.Ptr {
  92. return errors.New("传入参数类型必须是以指针形式")
  93. }
  94. //验证interface{}类型
  95. if beanValue.Elem().Kind() != reflect.Struct {
  96. return errors.New("传入interface{}必须是结构体")
  97. }
  98. aesKey, _ := base64.StdEncoding.DecodeString(secretKey)
  99. ivKey := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
  100. secretData, _ := base64.StdEncoding.DecodeString(encryptedData)
  101. block, err := aes.NewCipher(aesKey)
  102. if err != nil {
  103. return err
  104. }
  105. if len(secretData)%len(aesKey) != 0 {
  106. return errors.New("encryptedData is error")
  107. }
  108. blockMode := cipher.NewCBCDecrypter(block, ivKey)
  109. originData := make([]byte, len(secretData))
  110. blockMode.CryptBlocks(originData, secretData)
  111. originData = PKCS5UnPadding(originData)
  112. //fmt.Println("originDataStr:", string(originData))
  113. //解析
  114. err = json.Unmarshal(originData, beanPtr)
  115. if err != nil {
  116. return err
  117. }
  118. return nil
  119. }
  120. //支付通知的签名验证和参数签名后的Sign
  121. // aliPayPublicKey:支付宝公钥
  122. // notifyRsp:利用 gopay.ParseAliPayNotifyResult() 得到的结构体
  123. // 返回参数ok:是否验证通过
  124. // 返回参数err:错误信息
  125. func VerifyAliPayResultSign(aliPayPublicKey string, notifyRsp *AliPayNotifyRequest) (ok bool, err error) {
  126. body := make(BodyMap)
  127. body.Set("notify_time", notifyRsp.NotifyTime)
  128. body.Set("notify_type", notifyRsp.NotifyType)
  129. body.Set("notify_id", notifyRsp.NotifyId)
  130. body.Set("app_id", notifyRsp.AppId)
  131. body.Set("charset", notifyRsp.Charset)
  132. body.Set("version", notifyRsp.Version)
  133. //body.Set("sign", notifyRsp.Sign) //验签时去掉
  134. //body.Set("sign_type", notifyRsp.SignType) //验签时去掉
  135. body.Set("auth_app_id", notifyRsp.AuthAppId)
  136. body.Set("trade_no", notifyRsp.TradeNo)
  137. body.Set("out_trade_no", notifyRsp.OutTradeNo)
  138. body.Set("out_biz_no", notifyRsp.OutBizNo)
  139. body.Set("buyer_id", notifyRsp.BuyerId)
  140. body.Set("buyer_logon_id", notifyRsp.BuyerLogonId)
  141. body.Set("seller_id", notifyRsp.SellerId)
  142. body.Set("seller_email", notifyRsp.SellerEmail)
  143. body.Set("trade_status", notifyRsp.TradeStatus)
  144. body.Set("total_amount", notifyRsp.TotalAmount)
  145. body.Set("receipt_amount", notifyRsp.ReceiptAmount)
  146. body.Set("invoice_amount", notifyRsp.InvoiceAmount)
  147. body.Set("buyer_pay_amount", notifyRsp.BuyerPayAmount)
  148. body.Set("point_amount", notifyRsp.PointAmount)
  149. body.Set("refund_fee", notifyRsp.RefundFee)
  150. body.Set("subject", notifyRsp.Subject)
  151. body.Set("body", notifyRsp.Body)
  152. body.Set("gmt_create", notifyRsp.GmtCreate)
  153. body.Set("gmt_payment", notifyRsp.GmtPayment)
  154. body.Set("gmt_refund", notifyRsp.GmtRefund)
  155. body.Set("gmt_close", notifyRsp.GmtClose)
  156. body.Set("fund_bill_list", jsonToString(notifyRsp.FundBillList))
  157. body.Set("passback_params", notifyRsp.PassbackParams)
  158. body.Set("voucher_detail_list", jsonToString(notifyRsp.VoucherDetailList))
  159. newBody := make(BodyMap)
  160. for k, v := range body {
  161. if v != null {
  162. newBody.Set(k, v)
  163. }
  164. }
  165. pKey := FormatAliPayPublicKey(aliPayPublicKey)
  166. signData := sortAliPaySignParams(newBody)
  167. //log.Println("签名字符串:", signData)
  168. err = verifyAliPaySign(signData, notifyRsp.Sign, notifyRsp.SignType, pKey)
  169. if err != nil {
  170. return false, err
  171. }
  172. return true, nil
  173. }
  174. func jsonToString(v interface{}) (str string) {
  175. if v == nil {
  176. return ""
  177. }
  178. bs, err := json.Marshal(v)
  179. if err != nil {
  180. fmt.Println("err:", err)
  181. return ""
  182. }
  183. s := string(bs)
  184. if s == "null" {
  185. return ""
  186. }
  187. return s
  188. }
  189. //格式化秘钥
  190. func FormatPrivateKey(privateKey string) (pKey string) {
  191. buffer := new(bytes.Buffer)
  192. buffer.WriteString("-----BEGIN RSA PRIVATE KEY-----\n")
  193. rawLen := 64
  194. keyLen := len(privateKey)
  195. raws := keyLen / rawLen
  196. temp := keyLen % rawLen
  197. if temp > 0 {
  198. raws++
  199. }
  200. start := 0
  201. end := start + rawLen
  202. for i := 0; i < raws; i++ {
  203. if i == raws-1 {
  204. buffer.WriteString(privateKey[start:])
  205. } else {
  206. buffer.WriteString(privateKey[start:end])
  207. }
  208. buffer.WriteString("\n")
  209. start += rawLen
  210. end = start + rawLen
  211. }
  212. buffer.WriteString("-----END RSA PRIVATE KEY-----\n")
  213. pKey = buffer.String()
  214. return
  215. }
  216. //格式化秘钥
  217. func FormatAliPayPublicKey(publicKey string) (pKey string) {
  218. buffer := new(bytes.Buffer)
  219. buffer.WriteString("-----BEGIN PUBLIC KEY-----\n")
  220. rawLen := 64
  221. keyLen := len(publicKey)
  222. raws := keyLen / rawLen
  223. temp := keyLen % rawLen
  224. if temp > 0 {
  225. raws++
  226. }
  227. start := 0
  228. end := start + rawLen
  229. for i := 0; i < raws; i++ {
  230. if i == raws-1 {
  231. buffer.WriteString(publicKey[start:])
  232. } else {
  233. buffer.WriteString(publicKey[start:end])
  234. }
  235. buffer.WriteString("\n")
  236. start += rawLen
  237. end = start + rawLen
  238. }
  239. buffer.WriteString("-----END PUBLIC KEY-----\n")
  240. pKey = buffer.String()
  241. return
  242. }
  243. func verifyAliPaySign(signData, sign, signType, aliPayPublicKey string) (err error) {
  244. var (
  245. h hash.Hash
  246. hashs crypto.Hash
  247. )
  248. signBytes, err := base64.StdEncoding.DecodeString(sign)
  249. if err != nil {
  250. return err
  251. }
  252. //解析秘钥
  253. block, _ := pem.Decode([]byte(aliPayPublicKey))
  254. if block == nil {
  255. return errors.New("支付宝公钥Decode错误")
  256. }
  257. key, err := x509.ParsePKIXPublicKey(block.Bytes)
  258. if err != nil {
  259. log.Println("x509.ParsePKIXPublicKey:", err)
  260. return err
  261. }
  262. publicKey, ok := key.(*rsa.PublicKey)
  263. if !ok {
  264. return errors.New("支付宝公钥转换错误")
  265. }
  266. //判断签名方式
  267. switch signType {
  268. case "RSA":
  269. hashs = crypto.SHA1
  270. case "RSA2":
  271. hashs = crypto.SHA256
  272. default:
  273. hashs = crypto.SHA256
  274. }
  275. h = hashs.New()
  276. h.Write([]byte(signData))
  277. return rsa.VerifyPKCS1v15(publicKey, hashs, h.Sum(nil), signBytes)
  278. }
  279. //换取授权访问令牌(默认使用utf-8,RSA2)
  280. // appId:应用ID
  281. // privateKey:应用私钥
  282. // grantType:值为 authorization_code 时,代表用code换取;值为 refresh_token 时,代表用refresh_token换取,传空默认code换取
  283. // codeOrToken:支付宝授权码或refresh_token
  284. func AlipaySystemOauthToken(appId, privateKey, grantType, codeOrToken string) (rsp *AliPaySystemOauthTokenResponse, err error) {
  285. var bs []byte
  286. body := make(BodyMap)
  287. if "authorization_code" == grantType {
  288. body.Set("grant_type", "authorization_code")
  289. body.Set("code", codeOrToken)
  290. } else if "refresh_token" == grantType {
  291. body.Set("grant_type", "refresh_token")
  292. body.Set("refresh_token", codeOrToken)
  293. } else {
  294. body.Set("grant_type", "authorization_code")
  295. body.Set("code", codeOrToken)
  296. }
  297. bs, err = doAliPay(appId, privateKey, body, "alipay.system.oauth.token")
  298. if err != nil {
  299. return nil, err
  300. }
  301. //fmt.Println("bs:", string(bs))
  302. rsp = new(AliPaySystemOauthTokenResponse)
  303. err = json.Unmarshal(bs, rsp)
  304. if err != nil {
  305. return nil, err
  306. }
  307. if rsp.AliPaySystemOauthTokenResponse.AccessToken != "" {
  308. return rsp, nil
  309. } else {
  310. return
  311. }
  312. }
  313. //向支付宝发送请求
  314. func doAliPay(appId, privateKey string, body BodyMap, method string) (bytes []byte, err error) {
  315. //===============生成参数===================
  316. //pubBody := make(BodyMap)
  317. body.Set("app_id", appId)
  318. body.Set("method", method)
  319. body.Set("format", "JSON")
  320. body.Set("charset", "utf-8")
  321. body.Set("sign_type", "RSA2")
  322. body.Set("timestamp", time.Now().Format(TimeLayout))
  323. body.Set("version", "1.0")
  324. //pubBody.Set("biz_content", string(bodyStr))
  325. //===============获取签名===================
  326. pKey := FormatPrivateKey(privateKey)
  327. sign, err := getRsaSign(body, "RSA2", pKey)
  328. if err != nil {
  329. return nil, err
  330. }
  331. body.Set("sign", sign)
  332. //fmt.Println("rsaSign:", sign)
  333. //===============发起请求===================
  334. urlParam := FormatAliPayURLParam(body)
  335. //fmt.Println("urlParam:", urlParam)
  336. var url string
  337. agent := HttpAgent()
  338. //正式环境
  339. url = zfb_base_url
  340. //fmt.Println(url)
  341. agent.Post(url)
  342. _, bs, errs := agent.
  343. Type("form-data").
  344. SendString(urlParam).
  345. EndBytes()
  346. if len(errs) > 0 {
  347. return nil, errs[0]
  348. }
  349. return bs, nil
  350. }