2023-06-24 20:39:55 +08:00
|
|
|
|
// SiYuan - Refactor your thinking
|
2022-05-26 15:18:53 +08:00
|
|
|
|
// Copyright (c) 2020-present, b3log.org
|
|
|
|
|
//
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
// (at your option) any later version.
|
|
|
|
|
//
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU Affero General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
|
|
package mobile
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2025-03-19 17:54:37 +08:00
|
|
|
|
"net/http"
|
2022-05-26 15:18:53 +08:00
|
|
|
|
"os"
|
|
|
|
|
"path/filepath"
|
2025-03-19 17:54:37 +08:00
|
|
|
|
"strconv"
|
2022-05-26 15:18:53 +08:00
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
2025-03-19 17:54:37 +08:00
|
|
|
|
"github.com/88250/gulu"
|
2025-09-03 17:37:27 +08:00
|
|
|
|
"github.com/88250/lute/ast"
|
2024-01-21 21:18:33 +08:00
|
|
|
|
"github.com/siyuan-note/filelock"
|
2025-03-19 17:54:37 +08:00
|
|
|
|
"github.com/siyuan-note/httpclient"
|
2024-03-22 10:33:24 +08:00
|
|
|
|
"github.com/siyuan-note/logging"
|
2023-02-10 22:44:20 +08:00
|
|
|
|
"github.com/siyuan-note/siyuan/kernel/cache"
|
|
|
|
|
"github.com/siyuan-note/siyuan/kernel/job"
|
2022-05-26 15:18:53 +08:00
|
|
|
|
"github.com/siyuan-note/siyuan/kernel/model"
|
|
|
|
|
"github.com/siyuan-note/siyuan/kernel/server"
|
|
|
|
|
"github.com/siyuan-note/siyuan/kernel/sql"
|
|
|
|
|
"github.com/siyuan-note/siyuan/kernel/util"
|
|
|
|
|
_ "golang.org/x/mobile/bind"
|
|
|
|
|
)
|
|
|
|
|
|
2025-03-19 17:54:37 +08:00
|
|
|
|
// VerifyAppStoreTransaction 用于验证苹果 App Store 交易。
|
|
|
|
|
//
|
|
|
|
|
// accountToken UUID:
|
|
|
|
|
//
|
|
|
|
|
// 6ba7b810-9dad-11d1-0001-377616491562
|
|
|
|
|
// 6ba7b810-9dad-11d1-{Cloud Region}00{User ID},中间的 00 为保留位
|
|
|
|
|
//
|
|
|
|
|
// 返回码:
|
|
|
|
|
//
|
|
|
|
|
// 0:验证通过
|
|
|
|
|
// -1:云端区域无效
|
|
|
|
|
// -2:服务器通讯失败,需要重试
|
|
|
|
|
// -3:非 iOS 设备
|
|
|
|
|
// -4:账号未登录
|
|
|
|
|
// -5:账号状态异常
|
|
|
|
|
// -6:参数错误
|
|
|
|
|
// -7:校验 accountToken 失败
|
|
|
|
|
// -8:校验 transaction 失败
|
2025-03-19 22:17:54 +08:00
|
|
|
|
// -9:未知的商品
|
2025-03-19 18:50:53 +08:00
|
|
|
|
func VerifyAppStoreTransaction(accountToken, transactionID string) (retCode int) {
|
2025-03-19 17:54:37 +08:00
|
|
|
|
retCode = -2
|
2025-03-19 18:50:53 +08:00
|
|
|
|
retMsg := "unknown error"
|
2025-03-19 17:54:37 +08:00
|
|
|
|
|
2025-03-19 18:01:14 +08:00
|
|
|
|
accountToken = strings.TrimSpace(accountToken)
|
|
|
|
|
transactionID = strings.TrimSpace(transactionID)
|
|
|
|
|
if "" == accountToken || "" == transactionID {
|
|
|
|
|
retCode = -6
|
|
|
|
|
retMsg = "invalid parameters"
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if 36 != len(accountToken) {
|
|
|
|
|
retCode = -6
|
|
|
|
|
retMsg = fmt.Sprintf("invalid accountToken [%s]", accountToken)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-19 17:54:37 +08:00
|
|
|
|
if util.ContainerIOS != util.Container {
|
|
|
|
|
retCode = -3
|
|
|
|
|
retMsg = fmt.Sprintf("invalid container [%s]", util.Container)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-19 18:01:14 +08:00
|
|
|
|
user := model.Conf.GetUser()
|
|
|
|
|
if nil == user || "" == user.UserToken {
|
|
|
|
|
retCode = -4
|
|
|
|
|
retMsg = "account not logged in"
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-19 17:54:37 +08:00
|
|
|
|
cloudRegionArg := accountToken[19:20]
|
|
|
|
|
if "0" != cloudRegionArg && "1" != cloudRegionArg {
|
|
|
|
|
retCode = -1
|
|
|
|
|
retMsg = fmt.Sprintf("invalid cloud region [%s]", cloudRegionArg)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cloudRegion, _ := strconv.Atoi(cloudRegionArg)
|
|
|
|
|
if util.CurrentCloudRegion != cloudRegion {
|
|
|
|
|
retCode = -1
|
|
|
|
|
retMsg = fmt.Sprintf("invalid cloud region [cloudRegionArg=%s, currentRegion=%d]", cloudRegionArg, util.CurrentCloudRegion)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
userID := strings.ReplaceAll(accountToken[22:], "-", "")
|
2025-03-19 18:01:14 +08:00
|
|
|
|
if user.UserId != userID {
|
|
|
|
|
retCode = -5
|
|
|
|
|
retMsg = fmt.Sprintf("invalid user [userID=%s, accountToken=%s]", user.UserId, accountToken)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-19 17:54:37 +08:00
|
|
|
|
verifyURL := util.GetCloudServer() + "/apis/siyuan/verifyAppStoreTransaction"
|
|
|
|
|
result := gulu.Ret.NewResult()
|
|
|
|
|
request := httpclient.NewCloudRequest30s()
|
2025-03-19 18:01:14 +08:00
|
|
|
|
resp, reqErr := request.SetSuccessResult(result).SetCookies(&http.Cookie{Name: "symphony", Value: user.UserToken}).
|
2025-03-19 17:54:37 +08:00
|
|
|
|
SetBody(map[string]string{"transactionId": transactionID, "accountToken": accountToken, "userId": userID}).Post(verifyURL)
|
|
|
|
|
if nil != reqErr {
|
|
|
|
|
retCode = -2
|
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed: %s", reqErr)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if http.StatusUnauthorized == resp.StatusCode || http.StatusForbidden == resp.StatusCode {
|
|
|
|
|
retCode = -4
|
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [sc=%d]", resp.StatusCode)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if http.StatusOK != resp.StatusCode {
|
|
|
|
|
retCode = -2
|
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [sc=%d]", resp.StatusCode)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if -1 == result.Code {
|
|
|
|
|
retCode = -5
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if -3 == result.Code {
|
|
|
|
|
retCode = -6
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if -2 == result.Code {
|
|
|
|
|
retCode = -8
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if -4 == result.Code {
|
|
|
|
|
retCode = -8
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if -5 == result.Code {
|
|
|
|
|
retCode = -7
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-03-19 22:17:54 +08:00
|
|
|
|
if -6 == result.Code {
|
|
|
|
|
retCode = -9
|
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-03-19 17:54:37 +08:00
|
|
|
|
if -64 == result.Code {
|
|
|
|
|
retCode = -2
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if 0 != result.Code {
|
|
|
|
|
retCode = -2
|
2025-03-19 21:05:18 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction failed [code=%d, msg=%s]", result.Code, result.Msg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
logging.LogErrorf(retMsg)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
retCode = 0
|
2025-03-19 21:20:11 +08:00
|
|
|
|
retMsg = fmt.Sprintf("verify app store transaction [%s] success", transactionID)
|
2025-03-19 21:19:39 +08:00
|
|
|
|
logging.LogInfof(retMsg)
|
2025-03-19 17:54:37 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-04 19:33:02 +08:00
|
|
|
|
func StartKernelFast(container, appDir, workspaceBaseDir, localIPs string) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
go server.Serve(true)
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-10 22:44:20 +08:00
|
|
|
|
func StartKernel(container, appDir, workspaceBaseDir, timezoneID, localIPs, lang, osVer string) {
|
2022-05-26 15:18:53 +08:00
|
|
|
|
SetTimezone(container, appDir, timezoneID)
|
|
|
|
|
util.Mode = "prod"
|
2023-02-10 22:44:20 +08:00
|
|
|
|
util.MobileOSVer = osVer
|
2022-05-26 15:18:53 +08:00
|
|
|
|
util.LocalIPs = strings.Split(localIPs, ",")
|
2023-01-04 19:33:02 +08:00
|
|
|
|
util.BootMobile(container, appDir, workspaceBaseDir, lang)
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
|
|
|
|
model.InitConf()
|
|
|
|
|
go server.Serve(false)
|
|
|
|
|
go func() {
|
|
|
|
|
model.InitAppearance()
|
|
|
|
|
sql.InitDatabase(false)
|
2022-08-23 10:13:51 +08:00
|
|
|
|
sql.InitHistoryDatabase(false)
|
2023-08-04 12:05:29 +08:00
|
|
|
|
sql.InitAssetContentDatabase(false)
|
2022-05-26 15:18:53 +08:00
|
|
|
|
sql.SetCaseSensitive(model.Conf.Search.CaseSensitive)
|
2023-05-10 10:30:05 +08:00
|
|
|
|
sql.SetIndexAssetPath(model.Conf.Search.IndexAssetPath)
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
2022-10-22 11:55:12 +08:00
|
|
|
|
model.BootSyncData()
|
2022-05-26 15:18:53 +08:00
|
|
|
|
model.InitBoxes()
|
2023-01-18 16:20:57 +08:00
|
|
|
|
model.LoadFlashcards()
|
2024-04-30 09:48:31 +08:00
|
|
|
|
util.LoadAssetsTexts()
|
2022-05-26 15:18:53 +08:00
|
|
|
|
|
|
|
|
|
util.SetBooted()
|
2022-12-23 22:42:54 +08:00
|
|
|
|
util.PushClearAllMsg()
|
2023-01-26 23:30:29 +08:00
|
|
|
|
|
|
|
|
|
job.StartCron()
|
2024-04-28 20:56:32 +08:00
|
|
|
|
go model.AutoGenerateFileHistory()
|
2022-07-15 09:25:02 +08:00
|
|
|
|
go cache.LoadAssets()
|
2022-05-26 15:18:53 +08:00
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Language(num int) string {
|
|
|
|
|
return model.Conf.Language(num)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ShowMsg(msg string, timeout int) {
|
|
|
|
|
util.PushMsg(msg, timeout)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IsHttpServing() bool {
|
|
|
|
|
return util.HttpServing
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-21 21:18:33 +08:00
|
|
|
|
func SetHttpServerPort(port int) {
|
|
|
|
|
filelock.AndroidServerPort = port
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-28 14:28:46 +08:00
|
|
|
|
func GetCurrentWorkspacePath() string {
|
|
|
|
|
return util.WorkspaceDir
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-22 10:33:24 +08:00
|
|
|
|
func GetAssetAbsPath(asset string) (ret string) {
|
|
|
|
|
ret, err := model.GetAssetAbsPath(asset)
|
2024-09-04 04:40:50 +03:00
|
|
|
|
if err != nil {
|
2024-03-22 10:33:24 +08:00
|
|
|
|
logging.LogErrorf("get asset [%s] abs path failed: %s", asset, err)
|
|
|
|
|
ret = asset
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-11-02 12:21:51 +08:00
|
|
|
|
func GetMimeTypeByExt(ext string) string {
|
|
|
|
|
return util.GetMimeTypeByExt(ext)
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 15:18:53 +08:00
|
|
|
|
func SetTimezone(container, appDir, timezoneID string) {
|
|
|
|
|
if "ios" == container {
|
|
|
|
|
os.Setenv("ZONEINFO", filepath.Join(appDir, "app", "zoneinfo.zip"))
|
|
|
|
|
}
|
|
|
|
|
z, err := time.LoadLocation(strings.TrimSpace(timezoneID))
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("load location failed: %s\n", err)
|
|
|
|
|
time.Local = time.FixedZone("CST", 8*3600)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
time.Local = z
|
|
|
|
|
}
|
2024-11-07 16:51:59 +08:00
|
|
|
|
|
|
|
|
|
func DisableFeature(feature string) {
|
|
|
|
|
util.DisableFeature(feature)
|
|
|
|
|
}
|
2025-03-28 12:46:55 +08:00
|
|
|
|
|
|
|
|
|
func FilepathBase(path string) string {
|
|
|
|
|
return filepath.Base(path)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func FilterUploadFileName(name string) string {
|
|
|
|
|
return util.FilterUploadFileName(name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func AssetName(name string) string {
|
2025-09-03 17:37:27 +08:00
|
|
|
|
return util.AssetName(name, ast.NewNodeID())
|
2025-03-28 12:46:55 +08:00
|
|
|
|
}
|