diff --git a/app/hdl/hdl_callback_advertising.go b/app/hdl/hdl_callback_advertising.go index 0094408..4dec4b4 100644 --- a/app/hdl/hdl_callback_advertising.go +++ b/app/hdl/hdl_callback_advertising.go @@ -4,6 +4,7 @@ import ( "applet/app/db" "applet/app/md" "applet/app/utils" + "applet/app/utils/logx" "code.fnuoos.com/EggPlanet/egg_models.git/src/implement" "code.fnuoos.com/EggPlanet/egg_models.git/src/model" "code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git/rabbit" @@ -13,9 +14,29 @@ import ( "fmt" "github.com/gin-gonic/gin" "github.com/tidwall/gjson" + "io/ioutil" + "net/url" "strings" ) +func CallbackAlipayFace(c *gin.Context) { + body, _ := ioutil.ReadAll(c.Request.Body) + decodeArgs, err := url.QueryUnescape(string(body)) + if err != nil { + _ = logx.Warn(err) + return + } + data, err := url.ParseQuery(decodeArgs) + if err != nil { + return + } + dataMap := make(map[string]interface{}) + for k := range data { + dataMap[k] = data.Get(k) + } + callbackStr := utils.Serialize(dataMap) + fmt.Println("支付宝回调数据", string(callbackStr)) +} func CallbackChuanshanjia(c *gin.Context) { userId := c.Query("user_id") transId := c.Query("trans_id") diff --git a/app/hdl/hdl_college.go b/app/hdl/hdl_college.go index e26d71f..34354d5 100644 --- a/app/hdl/hdl_college.go +++ b/app/hdl/hdl_college.go @@ -1,6 +1,7 @@ package hdl import ( + "applet/app/mw" "applet/app/svc" "github.com/gin-gonic/gin" ) @@ -46,7 +47,13 @@ func CollegeList(c *gin.Context) { // @Failure 400 {object} md.Response "具体错误" // @Router /api/v1/college/detail [post] func CollegeDetail(c *gin.Context) { - svc.CollegeDetail(c) + uid := 0 + if c.GetHeader("Authorization") != "" { + mw.Auth(c) + user := svc.GetUser(c) + uid = int(user.Id) + } + svc.CollegeDetail(c, uid) } // CollegeLikeAdd diff --git a/app/hdl/hdl_config.go b/app/hdl/hdl_config.go index e9aa6dd..d667078 100644 --- a/app/hdl/hdl_config.go +++ b/app/hdl/hdl_config.go @@ -49,6 +49,7 @@ func Config(c *gin.Context) { Guide := make([]md.Guide, 0) json.Unmarshal([]byte(guideStr), &Guide) res.Guide = Guide + res.DownUrl = svc.GetSysCfgStr("kuaizhan_url") e.OutSuc(c, res, nil) return } diff --git a/app/hdl/hdl_user_real_name.go b/app/hdl/hdl_user_real_name.go new file mode 100644 index 0000000..1c16307 --- /dev/null +++ b/app/hdl/hdl_user_real_name.go @@ -0,0 +1,35 @@ +package hdl + +import ( + "applet/app/svc" + "github.com/gin-gonic/gin" +) + +// GetRealNameAuthBase +// @Summary 实名认证-基础信息 +// @Tags 实名认证 +// @Description 实名认证-分类 +// @Accept json +// @Produce json +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Success 200 {object} md.RealNameAuthBasicData "具体数据" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/faceRealName/base [get] +func GetRealNameAuthBase(c *gin.Context) { + svc.GetRealNameAuthBase(c) +} + +// RealNameSave +// @Summary 实名认证-保存 +// @Tags 实名认证 +// @Description 实名认证-保存 +// @Accept json +// @Produce json +// @param Authorization header string true "验证参数Bearer和token空格拼接" +// @Param req body md.RealNameAuthAddRequest true "参数" +// @Success 200 {object} md.RealNameAuthResp "具体数据" +// @Failure 400 {object} md.Response "具体错误" +// @Router /api/v1/faceRealName/save [post] +func RealNameSave(c *gin.Context) { + svc.RealNameSave(c) +} diff --git a/app/lib/alipay/api.go b/app/lib/alipay/api.go deleted file mode 100644 index 8b71df2..0000000 --- a/app/lib/alipay/api.go +++ /dev/null @@ -1,261 +0,0 @@ -package alipay - -import ( - "applet/app/cfg" - "applet/app/utils/logx" - "fmt" - - "github.com/iGoogle-ink/gopay" - "github.com/iGoogle-ink/gopay/alipay" -) - -// TradeAppPay is 支付宝APP支付 -// 抖音头条小程序使用APP调起 -func TradeAppPay(appID, priKey, subject, orderID, amount, notiURL, RSA, PKCS string, paySet *md.PayData) (string, error) { - //初始化支付宝客户端 - // appID 是在支付宝申请的APPID - // priKey 是支付宝私钥 - // subject 是支付订单的主题 - // orderID 是智莺这边生成的订单id - // amount 是付费金额 - // notiURL 通知地址url - // passback_params 回调通知参数 - - client := alipay.NewClient(appID, priKey, true) - client.DebugSwitch = gopay.DebugOn - //判断密钥的类型 - rsa_type := alipay.RSA2 - pkcs_type := alipay.PKCS1 - if RSA == "1" { - rsa_type = alipay.RSA - } - if PKCS == "1" { - pkcs_type = alipay.PKCS8 - } - if paySet.PayAliUseType == "1" { - rsa_type = alipay.RSA2 - pkcs_type = alipay.PKCS8 - } - //配置公共参数 - client.SetCharset("utf-8"). - SetSignType(rsa_type). - SetPrivateKeyType(pkcs_type) - if notiURL != "" { - client.SetNotifyUrl(notiURL) - } - //新支付宝支付 - if paySet.PayAliUseType == "1" { - appCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAppCertSn) - fmt.Println("-应用-") - fmt.Println(appCertSN) - if err != nil { - fmt.Println(err) - return "", err - } - if appCertSN == "" { - fmt.Println(err) - return "", err - } - client.SetAppCertSN(appCertSN) - //aliPayRootCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAlipayRootCertSn) - aliPayRootCertSN := "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6" - client.SetAliPayRootCertSN(aliPayRootCertSN) - aliPayPublicCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAlipayrsaPublicKey) - fmt.Println("-公钥-") - fmt.Println(aliPayPublicCertSN) - - if err != nil { - fmt.Println(err) - return "", err - } - if aliPayPublicCertSN == "" { - fmt.Println(err) - return "", err - } - client.SetAliPayPublicCertSN(aliPayPublicCertSN) - } - fmt.Println(client) - //请求参数 - body := make(gopay.BodyMap) - body.Set("subject", subject) - body.Set("body", subject) - body.Set("out_trade_no", orderID) - body.Set("total_amount", amount) - body.Set("timeout_express", "30m") - - // body.Set("passback_params", orderID) - //手机APP支付参数请求 - payParam, err := client.TradeAppPay(body) - if err != nil { - return "", logx.Warn(err) - } - return payParam, nil -} - -// TradeAppPay is 支付宝H5支付 -func TradeWapPay(appID, priKey, subject, orderID, amount, notiURL, RSA, PKCS, page_url string, paySet *md.PayData) (string, error) { - fmt.Println("notifyURL is:>>>>>>>>>>", notiURL) - //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB" - privateKey := priKey - //判断密钥的类型 - rsa_type := alipay.RSA2 - pkcs_type := alipay.PKCS1 - if RSA == "1" { - rsa_type = alipay.RSA - } - if PKCS == "1" { - pkcs_type = alipay.PKCS8 - } - if paySet.PayAliUseType == "1" { - rsa_type = alipay.RSA2 - pkcs_type = alipay.PKCS8 - } - //初始化支付宝客户端 - // appId:应用ID - // privateKey:应用秘钥 - // isProd:是否是正式环境 - client := alipay.NewClient(appID, privateKey, true) - //配置公共参数 - client.SetCharset("utf-8"). - SetSignType(rsa_type). - SetPrivateKeyType(pkcs_type). - SetReturnUrl(page_url). - SetNotifyUrl(notiURL) - //新支付宝支付 - if paySet.PayAliUseType == "1" { - appCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAppCertSn) - if err != nil { - fmt.Println("appCertSn_err:>>>>>>>>", err) - return "", err - } - if appCertSN == "" { - fmt.Println(err) - return "", err - } - client.SetAppCertSN(appCertSN) - //aliPayRootCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAlipayRootCertSn) - //if err != nil { - // - // fmt.Println("rootcertsn_err:>>>>>>>>>>", err) - // fmt.Println("rootcertsn_err:>>>>>>>>>>", cfg.WxappletFilepath.URL) - // fmt.Println("rootcertsn_err:>>>>>>>>>>", paySet.PayAlipayRootCertSn) - // return "", err - //} - //if aliPayRootCertSN == "" { - // fmt.Println(err) - // return "", err - //} - aliPayRootCertSN := "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6" - client.SetAliPayRootCertSN(aliPayRootCertSN) - aliPayPublicCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAlipayrsaPublicKey) - if err != nil { - fmt.Println("publicCertSn_err:>>>>>>>>>>>", err) - return "", err - } - if aliPayPublicCertSN == "" { - fmt.Println(err) - return "", err - } - client.SetAliPayPublicCertSN(aliPayPublicCertSN) - } - //请求参数 - body := make(gopay.BodyMap) - body.Set("subject", subject) - body.Set("out_trade_no", orderID) - // quit_url is 用户付款中途退出返回商户网站的地址 - body.Set("quit_url", notiURL) - body.Set("total_amount", amount) - // product_code is 销售产品码,商家和支付宝签约的产品码 - body.Set("product_code", "QUICK_WAP_WAY") - //手机网站支付请求 - payUrl, err := client.TradeWapPay(body) - if err != nil { - return "", logx.Warn(err) - - } - return payUrl, nil -} - -// TradeAppPay is 支付宝小程序本身支付 -func TradeCreate(appID, priKey, subject, orderID, amount, notiURL, RSA, PKCS string, paySet *md.PayData) (*alipay.TradeCreateResponse, error) { - //aliPayPublicKey := "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1wn1sU/8Q0rYLlZ6sq3enrPZw2ptp6FecHR2bBFLjJ+sKzepROd0bKddgj+Mr1ffr3Ej78mLdWV8IzLfpXUi945DkrQcOUWLY0MHhYVG2jSs/qzFfpzmtut2Cl2TozYpE84zom9ei06u2AXLMBkU6VpznZl+R4qIgnUfByt3Ix5b3h4Cl6gzXMAB1hJrrrCkq+WvWb3Fy0vmk/DUbJEz8i8mQPff2gsHBE1nMPvHVAMw1GMk9ImB4PxucVek4ZbUzVqxZXphaAgUXFK2FSFU+Q+q1SPvHbUsjtIyL+cLA6H/6ybFF9Ffp27Y14AHPw29+243/SpMisbGcj2KD+evBwIDAQAB" - privateKey := priKey - rsa_type := alipay.RSA2 - pkcs_type := alipay.PKCS1 - if RSA == "1" { - rsa_type = alipay.RSA - } - if PKCS == "1" { - pkcs_type = alipay.PKCS8 - } - if paySet.PayAliUseType == "1" { - rsa_type = alipay.RSA2 - pkcs_type = alipay.PKCS8 - } - //初始化支付宝客户端 - // appId:应用ID - // privateKey:应用私钥,支持PKCS1和PKCS8 - // isProd:是否是正式环境 - client := alipay.NewClient(appID, privateKey, true) - //配置公共参数 - client.SetCharset("utf-8"). - SetSignType(rsa_type). - SetPrivateKeyType(pkcs_type). - SetNotifyUrl(notiURL) - if paySet.PayAliUseType == "1" { - appCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAppCertSn) - if err != nil { - fmt.Println(err) - return nil, err - } - if appCertSN == "" { - fmt.Println(err) - return nil, err - } - client.SetAppCertSN(appCertSN) - //aliPayRootCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAlipayRootCertSn) - //if err != nil { - // fmt.Println(err) - // return nil, err - //} - //if aliPayRootCertSN == "" { - // fmt.Println(err) - // return nil, err - //} - aliPayRootCertSN := "687b59193f3f462dd5336e5abf83c5d8_02941eef3187dddf3d3b83462e1dfcf6" - client.SetAliPayRootCertSN(aliPayRootCertSN) - aliPayPublicCertSN, err := alipay.GetCertSN(cfg.WxappletFilepath.URL + "/" + paySet.PayAlipayrsaPublicKey) - if err != nil { - fmt.Println(err) - return nil, err - } - if aliPayPublicCertSN == "" { - fmt.Println(err) - return nil, err - } - client.SetAliPayPublicCertSN(aliPayPublicCertSN) - } - //请求参数 - body := make(gopay.BodyMap) - body.Set("subject", subject) - // 支付宝小程序支付时 buyer_id 为必传参数,需要提前获取,获取方法如下两种 - // 1、alipay.SystemOauthToken() 返回取值:rsp.SystemOauthTokenResponse.UserId - // 2、client.SystemOauthToken() 返回取值:aliRsp.SystemOauthTokenResponse.UserId - buyer_id, err := client.SystemOauthToken(body) - if err != nil { - return nil, logx.Warn(err) - } - body.Set("buyer_id", buyer_id) - body.Set("out_trade_no", orderID) - body.Set("total_amount", amount) - //创建订单 - aliRsp, err := client.TradeCreate(body) - - if err != nil { - return nil, logx.Warn(err) - } - logx.Warn("aliRsp:", *aliRsp) - logx.Warn("aliRsp.TradeNo:", aliRsp.Response.TradeNo) - return aliRsp, nil - -} diff --git a/app/lib/alipay/face.go b/app/lib/alipay/face.go new file mode 100644 index 0000000..7b5bae7 --- /dev/null +++ b/app/lib/alipay/face.go @@ -0,0 +1,39 @@ +package alipay + +import ( + "applet/app/db" + "applet/app/utils/cache" + "code.fnuoos.com/EggPlanet/egg_models.git/src/implement" + "code.fnuoos.com/EggPlanet/egg_system_rules.git/enum" + "errors" +) + +func FacePrepareAlipayCode(method string, params map[string]string) (interface{}, error) { + sysCfgDb := implement.NewSysCfgDb(db.Db, cache.GetPool().Get()) + sysCfgMap := sysCfgDb.SysCfgFindWithDb(enum.AlipayAppId, enum.AlipayPrivateKey, enum.AlipayPublicKey, enum.AlipayPublicContentRSA2, enum.AlipayRootContent, enum.AppPublicContent) + + // 获取私钥和APPID + var paySet = &PayData{ + AlipayAppId: sysCfgMap[enum.AlipayAppId], + AlipayPrivateKey: sysCfgMap[enum.AlipayPrivateKey], + AlipayPublicKey: sysCfgMap[enum.AlipayPublicKey], + AlipayPublicContentRSA2: sysCfgMap[enum.AlipayPublicContentRSA2], + AlipayRootContent: sysCfgMap[enum.AlipayRootContent], + AppPublicContent: sysCfgMap[enum.AppPublicContent], + } + notifyURL := "http://ddxq.izhim.com/api/v1/callback/alipay/face" + var param interface{} + var err error + switch method { + case "face_init": + param, err = UserCertifyOpenInit(params["name"], params["id_num"], params["oid"], notifyURL, paySet) + case "face_certify": + param, err = UserCertifyOpenCertify(params["certify_id"], notifyURL, paySet) + case "face_query": + param, err = UserCertifyOpenQuery(params["certify_id"], notifyURL, paySet) + default: + return "", errors.New("失败") + } + return param, err + +} diff --git a/app/lib/alipay/face_api.go b/app/lib/alipay/face_api.go new file mode 100644 index 0000000..aea8a82 --- /dev/null +++ b/app/lib/alipay/face_api.go @@ -0,0 +1,228 @@ +package alipay + +import ( + "context" + "crypto/rsa" + "crypto/x509" + "encoding/json" + "encoding/pem" + "errors" + "fmt" + "github.com/go-pay/crypto/xrsa" + "github.com/go-pay/gopay" + "github.com/go-pay/gopay/alipay" + "github.com/go-pay/xtime" + "github.com/syyongx/php2go" + "strings" + "time" +) + +const ( + // URL + baseUrl = "https://openapi.alipay.com/gateway.do" + sandboxBaseUrl = "https://openapi.alipaydev.com/gateway.do" + baseUrlUtf8 = "https://openapi.alipay.com/gateway.do?charset=utf-8" + sandboxBaseUrlUtf8 = "https://openapi.alipaydev.com/gateway.do?charset=utf-8" + + LocationShanghai = "Asia/Shanghai" + PKCS1 PKCSType = 1 + PKCS8 PKCSType = 2 + RSA = "RSA" + RSA2 = "RSA2" +) + +type PKCSType uint8 + +type UserCertifyOpenInitData struct { + AlipayUserCertifyOpenInitializeResponse struct { + CertifyID interface{} `json:"certify_id"` + Code interface{} `json:"code"` + Msg interface{} `json:"msg"` + } `json:"alipay_user_certify_open_initialize_response"` +} +type UserCertifyOpenQueryData struct { + AlipayUserCertifyOpenQueryResponse struct { + Code string `json:"code"` + FailReason string `json:"fail_reason"` + IdentityInfo string `json:"identity_info"` + MaterialInfo string `json:"material_info"` + Msg string `json:"msg"` + Passed interface{} `json:"passed"` + } `json:"alipay_user_certify_open_query_response"` + Sign string `json:"sign"` +} + +func commClient(notiURL string, paySet *PayData) (*alipay.Client, error) { + client, _ := alipay.NewClient(paySet.AlipayAppId, paySet.AlipayPrivateKey, true) + client.DebugSwitch = gopay.DebugOn + //配置公共参数 + client.SetCharset("utf-8"). + SetNotifyUrl(notiURL) + client.AutoVerifySign([]byte(paySet.AlipayPublicContentRSA2)) + // 传入证书内容 + err := client.SetCertSnByContent([]byte(paySet.AppPublicContent), []byte(paySet.AlipayRootContent), []byte(paySet.AlipayPublicContentRSA2)) + if err != nil { + return nil, err + } + return client, nil +} + +// UserCertifyOpenInit is 支付宝APP支身份认证初始化服务 +// alipay.user.certify.open.initialize +func UserCertifyOpenInit(realName, identityNum, orderID, notiURL string, paySet *PayData) (UserCertifyOpenInitData, error) { + var param = UserCertifyOpenInitData{} + //初始化支付宝客户端 + // appID 是在支付宝申请的APPID + // priKey 是支付宝私钥 + // realName 是姓名 + // identityNum 是身份证 + // orderID 是智莺这边生成的订单id + // notiURL 通知地址url + // passback_params 回调通知参数 + + client, _ := commClient(notiURL, paySet) + fmt.Println(client) + merchantConfig := map[string]string{ + "return_url": notiURL, + } + identityParam := map[string]string{ + "identity_type": "CERT_INFO", + "cert_type": "IDENTITY_CARD", + "cert_name": realName, + "cert_no": identityNum, + } + var bizContent = map[string]interface{}{ + "biz_code": "FACE", + "merchant_config": merchantConfig, + "identity_param": identityParam, + "outer_order_no": orderID, + } + //请求参数 + bizContentJson, _ := json.Marshal(bizContent) + bizContentStr := strings.ReplaceAll(string(bizContentJson), "\\u0026", "&") + + body := make(gopay.BodyMap) + body.Set("biz_content", bizContentStr) + err := client.PostAliPayAPISelfV2(context.Background(), body, "alipay.user.certify.open.initialize", ¶m) + if err != nil { + return param, err + } + return param, nil +} + +// UserCertifyOpenQuery is 身份认证记录查询 +// alipay.user.certify.open.query +func UserCertifyOpenQuery(certifyId, notiURL string, paySet *PayData) (UserCertifyOpenQueryData, error) { + var param = UserCertifyOpenQueryData{} + //初始化支付宝客户端 + // appID 是在支付宝申请的APPID + // priKey 是支付宝私钥 + // certifyId 是认证id 初始化获得 + // notiURL 通知地址url + // passback_params 回调通知参数 + + client, _ := commClient(notiURL, paySet) + fmt.Println(client) + var bizContent = map[string]interface{}{ + "certify_id": certifyId, + } + //请求参数 + bizContentJson, _ := json.Marshal(bizContent) + bizContentStr := strings.ReplaceAll(string(bizContentJson), "\\u0026", "&") + body := make(gopay.BodyMap) + body.Set("biz_content", bizContentStr) + //body.Set("timeout_express", "30m") + err := client.PostAliPayAPISelfV2(context.Background(), body, "alipay.user.certify.open.query", ¶m) + if err != nil { + return param, err + } + return param, nil +} + +// UserCertifyOpenCertify is 支付宝APP身份认证开始认证 +// alipay.user.certify.open.initialize +func UserCertifyOpenCertify(certifyId, notiURL string, paySet *PayData) (string, error) { + //初始化支付宝客户端 + // appID 是在支付宝申请的APPID + // priKey 是支付宝私钥 + // certifyId 是认证id 初始化获得 + // orderID 是智莺这边生成的订单id + // notiURL 通知地址url + // passback_params 回调通知参数 + client, _ := commClient(notiURL, paySet) + fmt.Println(client) + var bizContent = map[string]interface{}{ + "certify_id": certifyId, + } + //请求参数 + bizContentJson, _ := json.Marshal(bizContent) + bizContentStr := strings.ReplaceAll(string(bizContentJson), "\\u0026", "&") + body := make(gopay.BodyMap) + body.Set("biz_content", bizContentStr) + body.Set("method", "alipay.user.certify.open.certify") + body = checkPublicParam(client, body) + key := xrsa.FormatAlipayPrivateKey(paySet.AlipayPrivateKey) + var block *pem.Block + if block, _ = pem.Decode([]byte(key)); block == nil { + return "", errors.New("获取失败") + } + pkcs8Key, err := x509.ParsePKCS8PrivateKey(block.Bytes) + if err != nil { + return "", errors.New("获取失败") + + } + pk8, ok := pkcs8Key.(*rsa.PrivateKey) + if !ok { + return "", errors.New("获取失败") + + } + keys := pk8 + sign, err := alipay.GetRsaSign(body, body.GetString("sign_type"), keys) + if err != nil { + return "", fmt.Errorf("GetRsaSign Error: %v", err) + } + body.Set("sign", sign) + var str = "https://openapi.alipay.com/gateway.do" + for k, v := range body { + if strings.Contains(str, "?") == false { + str += "?" + k + "=" + php2go.URLEncode(v.(string)) + } else { + str += "&" + k + "=" + php2go.URLEncode(v.(string)) + } + } + return str, nil +} + +// 公共参数检查 +func checkPublicParam(a *alipay.Client, bm gopay.BodyMap) gopay.BodyMap { + bm.Set("format", "JSON") + if bm.GetString("app_id") == "" && a.AppId != "" { + bm.Set("app_id", a.AppId) + } + if bm.GetString("app_cert_sn") == "" && a.AppCertSN != "" { + bm.Set("app_cert_sn", a.AppCertSN) + } + if bm.GetString("alipay_root_cert_sn") == "" && a.AliPayRootCertSN != "" { + bm.Set("alipay_root_cert_sn", a.AliPayRootCertSN) + } + if bm.GetString("return_url") == "" && a.ReturnUrl != "" { + bm.Set("return_url", a.ReturnUrl) + } + bm.Set("charset", "utf-8") + if bm.GetString("charset") == "" && a.Charset != "" { + bm.Set("charset", a.Charset) + } + bm.Set("sign_type", RSA2) + if bm.GetString("sign_type") == "" && a.SignType != "" { + bm.Set("sign_type", a.SignType) + } + bm.Set("timestamp", time.Now().Format(xtime.TimeLayout)) + bm.Set("version", "1.0") + if bm.GetString("notify_url") == "" && a.NotifyUrl != "" { + bm.Set("notify_url", a.NotifyUrl) + } + if bm.GetString("app_auth_token") == "" && a.AppAuthToken != "" { + bm.Set("app_auth_token", a.AppAuthToken) + } + return bm +} diff --git a/app/lib/alipay/md.go b/app/lib/alipay/md.go new file mode 100644 index 0000000..2f62ae6 --- /dev/null +++ b/app/lib/alipay/md.go @@ -0,0 +1,10 @@ +package alipay + +type PayData struct { + AlipayAppId string `json:"alipay_app_id" label:"支付宝商家应用appid"` + AlipayPrivateKey string `json:"alipay_private_key" label:"支付宝商家应用私钥"` + AlipayPublicKey string `json:"alipay_public_key" label:"支付宝商家应用公钥"` + AlipayPublicContentRSA2 string `json:"alipay_public_content_rsa_2" label:"支付宝公钥证书"` + AlipayRootContent string `json:"alipay_root_content" label:"支付宝根证书"` + AppPublicContent string `json:"app_public_content" label:"应用公钥证书"` +} diff --git a/app/md/md_config.go b/app/md/md_config.go index ec2eac5..a057d25 100644 --- a/app/md/md_config.go +++ b/app/md/md_config.go @@ -9,6 +9,7 @@ type ConfigResp struct { PrivacyUrl string `json:"privacy_url" example:"隐私协议链接"` OssUrl string `json:"oss_url" example:"阿里云图片链接"` Guide []Guide `json:"guide"` + DownUrl string `json:"down_url"` } type VersionResp struct { Version []Version `json:"version"` diff --git a/app/md/realname_auth_base.go b/app/md/realname_auth_base.go new file mode 100644 index 0000000..d0eab74 --- /dev/null +++ b/app/md/realname_auth_base.go @@ -0,0 +1,28 @@ +package md + +type RealNameAuthBasicData struct { + AuthState string `json:"auth_state" example:"0未审核 1通过 2拒绝"` +} +type RealNameAuthAddRequest struct { + RealName string `json:"real_name"` + CardNo string `json:"card_no"` +} + +type UserCertifyRequest struct { + OrderId string `json:"order_id"` //支付订单 + RealName string `json:"real_name" ` + IdentityNum string `json:"identity_num" ` + CertifyId string `json:"certify_id"` + Uid string `json:"uid"` +} +type UserCertifyParams struct { + RealName string `json:"real_name" ` + IdentityNum string `json:"identity_num" ` + OrdId string `json:"ord_id"` + CertifyId string `json:"certify_id"` + Uid string `json:"uid"` +} +type RealNameAuthResp struct { + Oid string `json:"oid"` + Url string `json:"url"` +} diff --git a/app/router/router.go b/app/router/router.go index a286369..66895ba 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -56,6 +56,7 @@ func route(r *gin.RouterGroup) { r.GET("/article/html", hdl.ArticleHtml) //H5渲染的文章 rCallback := r.Group("/callback") { + rCallback.Any("/alipay/face", hdl.CallbackAlipayFace) //支付宝实名回调 rCallback.GET("/advertising/chuanshanjia", hdl.CallbackChuanshanjia) //穿山甲广告回调 rCallback.GET("/advertising/youlianghui", hdl.CallbackYoulianghui) //优量汇广告回调 } @@ -78,6 +79,8 @@ func route(r *gin.RouterGroup) { r.POST("/findPassword", hdl.FindPassword) //找回密码 r.POST("/inviteCode/userInfo", hdl.InviteCodeUserInfo) //邀请码查用户 } + r.POST("/college/detail", hdl.CollegeDetail) // 文章详情 + r.GET("/getModuleSetting", hdl.GetModuleSetting) // 获取页面样式 r.Use(mw.Auth) // 以下接口需要JWT验证 rComm(r.Group("/comm")) @@ -134,11 +137,11 @@ func route(r *gin.RouterGroup) { rWithdraw.GET("/index", hdl.WithdrawGetAmount) } } + rCollege := r.Group("/college") //学院 { rCollege.GET("/cate", hdl.CollegeCate) // 分类 rCollege.POST("/list", hdl.CollegeList) // 文章 - rCollege.POST("/detail", hdl.CollegeDetail) // 文章详情 rCollege.POST("/like/add", hdl.CollegeLikeAdd) // 文章点赞 rCollege.POST("/like/cancel", hdl.CollegeLikeCancel) // 文章取消点赞 rCollege.POST("/share/add", hdl.CollegeShareAdd) // 文章分享记录数量 @@ -163,6 +166,11 @@ func route(r *gin.RouterGroup) { rIm.POST("/user/grabRedPackage", hdl.GrabRedPackage) // IM-领取红包 rIm.GET("/redPackageDetail", hdl.RedPackageDetail) // IM-红包详情 } + rFaceRealName := r.Group("/faceRealName") // 实名认证 + { + rFaceRealName.GET("/base", hdl.GetRealNameAuthBase) //实名认证基础 + rFaceRealName.POST("/save", hdl.RealNameSave) + } } func rComm(r *gin.RouterGroup) { diff --git a/app/svc/svc_college.go b/app/svc/svc_college.go index 427c96b..dd0f908 100644 --- a/app/svc/svc_college.go +++ b/app/svc/svc_college.go @@ -7,6 +7,7 @@ import ( "applet/app/utils" "code.fnuoos.com/EggPlanet/egg_models.git/src/implement" "code.fnuoos.com/EggPlanet/egg_models.git/src/model" + "fmt" "github.com/gin-gonic/gin" "time" ) @@ -59,7 +60,7 @@ func CollegeList(c *gin.Context) { e.OutSuc(c, data, nil) return } -func CollegeDetail(c *gin.Context) { +func CollegeDetail(c *gin.Context, uid int) { eg := db.Db var req md.CollegeDetailReq err := c.ShouldBindJSON(&req) @@ -69,14 +70,13 @@ func CollegeDetail(c *gin.Context) { e.OutErr(c, err1.Code, err1.Error()) return } - user := GetUser(c) NewArticleDb := implement.NewArticleDb(eg) article, _ := NewArticleDb.GetArticle(req.Id) data := md.CollegeDetailResp{} if article != nil { data = md.CollegeDetailResp{ Id: utils.IntToStr(article.Id), - Url: "", + Url: fmt.Sprintf("%s%s?article_id=%s", GetSysCfgStr("wap_host"), "/api/v1/article/html", utils.AnyToString(article.Id)), Title: article.Title, Content: article.Content, IsLike: "0", @@ -85,7 +85,7 @@ func CollegeDetail(c *gin.Context) { LikeCount: NumFormat(article.LikeCount), ForwardCount: NumFormat(article.ForwardCount), } - count, _ := eg.Where("uid=? and article_id=?", user.Id, article.Id).Count(&model.ArticleUserLike{}) + count, _ := eg.Where("uid=? and article_id=?", uid, article.Id).Count(&model.ArticleUserLike{}) if count > 0 { data.IsLike = "1" } diff --git a/app/svc/svc_user_real_name.go b/app/svc/svc_user_real_name.go new file mode 100644 index 0000000..716718b --- /dev/null +++ b/app/svc/svc_user_real_name.go @@ -0,0 +1,261 @@ +package svc + +import ( + "applet/app/db" + "applet/app/e" + "applet/app/lib/alipay" + "applet/app/md" + "applet/app/utils" + "applet/app/utils/cache" + "code.fnuoos.com/EggPlanet/egg_models.git/src/implement" + "code.fnuoos.com/EggPlanet/egg_models.git/src/model" + "encoding/json" + "fmt" + "github.com/gin-gonic/gin" + "time" +) + +func GetRealNameAuthBase(c *gin.Context) { + var res = &md.RealNameAuthBasicData{ + AuthState: "0", + } + res.AuthState = "0" + //判断审核状态 + eg := db.Db + user := GetUser(c) + NewUserRealNameAuthDb := implement.NewUserRealNameAuthDb(eg) + list, _ := NewUserRealNameAuthDb.GetRealNameAuthByUid(utils.Int64ToStr(user.Id)) + if list != nil { + //如果是审核中的订单,判断是否人脸识别 调用人脸识别获取结果 + if list.State == 0 && list.CertifyId != "" { + state, _, _, err := GetCertifyQuery(c, utils.Int64ToStr(user.Id)) + if err == nil { + list.State = state + } + } + res.AuthState = utils.IntToStr(list.State + 1) + if list.State == 0 { //人脸识别 支付了但是没扫脸的情况 设置成没审核状态 + res.AuthState = "0" + } + if list.IsPay == 0 { + res.AuthState = "0" + } + } + e.OutSuc(c, res, nil) + return +} + +func RealNameSave(c *gin.Context) { + var args md.RealNameAuthAddRequest + if err := c.ShouldBindJSON(&args); err != nil { + e.OutErr(c, e.ERR_INVALID_ARGS, err) + return + } + eg := db.Db + user := GetUser(c) + NewUserRealNameAuthDb := implement.NewUserRealNameAuthDb(eg) + realData, _ := NewUserRealNameAuthDb.GetRealNameAuthByUidWithState(utils.Int64ToStr(user.Id), "1") + if realData != nil { + e.OutErr(c, 400, e.NewErr(400, "您已审核通过")) + return + } + //判断该身份证被多少个人绑定过 + count, _ := NewUserRealNameAuthDb.GetRealNameAuthCount(int(user.Id), args.CardNo) + if count > 0 { + e.OutErr(c, 400, e.NewErr(400, "该身份证已被绑定,绑定失败")) + return + } + // 加锁 防止并发提取 + mutexKey := fmt.Sprintf("realname:%s", utils.Int64ToStr(user.Id)) + withdrawAvailable, err := cache.Do("SET", mutexKey, 1, "EX", 5, "NX") + if err != nil { + e.OutErr(c, 400, e.NewErr(400, "请稍后再试")) + return + } + if withdrawAvailable != "OK" { + e.OutErr(c, 400, e.NewErr(400000, "请稍后再试")) + return + } + //调用初始化认证接口 + leave := 17 - len(utils.Int64ToStr(user.Id)) + outerOrderNo := "Egg" + utils.Int64ToStr(user.Id) + "T" + utils.Int64ToStr(time.Now().Unix()) + utils.RandPow(leave) + var tmp = &model.UserRealNameAuth{ + Uid: int(user.Id), + RealName: args.RealName, + CardNo: args.CardNo, + Amount: utils.StrToFloat64(GetSysCfgStr("user_real_name_money")), + AuditType: 1, + UpdateTime: time.Now(), + Oid: outerOrderNo, + } + isNeedPay := "1" + list, _ := NewUserRealNameAuthDb.GetRealNameAuthByUid(utils.Int64ToStr(user.Id)) + if list != nil { + if args.RealName != list.RealName || args.CardNo != list.CardNo || list.AlipayOid == "" { + list.AlipayOid = outerOrderNo + list.CertifyId = "" + } + if list.IsPay != 1 && list.IsPay != 5 { + //没付款的话,更新下订单号 + list.Oid = outerOrderNo + list.Amount = utils.StrToFloat64(GetSysCfgStr("user_real_name_money")) + } + if list.IsPay != 1 && utils.InArr(utils.IntToStr(tmp.IsPay), []string{"5", "6"}) { + list.IsPay = tmp.IsPay + list.Amount = 0 + } + if list.IsPay == 1 { + isNeedPay = "0" + } + if list.State != 1 { + list.State = 0 + } + if args.RealName != "" { + list.RealName = args.RealName + } + if args.CardNo != "" { + list.CardNo = args.CardNo + } + list.UpdateTime = time.Now() + eg.Where("id=?", list.Id).Update(list) + } else { + tmp.CreateTime = time.Now() + tmp.AlipayOid = outerOrderNo + db.InsertComm(eg, tmp) + list = tmp + } + //TODO 扣钱 自动用能量值抵扣 + if isNeedPay == "1" { + list.IsPay = 1 + eg.Where("id=?", list.Id).Update(list) + } + //调用初始化认证接口 + certifyID := list.CertifyId + if certifyID != "" && list.State != 1 { + c.Set("is_check", "1") + state, _, _, _ := GetCertifyQuery(c, utils.Int64ToStr(user.Id)) + if state == 1 { + e.OutErr(c, 400, e.NewErr(400, "已实名")) + return + } + } + var url = "" + if certifyID == "" || list.State == 2 || list.CreateTime.Unix() < time.Now().Unix()-20*3600 { + var param = &md.UserCertifyRequest{ + OrderId: outerOrderNo, + RealName: list.RealName, + IdentityNum: list.CardNo, + Uid: utils.Int64ToStr(user.Id), + } + data, _ := AliFace(c, param) + fmt.Println(data) + tmpId, ok := data.AlipayUserCertifyOpenInitializeResponse.CertifyID.(string) + if ok { + certifyID = tmpId + } + } else { + if list.AlipayOid != "" && list.State != 2 { + outerOrderNo = list.AlipayOid + } + } + //调用认证接口获取链接 + if certifyID != "" { + var param = &md.UserCertifyRequest{CertifyId: certifyID, Uid: utils.Int64ToStr(user.Id)} + url, _ = AliFaceCheck(c, param) + list.CertifyId = certifyID + list.AlipayOid = outerOrderNo + eg.Where("id=?", list.Id).Update(list) + } + e.OutSuc(c, md.RealNameAuthResp{Oid: outerOrderNo, Url: url}, nil) + return +} +func AliFace(c *gin.Context, pay *md.UserCertifyRequest) (alipay.UserCertifyOpenInitData, error) { + orderId := pay.OrderId //支付单号 + payParams := map[string]string{ + "oid": orderId, + "name": pay.RealName, + "id_num": pay.IdentityNum, + } + var data = alipay.UserCertifyOpenInitData{} + r, err := alipay.FacePrepareAlipayCode("face_init", payParams) + if err != nil { + return data, err + } + tmp, ok := r.(alipay.UserCertifyOpenInitData) + if ok { + data = tmp + } + return data, nil +} +func AliFaceCheck(c *gin.Context, pay *md.UserCertifyRequest) (string, error) { + payParams := map[string]string{ + "certify_id": pay.CertifyId, + } + var data = "" + r, err := alipay.FacePrepareAlipayCode("face_certify", payParams) + utils.FilePutContents("face", utils.SerializeStr(r)) + utils.FilePutContents("face", utils.SerializeStr(err)) + if err != nil { + return "", err + } + tmp, ok := r.(string) + if ok { + data = tmp + } + return data, nil +} + +func GetCertifyQuery(c *gin.Context, uid string) (int, int, string, error) { + + eg := db.Db + NewUserRealNameAuthDb := implement.NewUserRealNameAuthDb(eg) + realNameAuth, _ := NewUserRealNameAuthDb.GetRealNameAuth(utils.StrToInt(uid)) + if realNameAuth == nil { + return 0, 2, "未支付金额,认证失败", e.NewErr(400, "未支付金额,认证失败") + } + if realNameAuth.CertifyId == "" { + return 0, 2, "校验失败", e.NewErr(400, "校验失败") + } + var param = &md.UserCertifyRequest{CertifyId: realNameAuth.CertifyId} + data, _ := AliFaceQuery(c, param) + isTrueStr := "" + tmpData, ok := data.AlipayUserCertifyOpenQueryResponse.Passed.(string) + if ok { + isTrueStr = tmpData + } + tmpData1, ok := data.AlipayUserCertifyOpenQueryResponse.Passed.([]string) + if ok { + if len(tmpData1) > 0 { + isTrueStr = tmpData1[0] + } + } + fmt.Println(isTrueStr) + msg, _ := json.Marshal(data) + realNameAuth.Msg = string(msg) + if isTrueStr == "T" { + realNameAuth.State = 1 + eg.Where("id=?", realNameAuth.Id).Update(realNameAuth) + } else if realNameAuth.State != 1 && isTrueStr == "F" && c.GetString("is_check") != "1" { + realNameAuth.State = 2 + eg.Where("id=?", realNameAuth.Id).Update(realNameAuth) + } + return realNameAuth.State, realNameAuth.State, realNameAuth.Msg, nil +} +func AliFaceQuery(c *gin.Context, pay *md.UserCertifyRequest) (alipay.UserCertifyOpenQueryData, error) { + payParams := map[string]string{ + "certify_id": pay.CertifyId, + } + var data = alipay.UserCertifyOpenQueryData{} + r, err := alipay.FacePrepareAlipayCode("face_query", payParams) + utils.FilePutContents("face", utils.SerializeStr(payParams)) + utils.FilePutContents("face", utils.SerializeStr(r)) + utils.FilePutContents("face", utils.SerializeStr(err)) + if err != nil { + return data, err + } + tmp, ok := r.(alipay.UserCertifyOpenQueryData) + if ok { + data = tmp + } + return data, nil +} diff --git a/app/utils/string.go b/app/utils/string.go index 99fdf19..1d582de 100644 --- a/app/utils/string.go +++ b/app/utils/string.go @@ -3,9 +3,11 @@ package utils import ( "fmt" "github.com/syyongx/php2go" + "math/rand" "reflect" "sort" "strings" + "time" ) func Implode(glue string, args ...interface{}) string { @@ -25,6 +27,19 @@ func InArr(target string, str_array []string) bool { } return false } +func RandPow(l int) string { + var i = "1" + for j := 0; j < l; j++ { + i += "0" + } + k := StrToInt64(i) + n := rand.New(rand.NewSource(time.Now().UnixNano())).Int63n(k) + ls := "%0" + IntToStr(l) + "v" + str := fmt.Sprintf(ls, n) + //min := int(math.Pow10(l - 1)) + //max := int(math.Pow10(l) - 1) + return str +} // 把数组的值放到key里 func ArrayColumn(array interface{}, key string) (result map[string]interface{}, err error) { diff --git a/go.mod b/go.mod index cb4c67f..fcecd71 100644 --- a/go.mod +++ b/go.mod @@ -32,12 +32,16 @@ require ( ) require ( - code.fnuoos.com/EggPlanet/egg_models.git v0.2.1-0.20241128030209-743f36ef9dad + code.fnuoos.com/EggPlanet/egg_models.git v0.2.1-0.20241128110636-bdf6315267cb code.fnuoos.com/EggPlanet/egg_system_rules.git v0.0.4-0.20241128075251-3c7f4a91e52c code.fnuoos.com/go_rely_warehouse/zyos_go_es.git v1.0.1-0.20241118083738-0f22da9ba0be code.fnuoos.com/go_rely_warehouse/zyos_go_mq.git v0.0.5 github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible github.com/gin-contrib/sessions v1.0.1 + github.com/go-pay/crypto v0.0.1 + github.com/go-pay/gopay v1.5.98 + github.com/go-pay/util v0.0.4 + github.com/go-pay/xtime v0.0.2 github.com/go-sql-driver/mysql v1.8.1 github.com/gocolly/colly v1.2.0 github.com/google/uuid v1.3.0 @@ -112,14 +116,14 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.22.0 // indirect + golang.org/x/crypto v0.23.0 // indirect golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect - golang.org/x/net v0.24.0 // indirect + golang.org/x/net v0.25.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.26.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/text v0.18.0 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect - golang.org/x/tools v0.20.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.4.0 // indirect google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 // indirect