bilibili-backup/app/job/main/member/service/realname.go

262 lines
7.3 KiB
Go
Raw Permalink Normal View History

2019-04-22 10:59:20 +08:00
package service
import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"
"time"
"go-common/app/job/main/member/conf"
"go-common/app/job/main/member/model"
memmodel "go-common/app/service/main/member/model"
"go-common/library/log"
"go-common/library/net/ip"
"github.com/pkg/errors"
)
// constrs for gender
const (
_genderMale = "male"
_genderFemale = "female"
)
// realname alipay polling
func (s *Service) realnamealipaycheckproc() {
defer func() {
if x := recover(); x != nil {
log.Error("%+v", errors.WithStack(fmt.Errorf("service.realnamealipaycheckproc panic(%v)", x)))
go s.realnamealipaycheckproc()
log.Info("service.realnamealipaycheckproc recover")
}
}()
for {
var (
to = time.Now()
from = to.Add(-2 * time.Duration(conf.Conf.Biz.RealnameAlipayCheckTick))
expiredTime = from
startTime = expiredTime.AddDate(0, -1, 0)
)
log.Info("realname alipay check start from : %s , to : %s", from, to)
s.realnameAlipayCheckHandler(context.Background(), from, to)
// to = from
// from = to.Add(-2 * time.Duration(conf.Conf.Biz.RealnameAlipayCheckTick))
log.Info("realname alipay handle expired end startTime : %s , expiredTime : %s", startTime, expiredTime)
s.realnameAlipayExpiredHandler(context.Background(), startTime, expiredTime)
time.Sleep(time.Duration(conf.Conf.Biz.RealnameAlipayCheckTick))
}
}
// realnameAlipayCheckHandler 轮询时间段 [from,to] 中,未完成阿里实名的实名申请
func (s *Service) realnameAlipayCheckHandler(c context.Context, from, to time.Time) {
if conf.Conf.Biz.RealnameAlipayCheckLimit <= 0 {
log.Error("conf.Conf.Property.realnameAlipayCheckHandler [%d] <= 0", conf.Conf.Biz.RealnameAlipayCheckLimit)
return
}
var (
applys = make([]*model.RealnameAlipayApply, conf.Conf.Biz.RealnameAlipayCheckLimit)
startID int64
err error
)
for len(applys) >= conf.Conf.Biz.RealnameAlipayCheckLimit {
if startID, applys, err = s.dao.RealnameAlipayApplyList(c, startID, model.RealnameApplyStatusPending, from, to, conf.Conf.Biz.RealnameAlipayCheckLimit); err != nil {
log.Error("%+v", err)
return
}
for _, apply := range applys {
log.Info("Start check realname alipay apply mid (%d) bizno (%s)", apply.MID, apply.Bizno)
if err = s.realnameAlipayConfirm(c, apply); err != nil {
log.Error("%+v", err)
continue
}
}
}
for len(applys) >= conf.Conf.Biz.RealnameAlipayCheckLimit {
if startID, applys, err = s.dao.RealnameAlipayApplyList(c, startID, model.RealnameApplyStatusBack, from, to, conf.Conf.Biz.RealnameAlipayCheckLimit); err != nil {
log.Error("%+v", err)
return
}
for _, apply := range applys {
log.Info("Start check realname alipay apply mid (%d) bizno (%s)", apply.MID, apply.Bizno)
if err = s.realnameAlipayConfirm(c, apply); err != nil {
log.Error("%+v", err)
continue
}
}
}
}
func (s *Service) realnameAlipayConfirm(c context.Context, apply *model.RealnameAlipayApply) (err error) {
if apply.Bizno == "" {
return
}
var (
pass bool
reason string
)
if pass, reason, err = s.alipayQuery(c, apply.Bizno); err != nil {
return
}
// rpc call
var (
rpcConfirmArg = &memmodel.ArgRealnameAlipayConfirm{
MID: apply.MID,
Pass: pass,
Reason: reason,
}
)
if err = s.memrpc.RealnameAlipayConfirm(c, rpcConfirmArg); err != nil {
return
}
log.Info("Succeed to confirm realname alipay with arg: %+v", rpcConfirmArg)
if pass {
expArg := &model.AddExp{
Mid: apply.MID,
IP: ip.InternalIP(),
Ts: time.Now().Unix(),
Event: "identify",
}
if expErr := s.addExp(context.TODO(), expArg); expErr != nil {
log.Error("realname exp error(%+v) ", expErr)
return
}
log.Info("realname exp success(%+v)", expArg)
}
return
}
func (s *Service) alipayQuery(c context.Context, bizno string) (pass bool, reason string, err error) {
var (
param url.Values
biz struct {
Bizno string `json:"biz_no"`
}
)
biz.Bizno = bizno
if param, err = s.alipayParam("zhima.customer.certification.query", biz, ""); err != nil {
return
}
if pass, reason, err = s.dao.AlipayQuery(c, param); err != nil {
return
}
return
}
// alipayParam 构造阿里请求parambiz为 biz_content struct
func (s *Service) alipayParam(method string, biz interface{}, returnURL string) (p url.Values, err error) {
var (
sign string
bizBytes []byte
)
if bizBytes, err = json.Marshal(biz); err != nil {
err = errors.WithStack(err)
return
}
p = url.Values{}
p.Set("app_id", conf.Conf.Biz.RealnameAlipayAppID)
p.Set("method", method)
p.Set("charset", "utf-8")
p.Set("sign_type", "RSA2")
p.Set("timestamp", time.Now().Format("2006-01-02 15:04:05"))
p.Set("version", "1.0")
p.Set("biz_content", string(bizBytes))
if returnURL != "" {
p.Set("return_url", returnURL)
}
if sign, err = s.alipayCryptor.SignParam(p); err != nil {
return
}
p.Set("sign", sign)
return
}
// rejectExpiredRealnameAlipay 自动驳回超过两天还没有通过芝麻认证的实名认证
func (s *Service) realnameAlipayExpiredHandler(c context.Context, startTime, expiredTime time.Time) {
if conf.Conf.Biz.RealnameAlipayCheckLimit <= 0 {
log.Error("conf.Conf.Property.realnameAlipayCheckHandler [%d] <= 0", conf.Conf.Biz.RealnameAlipayCheckLimit)
return
}
var (
applys []*model.RealnameAlipayApply
startID int64
err error
)
// 每次查询一个月里100条过期的未处理的位处理的芝麻认证数据进行驳回
for {
log.Info("realname handle startID (%d)", startID)
startID, applys, err = s.dao.RealnameAlipayApplyList(c, startID, model.RealnameApplyStatusPending, startTime, expiredTime, conf.Conf.Biz.RealnameAlipayCheckLimit)
if err != nil {
log.Error("realnameAlipayExpiredHandler search err(%+v)", err)
return
}
// 没有查询到预期的过期数据,则停止循环,等待下一次检查
if len(applys) == 0 {
log.Error("realnameAlipayExpiredHandler search no row in result")
return
}
// 循环驳回验证超时的芝麻认证
for _, apply := range applys {
log.Info("Start expire realname alipay apply mid (%d) bizno (%s)", apply.MID, apply.Bizno)
var (
rpcConfirmArg = &memmodel.ArgRealnameAlipayConfirm{
MID: apply.MID,
Pass: false,
Reason: "超时自动驳回",
}
)
if err = s.memrpc.RealnameAlipayConfirm(c, rpcConfirmArg); err != nil {
log.Error("realnameAlipayExpiredHandler reject err(%+v)", err)
continue
}
}
time.Sleep(10 * time.Millisecond)
}
}
// ParseIdentity to birthday and gender
func ParseIdentity(id string) (birthday time.Time, gender string, err error) {
var (
ystr, mstr, dstr, gstr string
y, m, d, g int
)
switch len(id) {
case 15:
ystr, mstr, dstr = "19"+id[6:8], id[8:10], id[10:12]
gstr = id[14:15]
case 18:
ystr, mstr, dstr = id[6:10], id[10:12], id[12:14]
gstr = id[16:17]
default:
err = errors.Errorf("identity id invalid : %s", id)
return
}
if y, err = strconv.Atoi(ystr); err != nil {
err = errors.WithStack(err)
return
}
if m, err = strconv.Atoi(mstr); err != nil {
err = errors.WithStack(err)
return
}
if d, err = strconv.Atoi(dstr); err != nil {
err = errors.WithStack(err)
return
}
if g, err = strconv.Atoi(gstr); err != nil {
err = errors.WithStack(err)
return
}
birthday = time.Date(y, time.Month(m), d, 0, 0, 0, 0, time.Local)
if g%2 == 1 {
gender = _genderMale
} else {
gender = _genderFemale
}
return
}