withdraw.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. package toppay
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "fmt"
  6. "net/http"
  7. "net/url"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "bet24.com/log"
  12. "bet24.com/public"
  13. notification "bet24.com/servers/micros/notification/proto"
  14. "bet24.com/servers/payment/config"
  15. "bet24.com/servers/payment/db"
  16. "github.com/gin-gonic/gin"
  17. )
  18. // 提现请求
  19. func WithdrawOrder(c *gin.Context) {
  20. obj := db.NewKayaWithdrawReq()
  21. if err := c.ShouldBind(&obj.In); err != nil {
  22. log.Debug("%s query params err %v", "toppay.WithdrawOrder", err)
  23. c.String(http.StatusOK, "fail")
  24. return
  25. }
  26. obj.In.IPAddress = strings.Split(c.Request.RemoteAddr, ":")[0]
  27. obj.DoAction()
  28. if obj.Out.OrderID == "" {
  29. log.Debug("%s GenOrder fail obj.In=%+v obj.Out=%+v", "toppay.WithdrawOrder", obj.In, obj.Out)
  30. c.String(http.StatusOK, "fail")
  31. return
  32. }
  33. if obj.Out.GetStatus != 0 {
  34. log.Debug("%s GenOrder Audit obj.In=%+v obj.Out=%+v", "toppay.WithdrawOrder", obj.In, obj.Out)
  35. c.String(http.StatusOK, "fail")
  36. return
  37. }
  38. // 请求时,没有传手机号
  39. if obj.In.Mobile == "" {
  40. obj.In.Mobile = obj.Out.Tel
  41. }
  42. // 请求withdrawOrder的代码
  43. req := withdraw_req{
  44. MerchantCode: config.Server.TopPay.MerchantCode,
  45. OrderNum: obj.Out.OrderID,
  46. Money: obj.In.Amount,
  47. Description: "withdraw",
  48. Name: obj.In.RealName,
  49. BankCode: obj.In.BankCode,
  50. Number: obj.In.BankCard,
  51. NotifyUrl: config.Server.TopPay.Url_withdraw_notify,
  52. FeeType: 1,
  53. DateTime: TIME_FORMAT,
  54. }
  55. params := url.Values{}
  56. params.Set("merchantCode", req.MerchantCode)
  57. params.Set("orderNum", req.OrderNum)
  58. params.Set("money", strconv.Itoa(req.Money))
  59. params.Set("description", req.Description)
  60. params.Set("name", req.Name)
  61. params.Set("bankCode", req.BankCode)
  62. params.Set("number", req.Number)
  63. params.Set("notifyUrl", req.NotifyUrl)
  64. params.Set("feeType", strconv.Itoa(req.FeeType))
  65. params.Set("dateTime", req.DateTime)
  66. // 生成签名
  67. checkContent := createEncryptStr(params)
  68. log.Debug("toppay.WithdrawOrder.checkContent ==> %s", checkContent)
  69. // 商户请求我们接口时使用商户私钥对请求参数 进行加密
  70. mchPriKey := fmt.Sprintf(`-----BEGIN PRIVATE KEY-----
  71. %s
  72. -----END PRIVATE KEY-----
  73. `, config.Server.TopPay.MCH_PRIVATE_KEY)
  74. if err := public.RSA.SetPrivateKey(mchPriKey); err != nil {
  75. log.Error("toppay.WithdrawOrder set private key :%v ==> %+v", err, params)
  76. return
  77. }
  78. // 私钥加密
  79. prienctypt, err := public.RSA.PriKeyENCTYPT([]byte(checkContent))
  80. if err != nil {
  81. log.Error("toppay.WithdrawOrder RSA.PriKeyENCTYPT err %v", err)
  82. return
  83. }
  84. req.Sign = base64.StdEncoding.EncodeToString(prienctypt)
  85. // log.Debug("toppay.payOrder req ==> %+v ", params)
  86. buf, _ := json.Marshal(req)
  87. respBody := public.HttpPostByJson(config.Server.TopPay.Url_withdraw_order, string(buf))
  88. log.Debug("toppay.WithdrawOrder req ==> %+v resp ==> %+v", string(buf), respBody)
  89. var resp withdraw_resp
  90. if err := json.Unmarshal([]byte(respBody), &resp); err != nil {
  91. log.Error("toppay.WithdrawOrder json unmarshal req ==> %+v resp ==> %+v fail %v", params, respBody, err)
  92. c.String(http.StatusOK, "fail")
  93. return
  94. }
  95. log.Debug("toppay.WithdrawOrder resp ==> %+v", resp)
  96. // 请求响应码,00000表示成功,其他失败
  97. if resp.PlatRespCode != RESP_CODE_SUCCESS {
  98. log.Error("toppay.withdrawRequest post return resp fail ==> %+v", resp)
  99. // // 余额不足,退款
  100. // if resp.PlatRespCode == RESP_CODE_FAIL && resp.PlatRespMessage == "insufficient account balance" {
  101. // obj := db.NewKayaWithdrawNotify()
  102. // obj.In.OrderID = req.OrderNum
  103. // obj.In.DfTransactionId = resp.PlatOrderNum
  104. // obj.In.Status = 0
  105. // obj.In.DfDesc = fmt.Sprintf("%s", resp.PlatRespMessage)
  106. // obj.In.Balance = 0
  107. // obj.DoAction()
  108. //
  109. // log.Debug("kaya.WithdrawOrder obj.In=%+v obj.Out=%+v", obj.In, obj.Out)
  110. // }
  111. c.String(http.StatusOK, "fail")
  112. return
  113. }
  114. // go coreClient.AddNotification(obj.In.UserID, notification.Notification_Gold, "")
  115. // 更新银行信息
  116. // objBank := db.NewBankInfoUp()
  117. // objBank.In.UserID = obj.In.UserID
  118. // objBank.In.RealName = req.Name
  119. // objBank.In.BankCard = req.Number
  120. // objBank.In.BankName = req.BankCode
  121. // objBank.In.Mobile = obj.In.Mobile
  122. // objBank.In.EMail = obj.In.Email
  123. // objBank.In.Address = obj.In.Address
  124. // objBank.DoAction()
  125. // log.Debug("toppay.WithdrawNotify need save bankInfo")
  126. c.String(http.StatusOK, "success")
  127. return
  128. }
  129. // 提现通知
  130. func WithdrawNotify(c *gin.Context) {
  131. var resp withdrawNotify
  132. if err := c.ShouldBind(&resp); err != nil {
  133. log.Debug("%s query params err %v", "toppay.WithdrawNotify", err)
  134. c.String(http.StatusOK, "")
  135. return
  136. }
  137. log.Debug("toppay.WithdrawNotify resp ==> %+v", resp)
  138. params := url.Values{}
  139. params.Set("bankCode", resp.BankCode)
  140. params.Set("description", resp.Description)
  141. params.Set("fee", strconv.Itoa(resp.Fee))
  142. params.Set("feeType", strconv.Itoa(resp.FeeType))
  143. params.Set("money", strconv.Itoa(resp.Money))
  144. params.Set("name", resp.Name)
  145. params.Set("number", resp.Number)
  146. params.Set("orderNum", resp.OrderNum)
  147. params.Set("platOrderNum", resp.PlatOrderNum)
  148. params.Set("status", resp.Status)
  149. params.Set("statusMsg", resp.StatusMsg)
  150. // 生成签名
  151. checkContent := createEncryptStr(params)
  152. log.Debug("toppay.WithdrawNotify checkContent ==> %s", checkContent)
  153. // 商户使用 商户后台显示的平台公钥 进行解密
  154. platPubKey := fmt.Sprintf(`-----BEGIN PUBLIC KEY-----
  155. %s
  156. -----END PUBLIC KEY-----
  157. `, config.Server.TopPay.PLAT_PUBLIC_KEY)
  158. if err := public.RSA.SetPublicKey(platPubKey); err != nil {
  159. log.Error("toppay.WithdrawNotify set public key :%v ==> %+v", err, params)
  160. return
  161. }
  162. data, err := base64.StdEncoding.DecodeString(resp.PlatSign)
  163. if err != nil {
  164. log.Error("toppay.WithdrawNotify base64.StdEncoding.DecodeString err %v", err)
  165. return
  166. }
  167. // 公钥解密
  168. pubdecrypt, err := public.RSA.PubKeyDECRYPT(data)
  169. if err != nil {
  170. log.Error("toppay.WithdrawNotify RSA.PubKeyDECRYPT err %v", err)
  171. return
  172. }
  173. // 校验信息
  174. if checkContent != string(pubdecrypt) {
  175. log.Error("toppay.payOrder 签名失败 ==> %+v", resp)
  176. return
  177. }
  178. log.Debug("toppay.PayNotify 签名成功")
  179. // 状态:2-成功 4-失败
  180. if resp.Status != WITHDRAW_SUCCESS && resp.Status != WITHDRAW_FAIL {
  181. log.Error("toppay.WithdrawNotify req ==> %+v", resp)
  182. c.String(http.StatusOK, "")
  183. return
  184. }
  185. // 查询账户余额
  186. balance := queryAccount()
  187. // 状态(0=Failure 1=Success 2=Pending(Success))
  188. status := 0
  189. switch resp.Status {
  190. case "2": // 2=成功
  191. status = 1
  192. case "4": // 4=失败
  193. status = 0
  194. default:
  195. status = 2
  196. }
  197. obj := db.NewKayaWithdrawNotify()
  198. obj.In.OrderID = resp.OrderNum
  199. obj.In.DfTransactionId = resp.PlatOrderNum
  200. obj.In.Status = status
  201. obj.In.DfDesc = fmt.Sprintf("%s,Fee: %d", strings.ReplaceAll(resp.StatusMsg, "'", ""), resp.Fee)
  202. obj.In.Balance = balance
  203. obj.DoAction()
  204. log.Debug("toppay.WithdrawNotify obj.In=%+v obj.Out=%+v", obj.In, obj.Out)
  205. // 提现失败,退款
  206. // if resp.Status == WITHDRAW_FAIL {
  207. // go coreClient.AddNotification(obj.Out.UserID, notification.Notification_Gold, "")
  208. // }
  209. c.String(http.StatusOK, "success")
  210. return
  211. }
  212. // 账户余额
  213. func queryAccount() int {
  214. req := queryAccount_req{
  215. MerchantCode: config.Server.TopPay.MerchantCode,
  216. DateTime: time.Now().Format(TIME_FORMAT),
  217. }
  218. params := url.Values{}
  219. params.Set("merchantCode", req.MerchantCode)
  220. params.Set("dateTime", req.DateTime)
  221. // 生成签名
  222. checkContent := createEncryptStr(params)
  223. log.Debug("toppay.queryAccount.checkContent ==> %s", checkContent)
  224. // 商户请求我们接口时使用商户私钥对请求参数 进行加密
  225. mchPriKey := fmt.Sprintf(`-----BEGIN PRIVATE KEY-----
  226. %s
  227. -----END PRIVATE KEY-----
  228. `, config.Server.TopPay.MCH_PRIVATE_KEY)
  229. if err := public.RSA.SetPrivateKey(mchPriKey); err != nil {
  230. log.Error("toppay.queryAccount set private key :%v ==> %+v", err, params)
  231. return -1
  232. }
  233. // 私钥加密
  234. prienctypt, err := public.RSA.PriKeyENCTYPT([]byte(checkContent))
  235. if err != nil {
  236. log.Error("kaya.queryAccount RSA.PriKeyENCTYPT err %v", err)
  237. return -1
  238. }
  239. req.Sign = base64.StdEncoding.EncodeToString(prienctypt)
  240. // log.Debug("toppay.queryAccount req ==> %+v ", params)
  241. buf, _ := json.Marshal(req)
  242. respBody := public.HttpPostByJson(config.Server.TopPay.Url_queryAccount, string(buf))
  243. log.Debug("toppay.queryAccount req ==> %+v resp ==> %+v", params, respBody)
  244. var resp queryAccount_resp
  245. if err := json.Unmarshal([]byte(respBody), &resp); err != nil {
  246. log.Error("toppay.queryAccount json unmarshal req ==> %+v resp ==> %+v fail %v", params, respBody, err)
  247. return -1
  248. }
  249. log.Debug("toppay.queryAccount resp ==> %+v", resp)
  250. // 请求响应码
  251. if resp.PlatRespCode != RESP_CODE_SUCCESS {
  252. log.Error("toppay.queryAccount post return resp fail ==> %+v", resp)
  253. return -1
  254. }
  255. balance, err := strconv.Atoi(resp.Balance)
  256. if err != nil {
  257. log.Error("toppay.queryAccount get balance %v", err)
  258. return -1
  259. }
  260. return balance
  261. }
  262. // 提现审核
  263. func WithdrawAudit(c *gin.Context) {
  264. obj := db.NewKayaWithdrawAudit()
  265. if err := c.ShouldBind(&obj.In); err != nil {
  266. log.Debug("%s shouldBind err %v", "toppay.WithdrawAudit", err)
  267. return
  268. }
  269. obj.DoAction(nil)
  270. // 审核失败
  271. if obj.Out.RetCode != 1 {
  272. c.JSON(http.StatusOK, obj.Out)
  273. return
  274. }
  275. log.Debug("toppay.WithdrawAudit obj.In=%+v obj.Out=%+v", obj.In, obj.Out)
  276. // 审核成功
  277. // 状态 2=同意 11=拒绝
  278. if obj.In.Status != 2 {
  279. go notification.AddNotification(obj.Out.UserID, notification.Notification_Gold, "")
  280. c.JSON(http.StatusOK, obj.Out)
  281. return
  282. }
  283. // 请求withdrawOrder的代码
  284. req := withdraw_req{
  285. MerchantCode: config.Server.TopPay.MerchantCode,
  286. OrderNum: obj.Out.OrderID,
  287. Money: obj.Out.Amount,
  288. Description: "withdraw",
  289. Name: obj.Out.RealName,
  290. BankCode: obj.Out.BankName,
  291. Number: obj.Out.BankCard,
  292. NotifyUrl: config.Server.TopPay.Url_withdraw_notify,
  293. FeeType: 0,
  294. DateTime: TIME_FORMAT,
  295. }
  296. params := url.Values{}
  297. params.Set("merchantCode", req.MerchantCode)
  298. params.Set("orderNum", req.OrderNum)
  299. params.Set("money", strconv.Itoa(req.Money))
  300. params.Set("description", req.Description)
  301. params.Set("name", req.Name)
  302. params.Set("bankCode", req.BankCode)
  303. params.Set("number", req.Number)
  304. params.Set("notifyUrl", req.NotifyUrl)
  305. params.Set("feeType", strconv.Itoa(req.FeeType))
  306. params.Set("dateTime", req.DateTime)
  307. // 生成签名
  308. checkContent := createEncryptStr(params)
  309. log.Debug("toppay.WithdrawAudit.checkContent ==> %s", checkContent)
  310. // 商户请求我们接口时使用商户私钥对请求参数 进行加密
  311. mchPriKey := fmt.Sprintf(`-----BEGIN PRIVATE KEY-----
  312. %s
  313. -----END PRIVATE KEY-----
  314. `, config.Server.TopPay.MCH_PRIVATE_KEY)
  315. if err := public.RSA.SetPrivateKey(mchPriKey); err != nil {
  316. log.Error("toppay.WithdrawAudit set private key :%v ==> %+v", err, params)
  317. return
  318. }
  319. // 私钥加密
  320. prienctypt, err := public.RSA.PriKeyENCTYPT([]byte(checkContent))
  321. if err != nil {
  322. log.Error("toppay.WithdrawAudit RSA.PriKeyENCTYPT err %v", err)
  323. return
  324. }
  325. req.Sign = base64.StdEncoding.EncodeToString(prienctypt)
  326. // log.Debug("toppay.payOrder req ==> %+v ", params)
  327. buf, _ := json.Marshal(req)
  328. respBody := public.HttpPostByJson(config.Server.TopPay.Url_withdraw_order, string(buf))
  329. log.Debug("toppay.WithdrawAudit req ==> %+v resp ==> %+v", string(buf), respBody)
  330. var resp withdraw_resp
  331. if err := json.Unmarshal([]byte(respBody), &resp); err != nil {
  332. log.Error("toppay.WithdrawAudit json unmarshal req ==> %+v resp ==> %+v fail %v", params, respBody, err)
  333. c.String(http.StatusOK, "fail")
  334. return
  335. }
  336. log.Debug("toppay.WithdrawAudit resp ==> %+v", resp)
  337. // 请求响应码,00000表示成功,其他失败
  338. if resp.PlatRespCode != RESP_CODE_SUCCESS {
  339. log.Error("toppay.WithdrawAudit post return resp fail ==> %+v", resp)
  340. // 余额不足,退款
  341. if resp.PlatRespCode == RESP_CODE_FAIL && resp.PlatRespMessage == "insufficient account balance" {
  342. obj := db.NewKayaWithdrawNotify()
  343. obj.In.OrderID = req.OrderNum
  344. obj.In.DfTransactionId = resp.PlatOrderNum
  345. obj.In.Status = 0
  346. obj.In.DfDesc = fmt.Sprintf("%s", resp.PlatRespMessage)
  347. obj.In.Balance = 0
  348. obj.DoAction()
  349. log.Debug("toppay.WithdrawAudit obj.In=%+v obj.Out=%+v", obj.In, obj.Out)
  350. }
  351. c.JSON(http.StatusOK, obj.Out)
  352. return
  353. }
  354. // 更新银行信息
  355. objBank := db.NewBankInfoUp()
  356. objBank.In.UserID = obj.Out.UserID
  357. objBank.In.RealName = req.Name
  358. objBank.In.BankCard = req.Number
  359. objBank.In.BankName = req.BankCode
  360. objBank.In.Mobile = obj.Out.Mobile
  361. objBank.In.EMail = obj.Out.EMail
  362. objBank.In.Address = obj.Out.Address
  363. objBank.DoAction()
  364. log.Debug("toppay.WithdrawAudit need save bankInfo")
  365. c.JSON(http.StatusOK, obj.Out)
  366. return
  367. }