alipay_server_api.go 9.4 KB

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