This commit is contained in:
IT 老营长 @云轩领航-创始人 2024-11-26 23:12:41 +08:00
parent 096798dabf
commit 409aa0aed9
32 changed files with 592 additions and 51 deletions

3
go.mod
View File

@ -25,8 +25,9 @@ require (
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1046 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1047 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.1046 // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.1047 // indirect
github.com/wechatpay-apiv3/wechatpay-go v0.2.20 // indirect
golang.org/x/text v0.16.0 // indirect
gorm.io/driver/mysql v1.5.7 // indirect

4
go.sum
View File

@ -67,8 +67,12 @@ github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8
github.com/tdakkota/win32metadata v0.1.0/go.mod h1:77e6YvX0LIVW+O81fhWLnXAxxcyu/wdZdG7iwed7Fyk=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1046 h1:0FvA5Rw9dGqK5CTbWlgyE1HbiND1hLsoIfne4jzWuRI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1046/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1047 h1:eLEUnmSd82NBMNwergC/5RGqJqNDbsvprPtnG1UhxDI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1047/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.1046 h1:P8TrTPEWu4GjnEMyNgdYmV5jXigGtDMn+sVTLJJvW0c=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr v1.0.1046/go.mod h1:ifVagKrjnvy/ibrvLZjsELEh5WdRtchM8xyUlF88BNg=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.1047 h1:FF8uERgTL9NKxgUHrKHbVefETVL3J6DeL9t6qvIT5yI=
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.1047/go.mod h1:3tgFFSlybx6XyhvLWpnSjWYFMedTyQC9oyh8CH1Ak28=
github.com/tinygo-org/cbgo v0.0.4/go.mod h1:7+HgWIHd4nbAz0ESjGlJ1/v9LDU1Ox8MGzP9mah/fLk=
github.com/tinygo-org/pio v0.0.0-20231216154340-cd888eb58899/go.mod h1:LU7Dw00NJ+N86QkeTGjMLNkYcEYMor6wTDpTCu0EaH8=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=

View File

@ -280,12 +280,13 @@ func (s Table) UploadUpdate(m *ice.Message, field, uid string, arg ...string) {
p := m.UploadSave(path.Join(nfs.USR, kit.Select(field, m.Option(model.FIELD)), uid) + nfs.PS)
s.Update(m, kit.Dict(kit.Select(m.Option(model.FIELD), field), p), model.UID, uid)
}
func (s Table) UploadCreate(m *ice.Message, field, uid string, arg ...string) {
func (s Table) UploadCreate(m *ice.Message, field, uid string, arg ...string) string {
if m.IsErr() {
return
return ""
}
p := m.UploadSave(path.Join(nfs.USR, kit.Select(field, m.Option(model.FIELD)), uid) + nfs.PS)
s.Create(m, kit.Select(m.Option(model.FIELD), field), p, model.UID, uid, model.USER_UID, m.Option(model.USER_UID))
return p
}
func (s Table) ChangeStatus(m *ice.Message, place_uid, uid string, from, to int, arg ...string) *ice.Message {
msg := s.ValueList(m.Spawn(), []string{place_uid, uid}, model.STATUS)

View File

@ -65,7 +65,7 @@ $output div.item.card:not(:last-child) { margin-bottom:2px; }
body:not(.width1) $output div.item.card { flex-direction:row-reverse; }
body:not(.width1) $output div.item.card>div.action { position:static; flex-shrink:0; }
body:not(.width1) $output div.item.card>div.output { flex-grow:1; }
$output div.item.card>div.output>div { width:100%; }
$output div.item.card>div.output>div { width:100%; width:calc(100% - 53px); overflow:hidden; }
$output div.item.card div.title { margin-bottom:5px; width:100%; display:flex; align-items:center; position:relative; }
$output div.item.card div.title span:first-child { word-break:break-all; }
$output div.item.card div.title span.auth { font-size:14px; }

View File

@ -40,7 +40,7 @@ func (s user) Remove(m *ice.Message, arg ...string) {
func (s user) List(m *ice.Message, arg ...string) {
if len(arg) == 0 {
if m.IsTech() {
s.Limit(m, 50)
s.Limit(m, 100)
s.Select(m, arg...).Table(func(value ice.Maps) {
if value[model.UID] != m.Option(model.USER_UID) {
m.PushButton(s.SetCookie, s.Remove)

View File

@ -7,8 +7,6 @@ import (
_ "shylinux.com/x/community/src/huodongzuzhi"
_ "shylinux.com/x/community/src/renzhengshouquan"
_ "shylinux.com/x/community/src/yuehaoxitong"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/model"
)
func main() { print(ice.Run()) }
@ -16,4 +14,4 @@ func main() { print(ice.Run()) }
func init() {
ice.Info.CodeMain = "src/gonganxitong/portal.go"
ice.Info.NodeMain = "web.team.gonganxitong.portal"
}
}

View File

@ -5,6 +5,12 @@ import (
_ "shylinux.com/x/mysql-story/src/db/mysql"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/model"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/ocr"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/realname"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/realname/model"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/sms"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/sms/model"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentdocument"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentmeeting"
_ "shylinux.com/x/community/src/renzhengshouquan/external/tencentmeeting/model"

View File

@ -1 +1,4 @@
$output div.item.card div.output div.output img { height:unset; width:100%; margin-right:0; }
$output div.item.card div.output div.output img { height:unset; width:100%; margin-right:0; }
$input div.item.text.verify input[type=button] {
border-radius:0; height:30px; position:absolute; right:1px; width:unset;
}

View File

@ -1,56 +1,107 @@
package renzhengshouquan
import (
"encoding/base64"
"math/rand"
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/mdb"
"shylinux.com/x/icebergs/base/nfs"
// "shylinux.com/x/icebergs/base/web"
"shylinux.com/x/toolkits"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
cloudprofile "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
ocr "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr/v20181119"
"shylinux.com/x/community/src/renzhengshouquan/model"
)
type cert struct {
Table
order string `data:"1"`
fields string `data:"title,content,path,user_uid"`
fields string `data:"cert_status,path,number,name,type,address,mobile,verify,user_uid"`
upload string `name:"upload" role:"leader"`
remove string `name:"remove" role:"leader"`
verify string `name:"verify mobile* verify*" role:"void"`
}
func (s cert) Upload(m *ice.Message, arg ...string) {
m.WarnNotValid(!kit.IsIn(m.OptionDefault(mdb.FIELD, "cert"), "cert"))
s.UploadCreate(m, model.PATH, m.Option(model.AUTH_UID))
p := s.UploadCreate(m.Options(mdb.FIELD, "cert"), model.PATH, "")
switch AuthType(kit.Int(m.Cmd(Auth{}, s.Select, model.UID, m.Option(model.AUTH_UID)).Append(model.AUTH_TYPE))) {
case AuthPersonal:
msg := m.Cmd(OcrVendor, OcrVendor.IDCard, p)
s.Update(m, kit.Dict(
model.NUMBER, msg.Append("IdNum"),
model.NAME, msg.Append("Name"),
model.TYPE, msg.Append("Sex"),
model.BIRTH, msg.Append("Birth"),
model.ADDRESS, msg.Append("Address"),
), m.OptionSimple(model.AUTH_UID)...)
case AuthCompany:
msg := m.Cmd(OcrVendor, OcrVendor.BizLicense, p)
s.Update(m, kit.Dict(
model.NUMBER, msg.Append("RegNum"),
model.NAME, msg.Append("Name"),
model.TYPE, msg.Append("Type"),
model.PERSON, msg.Append("Person"),
model.PERIOD, msg.Append("Period"),
model.ADDRESS, msg.Append("Address"),
model.AUTHOR, msg.Append("RegistrationAuthority"),
), m.OptionSimple(model.AUTH_UID)...)
}
}
func (s cert) List(m *ice.Message, arg ...string) {
if len(arg) == 1 {
s.Select(m, model.AUTH_UID, arg[0]).PushAction(s.Remove).Action(s.Upload).Display("").DisplayCSS("")
s.Select(m, model.AUTH_UID, arg[0]).Table(func(value ice.Maps) {
switch CertStatus(kit.Int(value[model.CERT_STATUS])) {
case CertUpload:
m.PushButton(s.Verify)
case CertVerify:
m.PushButton(s.Check)
default:
m.PushButton(s.Verify)
// m.PushButton()
}
}).Action(s.Upload).Display("").DisplayCSS("")
s.Button(m, "", s.Upload)
}
// _msg := m.Cmd(web.CHAT_WX_OCR, "", m.Append(model.PATH), "bizlicense")
// m.Echo(kit.Formats(_msg))
s.BizLicenseOCR(m)
}
func (s cert) newClient(m *ice.Message, arg ...string) *ocr.Client {
msg := m.Cmd("web.team.renzhengshouquan.external.tencentcloud.tencentcloud", "4c6a8ccf186816b332ad9dc5655255dd")
credential := common.NewCredential(msg.Append("secret_id"), msg.Append("secret_key"))
client, _ := ocr.NewClient(credential, "", cloudprofile.NewClientProfile())
return client
func (s cert) Verify(m *ice.Message, arg ...string) {
if m.Option(model.VERIFY) == "000" {
verify := kit.Format("%06d", rand.Intn(10000))
s.Update(m, kit.Dict(model.VERIFY, verify), m.OptionSimple(model.AUTH_UID, model.UID)...)
m.Cmd(SmsVendor, SmsVendor.Send, m.Option(model.MOBILE), verify)
} else {
msg := s.Select(m.Spawn(), m.OptionSimple(model.AUTH_UID, model.UID)...)
if msg.Append(model.VERIFY) == m.Option(model.VERIFY) {
s.Check(m)
}
}
}
func (s cert) BizLicenseOCR(m *ice.Message, arg ...string) *ice.Message {
request := ocr.NewBizLicenseOCRRequest()
request.ImageBase64 = common.StringPtr(base64.StdEncoding.EncodeToString([]byte(m.Cmdx(nfs.CAT, m.Append(model.PATH)))))
response, err := s.newClient(m).BizLicenseOCR(request)
m.Warn(err)
m.SetAppend()
m.PushDetail(kit.Value(kit.UnMarshal(response.ToJsonString()), "Response"))
return m
func (s cert) Check(m *ice.Message, arg ...string) {
if !m.Cmdy(RealnameVendor, RealnameVendor.Check, m.Option(model.MOBILE), m.Option(model.NUMBER), m.Option(model.NAME)).IsErr() {
s.Update(m, kit.Dict(model.STATUS, CertCheck), m.OptionSimple(model.AUTH_UID, model.UID)...)
}
}
func init() { ice.TeamCtxCmd(cert{}) }
type CertStatus int
const (
CertUpload CertStatus = iota
CertVerify
CertCheck
)
var CertStatusList = map[CertStatus]string{
CertUpload: "upload",
CertVerify: "verify",
CertCheck: "check",
}
func (s CertStatus) String() string { return CertStatusList[s] }
var OcrVendor interface {
IDCard(m *ice.Message, arg ...string)
BizLicense(m *ice.Message, arg ...string)
}
var SmsVendor interface {
Send(m *ice.Message, arg ...string)
}
var RealnameVendor interface {
Check(m *ice.Message, arg ...string)
}

View File

@ -1,12 +1,29 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.myView(can, msg, function(value) { return [
{view: html.TITLE, list: [value.title]},
{view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value), value.user_name]},
// {view: html.TITLE, list: [value.title]},
// {view: html.STATUS, list: [value.uid.slice(0, 6), can.onimport.timeView(can, value), value.user_name]},
{view: html.TITLE, list: [value.name]},
{view: html.STATUS, list: [value.number]},
{view: html.STATUS, list: [value.address]},
{view: html.OUTPUT, list: [{img: can.misc.Resource(can, value.path)}]},
] }, function(event, value) {})
},
})
Volcanos(chat.ONACTION, {
upload: function(event, can) { can.user.upload(can.request(event, {_handle: ice.TRUE}), can) },
beforeInputs: function(event, can, button, sub) {
can.page.Select(can, sub._target, "table>tr>td>div.item.text.verify", function(target) {
can.page.Append(can, target, [{type: html.INPUT, data: {type: html.BUTTON}, name: "verify", value: "发送验证码", onclick: function(event) {
if (sub.Option("mobile") == "") {
return can.onmotion.delay(can, function() {
can.user.toast(can, "手机号不能为空"), sub.focus("mobile")
})
}
can.runAction(can.request(event, sub.Option(), {verify: "000"}), "verify", [], function() {
can.user.toast(can, "验证码发送成功")
})
}}])
})
},
})

View File

@ -44,12 +44,18 @@ func (s Table) RewriteAppend(m *ice.Message, arg ...string) *ice.Message {
value = AuthType(kit.Int(value)).String()
case model.AUTH_STATUS:
value = AuthStatus(kit.Int(value)).String()
case model.CERT_STATUS:
value = CertStatus(kit.Int(value)).String()
}
return value
})
return s.Table.RewriteAppend(m)
}
func (s Table) GetAuthUID(m *ice.Message, arg ...string) string {
return "4c6a8ccf186816b332ad9dc5655255dd"
}
type Tables struct{ Table }
func (s Tables) BeforeMigrate(m *ice.Message, arg ...string) {}

View File

@ -2,6 +2,11 @@ package model
import "shylinux.com/x/mysql-story/src/db"
const (
SECRET_ID = "secret_id"
SECRET_KEY = "secret_key"
)
type Tencentcloud struct {
db.ModelWithUID
AuthUID string `gorm:"type:char(32);index"`

View File

@ -0,0 +1,39 @@
package ocr
import (
"shylinux.com/x/ice"
"shylinux.com/x/community/src/renzhengshouquan"
"shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
sdk "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/ocr/v20181119"
)
type ocr struct {
tencentcloud.Tencentcloud
}
func (s ocr) List(m *ice.Message, arg ...string) {}
func (s ocr) BizLicense(m *ice.Message, arg ...string) {
request := sdk.NewBizLicenseOCRRequest()
request.ImageBase64 = common.StringPtr(s.ImageData(m, arg...))
response, err := s.newClient(m).BizLicenseOCR(request)
s.ParseResponse(m, response, err)
}
func (s ocr) IDCard(m *ice.Message, arg ...string) {
request := sdk.NewIDCardOCRRequest()
request.ImageBase64 = common.StringPtr(s.ImageData(m, arg...))
response, err := s.newClient(m).IDCardOCR(request)
s.ParseResponse(m, response, err)
}
func init() { ice.TeamCtxCmd(ocr{}) }
func (s ocr) newClient(m *ice.Message, arg ...string) *sdk.Client {
c, _ := sdk.NewClient(s.NewCredential(m), "", s.NewProfile(m))
return c
}
func init() { renzhengshouquan.OcrVendor = ocr{} }

View File

@ -0,0 +1,5 @@
section "图文识别"
refer `
文档 https://cloud.tencent.com/document/product/866/45338
调试 https://console.cloud.tencent.com/api/explorer?Product=ocr&Version=2018-11-19&Action=RecognizeEncryptedIDCardOCR
`

View File

@ -0,0 +1,14 @@
package model
import "shylinux.com/x/mysql-story/src/db"
type Realname struct {
db.ModelWithUID
AuthUID string `gorm:"type:char(32);index"`
UserUID string `gorm:"type:char(32)"`
SourceID string `gorm:"type:varchar(64)"`
SecretID string `gorm:"type:varchar(64)"`
SecretKey string `gorm:"type:varchar(64)"`
}
func init() { db.CmdModels("", &Realname{}) }

View File

@ -0,0 +1,67 @@
package realname
import (
"crypto/hmac"
"crypto/sha1"
"encoding/base64"
"fmt"
"net/http"
"time"
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/web"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/renzhengshouquan"
"shylinux.com/x/community/src/renzhengshouquan/model"
)
type realname struct {
renzhengshouquan.Table
order string `data:"16"`
fields string `data:"auth_uid,user_uid,source_id,secret_id,secret_key"`
create string `name:"create source_id* secret_id* secret_key*" role:"leader"`
remove string `name:"remove" role:"leader"`
}
func (s realname) List(m *ice.Message, arg ...string) {
s.ValueList(m, arg).Display("")
kit.If(m.Length() > 0, func() { m.Action() })
}
func init() { ice.TeamCtxCmd(realname{}) }
func init() { renzhengshouquan.RealnameVendor = realname{} }
func (s realname) Check(m *ice.Message, arg ...string) {
msg := s.Select(m.Spawn(), model.AUTH_UID, "4c6a8ccf186816b332ad9dc5655255dd")
source := msg.Append("source_id")
secretId := msg.Append("secret_id")
secretKey := msg.Append("secret_key")
// source := "market-2qkoxdj5i"
// secretId := "AKIDfjSG99M0m5gqr0aiyN4Ho0rfut22jybmlrj1"
// secretKey := "3oga413JEe58di8k2NkVim5s79Qmuw17DWVV6spD"
// source := "market-dw3yg5tm8"
// secretId := "AKIDHFZ1EdTz3D7Y4nMYESfSKdv1RTpkbKe7LjpU"
// secretKey := "cpcts0905vj0wm2qw6l8az5dermgvp8m7op4wzgw"
auth, datetime := calcAuthorization(source, secretId, secretKey)
m.Option(web.SPIDE_HEADER, map[string]string{"X-Source": source, "Authorization": auth, "X-Date": datetime})
res := m.Cmdx(web.SPIDE, ice.DEV, web.SPIDE_RAW, http.MethodPost, "https://service-rbgpp2hy-1305308687.gz.apigw.tencentcs.com/release/release/mobile/3-realnameauth",
web.SPIDE_FORM, "mobile_number", arg[0], "idcard_number", arg[1], "name", arg[2])
m.WarnNotRight(kit.Value(kit.UnMarshal(res), "data.result") != "0")
// m.Cmdy(web.SPIDE, ice.DEV, web.SPIDE_RAW, http.MethodPost, "https://service-91ii7z5b-1300755093.ap-beijing.apigateway.myqcloud.com/release/phone3element",
// web.SPIDE_FORM, "mobile", arg[0], "idCard", arg[1], "realName", arg[2])
}
func calcAuthorization(source string, secretId string, secretKey string) (auth string, datetime string) {
timeLocation, _ := time.LoadLocation("Etc/GMT")
datetime = time.Now().In(timeLocation).Format("Mon, 02 Jan 2006 15:04:05 GMT")
signStr := fmt.Sprintf("x-date: %s\nx-source: %s", datetime, source)
mac := hmac.New(sha1.New, []byte(secretKey))
mac.Write([]byte(signStr))
sign := base64.StdEncoding.EncodeToString(mac.Sum(nil))
auth = fmt.Sprintf("hmac id=\"%s\", algorithm=\"hmac-sha1\", headers=\"x-date x-source\", signature=\"%s\"", secretId, sign)
return auth, datetime
}

View File

@ -0,0 +1,8 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.myView(can, msg, function(value) { return [
{view: html.TITLE, list: [value.source_id]},
{view: html.STATUS, list: [value.secret_id]},
] })
},
})

View File

@ -0,0 +1,11 @@
{
"realname": "实名验证",
"icons": {
"realname": "https://img.icons8.com/officel/80/video-conference.png"
},
"input": {
"source_id": "SourceID",
"secret_id": "SecretID",
"secret_key": "SecretKey"
}
}

View File

@ -0,0 +1,9 @@
section "实名验证"
refer `
后台 https://console.cloud.tencent.com/servicemarket/services/market-2qkoxdj5i
文档 https://market.cloud.tencent.com/products/30034?keyword=%E6%89%8B%E6%9C%BA%E4%B8%89%E8%A6%81%E7%B4%A0%E5%AE%9E%E5%90%8D%E8%AE%A4%E8%AF%81
`
refer `
后台 https://console.cloud.tencent.com/servicemarket/services/market-dw3yg5tm8
文档 https://market.cloud.tencent.com/products/17673
`

View File

@ -0,0 +1,23 @@
package model
import "shylinux.com/x/mysql-story/src/db"
const (
AUTH_UID = "auth_uid"
SIGN_NAME = "sign_name"
TEMPLATE_ID = "template_id"
APP_ID = "app_id"
MOBILE = "mobile"
VERIFY = "verify"
)
type Sms struct {
db.ModelWithUID
AuthUID string `gorm:"type:char(32);index"`
UserUID string `gorm:"type:char(32);index"`
SignName string `gorm:"type:varchar(64)"`
TemplateID string `gorm:"type:varchar(64)"`
AppID string `gorm:"type:varchar(32)"`
}
func init() { db.CmdModels("", &Sms{}) }

View File

@ -0,0 +1,49 @@
package sms
import (
"shylinux.com/x/ice"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/renzhengshouquan"
"shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud"
"shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/sms/model"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
sdk "github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms/v20210111"
)
type sms struct {
renzhengshouquan.Table
tencentcloud.Tencentcloud
order string `data:"17"`
fields string `data:"auth_uid,user_uid,sign_name AS sign_name,template_id,app_id"`
create string `name:"create app_id* sign_name* template_id*" role:"leader"`
remove string `name:"remove" role:"leader"`
send string `name:"send mobile verify" role:"leader"`
}
func (s sms) List(m *ice.Message, arg ...string) {
s.ValueList(m, arg).Display("")
m.PushAction(s.Send, s.Remove)
kit.If(m.Length() > 0, func() { m.Action() })
}
func (s sms) Send(m *ice.Message, arg ...string) {
msg := s.Select(m.Spawn(), model.AUTH_UID, s.GetAuthUID(m))
request := sdk.NewSendSmsRequest()
request.SignName = common.StringPtr(msg.Append(model.SIGN_NAME))
request.TemplateId = common.StringPtr(msg.Append(model.TEMPLATE_ID))
request.SmsSdkAppId = common.StringPtr(msg.Append(model.APP_ID))
request.PhoneNumberSet = common.StringPtrs([]string{m.Option(model.MOBILE)})
request.TemplateParamSet = common.StringPtrs([]string{m.Option(model.VERIFY)})
response, err := s.newClient(m).SendSms(request)
s.ParseResponse(m, response, err)
}
func init() { ice.TeamCtxCmd(sms{}) }
func init() { renzhengshouquan.SmsVendor = sms{} }
func (s sms) newClient(m *ice.Message, arg ...string) *sdk.Client {
c, _ := sdk.NewClient(s.NewCredential(m), "ap-guangzhou", s.NewProfile(m))
return c
}

View File

@ -0,0 +1,7 @@
Volcanos(chat.ONIMPORT, {
_init: function(can, msg) {
can.onimport.myView(can, msg, function(value) { return [
{view: html.TITLE, list: [value.sign_name, value.template_id, value.app_id]},
] })
},
})

View File

@ -0,0 +1,11 @@
{
"sms": "发送短信",
"icons": {
"sms": "https://img.icons8.com/officel/80/sms.png"
},
"input": {
"app_id": "AppID",
"sign_name": "SignName",
"template_id": "TemplateID"
}
}

View File

@ -0,0 +1,5 @@
chapter "短信"
refer `
后台 https://console.cloud.tencent.com/smsv2
调试 https://console.cloud.tencent.com/api/explorer?Product=sms&Version=2021-01-11&Action=SendSms
`

View File

@ -1,15 +1,22 @@
package tencentcloud
import (
"encoding/base64"
"shylinux.com/x/ice"
"shylinux.com/x/icebergs/base/nfs"
kit "shylinux.com/x/toolkits"
"shylinux.com/x/community/src/renzhengshouquan"
"shylinux.com/x/community/src/renzhengshouquan/external/tencentcloud/model"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common"
"github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common/profile"
)
type tencentcloud struct {
renzhengshouquan.Table
order string `data:"13"`
order string `data:"15"`
fields string `data:"secret_id,secret_key,user_uid"`
create string `name:"create secret_id* secret_key*" role:"leader"`
remove string `name:"remove" role:"leader"`
@ -21,3 +28,23 @@ func (s tencentcloud) List(m *ice.Message, arg ...string) {
}
func init() { ice.TeamCtxCmd(tencentcloud{}) }
type Tencentcloud struct{ tencentcloud }
func init() { ice.TeamCtxCmd(Tencentcloud{}) }
func (s Tencentcloud) NewCredential(m *ice.Message, arg ...string) *common.Credential {
msg := m.Cmd(s, "4c6a8ccf186816b332ad9dc5655255dd")
return common.NewCredential(msg.Append(model.SECRET_ID), msg.Append(model.SECRET_KEY))
}
func (s Tencentcloud) NewProfile(m *ice.Message, arg ...string) *profile.ClientProfile {
return profile.NewClientProfile()
}
func (s Tencentcloud) ImageData(m *ice.Message, arg ...string) string {
return base64.StdEncoding.EncodeToString([]byte(m.Cmdx(nfs.CAT, arg[0])))
}
func (s Tencentcloud) ParseResponse(m *ice.Message, res interface{ ToJsonString() string }, err error) {
if !m.Warn(err) {
m.PushDetail(kit.Value(kit.UnMarshal(res.ToJsonString()), "Response"))
}
}

View File

@ -22,6 +22,7 @@ const (
AUTH_STATUS = "auth_status"
AUTH_AVATAR = "auth_avatar"
CERT_UID = "cert_uid"
CERT_STATUS = "cert_status"
PLACE_NAME = "place_name"
STREET_NAME = "street_name"
COMPANY_UID = "company_uid"
@ -37,6 +38,14 @@ const (
INDEX = "index"
VALUE = "value"
PATH = "path"
NUMBER = "number"
BIRTH = "birth"
PERIOD = "period"
PERSON = "person"
AUTHOR = "author"
ADDRESS = "address"
MOBILE = "mobile"
VERIFY = "verify"
)
type UserAuth struct {
@ -55,11 +64,21 @@ type Auth struct {
Status uint8 `gorm:"default:0"`
}
type Cert struct {
db.ModelContent
db.ModelWithUID
AuthUID string `gorm:"type:char(32);index"`
UserUID string `gorm:"type:char(32);index"`
Path string `gorm:"type:varchar(255)"`
Type string `gorm:"type:char(8)"`
Size int `gorm:"default:0"`
Number string `gorm:"type:varchar(32)"`
Name string `gorm:"type:varchar(32)"`
Type string `gorm:"type:varchar(32)"`
Birth string `gorm:"type:varchar(32)"`
Period string `gorm:"type:varchar(32)"`
Person string `gorm:"type:varchar(32)"`
Author string `gorm:"type:varchar(32)"`
Address string `gorm:"type:varchar(255)"`
Status uint8 `gorm:"default:0"`
Mobile string `gorm:"type:varchar(16)"`
Verify string `gorm:"type:varchar(16)"`
}
func init() { db.CmdModels("", &UserAuth{}, &Auth{}, &Cert{}) }

View File

@ -3,6 +3,7 @@
"cert": "上传证件", "auth": "认证授权", "admin": "管理后台", "profile": "用户名片",
"certList": "证件", "memberList": "成员",
"issue": "认证", "revoke": "吊销", "enter": "进入",
"verify": "验证",
"style": {
"issue": "notice",
"revoke": "danger",
@ -21,7 +22,13 @@
"auth_name": "认证主体",
"auth_type": "认证类型",
"auth_status": "认证状态",
"from_uid": "认证机构"
"mobile": "手机号",
"verify": "验证码",
"from_uid": "认证机构",
"icons": {
"mobile": "bi bi-phone",
"verify": "bi bi-123"
}
},
"value": {
"user_auth_role": {

View File

@ -18,6 +18,15 @@
"time": "2024-08-06 18:45:35.904"
}
},
"22574299a657140d473f0216b8d83710": {
"meta": {
"icons": "https://img.icons8.com/officel/50/documents.png",
"index": "web.team.gonganxitong.document",
"name": "在线文档",
"order": "93",
"time": "2024-11-25 15:33:24.095"
}
},
"27c6988eeb07c78cbb49aa15c577cfa4": {
"meta": {
"icons": "https://img.icons8.com/officel/80/edit-property.png",
@ -33,7 +42,7 @@
"icons": "https://img.icons8.com/officel/80/agreement.png",
"index": "web.team.gonganxitong.contract",
"name": "在线合同",
"order": "93",
"order": "94",
"time": "2024-11-24 09:19:03.732"
}
},
@ -46,6 +55,15 @@
"time": "2024-09-07 08:23:04.093"
}
},
"882a999b4a72a9866d9e4eef110d335a": {
"meta": {
"icons": "https://img.icons8.com/officel/50/ios-photos.png",
"index": "web.team.gonganxitong.photo",
"name": "在线相册",
"order": "95",
"time": "2024-11-25 16:22:57.607"
}
},
"8ce4dfb877e04e3be5144253fdd5d8ff": {
"meta": {
"icons": "https://img.icons8.com/officel/80/receipt-approved.png",
@ -124,7 +142,7 @@
"icons": "https://img.icons8.com/officel/80/online-payment-with-a-credit-card.png",
"index": "web.team.gonganxitong.paymentlist",
"name": "在线支付",
"order": "92",
"order": "91",
"time": "2024-11-22 11:37:54.098"
}
},
@ -159,7 +177,7 @@
"icons": "https://img.icons8.com/officel/80/video-conference.png",
"index": "web.team.gonganxitong.meeting",
"name": "在线会议",
"order": "91",
"order": "92",
"role": "leader,worker",
"time": "2024-11-19 15:35:47.453"
}

View File

@ -121,6 +121,15 @@
"time": "2024-09-07 08:23:04.061"
}
},
"8548d5ce3faee7bd508d2fb53d57f35b": {
"meta": {
"icons": "https://img.icons8.com/officel/50/ios-photos.png",
"index": "web.team.guanlixitong.photo",
"name": "在线相册",
"order": "95",
"time": "2024-11-25 18:11:44.299"
}
},
"9c18032c5bc252f2986e1b20e7e77db7": {
"meta": {
"icons": "https://img.icons8.com/officel/80/property-with-timer.png",
@ -223,11 +232,21 @@
"time": "2024-08-20 11:07:54.833"
}
},
"e2ade31e19fd70911169780be6757fa3": {
"meta": {
"icons": "https://img.icons8.com/officel/80/agreement.png",
"index": "web.team.guanlixitong.contract",
"name": "在线合同",
"order": "94",
"time": "2024-11-25 18:11:44.307"
}
},
"e595a0bbefbcfaa89f45dd875cc6fe0b": {
"meta": {
"icons": "https://img.icons8.com/officel/80/upload-link-document.png",
"icons": "https://img.icons8.com/officel/50/documents.png",
"index": "web.team.guanlixitong.document",
"name": "在线文档",
"order": "93",
"time": "2024-11-10 09:43:58.429"
}
},

View File

@ -9,6 +9,24 @@
"time": "2024-08-25 12:53:13.205"
}
},
"3e9e80db9ae3768b7a44774c7afa5f65": {
"meta": {
"icons": "https://img.icons8.com/officel/80/agreement.png",
"index": "web.team.huodongzuzhi.contract",
"name": "在线合同",
"order": "94",
"time": "2024-11-25 18:11:44.294"
}
},
"49432b349d456f4108dcfa7d28435bac": {
"meta": {
"icons": "https://img.icons8.com/officel/50/documents.png",
"index": "web.team.huodongzuzhi.document",
"name": "在线文档",
"order": "93",
"time": "2024-11-25 18:19:23.750"
}
},
"595eb34d7ebe62e160c02ed5b127d637": {
"meta": {
"icons": "https://img.icons8.com/officel/80/test-partial-passed.png",
@ -113,6 +131,15 @@
"time": "2024-11-19 15:35:47.287"
}
},
"e5ce14fa8331355abad8cc68c25c74a4": {
"meta": {
"icons": "https://img.icons8.com/officel/50/ios-photos.png",
"index": "web.team.huodongzuzhi.photo",
"name": "在线相册",
"order": "95",
"time": "2024-11-25 18:11:44.292"
}
},
"ed9cb73417ae9e3e63526f1c459e9c7b": {
"meta": {
"icons": "https://img.icons8.com/officel/80/online-payment-with-a-credit-card.png",

View File

@ -1,4 +1,14 @@
{
"015b4784c16b63975824abbb3ff4ec9f": {
"meta": {
"enable": "false",
"icons": "https://img.icons8.com/officel/50/ios-photos.png",
"index": "web.team.renzhengshouquan.photo",
"name": "在线相册",
"order": "95",
"time": "2024-11-25 18:11:44.117"
}
},
"0d7f068029dbf7f9f0d307070cc3a79b": {
"meta": {
"icons": "https://img.icons8.com/officel/80/receipt-approved.png",
@ -9,12 +19,32 @@
"time": "2024-08-29 12:42:12.319"
}
},
"1c4fee90e6a7bdb8ab6f1ccb23f3273f": {
"meta": {
"enable": "false",
"icons": "https://img.icons8.com/officel/50/documents.png",
"index": "web.team.renzhengshouquan.document",
"name": "在线文档",
"order": "93",
"time": "2024-11-25 18:19:23.561"
}
},
"1d15ae175ffe375630da1466417d2d5d": {
"meta": {
"enable": "false",
"icons": "https://img.icons8.com/officel/80/agreement.png",
"index": "web.team.renzhengshouquan.contract",
"name": "在线合同",
"order": "94",
"time": "2024-11-25 18:11:44.121"
}
},
"1d7c44014bc23b3db4551534359c95c4": {
"meta": {
"icons": "https://img.icons8.com/officel/80/video-conference.png",
"index": "web.team.renzhengshouquan.external.tencentmeeting.tencentmeeting",
"name": "腾讯会议",
"order": "10",
"order": "12",
"role": "leader",
"time": "2024-11-19 11:33:13.771"
}
@ -69,6 +99,15 @@
"time": "2024-08-29 12:42:12.275"
}
},
"692895230d60d29c2a56531f81927efb": {
"meta": {
"icons": "https://img.icons8.com/officel/80/cloud.png",
"index": "web.team.renzhengshouquan.external.tencentcloud.tencentcloud",
"name": "腾讯云",
"order": "15",
"time": "2024-11-25 20:45:31.111"
}
},
"732373815fa26c85ad04dd57ca57db39": {
"meta": {
"icons": "https://img.icons8.com/officel/80/edit-property.png",
@ -95,7 +134,7 @@
"icons": "https://img.icons8.com/officel/80/online-payment-with-a-credit-card.png",
"index": "web.team.renzhengshouquan.paymentlist",
"name": "在线支付",
"order": "92",
"order": "91",
"time": "2024-11-22 17:42:50.659"
}
},
@ -108,6 +147,15 @@
"time": "2024-09-22 20:30:11.224"
}
},
"8780d5d1b9b5608cef9098e9393c0cb4": {
"meta": {
"icons": "https://img.icons8.com/officel/80/video-conference.png",
"index": "web.team.renzhengshouquan.external.tencentcloud.realname.realname",
"name": "实名验证",
"order": "16",
"time": "2024-11-26 14:42:04.095"
}
},
"89cf6f6cc69c13b7d541a0d61eae66e1": {
"meta": {
"icons": "https://img.icons8.com/officel/80/identification-documents--v2.png",
@ -142,6 +190,15 @@
"time": "2024-09-07 08:23:04.033"
}
},
"bdf8a62a495ddba04e61bc457ed5fc25": {
"meta": {
"icons": "https://img.icons8.com/officel/80/sms.png",
"index": "web.team.renzhengshouquan.external.tencentcloud.sms.sms",
"name": "发送短信",
"order": "17",
"time": "2024-11-26 20:23:46.898"
}
},
"bfecb55b11fe68186270fe1b4b8de8cf": {
"meta": {
"icons": "https://img.icons8.com/officel/80/person-at-home.png",
@ -158,7 +215,7 @@
"icons": "https://img.icons8.com/officel/80/video-conference.png",
"index": "web.team.renzhengshouquan.meeting",
"name": "在线会议",
"order": "91",
"order": "92",
"role": "leader,worker",
"time": "2024-11-19 15:35:47.185"
}

View File

@ -8,6 +8,15 @@
"time": "2024-08-11 09:30:00.532"
}
},
"182e191dda10c617c12a7c9147737dc6": {
"meta": {
"icons": "https://img.icons8.com/officel/80/agreement.png",
"index": "web.team.yuehaoxitong.contract",
"name": "在线合同",
"order": "94",
"time": "2024-11-25 18:11:44.106"
}
},
"1931ecf1d36391b72df54d374a91c8ed": {
"meta": {
"icons": "https://img.icons8.com/officel/80/meeting-room.png",
@ -124,6 +133,15 @@
"time": "2024-08-20 11:07:54.887"
}
},
"a3d526b8fc09121a7186775cca6d9026": {
"meta": {
"icons": "https://img.icons8.com/officel/50/ios-photos.png",
"index": "web.team.yuehaoxitong.photo",
"name": "在线相册",
"order": "95",
"time": "2024-11-25 18:11:44.112"
}
},
"a56cb18131ff45616849e4555e29d35d": {
"meta": {
"icons": "https://img.icons8.com/officel/80/edit-property.png",
@ -194,6 +212,15 @@
"time": "2024-08-12 08:56:10.816"
}
},
"cb5d53223069ec8d9914ec30ca84ec4a": {
"meta": {
"icons": "https://img.icons8.com/officel/50/documents.png",
"index": "web.team.yuehaoxitong.document",
"name": "在线文档",
"order": "93",
"time": "2024-11-25 18:19:23.441"
}
},
"d1e03d214890c9a4b9557d3f6a36c7e9": {
"meta": {
"icons": "https://img.icons8.com/officel/80/activity-grid.png",