123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434 |
- package main
- import (
- "context"
- "encoding/json"
- "encoding/xml"
- "errors"
- "flag"
- "fmt"
- "io/ioutil"
- stdlog "log"
- "math/rand"
- "net/http"
- "os"
- "os/signal"
- "runtime"
- "syscall"
- "time"
- "xiaoniaokuaiyan.com/xiaoniao/pay/ali"
- "gopkg.in/guregu/null.v3"
- "github.com/go-kit/kit/log"
- "github.com/go-zoo/bone"
- "github.com/smartwalle/alipay/v3"
- "xiaoniaokuaiyan.com/xiaoniao/config"
- dal "xiaoniaokuaiyan.com/xiaoniao/dal"
- "xiaoniaokuaiyan.com/xiaoniao/pay/wx"
- "xiaoniaokuaiyan.com/xiaoniao/retry"
- "xiaoniaokuaiyan.com/xiaoniao/search"
- "xiaoniaokuaiyan.com/xiaoniao/server"
- service "xiaoniaokuaiyan.com/xiaoniao/service"
- "xiaoniaokuaiyan.com/xiaoniao/util"
- )
- func checkRuntimeErr(err error) bool {
- if err != nil {
- stdlog.Fatalf("error: %v", err)
- return true
- }
- return false
- }
- func wxScanPaycbHandler(w http.ResponseWriter, req *http.Request) {
- if req.Method != "POST" {
- w.WriteHeader(http.StatusMethodNotAllowed)
- return
- }
- xmlDec := xml.NewDecoder(req.Body)
- defer req.Body.Close()
- payResult := &wx.UnionPayResult{}
- err := xmlDec.Decode(payResult)
- stdlog.Println("wxpaycb:", payResult)
- if err != nil {
- stdlog.Println("wxpaycb_err:", err)
- w.Write([]byte(err.Error()))
- return
- }
- db := util.GetWriteSqlDB()
- tcwp := struct {
- ThirdPNO null.String `db:"third_pay_no"`
- Source null.String `db:"usefor"`
- Remark null.String `db:"remark"`
- }{}
- db.Get(&tcwp, "select usefor,third_pay_no,remark from t_custom_wxscan_pay where id = ?", payResult.OutTradeNo)
- if tcwp.ThirdPNO.Valid {
- writeWxPayCbOk(w)
- return
- }
- //thirdPNO := null.String{}
- //db.Get(&thirdPNO, "select third_pay_no from t_custom_wxscan_pay where id = ?", payResult.OutTradeNo)
- //if thirdPNO.Valid {
- // writeWxPayCbOk(w)
- // return
- //}
- kv, _ := util.StructToMap(payResult)
- delete(kv, "sign")
- jssdk := wx.NewJsSdk()
- csign := jssdk.ComputePaySignature(kv, config.IniConf.Section("weixin").Key("wx.apikey").Value())
- if csign != payResult.Sign {
- stdlog.Println("wxpaycb_err: wrong sign")
- _, err = util.SendMail(util.MailList{
- {"liuguiqi", "liugq@xniao.com.cn"},
- {"guoxiaozhou", "43572650@qq.com"},
- {"houyoufang", "houyf@xniao.com.cn"},
- }, "您的商户订单号为:"+payResult.OutTradeNo+"由于签名校验错误导致订单信息", "微信支付回调错误消息提醒")
- if err != nil {
- stdlog.Println("SEND_MAIL_ERROR:", err)
- }
- w.Write([]byte("wrong sign"))
- return
- }
- if payResult.ReturnCode == "SUCCESS" && payResult.ResultCode == "SUCCESS" {
- payTime, _ := time.Parse("20060102150405", payResult.TimeEnd)
- actualPay := payResult.TotalFee
- _, 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)
- if err != nil {
- stdlog.Println("UPDATE_SCANPAY_STATUS:", err)
- } else {
- client := util.GetRedis()
- msg := map[string]interface{}{
- "user": "system",
- "channel": "SCANPAY-INFORM",
- "data": map[string]interface{}{
- "id": payResult.OutTradeNo,
- "total_fee": payResult.TotalFee,
- },
- }
- buf, _ := json.Marshal(msg)
- client.Publish("xn-message", string(buf))
- }
- }
- writeWxPayCbOk(w)
- if tcwp.Source.ValueOrZero() == "jsl" && tcwp.Remark.ValueOrZero() != "" {
- go orderSrv.JinShuiLianServer(tcwp.Remark.ValueOrZero())
- }
- }
- func writeWxPayCbOk(w http.ResponseWriter) {
- okXml := `<xml>
- <return_code><![CDATA[SUCCESS]]></return_code>
- <return_msg><![CDATA[OK]]></return_msg>
- </xml>`
- w.Write([]byte(okXml))
- }
- func wxPaycbHandler(w http.ResponseWriter, req *http.Request) {
- if req.Method != "POST" {
- w.WriteHeader(http.StatusMethodNotAllowed)
- return
- }
- //xmlDec := xml.NewDecoder(req.Body)
- buf, _ := ioutil.ReadAll(req.Body)
- defer req.Body.Close()
- payResult := &wx.UnionPayResult{}
- err := xml.Unmarshal(buf, payResult)
- //err := xmlDec.Decode(payResult)
- stdlog.Println("wxpaycb:", payResult)
- if err != nil {
- stdlog.Println("wxpaycb_err:", err)
- w.Write([]byte(err.Error()))
- return
- }
- db := util.GetWriteSqlDB()
- thirdPNO := null.String{}
- db.Get(&thirdPNO, "select third_pay_no from t_order where pay_no = ?", payResult.OutTradeNo)
- if thirdPNO.Valid {
- writeWxPayCbOk(w)
- return
- }
- kv, _ := util.StructToMap(payResult)
- delete(kv, "sign")
- jssdk := wx.NewJsSdk()
- csign := jssdk.ComputePaySignature(kv, config.IniConf.Section("weixin").Key("wx.apikey").Value())
- if csign != payResult.Sign {
- fmt.Println(string(buf))
- stdlog.Println("wxpaycb_err: wrong sign", csign)
- go func() {
- retry.Run(&retry.Policy{Attempts: 3, Sleep: time.Second, Factor: 2},
- func() error {
- rt, _ := orderSrv.WxPayQuery(map[string]string{"out_trade_no": payResult.OutTradeNo})
- if rt != nil && rt["status"] == "SUCCESS" {
- return retry.Stop(errors.New("success"))
- }
- return errors.New("OUT_TIMES")
- })
- }()
- _, err = util.SendMail(util.MailList{
- {"liuguiqi", "liugq@xniao.com.cn"},
- {"guoxiaozhou", "43572650@qq.com"},
- {"houyoufang", "houyf@xniao.com.cn"},
- }, "您的商户订单号为:"+payResult.OutTradeNo+"由于签名校验错误导致订单信息", "微信支付回调错误消息提醒")
- if err != nil {
- stdlog.Println("SEND_MAIL_ERROR:", err)
- }
- w.Write([]byte("wrong sign"))
- return
- }
- if payResult.ReturnCode == "SUCCESS" && payResult.ResultCode == "SUCCESS" {
- orderSrv.WxPayCB(kv)
- /*db := util.GetWriteSqlDB()
- payTime, _ := time.Parse("20060102150405", payResult.TimeEnd)
- actualPay := payResult.TotalFee
- _, 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)
- if err != nil {
- stdlog.Println("UPDATE_PAY_STATUS:", err)
- } else {
- go func() {
- strSql := "select id, mobile, custom_mobile from t_order where pay_no = ?"
- var orderItem = &entity.OrderDB{}
- err = db.Get(orderItem, strSql, payResult.OutTradeNo)
- if err == nil {
- sms := &service.SMSService{dal.DefaultSMSCodeDal}
- sms.SendSMS(orderItem.Mobile, int(constants.SMS_ORDER_PAID_INFORM), map[string]string{"orderId": orderItem.Id})
- }
- //inform admin
- client := util.GetRedis()
- client.Select(12)
- msg := map[string]interface{}{
- "user": "system",
- "orderid": orderItem.Id,
- "status": constants.ORDERSTATUS_UNRECEIVE,
- }
- buf, _ := json.Marshal(msg)
- client.Publish("order-status-change", string(buf))
- client.HDel("order_unpay", orderItem.Id)
- }()
- var wxType = ""
- if payResult.AppId == config.IniConf.Section("weixin").Key("wx.mp.appid").Value() {
- wxType = "mp"
- }
- _, err = orderSrv.SendWxPaySuccessMsg(map[string]string{
- "pay_no": payResult.OutTradeNo,
- "openid": payResult.OpenId,
- "money": fmt.Sprintf("%.2f元", float32(payResult.TotalFee)/100),
- "wx_type": wxType,
- })
- if err != nil {
- stdlog.Println(err)
- }
- }*/
- }
- writeWxPayCbOk(w)
- }
- func aliPayHandler(w http.ResponseWriter, req *http.Request) {
- if req.Method != "POST" {
- w.WriteHeader(http.StatusMethodNotAllowed)
- return
- }
- payResult, err := ali.GetAliClient().GetTradeNotification(req)
- if err != nil {
- fmt.Fprint(w, err.Error())
- return
- }
- defer fmt.Fprint(w, "success")
- db := util.GetWriteSqlDB()
- thirdPNO := null.String{}
- db.Get(&thirdPNO, "select third_pay_no from t_order where pay_no = ?", payResult.OutTradeNo)
- if thirdPNO.Valid {
- return
- }
- if payResult.TradeStatus == alipay.TradeStatusSuccess {
- //成功
- kv := map[string]string{
- "gmt_payment": payResult.GmtPayment,
- "total_amount": payResult.TotalAmount,
- "out_trade_no": payResult.OutTradeNo,
- "trade_no": payResult.TradeNo,
- }
- orderSrv.AliPayCB(kv)
- } else {
- //去主动查询
- }
- }
- var orderSrv *service.OrderService
- var Version string
- func main() {
- runtime.GOMAXPROCS(runtime.NumCPU() * 2)
- fs := flag.NewFlagSet("", flag.ExitOnError)
- var (
- httpAddr = fs.String("http.addr", ":8000", "Address for HTTP (JSON) server")
- //grpcAddr = fs.String("grpc.addr", ":8001", "Address for grpc server")
- configFile = fs.String("f", "config.ini", "app config file")
- version = fs.Bool("version", false, "print app version")
- )
- fs.Parse(os.Args[1:])
- if *version {
- fmt.Println(Version)
- return
- }
- config.Reload(*configFile)
- port := ":" + config.IniConf.Section("server").Key("Listen").String()
- if port != ":" {
- httpAddr = &port
- }
- var logger log.Logger
- {
- logger = log.NewLogfmtLogger(os.Stderr)
- logger = log.With(logger, "ts", log.DefaultTimestamp)
- logger = log.With(logger, "caller", log.DefaultCaller)
- stdlog.SetFlags(0) // flags are handled by Go kit's logger
- stdlog.SetOutput(log.NewStdlibAdapter(logger)) // redirect anything using stdlib log to us
- }
- // Business domain
- //var svc interface{}
- //{
- userSvc := &service.UserService{
- IUser: dal.DefaultUserDal,
- }
- smsSvc := &service.SMSService{
- ISMSCode: dal.DefaultSMSCodeDal,
- }
- authSvc := &service.AuthService{}
- fileSvc := &service.FileService{}
- searchSrv := &service.SearchService{}
- cartSrv := &service.CartService{
- ICart: dal.DefaultCartDal,
- }
- couponSrv := &service.CouponService{
- ICoupon: dal.DefaultCouponDal,
- }
- ptSrv := &service.ProductivityService{}
- wxSrv := &service.WeixinService{
- Weixin: wx.NewWeixin(config.IniConf.Section("weixin").Key("wx.appid").Value(), config.IniConf.Section("weixin").Key("wx.secret").Value()),
- WeixinMp: wx.NewWeixin(config.IniConf.Section("weixin").Key("wx.mp.appid").Value(), config.IniConf.Section("weixin").Key("wx.mp.secret").Value()),
- JsSdk: wx.NewJsSdk(),
- }
- orderSrv = &service.OrderService{
- IOrder: dal.DefaultOrderDal,
- WeixinService: wxSrv,
- }
- citySrv := &service.CityService{
- ICity: dal.DefaultCityDal,
- }
- ulSrv := &service.UserLinkerService{
- IUserLinker: dal.DefaultUserLinkerDal,
- }
- productSrv := &service.ProductService{
- IProduct: dal.DefaultProductDal,
- }
- duSrv := &service.DeliverUserService{
- IDeliverUserDal: dal.DefaultDeliverUserDal,
- WeixinService: wxSrv,
- }
- sysSrv := &service.SystemService{}
- actSrv := &service.ActivityService{
- WeixinService: wxSrv,
- }
- gbSrv := &service.GroupBloodService{
- WeixinService: wxSrv,
- }
- paySrv := &service.PayService{}
- jdlSrv := &service.JDLService{}
- svc := loggingMiddleware{
- UserService: userSvc,
- AuthService: authSvc,
- SearchService: searchSrv,
- FileService: fileSvc,
- OrderService: orderSrv,
- SMSService: smsSvc,
- CartService: cartSrv,
- CouponService: couponSrv,
- ProductivityService: ptSrv,
- WeixinService: wxSrv,
- CityService: citySrv,
- UserLinkerService: ulSrv,
- ProductService: productSrv,
- DeliverUserService: duSrv,
- SystemService: sysSrv,
- ActivityService: actSrv,
- GroupBloodService: gbSrv,
- PayService: paySrv,
- JDLService: jdlSrv,
- Logger: logger,
- }
- //svc := loggingMiddleware{userSvc, authSvc, searchSrv, fileSvc, orderSrv, smsSvc, cartSrv, couponSrv, ptSrv, wxSrv, citySrv, ulSrv, productSrv, duSrv, sysSrv, thirdSrv, actSrv, gbSrv, paySrv, jdlSrv, logger}
- //}
- // Mechanical stuff
- rand.Seed(time.Now().UnixNano())
- errc := make(chan error)
- var mServer *http.Server
- go func() {
- errc <- interrupt()
- mServer.Shutdown(context.Background())
- }()
- // Transport: gRPC
- /*go func() {
- transportLogger := log.NewContext(logger).With("transport", "gRPC")
- ln, err := net.Listen("tcp", *grpcAddr)
- if err != nil {
- errc <- err
- return
- }
- s := grpc.NewServer() // uses its own, internal context
- pb.RegisterUserServiceServer(s, grpcBinding{svc})
- transportLogger.Log("addr", *grpcAddr)
- errc <- s.Serve(ln)
- }()*/
- // Transport: HTTP/JSON
- //root := context.Background()
- go func() {
- var (
- transportLogger = log.With(logger, "transport", "HTTP/JSON")
- mux = bone.New()
- )
- mux.HandleFunc("/wx/paycb", wxPaycbHandler)
- mux.HandleFunc("/wx/scanpaycb", wxScanPaycbHandler)
- //mux.HandleFunc("/wx/paycb", wxPaycbHandlerV2)
- //mux.HandleFunc("/wx/scanpaycb", wxScanPaycbHandlerV2)
- mux.HandleFunc("/zfb/paycb", aliPayHandler)
- mux.GetFunc("/version", func(w http.ResponseWriter, req *http.Request) {
- fmt.Fprintf(w, "current app version is %s", Version)
- })
- RegistService(svc, mux)
- transportLogger.Log("addr", *httpAddr)
- mServer = &http.Server{Addr: *httpAddr, Handler: mux}
- //errc <- http.ListenAndServe(*httpAddr, mux)
- errc <- mServer.ListenAndServe()
- }()
- go search.UpdateIndex()
- go util.TimingTask()
- go func() {
- ch := make(chan os.Signal)
- signal.Notify(ch, syscall.SIGUSR2) //syscall.SIGHUP
- for {
- <-ch
- config.Reload("")
- }
- }()
- logger.Log("fatal", <-errc)
- }
- func interrupt() error {
- c := make(chan os.Signal)
- signal.Notify(c, os.Interrupt, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL)
- return fmt.Errorf("%s", <-c)
- }
- func RegistService(svc server.Service, mux *bone.Mux) {
- handlers := svc.GetMeta()
- for uri, handler := range handlers {
- mux.Handle(uri, handler)
- }
- }
|