123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- package service
- import (
- "bytes"
- "database/sql"
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "log"
- "net/http"
- "strconv"
- "strings"
- "time"
- "xiaoniaokuaiyan.com/xiaoniao/config"
- "xiaoniaokuaiyan.com/xiaoniao/pay/wx"
- "gopkg.in/guregu/null.v3"
- "xiaoniaokuaiyan.com/xiaoniao/dal"
- "xiaoniaokuaiyan.com/xiaoniao/entity"
- "xiaoniaokuaiyan.com/xiaoniao/util"
- )
- type ActivityService struct {
- *WeixinService
- }
- func (srv *ActivityService) AddReporter(reporter *entity.ActReporter) (interface{}, error) {
- if !util.IsMobile(reporter.Mobile) {
- return nil, errors.New("wrong mobile phone number")
- }
- db := util.GetWriteSqlDB()
- reporter.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
- strSql, mkv := util.GenerateInsertSqlFromStruct("t_activity_reporter", reporter)
- result, err := db.NamedExec(strSql, mkv)
- if err != nil {
- return nil, err
- }
- if ra, _ := result.RowsAffected(); ra <= 0 {
- return nil, errors.New("add failed")
- }
- return true, nil
- }
- func (srv *ActivityService) AddActInfo(item *entity.ActInfo) (interface{}, error) {
- db := util.GetWriteSqlDB()
- if strings.HasPrefix(item.Source, "-") {
- item.Source = item.Source[1:]
- strSql := "select count(*) from t_activity_info where mobile = ? and source = ?;"
- var tc int
- derr := db.Get(&tc, strSql, item.Mobile.String, item.Source)
- if derr != nil {
- return nil, derr
- }
- if tc > 0 {
- return nil, errors.New("1::already submit")
- }
- }
- var params = map[string]string{}
- if item.Extra.Valid && item.Extra.String != "" {
- err := json.Unmarshal([]byte(item.Extra.String), ¶ms)
- if err != nil {
- return nil, err
- }
- }
- if item.Source == "medicine" || item.Source == "SendBack" || item.Source == "directbind" {
- smsSvc := &SMSService{
- ISMSCode: dal.DefaultSMSCodeDal,
- }
- _, err := smsSvc.ValidateCode(item.Mobile.String, params["vcode"], 8)
- if err != nil {
- return nil, errors.New("2::wrong validate code")
- }
- var bindTimes int
- var todayStr = time.Now().Format("2006-01-02")
- db.Get(&bindTimes, "SELECT count(distinct ex_code) from t_activity_info where mobile = ? and source =? and (created_at between ? and ?);", item.Mobile.String, item.Source, todayStr, todayStr+" 23:59:59")
- //20211127 从1 改成5
- if bindTimes >= 5 {
- return nil, errors.New("3::beyond binding times today")
- }
- }
- item.CreatedAt = time.Now().Format("2006-01-02 15:04:05")
- strSql, mkv := util.GenerateInsertSqlFromStruct("t_activity_info", item)
- result, err := db.NamedExec(strSql, mkv)
- if err != nil {
- return nil, err
- }
- if ra, _ := result.RowsAffected(); ra <= 0 {
- return nil, errors.New("add failed")
- }
- id, _ := result.LastInsertId()
- item.Id = int(id)
- //保存订单信息
- if item.Source == "medicine" || item.Source == "SendBack" {
- if !item.ExCode.Valid || item.ExCode.String == "" {
- //20220623 如果ExCode 是空,直接跳转结尾并且通知redis
- goto JUMP
- }
- var upItem = struct {
- CustomName string `db:"custom_name"`
- Mobile string `db:"mobile"`
- Age int `db:"age"`
- Birthday string `db:"birthday"`
- Gender string `db:"gender"`
- ExpressStatus string `db:"expressstatus"`
- }{}
- err = db.Get(&upItem, "select name as custom_name, gender, age, mobile,birthday, expressstatus from t_order t1 left join t_order_extra t2 on t1.id = t2.order_id where id = ?;", item.ExCode.String)
- if err != nil {
- //return nil, err
- //20220623 去除返回报错逻辑,直接跳转结尾并且通知redis
- goto JUMP
- }
- //20220520 修改生日逻辑
- var sqlResult sql.Result
- if _, ok := params["birthday"]; ok {
- btime, _ := time.Parse("2006-01-02", params["birthday"])
- age := time.Now().Year() - btime.Year()
- sqlResult, err = db.Exec("update t_order set name =?, gender =?, age =?, mobile =?, birthday =? where id = ?", item.CustomName.String, item.Gender.String, age, item.Mobile.String, params["birthday"], item.ExCode.String)
- if err != nil {
- } else if ra, _ := sqlResult.RowsAffected(); ra > 0 {
- go util.InsertMongo(item.ExCode.String, "回寄/活动", 1, map[string]interface{}{"name": item.CustomName.String, "gender": item.Gender.String, "age": age, "mobile": item.Mobile.String, "birthday": params["birthday"], "url": "/act/addinfo"})
- }
- } else {
- sqlResult, err = db.Exec("update t_order set name =?, mobile =? where id = ?", item.CustomName.String, item.Mobile.String, item.ExCode.String)
- if err != nil {
- } else if ra, _ := sqlResult.RowsAffected(); ra > 0 {
- go util.InsertMongo(item.ExCode.String, "回寄/活动", 1, map[string]interface{}{"name": item.CustomName.String, "mobile": item.Mobile.String, "url": "/act/addinfo"})
- }
- }
- //20220704 熠保项目 修改 blood_code
- sqlResult, _ = db.Exec("update t_order set blood_codes =? where id = ? and (trim(blood_codes)='' or blood_codes is null)", item.Address.String, item.ExCode.String)
- if ra, _ := sqlResult.RowsAffected(); ra > 0 {
- go util.InsertMongo(item.ExCode.String, "回寄/活动", 1, map[string]interface{}{"blood_codes": item.Address.String, "url": "/act/addinfo"})
- db.Exec("insert into t_activity_info(custom_name,age,gender,mobile,address,ex_code,source,created_at) values(?,?,?,?,?,?,'order_update',?);", upItem.CustomName, upItem.Age, upItem.Gender, upItem.Mobile, upItem.Birthday, item.ExCode.String, item.CreatedAt)
- }
- }
- JUMP:
- //推送消息
- msg := map[string]string{
- "user": "system",
- "oper": "add",
- "source": item.Source,
- }
- buf, _ := json.Marshal(msg)
- client := util.GetRedis()
- client.Publish("act-change", string(buf))
- return item, nil
- }
- func (srv *ActivityService) GetActInfo(mobile string, source string) (interface{}, error) {
- var strSql = "select * from t_activity_info where mobile = ? and source = ?;"
- if source == "BCODE" {
- return _getActInfoByBloodcode(mobile)
- } else if source == "fapiao" || source == "daneng" || source == "renbao" {
- return _getActInfoByExCode(mobile)
- }
- var infos = []entity.ActInfo{}
- db := util.GetSqlDB()
- err := db.Select(&infos, strSql, mobile, source)
- if err != nil {
- return nil, fmt.Errorf("failed to query actinfo: %v", err)
- }
- return infos, nil
- }
- func _getActInfoByBloodcode(bcode string) (interface{}, error) {
- strSql := "select * from t_activity_info where address = ? order by id desc;"
- var infos = []entity.ActInfo{}
- db := util.GetSqlDB()
- err := db.Select(&infos, strSql, bcode)
- if err != nil {
- return nil, fmt.Errorf("failed to query actinfo: %v", err)
- }
- return infos, nil
- }
- // qz add 添加按照excode 查询,20200810
- // qz add 添加人保 按照excode 查询 20210629
- func _getActInfoByExCode(exCode string) (interface{}, error) {
- strSql := "select * from t_activity_info where ex_code = ? order by id desc;"
- var infos = []entity.ActInfo{}
- db := util.GetSqlDB()
- err := db.Select(&infos, strSql, exCode)
- if err != nil {
- return nil, fmt.Errorf("failed to query actinfo: %v", err)
- }
- return infos, nil
- }
- func (src *ActivityService) UpdateActInfo(item *entity.ActInfo) (interface{}, error) {
- var params = map[string]string{}
- if item.Extra.Valid && item.Extra.String != "" {
- err := json.Unmarshal([]byte(item.Extra.String), ¶ms)
- if err != nil {
- return nil, err
- }
- }
- if item.Source == "fapiao" || item.Source == "daneng" {
- smsSvc := &SMSService{
- ISMSCode: dal.DefaultSMSCodeDal,
- }
- _, err := smsSvc.ValidateCode(item.Mobile.String, params["vcode"], 9)
- if err != nil {
- return nil, errors.New("2::wrong validate code")
- }
- }
- var source = item.Source
- item.Source = ""
- strSql, mkv := util.GenerateUpdateSqlFromStruct("t_activity_info", item, fmt.Sprintf(" where id =%d", item.Id))
- db := util.GetWriteSqlDB()
- _, err := db.NamedExec(strSql, mkv)
- if err != nil {
- return nil, err
- }
- if source == "SendBack" && item.ExCode.Valid {
- return _updateSendBack(item)
- }
- return false, nil
- }
- //func _updateSendBack(item *entity.ActInfo) (interface{}, error) {
- // var params = map[string]string{}
- // if item.Extra.Valid && item.Extra.String != "" {
- // err := json.Unmarshal([]byte(item.Extra.String), ¶ms)
- // if err != nil {
- // return nil, err
- // }
- // }
- // var expressStatus string
- // db := util.GetWriteSqlDB()
- // err := db.Get(&expressStatus, "select expressstatus from t_order_extra where order_id = ?;", item.ExCode.String)
- // if err != nil {
- // return nil, err
- // }
- // //20220518 外面source 给洗掉了,而且外面判断sendback了,所以这里去掉sendback判断
- // //if item.Source == "SendBack" && (expressStatus == "200" || expressStatus == "100") {
- // if expressStatus == "200" || expressStatus == "100" {
- // db.Exec("update t_order_extra set expressstatus='300', express_user=?, expressnumber_user=? where order_id = ?;", params["express"], params["expressno"], item.ExCode.String)
- // }
- // return true, nil
- //}
- func _updateSendBack(item *entity.ActInfo) (interface{}, error) {
- var params = map[string]string{}
- if item.Extra.Valid && item.Extra.String != "" {
- err := json.Unmarshal([]byte(item.Extra.String), ¶ms)
- if err != nil {
- return nil, err
- }
- }
- var data struct {
- ExpressStatus string `db:"expressstatus"`
- ExpressTime null.String `db:"express_time"`
- }
- db := util.GetWriteSqlDB()
- err := db.Get(&data, "select expressstatus,express_time from t_order_extra where order_id = ?;", item.ExCode.String)
- if err != nil {
- return nil, err
- }
- //20220518 外面source 给洗掉了,而且外面判断sendback了,所以这里去掉sendback判断
- if data.ExpressStatus == "200" || data.ExpressStatus == "100" {
- //20220519 修改原来改成状态300 换成改为210 同时判断extra 里面是否有sendStartTime 更新到express_time 字段中
- db.Exec("update t_order_extra set expressstatus='210', express_user=?, expressnumber_user=? where order_id = ?;", params["express"], params["expressno"], item.ExCode.String)
- sst, ok := params["sendStartTime"]
- if !ok {
- sst = time.Now().Format("2006-01-02 15:04:05")
- }
- if !data.ExpressTime.Valid || data.ExpressTime.String == "" {
- db.Exec("update t_order_extra set express_time = ? where order_id = ?;", fmt.Sprintf("{\"setStartTime\": \"%s\"}", sst), item.ExCode.String)
- } else {
- _, err := db.Exec("update t_order_extra set express_time = JSON_SET(express_time,'$.setStartTime','"+sst+"') where order_id = ?;", item.ExCode.String)
- fmt.Println(err)
- }
- }
- return true, nil
- }
- func (srv *ActivityService) WithdrawActInfo(item *entity.ActInfo) (interface{}, error) {
- //根据id 获取信息
- var strSql = "select * from t_activity_info where id=? and source in ('fapiao','daneng') and status='500'"
- var infos = entity.ActInfo{}
- db := util.GetSqlDB()
- err := db.Get(&infos, strSql, item.Id)
- if err != nil {
- return nil, fmt.Errorf("1::failed to query actinfo: %v", err)
- }
- var params = map[string]string{}
- if infos.Extra.Valid && infos.Extra.String != "" {
- err := json.Unmarshal([]byte(infos.Extra.String), ¶ms)
- if err != nil {
- return nil, err
- }
- }
- if params["openid"] == "" || params["price"] == "" {
- return nil, fmt.Errorf("2::none openid [%s], or price: [%s]", params["openid"], params["price"])
- }
- _, err = strconv.ParseInt(params["price"], 10, 64)
- if err != nil {
- return nil, fmt.Errorf("3::price: [%s] not real int ", params["price"])
- }
- strSql = "update t_activity_info set status = '600' where id = ? "
- tx := db.MustBegin()
- sqlResult, err := tx.Exec(strSql, item.Id)
- if err != nil {
- return false, err
- }
- if la, err := sqlResult.RowsAffected(); la <= 0 {
- return false, err
- }
- wxJsSdk := wx.NewJsSdk()
- weixin := wx.NewWeixin(wx.DefaultConfig["appid"], wx.DefaultConfig["secret"])
- nonceStr := wxJsSdk.GenerateNoncestr(32)
- billno := fmt.Sprintf("HB%s%s", time.Now().Format("20060102150405"), util.RandNumString(6))
- reqItem := map[string]string{
- "mch_id": wx.DefaultConfig["mch_id"],
- "nonce_str": nonceStr,
- "mch_billno": billno,
- "wxappid": wx.DefaultConfig["appid"],
- "send_name": "小鸟快验",
- "re_openid": params["openid"],
- "total_amount": params["price"],
- "total_num": "1",
- "wishing": "报销费用",
- "client_ip": "127.0.0.1",
- "act_name": "红包提现",
- "remark": "readpack",
- "scene_id": "PRODUCT_4",
- }
- sign := wxJsSdk.ComputePaySignature(reqItem, wx.DefaultConfig["apikey"])
- reqItem["sign"] = sign
- rel, err := weixin.SendRedpack(reqItem, wx.DefaultConfig["cert_file"], wx.DefaultConfig["key_file"])
- log.Println(rel)
- str := ""
- if err != nil {
- log.Println(err)
- str = err.Error()
- } else {
- arrayByte, _ := json.Marshal(rel)
- str = string(arrayByte)
- }
- if rel["return_code"] == "SUCCESS" && rel["result_code"] == "SUCCESS" {
- tx.Exec("insert into t_activity_withdraw_record(billno, money, activity_id,openid,result,is_success) values(?,?,?,?,?,1);", billno, params["price"], item.Id, params["openid"], str)
- //tx.Exec("insert into t_deliver_msg(deliver_user_id, title, content,created_at) values(?,?,?,?);", duId, "余额提取成功", fmt.Sprintf("您于%s成提取%d元,系统以微信红包的形式发送至您的微信账号,注意查收。", time.Now().Format("2006-01-02"), money/100), time.Now().Format("2006-01-02 15:04:05"))
- tx.Commit()
- } else {
- tx.Tx.Rollback()
- db.Exec("insert into t_activity_withdraw_record(billno, money, activity_id,openid,result,is_success) values(?,?,?,?,?,0);", billno, params["price"], item.Id, params["openid"], str)
- errCode := 0
- var errMsg string
- switch rel["err_code"] {
- case "NO_AUTH":
- errCode = 10
- errMsg = "发放失败,此请求可能存在风险,已被微信拦截"
- case "SENDNUM_LIMIT":
- errCode = 11
- errMsg = "该用户今日领取红包个数超过限制"
- case "ILLEGAL_APPID":
- errCode = 13
- errMsg = "非法appid,请确认是否为公众号的appid,不能为APP的appid"
- case "MONEY_LIMIT":
- errCode = 14
- errMsg = "红包金额发放限制"
- case "SEND_FAILED":
- errCode = 15
- errMsg = "红包发放失败,请更换单号再重试"
- case "FATAL_ERROR":
- errCode = 16
- errMsg = "openid和原始单参数不一致"
- case "CA_ERROR":
- errCode = 17
- errMsg = "商户API证书校验出错"
- case "SIGN_ERROR":
- errCode = 18
- errMsg = "签名错误"
- case "SYSTEMERROR":
- errCode = 19
- errMsg = "请求已受理,请稍后使用原单号查询发放结果"
- case "XML_ERROR":
- errCode = 20
- errMsg = "输入xml参数格式错误"
- case "FREQ_LIMIT":
- errCode = 21
- errMsg = "超过频率限制,请稍后再试"
- case "API_METHOD_CLOSED":
- errCode = 22
- errMsg = "你的商户号API发放方式已关闭,请联系管理员在商户平台开启"
- case "NOTENOUGH":
- errCode = 23
- errMsg = "帐号余额不足,请到商户平台充值后再重试"
- case "OPENID_ERROR":
- errCode = 24
- errMsg = "openid和appid不匹配"
- case "MSGAPPID_ERROR":
- errCode = 25
- errMsg = "触达消息给用户appid有误"
- case "ACCEPTMODE_ERROR":
- errCode = 26
- errMsg = "主、子商户号关系校验失败"
- case "PROCESSING":
- errCode = 27
- errMsg = "请求已受理,请稍后使用原单号查询发放结果"
- case "PARAM_ERROR":
- errCode = 28
- errMsg = "参数错误"
- case "SENDAMOUNT_LIMIT":
- errCode = 29
- errMsg = "您的商户号今日发放金额超过限制,如有需要请登录微信支付商户平台更改API安全配置"
- case "RCVDAMOUNT_LIMIT":
- errCode = 30
- errMsg = "该用户今日领取金额超过限制,如有需要请登录微信支付商户平台更改API安全配置"
- default:
- errCode = 4
- errMsg = fmt.Sprintf("failure withdraw , check db for more information with billno [%s]", billno)
- }
- return nil, fmt.Errorf("%d::[%s]", errCode, errMsg)
- //return false,nil
- }
- return true, nil
- }
- // 20220505 开票
- func (srv *ActivityService) AddInvoice(item *entity.ActInfo) (interface{}, error) {
- //todo 查询是否有开票item.excode
- count, err := GetInvoiceCount(item.ExCode.String)
- if err != nil || count > 0 {
- return nil, fmt.Errorf("1::already fapiao record")
- }
- url := config.IniConf.Section("server").Key("fapiaoapi").String()
- param := map[string]string{}
- err = json.Unmarshal([]byte(item.Extra.String), ¶m)
- if !item.Extra.Valid || err != nil {
- return nil, fmt.Errorf("2::data extra error")
- }
- param["order_id"] = item.ExCode.String
- db := util.GetSqlDB()
- var price int
- db.Get(&price, "select actual_payment from t_order where id = ?", item.ExCode.String)
- if price == 0 {
- return nil, fmt.Errorf("3::payment is 0")
- }
- param["price"] = strconv.FormatFloat(float64(price)/100, 'f', -1, 64)
- path := "/fp/send"
- b, err := json.Marshal(param)
- reader := bytes.NewReader(b)
- resp, err := http.Post(url+path, "application/json", reader)
- if err != nil {
- return nil, fmt.Errorf("4::send response error %s", err.Error())
- }
- r, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return nil, fmt.Errorf("5::response read error %s", err.Error())
- }
- defer resp.Body.Close()
- result := struct {
- Code int `json:"code"`
- Msg string `json:"msg"`
- }{}
- err = json.Unmarshal(r, &result)
- if err != nil || result.Code != 0 {
- return nil, fmt.Errorf("6::response Unmarshal error %s", string(r))
- }
- return "success", nil
- }
- // 20220505 获取开票
- func GetInvoiceCount(oid string) (int, error) {
- db := util.GetSqlDB()
- var count int
- //err:=db.Get(&count,"select count(1) from t_fapiao_trd where order_id = ? and status !=4",oid)
- //这里不做状态判断,如果提交过,不论成功失败,不可重复提交,后续问题交由财务或开发处理
- err := db.Get(&count, "select count(1) from t_fapiao_trd where order_id = ? ", oid)
- return count, err
- }
- func (srv *ActivityService) GetInvoice(oid string) ([]entity.ActInfo, error) {
- db := util.GetSqlDB()
- data := struct {
- Type string `json:"type"`
- Title string `json:"title"`
- Num string `json:"num"`
- Email string `json:"email"`
- }{}
- //20220524 防止之前开票过,这次又开票
- var strSql = "select * from t_activity_info where ex_code = ? and source = ?;"
- var infos = []entity.ActInfo{}
- db.Select(&infos, strSql, oid, "invoice")
- if len(infos) > 0 {
- return infos, nil
- }
- err := db.Get(&data, "select type,title,tax_num as num,email from t_fapiao_trd where order_id = ? order by created_at desc limit 1", oid)
- if err != nil {
- return nil, fmt.Errorf("failed to query invoice: %v", err)
- }
- b, _ := json.Marshal(data)
- return []entity.ActInfo{{
- ExCode: null.StringFrom(oid),
- Extra: null.StringFrom(string(b)),
- }}, nil
- }
|