main.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "encoding/xml"
  6. "errors"
  7. "flag"
  8. "fmt"
  9. "io/ioutil"
  10. stdlog "log"
  11. "math/rand"
  12. "net/http"
  13. "os"
  14. "os/signal"
  15. "runtime"
  16. "syscall"
  17. "time"
  18. "xiaoniaokuaiyan.com/xiaoniao/pay/ali"
  19. "gopkg.in/guregu/null.v3"
  20. "github.com/go-kit/kit/log"
  21. "github.com/go-zoo/bone"
  22. "github.com/smartwalle/alipay/v3"
  23. "xiaoniaokuaiyan.com/xiaoniao/config"
  24. dal "xiaoniaokuaiyan.com/xiaoniao/dal"
  25. "xiaoniaokuaiyan.com/xiaoniao/pay/wx"
  26. "xiaoniaokuaiyan.com/xiaoniao/retry"
  27. "xiaoniaokuaiyan.com/xiaoniao/search"
  28. "xiaoniaokuaiyan.com/xiaoniao/server"
  29. service "xiaoniaokuaiyan.com/xiaoniao/service"
  30. "xiaoniaokuaiyan.com/xiaoniao/util"
  31. )
  32. func checkRuntimeErr(err error) bool {
  33. if err != nil {
  34. stdlog.Fatalf("error: %v", err)
  35. return true
  36. }
  37. return false
  38. }
  39. func wxScanPaycbHandler(w http.ResponseWriter, req *http.Request) {
  40. if req.Method != "POST" {
  41. w.WriteHeader(http.StatusMethodNotAllowed)
  42. return
  43. }
  44. xmlDec := xml.NewDecoder(req.Body)
  45. defer req.Body.Close()
  46. payResult := &wx.UnionPayResult{}
  47. err := xmlDec.Decode(payResult)
  48. stdlog.Println("wxpaycb:", payResult)
  49. if err != nil {
  50. stdlog.Println("wxpaycb_err:", err)
  51. w.Write([]byte(err.Error()))
  52. return
  53. }
  54. db := util.GetWriteSqlDB()
  55. tcwp := struct {
  56. ThirdPNO null.String `db:"third_pay_no"`
  57. Source null.String `db:"usefor"`
  58. Remark null.String `db:"remark"`
  59. }{}
  60. db.Get(&tcwp, "select usefor,third_pay_no,remark from t_custom_wxscan_pay where id = ?", payResult.OutTradeNo)
  61. if tcwp.ThirdPNO.Valid {
  62. writeWxPayCbOk(w)
  63. return
  64. }
  65. //thirdPNO := null.String{}
  66. //db.Get(&thirdPNO, "select third_pay_no from t_custom_wxscan_pay where id = ?", payResult.OutTradeNo)
  67. //if thirdPNO.Valid {
  68. // writeWxPayCbOk(w)
  69. // return
  70. //}
  71. kv, _ := util.StructToMap(payResult)
  72. delete(kv, "sign")
  73. jssdk := wx.NewJsSdk()
  74. csign := jssdk.ComputePaySignature(kv, config.IniConf.Section("weixin").Key("wx.apikey").Value())
  75. if csign != payResult.Sign {
  76. stdlog.Println("wxpaycb_err: wrong sign")
  77. _, err = util.SendMail(util.MailList{
  78. {"liuguiqi", "liugq@xniao.com.cn"},
  79. {"guoxiaozhou", "43572650@qq.com"},
  80. {"houyoufang", "houyf@xniao.com.cn"},
  81. }, "您的商户订单号为:"+payResult.OutTradeNo+"由于签名校验错误导致订单信息", "微信支付回调错误消息提醒")
  82. if err != nil {
  83. stdlog.Println("SEND_MAIL_ERROR:", err)
  84. }
  85. w.Write([]byte("wrong sign"))
  86. return
  87. }
  88. if payResult.ReturnCode == "SUCCESS" && payResult.ResultCode == "SUCCESS" {
  89. payTime, _ := time.Parse("20060102150405", payResult.TimeEnd)
  90. actualPay := payResult.TotalFee
  91. _, err = db.Exec("update t_custom_wxscan_pay set third_pay_no = ?, actual_payment = ?, payment_time = ? where id = ?", payResult.TransactionId, actualPay, payTime.Format("2006-01-02 15:04:05"), payResult.OutTradeNo)
  92. if err != nil {
  93. stdlog.Println("UPDATE_SCANPAY_STATUS:", err)
  94. } else {
  95. client := util.GetRedis()
  96. msg := map[string]interface{}{
  97. "user": "system",
  98. "channel": "SCANPAY-INFORM",
  99. "data": map[string]interface{}{
  100. "id": payResult.OutTradeNo,
  101. "total_fee": payResult.TotalFee,
  102. },
  103. }
  104. buf, _ := json.Marshal(msg)
  105. client.Publish("xn-message", string(buf))
  106. }
  107. }
  108. writeWxPayCbOk(w)
  109. if tcwp.Source.ValueOrZero() == "jsl" && tcwp.Remark.ValueOrZero() != "" {
  110. go orderSrv.JinShuiLianServer(tcwp.Remark.ValueOrZero())
  111. }
  112. }
  113. func writeWxPayCbOk(w http.ResponseWriter) {
  114. okXml := `<xml>
  115. <return_code><![CDATA[SUCCESS]]></return_code>
  116. <return_msg><![CDATA[OK]]></return_msg>
  117. </xml>`
  118. w.Write([]byte(okXml))
  119. }
  120. func wxPaycbHandler(w http.ResponseWriter, req *http.Request) {
  121. if req.Method != "POST" {
  122. w.WriteHeader(http.StatusMethodNotAllowed)
  123. return
  124. }
  125. //xmlDec := xml.NewDecoder(req.Body)
  126. buf, _ := ioutil.ReadAll(req.Body)
  127. defer req.Body.Close()
  128. payResult := &wx.UnionPayResult{}
  129. err := xml.Unmarshal(buf, payResult)
  130. //err := xmlDec.Decode(payResult)
  131. stdlog.Println("wxpaycb:", payResult)
  132. if err != nil {
  133. stdlog.Println("wxpaycb_err:", err)
  134. w.Write([]byte(err.Error()))
  135. return
  136. }
  137. db := util.GetWriteSqlDB()
  138. thirdPNO := null.String{}
  139. db.Get(&thirdPNO, "select third_pay_no from t_order where pay_no = ?", payResult.OutTradeNo)
  140. if thirdPNO.Valid {
  141. writeWxPayCbOk(w)
  142. return
  143. }
  144. kv, _ := util.StructToMap(payResult)
  145. delete(kv, "sign")
  146. jssdk := wx.NewJsSdk()
  147. csign := jssdk.ComputePaySignature(kv, config.IniConf.Section("weixin").Key("wx.apikey").Value())
  148. if csign != payResult.Sign {
  149. fmt.Println(string(buf))
  150. stdlog.Println("wxpaycb_err: wrong sign", csign)
  151. go func() {
  152. retry.Run(&retry.Policy{Attempts: 3, Sleep: time.Second, Factor: 2},
  153. func() error {
  154. rt, _ := orderSrv.WxPayQuery(map[string]string{"out_trade_no": payResult.OutTradeNo})
  155. if rt != nil && rt["status"] == "SUCCESS" {
  156. return retry.Stop(errors.New("success"))
  157. }
  158. return errors.New("OUT_TIMES")
  159. })
  160. }()
  161. _, err = util.SendMail(util.MailList{
  162. {"liuguiqi", "liugq@xniao.com.cn"},
  163. {"guoxiaozhou", "43572650@qq.com"},
  164. {"houyoufang", "houyf@xniao.com.cn"},
  165. }, "您的商户订单号为:"+payResult.OutTradeNo+"由于签名校验错误导致订单信息", "微信支付回调错误消息提醒")
  166. if err != nil {
  167. stdlog.Println("SEND_MAIL_ERROR:", err)
  168. }
  169. w.Write([]byte("wrong sign"))
  170. return
  171. }
  172. if payResult.ReturnCode == "SUCCESS" && payResult.ResultCode == "SUCCESS" {
  173. orderSrv.WxPayCB(kv)
  174. /*db := util.GetWriteSqlDB()
  175. payTime, _ := time.Parse("20060102150405", payResult.TimeEnd)
  176. actualPay := payResult.TotalFee
  177. _, err = db.Exec("update t_order set status = ?, third_pay_no = ?, actual_payment = ?, payment_time = ?, pay_type = ? where pay_no = ?", 2, payResult.TransactionId, actualPay, payTime.Format("2006-01-02 15:04:05"), constants.PAYMENTTYPE_WEIXIN, payResult.OutTradeNo)
  178. if err != nil {
  179. stdlog.Println("UPDATE_PAY_STATUS:", err)
  180. } else {
  181. go func() {
  182. strSql := "select id, mobile, custom_mobile from t_order where pay_no = ?"
  183. var orderItem = &entity.OrderDB{}
  184. err = db.Get(orderItem, strSql, payResult.OutTradeNo)
  185. if err == nil {
  186. sms := &service.SMSService{dal.DefaultSMSCodeDal}
  187. sms.SendSMS(orderItem.Mobile, int(constants.SMS_ORDER_PAID_INFORM), map[string]string{"orderId": orderItem.Id})
  188. }
  189. //inform admin
  190. client := util.GetRedis()
  191. client.Select(12)
  192. msg := map[string]interface{}{
  193. "user": "system",
  194. "orderid": orderItem.Id,
  195. "status": constants.ORDERSTATUS_UNRECEIVE,
  196. }
  197. buf, _ := json.Marshal(msg)
  198. client.Publish("order-status-change", string(buf))
  199. client.HDel("order_unpay", orderItem.Id)
  200. }()
  201. var wxType = ""
  202. if payResult.AppId == config.IniConf.Section("weixin").Key("wx.mp.appid").Value() {
  203. wxType = "mp"
  204. }
  205. _, err = orderSrv.SendWxPaySuccessMsg(map[string]string{
  206. "pay_no": payResult.OutTradeNo,
  207. "openid": payResult.OpenId,
  208. "money": fmt.Sprintf("%.2f元", float32(payResult.TotalFee)/100),
  209. "wx_type": wxType,
  210. })
  211. if err != nil {
  212. stdlog.Println(err)
  213. }
  214. }*/
  215. }
  216. writeWxPayCbOk(w)
  217. }
  218. func aliPayHandler(w http.ResponseWriter, req *http.Request) {
  219. if req.Method != "POST" {
  220. w.WriteHeader(http.StatusMethodNotAllowed)
  221. return
  222. }
  223. payResult, err := ali.GetAliClient().GetTradeNotification(req)
  224. if err != nil {
  225. fmt.Fprint(w, err.Error())
  226. return
  227. }
  228. defer fmt.Fprint(w, "success")
  229. db := util.GetWriteSqlDB()
  230. thirdPNO := null.String{}
  231. db.Get(&thirdPNO, "select third_pay_no from t_order where pay_no = ?", payResult.OutTradeNo)
  232. if thirdPNO.Valid {
  233. return
  234. }
  235. if payResult.TradeStatus == alipay.TradeStatusSuccess {
  236. //成功
  237. kv := map[string]string{
  238. "gmt_payment": payResult.GmtPayment,
  239. "total_amount": payResult.TotalAmount,
  240. "out_trade_no": payResult.OutTradeNo,
  241. "trade_no": payResult.TradeNo,
  242. }
  243. orderSrv.AliPayCB(kv)
  244. } else {
  245. //去主动查询
  246. }
  247. }
  248. var orderSrv *service.OrderService
  249. var Version string
  250. func main() {
  251. runtime.GOMAXPROCS(runtime.NumCPU() * 2)
  252. fs := flag.NewFlagSet("", flag.ExitOnError)
  253. var (
  254. httpAddr = fs.String("http.addr", ":8000", "Address for HTTP (JSON) server")
  255. //grpcAddr = fs.String("grpc.addr", ":8001", "Address for grpc server")
  256. configFile = fs.String("f", "config.ini", "app config file")
  257. version = fs.Bool("version", false, "print app version")
  258. )
  259. fs.Parse(os.Args[1:])
  260. if *version {
  261. fmt.Println(Version)
  262. return
  263. }
  264. config.Reload(*configFile)
  265. port := ":" + config.IniConf.Section("server").Key("Listen").String()
  266. if port != ":" {
  267. httpAddr = &port
  268. }
  269. var logger log.Logger
  270. {
  271. logger = log.NewLogfmtLogger(os.Stderr)
  272. logger = log.With(logger, "ts", log.DefaultTimestamp)
  273. logger = log.With(logger, "caller", log.DefaultCaller)
  274. stdlog.SetFlags(0) // flags are handled by Go kit's logger
  275. stdlog.SetOutput(log.NewStdlibAdapter(logger)) // redirect anything using stdlib log to us
  276. }
  277. // Business domain
  278. //var svc interface{}
  279. //{
  280. userSvc := &service.UserService{
  281. IUser: dal.DefaultUserDal,
  282. }
  283. smsSvc := &service.SMSService{
  284. ISMSCode: dal.DefaultSMSCodeDal,
  285. }
  286. authSvc := &service.AuthService{}
  287. fileSvc := &service.FileService{}
  288. searchSrv := &service.SearchService{}
  289. cartSrv := &service.CartService{
  290. ICart: dal.DefaultCartDal,
  291. }
  292. couponSrv := &service.CouponService{
  293. ICoupon: dal.DefaultCouponDal,
  294. }
  295. ptSrv := &service.ProductivityService{}
  296. wxSrv := &service.WeixinService{
  297. Weixin: wx.NewWeixin(config.IniConf.Section("weixin").Key("wx.appid").Value(), config.IniConf.Section("weixin").Key("wx.secret").Value()),
  298. WeixinMp: wx.NewWeixin(config.IniConf.Section("weixin").Key("wx.mp.appid").Value(), config.IniConf.Section("weixin").Key("wx.mp.secret").Value()),
  299. JsSdk: wx.NewJsSdk(),
  300. }
  301. orderSrv = &service.OrderService{
  302. IOrder: dal.DefaultOrderDal,
  303. WeixinService: wxSrv,
  304. }
  305. citySrv := &service.CityService{
  306. ICity: dal.DefaultCityDal,
  307. }
  308. ulSrv := &service.UserLinkerService{
  309. IUserLinker: dal.DefaultUserLinkerDal,
  310. }
  311. productSrv := &service.ProductService{
  312. IProduct: dal.DefaultProductDal,
  313. }
  314. duSrv := &service.DeliverUserService{
  315. IDeliverUserDal: dal.DefaultDeliverUserDal,
  316. WeixinService: wxSrv,
  317. }
  318. sysSrv := &service.SystemService{}
  319. actSrv := &service.ActivityService{
  320. WeixinService: wxSrv,
  321. }
  322. gbSrv := &service.GroupBloodService{
  323. WeixinService: wxSrv,
  324. }
  325. paySrv := &service.PayService{}
  326. jdlSrv := &service.JDLService{}
  327. svc := loggingMiddleware{
  328. UserService: userSvc,
  329. AuthService: authSvc,
  330. SearchService: searchSrv,
  331. FileService: fileSvc,
  332. OrderService: orderSrv,
  333. SMSService: smsSvc,
  334. CartService: cartSrv,
  335. CouponService: couponSrv,
  336. ProductivityService: ptSrv,
  337. WeixinService: wxSrv,
  338. CityService: citySrv,
  339. UserLinkerService: ulSrv,
  340. ProductService: productSrv,
  341. DeliverUserService: duSrv,
  342. SystemService: sysSrv,
  343. ActivityService: actSrv,
  344. GroupBloodService: gbSrv,
  345. PayService: paySrv,
  346. JDLService: jdlSrv,
  347. Logger: logger,
  348. }
  349. //svc := loggingMiddleware{userSvc, authSvc, searchSrv, fileSvc, orderSrv, smsSvc, cartSrv, couponSrv, ptSrv, wxSrv, citySrv, ulSrv, productSrv, duSrv, sysSrv, thirdSrv, actSrv, gbSrv, paySrv, jdlSrv, logger}
  350. //}
  351. // Mechanical stuff
  352. rand.Seed(time.Now().UnixNano())
  353. errc := make(chan error)
  354. var mServer *http.Server
  355. go func() {
  356. errc <- interrupt()
  357. mServer.Shutdown(context.Background())
  358. }()
  359. // Transport: gRPC
  360. /*go func() {
  361. transportLogger := log.NewContext(logger).With("transport", "gRPC")
  362. ln, err := net.Listen("tcp", *grpcAddr)
  363. if err != nil {
  364. errc <- err
  365. return
  366. }
  367. s := grpc.NewServer() // uses its own, internal context
  368. pb.RegisterUserServiceServer(s, grpcBinding{svc})
  369. transportLogger.Log("addr", *grpcAddr)
  370. errc <- s.Serve(ln)
  371. }()*/
  372. // Transport: HTTP/JSON
  373. //root := context.Background()
  374. go func() {
  375. var (
  376. transportLogger = log.With(logger, "transport", "HTTP/JSON")
  377. mux = bone.New()
  378. )
  379. mux.HandleFunc("/wx/paycb", wxPaycbHandler)
  380. mux.HandleFunc("/wx/scanpaycb", wxScanPaycbHandler)
  381. //mux.HandleFunc("/wx/paycb", wxPaycbHandlerV2)
  382. //mux.HandleFunc("/wx/scanpaycb", wxScanPaycbHandlerV2)
  383. mux.HandleFunc("/zfb/paycb", aliPayHandler)
  384. mux.GetFunc("/version", func(w http.ResponseWriter, req *http.Request) {
  385. fmt.Fprintf(w, "current app version is %s", Version)
  386. })
  387. RegistService(svc, mux)
  388. transportLogger.Log("addr", *httpAddr)
  389. mServer = &http.Server{Addr: *httpAddr, Handler: mux}
  390. //errc <- http.ListenAndServe(*httpAddr, mux)
  391. errc <- mServer.ListenAndServe()
  392. }()
  393. go search.UpdateIndex()
  394. go util.TimingTask()
  395. go func() {
  396. ch := make(chan os.Signal)
  397. signal.Notify(ch, syscall.SIGUSR2) //syscall.SIGHUP
  398. for {
  399. <-ch
  400. config.Reload("")
  401. }
  402. }()
  403. logger.Log("fatal", <-errc)
  404. }
  405. func interrupt() error {
  406. c := make(chan os.Signal)
  407. signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL)
  408. return fmt.Errorf("%s", <-c)
  409. }
  410. func RegistService(svc server.Service, mux *bone.Mux) {
  411. handlers := svc.GetMeta()
  412. for uri, handler := range handlers {
  413. mux.Handle(uri, handler)
  414. }
  415. }