api.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. package unicom
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/des"
  6. "crypto/md5"
  7. "encoding/base64"
  8. "encoding/hex"
  9. "encoding/json"
  10. "errors"
  11. "net/http"
  12. "net/url"
  13. "sort"
  14. "strconv"
  15. "strings"
  16. "time"
  17. "go-common/app/interface/main/app-wall/model"
  18. "go-common/app/interface/main/app-wall/model/unicom"
  19. "go-common/library/ecode"
  20. "go-common/library/log"
  21. httpx "go-common/library/net/http/blademaster"
  22. )
  23. const (
  24. _cpid = "bilibl"
  25. _spid = "979"
  26. _apptype = "2"
  27. _broadbandPass = "9ed226d9"
  28. // url
  29. _orderURL = "/videoif/order.do"
  30. _ordercancelURL = "/videoif/cancelOrder.do"
  31. _sendsmscodeURL = "/videoif/sendSmsCode.do"
  32. _smsNumberURL = "/videoif/smsNumber.do"
  33. // unicom
  34. _unicomIPURL = "/web/statistics/subsystem_2/query_ip.php"
  35. _unicomUser = "000012"
  36. _unicomPass = "1pibH5e1BN4V"
  37. _unicomFlowExchangeURL = "/openservlet"
  38. _unicomAppKey = "com.aop.app.bilibili"
  39. _unicomSecurity = "DVniSMVU6Z3cCIG3vbOn4Fqbof+QJ/6etD+lpa4M4clgj/Dv6XT0syTR8Xgu5nVzKuzro8eiTUzHy/QAzGjp+A=="
  40. _unicomAppMethodFlow = "com.ssp.method.outflowchange"
  41. _unicomMethodNumber = "com.aop.method.checkusernumber"
  42. _unicomMethodFlowPre = "com.ssp.method.outflowpre"
  43. _unicomMethodQryFlowChange = "com.ssp.method.outqryflowchange"
  44. )
  45. // Order unicom order
  46. func (d *Dao) Order(c context.Context, usermob, channel string, ordertype int) (data *unicom.BroadbandOrder, msg string, err error) {
  47. params := url.Values{}
  48. params.Set("cpid", _cpid)
  49. params.Set("spid", _spid)
  50. params.Set("ordertype", strconv.Itoa(ordertype))
  51. params.Set("userid", usermob)
  52. params.Set("apptype", _apptype)
  53. if channel != "" {
  54. params.Set("channel", channel)
  55. }
  56. var res struct {
  57. Code string `json:"resultcode"`
  58. Msg string `json:"errorinfo"`
  59. *unicom.BroadbandOrder
  60. }
  61. if err = d.broadbandHTTPGet(c, d.orderURL, params, &res); err != nil {
  62. log.Error("unicom order url(%v) error(%v)", d.orderURL+"?"+params.Encode(), err)
  63. return
  64. }
  65. b, _ := json.Marshal(&res)
  66. log.Info("unicom order url(%v) response(%s)", d.orderURL+"?"+params.Encode(), b)
  67. if res.Code != "0" {
  68. err = ecode.String(res.Code)
  69. msg = res.Msg
  70. log.Error("unicom order url(%v) code(%s) Msg(%s)", d.orderURL+"?"+params.Encode(), res.Code, res.Msg)
  71. return
  72. }
  73. data = res.BroadbandOrder
  74. return
  75. }
  76. // CancelOrder unicom cancel order
  77. func (d *Dao) CancelOrder(c context.Context, usermob string) (data *unicom.BroadbandOrder, msg string, err error) {
  78. params := url.Values{}
  79. params.Set("cpid", _cpid)
  80. params.Set("spid", _spid)
  81. params.Set("userid", usermob)
  82. params.Set("apptype", _apptype)
  83. var res struct {
  84. Code string `json:"resultcode"`
  85. Msg string `json:"errorinfo"`
  86. *unicom.BroadbandOrder
  87. }
  88. if err = d.broadbandHTTPGet(c, d.ordercancelURL, params, &res); err != nil {
  89. log.Error("unicom cancel order url(%s) error(%v)", d.ordercancelURL+"?"+params.Encode(), err)
  90. return
  91. }
  92. b, _ := json.Marshal(&res)
  93. log.Info("unicom cancel order url(%s) response(%s)", d.ordercancelURL+"?"+params.Encode(), b)
  94. if res.Code != "0" {
  95. err = ecode.String(res.Code)
  96. msg = res.Msg
  97. log.Error("unicom cancel order url(%v) code(%s) Msg(%s)", d.orderURL+"?"+params.Encode(), res.Code, res.Msg)
  98. return
  99. }
  100. data = res.BroadbandOrder
  101. return
  102. }
  103. // UnicomIP unicom ip orders
  104. func (d *Dao) UnicomIP(c context.Context, now time.Time) (unicomIPs []*unicom.UnicomIP, err error) {
  105. params := url.Values{}
  106. params.Set("user", _unicomUser)
  107. tick := strconv.FormatInt(now.Unix(), 10)
  108. params.Set("tick", tick)
  109. mh := md5.Sum([]byte(_unicomUser + tick + _unicomPass))
  110. var (
  111. key string
  112. )
  113. if key = hex.EncodeToString(mh[:]); len(key) > 16 {
  114. key = key[:16]
  115. }
  116. params.Set("key", key)
  117. var res struct {
  118. Code int `json:"code"`
  119. LastUpdateTime int64 `json:"last_update_time"`
  120. Desc []struct {
  121. StartIP string `json:"start_ip"`
  122. Length string `json:"length"`
  123. } `json:"desc"`
  124. }
  125. if err = d.broadbandHTTPPost(c, d.unicomIPURL, params, &res); err != nil {
  126. log.Error("unicom ip order url(%s) error(%v)", d.unicomIPURL+"?"+params.Encode(), err)
  127. return
  128. }
  129. if res.Code != 0 {
  130. err = ecode.Int(res.Code)
  131. log.Error("unicom ip order url(%s) res code (%d)", d.unicomIPURL+"?"+params.Encode(), res.Code)
  132. return
  133. }
  134. b, _ := json.Marshal(&res)
  135. log.Info("unicom ip url(%s) response(%s)", d.unicomIPURL+"?"+params.Encode(), b)
  136. for _, uip := range res.Desc {
  137. uiplen, _ := strconv.Atoi(uip.Length)
  138. if uiplen < 1 {
  139. log.Error("unicom ip length 0")
  140. continue
  141. }
  142. ipEndInt := model.InetAtoN(uip.StartIP) + uint32((uiplen - 1))
  143. ipEnd := model.InetNtoA(ipEndInt)
  144. unicomIP := &unicom.UnicomIP{}
  145. unicomIP.UnicomIPStrToint(uip.StartIP, ipEnd)
  146. unicomIPs = append(unicomIPs, unicomIP)
  147. }
  148. return
  149. }
  150. // SendSmsCode unicom sms code
  151. func (d *Dao) SendSmsCode(c context.Context, phone string) (msg string, err error) {
  152. var (
  153. key = []byte(_broadbandPass)
  154. phoneByte = []byte(phone)
  155. userid string
  156. )
  157. userid, err = d.desEncrypt(phoneByte, key)
  158. if err != nil {
  159. log.Error("d.desEncrypt error(%v)", err)
  160. return
  161. }
  162. params := url.Values{}
  163. params.Set("cpid", _cpid)
  164. params.Set("userid", string(userid))
  165. params.Set("apptype", _apptype)
  166. var res struct {
  167. Code string `json:"resultcode"`
  168. Msg string `json:"errorinfo"`
  169. }
  170. if err = d.unicomHTTPGet(c, d.sendsmscodeURL, params, &res); err != nil {
  171. log.Error("unicom sendsmscode url(%v) error(%v)", d.sendsmscodeURL+"?"+params.Encode(), err)
  172. return
  173. }
  174. b, _ := json.Marshal(&res)
  175. log.Info("unicom sendsmscode url(%v) response(%s)", d.sendsmscodeURL+"?"+params.Encode(), b)
  176. if res.Code != "0" {
  177. err = ecode.String(res.Code)
  178. msg = res.Msg
  179. log.Error("unicom sendsmscode url(%v) code(%s) Msg(%s)", d.sendsmscodeURL+"?"+params.Encode(), res.Code, res.Msg)
  180. return
  181. }
  182. return
  183. }
  184. // SmsNumber unicom sms usermob
  185. func (d *Dao) SmsNumber(c context.Context, phone string, code int) (usermob string, msg string, err error) {
  186. var (
  187. key = []byte(_broadbandPass)
  188. phoneByte = []byte(phone)
  189. userid string
  190. )
  191. userid, err = d.desEncrypt(phoneByte, key)
  192. if err != nil {
  193. log.Error("d.desEncrypt error(%v)", err)
  194. return
  195. }
  196. params := url.Values{}
  197. params.Set("cpid", _cpid)
  198. params.Set("userid", userid)
  199. params.Set("vcode", strconv.Itoa(code))
  200. params.Set("apptype", _apptype)
  201. var res struct {
  202. Code string `json:"resultcode"`
  203. Usermob string `json:"userid"`
  204. Msg string `json:"errorinfo"`
  205. }
  206. if err = d.unicomHTTPGet(c, d.smsNumberURL, params, &res); err != nil {
  207. log.Error("unicom smsNumberURL url(%v) error(%v)", d.smsNumberURL+"?"+params.Encode(), err)
  208. return
  209. }
  210. b, _ := json.Marshal(&res)
  211. log.Info("unicom sendsmsnumber url(%v) response(%s)", d.smsNumberURL+"?"+params.Encode(), b)
  212. if res.Code != "0" {
  213. err = ecode.String(res.Code)
  214. msg = res.Msg
  215. log.Error("unicom sendsmsnumber url(%v) code(%s) Msg(%s)", d.smsNumberURL+"?"+params.Encode(), res.Code, res.Msg)
  216. return
  217. }
  218. usermob = res.Usermob
  219. return
  220. }
  221. // FlowExchange flow exchange
  222. func (d *Dao) FlowExchange(c context.Context, phone int, flowcode string, requestNo int64, ts time.Time) (orderID, outorderID, msg string, err error) {
  223. outorderIDStr := "bili" + ts.Format("20060102") + strconv.FormatInt(requestNo%10000000, 10)
  224. if len(outorderIDStr) > 22 {
  225. outorderIDStr = outorderIDStr[:22]
  226. }
  227. param := url.Values{}
  228. param.Set("appkey", _unicomAppKey)
  229. param.Set("apptx", strconv.FormatInt(requestNo, 10))
  230. param.Set("flowexchangecode", flowcode)
  231. param.Set("method", _unicomAppMethodFlow)
  232. param.Set("outorderid", outorderIDStr)
  233. param.Set("timestamp", ts.Format("2006-01-02 15:04:05"))
  234. param.Set("usernumber", strconv.Itoa(phone))
  235. urlVal := d.urlParams(param)
  236. urlVal = urlVal + "&" + d.sign(urlVal)
  237. var res struct {
  238. Code string `json:"respcode"`
  239. Msg string `json:"respdesc"`
  240. OrderID string `json:"orderid"`
  241. OutorderID string `json:"outorderid"`
  242. }
  243. if err = d.unicomHTTPGet(c, d.unicomFlowExchangeURL+"?"+urlVal, nil, &res); err != nil {
  244. log.Error("unicom flow change url(%v) error(%v)", d.unicomFlowExchangeURL+"?"+urlVal, err)
  245. return
  246. }
  247. b, _ := json.Marshal(&res)
  248. log.Info("unicom flow url(%v) response(%s)", d.unicomFlowExchangeURL+"?"+urlVal, b)
  249. msg = res.Msg
  250. if res.Code != "0000" {
  251. err = ecode.String(res.Code)
  252. log.Error("unicom flow change url(%v) code(%v) msg(%v)", d.unicomFlowExchangeURL+"?"+urlVal, res.Code, res.Msg)
  253. return
  254. }
  255. orderID = res.OrderID
  256. outorderID = res.OutorderID
  257. return
  258. }
  259. // PhoneVerification unicom phone verification
  260. func (d *Dao) PhoneVerification(c context.Context, phone string, requestNo int64, ts time.Time) (msg string, err error) {
  261. param := url.Values{}
  262. param.Set("appkey", _unicomAppKey)
  263. param.Set("apptx", strconv.FormatInt(requestNo, 10))
  264. param.Set("method", _unicomMethodNumber)
  265. param.Set("timestamp", ts.Format("2006-01-02 15:04:05"))
  266. param.Set("usernumber", phone)
  267. urlVal := d.urlParams(param)
  268. urlVal = urlVal + "&" + d.sign(urlVal)
  269. var res struct {
  270. Code string `json:"respcode"`
  271. Msg string `json:"respdesc"`
  272. }
  273. if err = d.unicomHTTPGet(c, d.unicomFlowExchangeURL+"?"+urlVal, nil, &res); err != nil {
  274. log.Error("unicom phone url(%v) error(%v)", d.unicomFlowExchangeURL+"?"+urlVal, err)
  275. return
  276. }
  277. b, _ := json.Marshal(&res)
  278. log.Info("unicom phone url(%v) response(%s)", d.unicomFlowExchangeURL+"?"+urlVal, b)
  279. msg = res.Msg
  280. if res.Code != "0000" {
  281. err = ecode.String(res.Code)
  282. log.Error("unicom phone url(%v) code(%v) msg(%v)", d.unicomFlowExchangeURL+"?"+urlVal, res.Code, res.Msg)
  283. return
  284. }
  285. return
  286. }
  287. // FlowPre unicom phone flow pre
  288. func (d *Dao) FlowPre(c context.Context, phone int, requestNo int64, ts time.Time) (msg string, err error) {
  289. param := url.Values{}
  290. param.Set("appkey", _unicomAppKey)
  291. param.Set("apptx", strconv.FormatInt(requestNo, 10))
  292. param.Set("method", _unicomMethodFlowPre)
  293. param.Set("timestamp", ts.Format("2006-01-02 15:04:05"))
  294. param.Set("usernumber", strconv.Itoa(phone))
  295. urlVal := d.urlParams(param)
  296. urlVal = urlVal + "&" + d.sign(urlVal)
  297. var res struct {
  298. Code string `json:"respcode"`
  299. Notice string `json:"noticecontent"`
  300. Msg string `json:"respdesc"`
  301. }
  302. if err = d.unicomHTTPGet(c, d.unicomFlowExchangeURL+"?"+urlVal, nil, &res); err != nil {
  303. log.Error("unicom flowpre url(%v) error(%v)", d.unicomFlowExchangeURL+"?"+urlVal, err)
  304. return
  305. }
  306. b, _ := json.Marshal(&res)
  307. log.Info("unicom flowpre url(%v) response(%s)", d.unicomFlowExchangeURL+"?"+urlVal, b)
  308. msg = res.Msg
  309. if res.Code != "0000" {
  310. if res.Code == "0001" {
  311. err = ecode.String(res.Code)
  312. msg = res.Notice
  313. } else {
  314. err = ecode.String(res.Code)
  315. log.Error("unicom flowpre url(%v) code(%v) msg(%v)", d.unicomFlowExchangeURL+"?"+urlVal, res.Code, res.Msg)
  316. }
  317. return
  318. }
  319. return
  320. }
  321. // FlowQry unicom phone qryflowchange
  322. func (d *Dao) FlowQry(c context.Context, phone int, requestNo int64, outorderid, orderid string, ts time.Time) (orderstatus, msg string, err error) {
  323. param := url.Values{}
  324. param.Set("appkey", _unicomAppKey)
  325. param.Set("apptx", strconv.FormatInt(requestNo, 10))
  326. param.Set("method", _unicomMethodQryFlowChange)
  327. param.Set("orderid", orderid)
  328. param.Set("outorderid", outorderid)
  329. param.Set("timestamp", ts.Format("2006-01-02 15:04:05"))
  330. param.Set("usernumber", strconv.Itoa(phone))
  331. urlVal := d.urlParams(param)
  332. urlVal = urlVal + "&" + d.sign(urlVal)
  333. var res struct {
  334. Code string `json:"respcode"`
  335. Orderstatus string `json:"orderstatus"`
  336. Failurtype string `json:"failurtype"`
  337. Msg string `json:"respdesc"`
  338. }
  339. if err = d.unicomHTTPGet(c, d.unicomFlowExchangeURL+"?"+urlVal, nil, &res); err != nil {
  340. log.Error("unicom flowQry url(%v) error(%v)", d.unicomFlowExchangeURL+"?"+urlVal, err)
  341. return
  342. }
  343. b, _ := json.Marshal(&res)
  344. log.Info("unicom flowQry url(%v) response(%s)", d.unicomFlowExchangeURL+"?"+urlVal, b)
  345. msg = res.Msg
  346. if res.Code != "0000" {
  347. err = ecode.String(res.Code)
  348. log.Error("unicom flowQry url(%v) code(%v) msg(%v)", d.unicomFlowExchangeURL+"?"+urlVal, res.Code, res.Msg)
  349. return
  350. }
  351. orderstatus = res.Orderstatus
  352. return
  353. }
  354. // broadbandHTTPGet http get
  355. func (d *Dao) broadbandHTTPGet(c context.Context, urlStr string, params url.Values, res interface{}) (err error) {
  356. return d.wallHTTP(c, d.client, http.MethodGet, urlStr, params, res)
  357. }
  358. // broadbandHTTPPost http post
  359. func (d *Dao) broadbandHTTPPost(c context.Context, urlStr string, params url.Values, res interface{}) (err error) {
  360. return d.wallHTTP(c, d.client, http.MethodPost, urlStr, params, res)
  361. }
  362. // unicomHTTPGet http get
  363. func (d *Dao) unicomHTTPGet(c context.Context, urlStr string, params url.Values, res interface{}) (err error) {
  364. return d.wallHTTP(c, d.uclient, http.MethodGet, urlStr, params, res)
  365. }
  366. // wallHTTP http
  367. func (d *Dao) wallHTTP(c context.Context, client *httpx.Client, method, urlStr string, params url.Values, res interface{}) (err error) {
  368. var (
  369. req *http.Request
  370. )
  371. ru := urlStr
  372. if params != nil {
  373. ru = urlStr + "?" + params.Encode()
  374. }
  375. switch method {
  376. case http.MethodGet:
  377. req, err = http.NewRequest(http.MethodGet, ru, nil)
  378. default:
  379. req, err = http.NewRequest(http.MethodPost, urlStr, strings.NewReader(params.Encode()))
  380. }
  381. if err != nil {
  382. log.Error("unicom_http.NewRequest url(%s) error(%v)", urlStr+"?"+params.Encode(), err)
  383. return
  384. }
  385. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  386. req.Header.Set("X-BACKEND-BILI-REAL-IP", "")
  387. return d.client.Do(c, req, &res)
  388. }
  389. func (d *Dao) desEncrypt(src, key []byte) (string, error) {
  390. block, err := des.NewCipher(key)
  391. if err != nil {
  392. return "", err
  393. }
  394. bs := block.BlockSize()
  395. src = d.pkcs5Padding(src, bs)
  396. if len(src)%bs != 0 {
  397. return "", errors.New("Need a multiple of the blocksize")
  398. }
  399. out := make([]byte, len(src))
  400. dst := out
  401. for len(src) > 0 {
  402. block.Encrypt(dst, src[:bs])
  403. src = src[bs:]
  404. dst = dst[bs:]
  405. }
  406. encodeString := base64.StdEncoding.EncodeToString(out)
  407. return encodeString, nil
  408. }
  409. func (d *Dao) pkcs5Padding(ciphertext []byte, blockSize int) []byte {
  410. padding := blockSize - len(ciphertext)%blockSize
  411. padtext := bytes.Repeat([]byte{byte(padding)}, padding)
  412. return append(ciphertext, padtext...)
  413. }
  414. func (d *Dao) urlParams(v url.Values) string {
  415. if v == nil {
  416. return ""
  417. }
  418. var buf bytes.Buffer
  419. keys := make([]string, 0, len(v))
  420. for k := range v {
  421. keys = append(keys, k)
  422. }
  423. sort.Strings(keys)
  424. for _, k := range keys {
  425. vs := v[k]
  426. prefix := k + "="
  427. for _, v := range vs {
  428. if buf.Len() > 0 {
  429. buf.WriteByte('&')
  430. }
  431. buf.WriteString(prefix)
  432. buf.WriteString(v)
  433. }
  434. }
  435. return buf.String()
  436. }
  437. func (d *Dao) sign(params string) string {
  438. str := strings.Replace(params, "&", "$", -1)
  439. str2 := strings.Replace(str, "=", "$", -1)
  440. mh := md5.Sum([]byte(_unicomSecurity + "$" + str2 + "$" + _unicomSecurity))
  441. signparam := url.Values{}
  442. signparam.Set("sign", base64.StdEncoding.EncodeToString(mh[:]))
  443. return signparam.Encode()
  444. }