bilibili-backup/app/interface/main/account/service/realname/alipay.go

220 lines
5.7 KiB
Go
Raw Normal View History

2019-04-22 10:59:20 +08:00
package realname
import (
"context"
"encoding/json"
"fmt"
"math/rand"
"net/url"
"regexp"
"time"
"go-common/app/interface/main/account/conf"
"go-common/app/interface/main/account/model"
memmodel "go-common/app/service/main/member/model"
"go-common/library/ecode"
"go-common/library/log"
"github.com/pkg/errors"
)
var (
_idCard18Regexp = regexp.MustCompile(`^\d{17}[\d|x]$`)
_idCard15Regexp = regexp.MustCompile(`^\d{15}$`)
)
// AlipayApply 提交芝麻认证申请
func (s *Service) AlipayApply(c context.Context, mid int64, param *model.ParamRealnameAlipayApply) (res *model.RealnameAlipayApply, err error) {
if !s.alipayAntispamCheck(c, mid) {
err = ecode.RealnameAlipayAntispam
return
}
if !s.checkID(param.CardNum) {
err = ecode.RealnameCardNumErr
return
}
var bizno string
if bizno, err = s.alipayInit(c, param.Realname, param.CardNum); err != nil {
return
}
res = &model.RealnameAlipayApply{}
if res.URL, err = s.alipayCertifyURL(c, bizno); err != nil {
return
}
var (
arg = &memmodel.ArgRealnameAlipayApply{
MID: mid,
CaptureCode: param.Capture,
Realname: param.Realname,
CardCode: param.CardNum,
IMGToken: param.ImgToken,
Bizno: bizno,
}
)
if err = s.memRPC.RealnameAlipayApply(c, arg); err != nil {
res = nil
return
}
s.addmiss(func() {
if missErr := s.alipayAntispamIncrease(context.Background(), mid); missErr != nil {
log.Error("%+v", err)
}
})
return
}
func (s *Service) checkID(card string) bool {
if !_idCard15Regexp.MatchString(card) && !_idCard18Regexp.MatchString(card) {
return false
}
return true
}
func (s *Service) alipayInit(c context.Context, realname, cardNum string) (bizno string, err error) {
var (
biz struct {
TransID string `json:"transaction_id"`
ProdCode string `json:"product_code"`
BizCode string `json:"biz_code"`
IdenParam struct {
IdentityType string `json:"identity_type"`
CertType string `json:"cert_type"`
CertName string `json:"cert_name"`
CertNo string `json:"cert_no"`
} `json:"identity_param"`
}
param url.Values
)
biz.TransID = s.alipayTransactionID() // 商户请求的唯一标志32位长度的字母数字下划线组合。该标识作为对账的关键信息商户要保证其唯一性.
biz.ProdCode = "w1010100000000002978" // 芝麻认证产品码
biz.BizCode = "FACE" // 认证场景码,支持的场景码有: FACE多因子活体人脸认证 SMART_FACE多因子快捷活体人脸认证 FACE_SDKSDK活体人脸认证 签约的协议决定了可以使用的场景
biz.IdenParam.IdentityType = "CERT_INFO"
biz.IdenParam.CertType = "IDENTITY_CARD"
biz.IdenParam.CertName = realname
biz.IdenParam.CertNo = cardNum
if param, err = s.alipayParam("zhima.customer.certification.initialize", biz, ""); err != nil {
return
}
if bizno, err = s.realnameDao.AlipayInit(c, param); err != nil {
log.Error("%+v", err)
err = ecode.RealnameAlipayErr
return
}
if bizno == "" {
err = ecode.RealnameAlipayErr
return
}
return
}
func (s *Service) alipayCertifyURL(c context.Context, bizno string) (u 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.certify", biz, "bilibili://auth.zhima"); err != nil {
return
}
u = conf.Conf.Realname.Alipay.Gateway + "?" + param.Encode()
return
}
// AlipayConfirm 查询芝麻认证状态
func (s *Service) AlipayConfirm(c context.Context, mid int64) (res *model.RealnameAlipayConfirm, err error) {
var (
pass bool
reason string
rpcarg = &memmodel.ArgMemberMid{
Mid: mid,
}
rpcres *memmodel.RealnameAlipayInfo
)
if rpcres, err = s.memRPC.RealnameAlipayBizno(c, rpcarg); err != nil {
return
}
if pass, reason, err = s.alipayQuery(c, rpcres.Bizno); err != nil {
log.Error("%+v", err)
err = ecode.RealnameAlipayErr
return
}
res = &model.RealnameAlipayConfirm{
Reason: reason,
}
if pass {
res.Passed = model.RealnameTrue
} else {
res.Passed = model.RealnameFalse
}
// rpc call
var (
rpcConfirmArg = &memmodel.ArgRealnameAlipayConfirm{
MID: mid,
Pass: pass,
Reason: reason,
}
)
if err = s.memRPC.RealnameAlipayConfirm(c, rpcConfirmArg); err != nil {
return
}
s.addmiss(func() {
if missErr := s.setAlipayAntispamPassFlag(context.Background(), mid, false); missErr != nil {
log.Error("%+v", err)
}
})
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.realnameDao.AlipayQuery(c, param); err != nil {
log.Error("%+v", err)
err = ecode.RealnameAlipayErr
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.Realname.Alipay.AppID)
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
}
func (s *Service) alipayTransactionID() string {
return fmt.Sprintf("BILI%d%d", time.Now().UnixNano(), rand.Intn(100000))
}