go-common/app/job/main/member/service/realname.go
2019-04-22 18:49:16 +08:00

262 lines
7.3 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
}