| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460 |
- import { cryptoFramework } from "@kit.CryptoArchitectureKit";
- import { LogUtil, PreferencesUtil, StrUtil, ToastUtil } from "@pura/harmony-utils";
- import { CommonConstants, STR_LOCK_VIDEO, VIP_FILEPATH } from "../constants/CommonConstants";
- import { http } from "@kit.NetworkKit";
- import { bundleManager } from "@kit.AbilityKit";
- import { BusinessError } from '@kit.BasicServicesKit';
- import { hilog } from "@kit.PerformanceAnalysisKit";
- import { FileUtil } from "@pura/harmony-utils";
- import { fileUri, picker } from "@kit.CoreFileKit";
- import { VipPage } from "../../pages/VipPage";
- // 用户相关接口定义
- export interface WechatUserInfo {
- openid?: string;
- nickname?: string;
- sex?: number;
- language?: string;
- city?: string;
- province?: string;
- country?: string;
- headimgurl?: string;
- privilege?: string[];
- unionid?: string;
- }
- export interface Subscription {
- plan_id: string;
- plan_name: string;
- plan_description: string;
- price: string;
- start_date: string;
- end_date: string;
- status: string;
- auto_renew: string;
- features: string[];
- }
- export interface SubscriptionInfo {
- has_active_subscription: boolean;
- subscriptions: Subscription[];
- }
- export interface responseData {
- token_info?: object;
- user_info: WechatUserInfo;
- }
- export interface WechatUserInfoData {
- token_info?: object;
- user_info: WechatUserInfo;
- system_info?: SystemInfo;
- subscription_info?: SubscriptionInfo;
- }
- export interface ApiResponse {
- code: number;
- msg: string;
- data?: WechatUserInfoData;
- }
- export interface WechatUserInfoApiResponse {
- code: number;
- msg: string;
- data: WechatUserInfoData;
- }
- export interface HuaweiUserInfo {
- openid: string;
- unionid?: string;
- nickname: string;
- headimgurl: string;
- }
- export interface SystemInfo {
- user_id: number | string;
- token: string;
- }
- export interface HuaweiUserInfoApiData {
- user_info: HuaweiUserInfo;
- system_info?: SystemInfo;
- subscription_info?: SubscriptionInfo;
- }
- export interface HuaweiUserInfoApiResponse {
- code: number;
- msg: string;
- data: HuaweiUserInfoApiData;
- }
- export interface VipFeature {
- icon: Resource;
- title: string;
- description: string;
- isVipOnly: boolean;
- hasCome: boolean;
- }
- export interface VipPlanApi {
- id: string;
- name: string;
- description: string;
- price: string;
- original_price:string;
- discount_percent:number;
- duration: string;
- features: string;
- sort_order: string;
- status: string;
- created_at: string;
- updated_at: string;
- }
- export interface VipPlanListApiData {
- plans: VipPlanApi[];
- show_wx_login?: boolean;
- }
- export interface VipPlanListApiResponse {
- code: number;
- msg: string;
- data: VipPlanListApiData;
- }
- export interface WeChatPrepayId {
- prepay_id: string;
- }
- export interface UserInfoApiData {
- user_info: WechatUserInfo;
- system_info: SystemInfo;
- subscription_info: SubscriptionInfo;
- }
- export interface UserInfoApiResponse {
- code: number;
- msg: string;
- data: UserInfoApiData;
- }
- export default class UserUtil {
- // 微信是否安装
- static async isHasWX(): Promise<boolean> {
- try {
- let link = 'weixin://';
- let data = bundleManager.canOpenLink(link);
- if (data) {
- return true;
- } else {
- ToastUtil.showToast('微信未安装');
- return false;
- }
- } catch (err) {
- let message = (err as BusinessError).message;
- console.error('canOpenLink failed: %{public}s', message);
- return false;
- }
- }
- // 创建微信订单
- static async createWeChatOrder(app_id: string, mch_id: string, description: string, amount: number, out_trade_no_pre: string, uid: number, plan_id: string): Promise<string> {
- let requestUrl = CommonConstants.WX_PAY_API
- + '?app_id=' + encodeURIComponent(app_id.trim())
- + '&mch_id=' + encodeURIComponent(mch_id.trim())
- + '&description=' + encodeURIComponent(description.trim())
- + '&amount=' + encodeURIComponent(amount)
- + '&uid=' + encodeURIComponent(uid)
- + '&plan_id=' + encodeURIComponent(plan_id)
- + '&out_trade_no_pre=' + encodeURIComponent(out_trade_no_pre);
- const httpRequest: http.HttpRequest = http.createHttp();
- const options: http.HttpRequestOptions = {
- method: http.RequestMethod.GET,
- readTimeout: 6000,
- connectTimeout: 6000,
- };
- try {
- const response: http.HttpResponse = await httpRequest.request(requestUrl, options);
- if (response.responseCode === 200) {
- let responseData: WeChatPrepayId;
- if (typeof response.result === 'string') {
- responseData = JSON.parse(response.result) as WeChatPrepayId;
- } else if (response.result instanceof Object) {
- responseData = response.result as WeChatPrepayId;
- } else {
- throw new Error('Unexpected response format');
- }
- const prepayId: string = responseData.prepay_id;
- return prepayId;
- } else {
- ToastUtil.showToast('微信下单失败');
- return '';
- }
- } catch (error) {
- ToastUtil.showToast('微信下单异常');
- return '';
- }
- }
- // 构造签名串
- static constructSignatureString(appId: string, timestamp: string, nonceStr: string, prepayId: string): string {
- return `${appId}\n${timestamp}\n${nonceStr}\n${prepayId}\n`;
- }
- // 微信支付签名
- static async rsaSign2048( message: string): Promise<Uint8Array> {
- try {
- let keyGen = cryptoFramework.createAsyKeyGenerator("RSA2048")
- let key = keyGen.convertPemKeySync(null, CommonConstants.WX_PAY_RSA_PRIVATE_KEY)
- let sign = cryptoFramework.createSign('RSA2048|PKCS1|SHA256');
- let msgBlob: cryptoFramework.DataBlob = {data: StrUtil.strToUint8Array(message)}
- sign.initSync(key.priKey)
- let signature = await sign.sign(msgBlob)
- return signature.data
- } catch (error) {
- console.error(error, `onecold error code: ${error.code}`)
- return new Uint8Array()
- }
- }
- // 通过code换取用户信息
- static async getUserInfoByCode(code: string): Promise<UserInfoApiData |WechatUserInfoData| null> {
- try {
- const url = `https://pay.ss5.xyz/wechat/user_info?code=${encodeURIComponent(code)}`;
- const httpRequest = http.createHttp();
- const options: http.HttpRequestOptions = {
- method: http.RequestMethod.GET,
- readTimeout: 3000,
- connectTimeout: 3000,
- };
- const response: http.HttpResponse = await httpRequest.request(url, options);
- if (response.responseCode === 200) {
- let res = response.result as string;
- LogUtil.debug("getUserInfoByCode res =" + res)
- let json: WechatUserInfoApiResponse = JSON.parse(res) as WechatUserInfoApiResponse;
- if (json.code === 0 && json.data && json.data.user_info) {
- const userId = json.data.system_info?.user_id ? Number(json.data.system_info?.user_id) : 0;
- hilog.info(0x0000, 'UserUtil', `getUserInfoByCode: userId set to ${userId}`);
- const userName = json.data.user_info.nickname || '微信用户';
- const userAvatarUrl = json.data.user_info.headimgurl && json.data.user_info.headimgurl.length > 0 ? json.data.user_info.headimgurl : '';
- // 解析订阅信息
- const subInfo = json.data.subscription_info;
- let hasActiveSubscription = false;
- let subscriptionName = '';
- let subscriptionEndDate = '';
- if (subInfo && subInfo.has_active_subscription && subInfo.subscriptions && subInfo.subscriptions.length > 0) {
- hasActiveSubscription = true;
- subscriptionName = subInfo.subscriptions[0].plan_name;
- subscriptionEndDate = subInfo.subscriptions[0].end_date;
- }
- // 保存登录状态和用户信息
- PreferencesUtil.putSync('isLogin', true);
- PreferencesUtil.putSync('userId', userId);
- PreferencesUtil.putSync('userName', userName);
- PreferencesUtil.putSync('userAvatarUrl', userAvatarUrl);
- PreferencesUtil.putSync('subscriptionName', subscriptionName);
- PreferencesUtil.putSync('subscriptionEndDate', subscriptionEndDate);
- PreferencesUtil.putSync('hasActiveSubscription', hasActiveSubscription);
- PreferencesUtil.putSync('userToken', json.data.system_info?.token || '');
- ToastUtil.showToast('微信登录成功');
- return json.data;
- } else {
- // ToastUtil.showToast('用户信息解析失败');
- return null;
- }
- } else {
- // ToastUtil.showToast('获取用户信息失败');
- return null;
- }
- } catch (e) {
- // ToastUtil.showToast('登录失败' + (e && e.message ? (': ' + e.message) : ''));
- return null;
- }
- }
- // 通过华为账号信息换取用户信息和会员状态
- static async getUserInfoByHuawei(openID: string, unionID: string, nickname: string, avatarUri: string): Promise<HuaweiUserInfoApiData | null> {
- try {
- const url = `https://pay.ss5.xyz/user/huawei?openID=${encodeURIComponent(openID)}&unionID=${encodeURIComponent(unionID)}&nickname=${encodeURIComponent(nickname)}&avatarUri=${encodeURIComponent(avatarUri)}`;
- const httpRequest = http.createHttp();
- const options: http.HttpRequestOptions = {
- method: http.RequestMethod.GET,
- readTimeout: 3000,
- connectTimeout: 3000,
- };
- const response: http.HttpResponse = await httpRequest.request(url, options);
- if (response.responseCode === 200) {
- let res = response.result as string;
- let json: HuaweiUserInfoApiResponse = JSON.parse(res) as HuaweiUserInfoApiResponse;
- if (json.code === 0 && json.data && json.data.user_info) {
- const userId = json.data.system_info?.user_id ? Number(json.data.system_info?.user_id) : 0;
- const userName = json.data.user_info.nickname || '华为用户';
- const userAvatarUrl = json.data.user_info.headimgurl || '';
- // 处理会员信息
- const subInfo = json.data.subscription_info;
- let hasActiveSubscription = false;
- let subscriptionName = '';
- let subscriptionEndDate = '';
- if (subInfo && subInfo.has_active_subscription && subInfo.subscriptions && subInfo.subscriptions.length > 0) {
- hasActiveSubscription = true;
- subscriptionName = subInfo.subscriptions[0].plan_name;
- subscriptionEndDate = subInfo.subscriptions[0].end_date;
- }
- // 保存登录状态
- PreferencesUtil.putSync('isLogin', true);
- PreferencesUtil.putSync('userId', userId);
- PreferencesUtil.putSync('userName', userName);
- PreferencesUtil.putSync('userAvatarUrl', userAvatarUrl);
- PreferencesUtil.putSync('subscriptionName', subscriptionName);
- PreferencesUtil.putSync('subscriptionEndDate', subscriptionEndDate);
- PreferencesUtil.putSync('hasActiveSubscription', hasActiveSubscription);
- PreferencesUtil.putSync('userToken', json.data.system_info?.token || '');
- ToastUtil.showToast('华为登录成功');
- return json.data;
- } else {
- // ToastUtil.showToast('用户信息解析失败');
- return null;
- }
- } else {
- // ToastUtil.showToast('获取用户信息失败');
- return null;
- }
- } catch (e) {
- // ToastUtil.showToast('登录失败' + (e && e.message ? (': ' + e.message) : ''));
- return null;
- }
- }
- // 刷新用户信息
- static async fetchUserInfo(): Promise<UserInfoApiData | null> {
- try {
- let token=PreferencesUtil.getStringSync('userToken','');
- const url = `https://pay.ss5.xyz/user/info?token=${encodeURIComponent(token)}`;
- const httpRequest = http.createHttp();
- const options: http.HttpRequestOptions = {
- method: http.RequestMethod.GET,
- readTimeout: 3000,
- connectTimeout: 3000,
- };
- const response: http.HttpResponse = await httpRequest.request(url, options);
- if (response.responseCode === 200) {
- let res = response.result as string;
- let json: UserInfoApiResponse = JSON.parse(res) as UserInfoApiResponse;
- if (json.code === 0 && json.data) {
- const userId = json.data.system_info?.user_id ? Number(json.data.system_info?.user_id) : 0;
- const userName = json.data.user_info.nickname || '匿名用户';
- const userAvatarUrl = json.data.user_info.headimgurl || '';
- // 处理会员信息
- const subInfo = json.data.subscription_info;
- let hasActiveSubscription = false;
- let subscriptionName = '';
- let subscriptionEndDate = '';
- let plan_id = '';
- if (subInfo && subInfo.has_active_subscription && subInfo.subscriptions && subInfo.subscriptions.length > 0) {
- hasActiveSubscription = true;
- subscriptionName = subInfo.subscriptions[0].plan_name;
- subscriptionEndDate = subInfo.subscriptions[0].end_date;
- plan_id = subInfo.subscriptions[0].plan_id
- }
- // 保存登录状态
- PreferencesUtil.putSync('isLogin', true);
- PreferencesUtil.putSync('userId', userId);
- PreferencesUtil.putSync('userName', userName);
- PreferencesUtil.putSync('userAvatarUrl', userAvatarUrl);
- PreferencesUtil.putSync('subscriptionName', subscriptionName);
- PreferencesUtil.putSync('subscriptionEndDate', subscriptionEndDate);
- PreferencesUtil.putSync('hasActiveSubscription', hasActiveSubscription);
- PreferencesUtil.putSync('userToken', json.data.system_info?.token || '');
- if(plan_id=='1'){
- PreferencesUtil.putSync('isForever', true);
- }else{
- PreferencesUtil.putSync('isForever', false);
- }
- return json.data;
- } else {
- return null;
- }
- } else {
- return null;
- }
- } catch (e) {
- return null;
- }
- }
- /**
- * 退出登录
- * 清除用户登录状态和相关信息
- */
- static logout(): boolean {
- // 清除登录状态
- PreferencesUtil.deleteSync('isLogin');
- PreferencesUtil.deleteSync('userId');
- PreferencesUtil.deleteSync('userName');
- PreferencesUtil.deleteSync('userAvatarUrl');
- PreferencesUtil.deleteSync('subscriptionName');
- PreferencesUtil.deleteSync('subscriptionEndDate');
- PreferencesUtil.deleteSync('hasActiveSubscription');
- PreferencesUtil.deleteSync('userToken');
- PreferencesUtil.deleteSync('isForever');
- // 显示退出登录提示
- return true;
- }
- /**
- * 本地会员同步到服务器
- * @param expireDate
- * @returns
- */
- static async syncLocalNobleToServer(expireDate: string): Promise<boolean> {
- try {
- const token = PreferencesUtil.getStringSync('userToken', '');
- if (!token || !expireDate) {
- ToastUtil.showToast('缺少token或到期时间');
- return false;
- }
- const url = `https://pay.ss5.xyz/user/sync_noble?token=${encodeURIComponent(token)}&expireDate=${encodeURIComponent(expireDate)}`;
- const httpRequest = http.createHttp();
- const options: http.HttpRequestOptions = {
- method: http.RequestMethod.GET,
- readTimeout: 3000,
- connectTimeout: 3000,
- };
- const response: http.HttpResponse = await httpRequest.request(url, options);
- if (response.responseCode === 200) {
- let res = response.result as string;
- let json = JSON.parse(res) as ApiResponse;
- if (json.code === 0) {
- ToastUtil.showToast('会员同步成功');
- PreferencesUtil.putSync('isNoble', false);
- PreferencesUtil.putSync('nobleExpireDate', '');
- // 删除本地会员文件
- try {
- const documentViewPicker = new picker.DocumentViewPicker()
- let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
- let download_path = new fileUri.FileUri(documentSaveResult[0]).path + '/'
- let filePath = download_path + STR_LOCK_VIDEO+ '/' + VIP_FILEPATH
- if (FileUtil.accessSync(filePath)) {
- FileUtil.unlink(filePath);
- }
- } catch (e) {
- console.log("Heanup exception="+e)
- // 可忽略或打印日志
- }
- return true;
- } else {
- ToastUtil.showToast('会员同步失败:' + (json.msg || '未知错误'));
- return false;
- }
- } else {
- ToastUtil.showToast('会员同步接口请求失败');
- return false;
- }
- } catch (e) {
- ToastUtil.showToast('会员同步异常' + (e && e.message ? (': ' + e.message) : ''));
- return false;
- }
- }
- }
|