| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129 |
- import { promptAction, router, window } from '@kit.ArkUI';
- import TitleBar from '../view/TitleBar';
- import { webview } from '@kit.ArkWeb';
- import { CommonConstants, STR_LOCK_VIDEO, VIP_FILEPATH } from '../common/constants/CommonConstants';
- import { AES,
- AppUtil,
- Base64Util,
- CryptoHelper, DateUtil,
- DeviceUtil,
- DisplayUtil,
- FileUtil, LogUtil, PreferencesUtil,
- RandomUtil,
- StrUtil,
- ToastUtil } from '@pura/harmony-utils';
- import { BusinessError } from '@kit.BasicServicesKit';
- import { Pay } from '@cashier_alipay/cashiersdk';
- import { OrderInfoUtil } from '../alipay/OrderInfoUtil';
- import { Utility } from '../common/util/Utility';
- import fileIo, { ReadTextOptions } from '@ohos.file.fs';
- import { fileUri, picker } from '@kit.CoreFileKit';
- import { VipData } from '../viewmodel/VipData';
- import { DialogHelper } from '@pura/harmony-dialog';
- import { common, ConfigurationConstant } from '@kit.AbilityKit';
- import * as wxOpenSdk from '@tencent/wechat_open_sdk';
- import { OnWXResp, WXApi, WXEventHandler } from '../common/util/WXApiWrap';
- import { ErrCode } from '@tencent/wechat_open_sdk';
- import { hilog } from '@kit.PerformanceAnalysisKit';
- import { http } from '@kit.NetworkKit';
- import { bundleManager } from '@kit.AbilityKit';
- import { cryptoFramework } from '@kit.CryptoArchitectureKit';
- import { JSON } from '@kit.ArkTS';
- import { BreakpointTypeEnum } from '../common/util/BreakpointSystem';
- import { resourceManager } from '@kit.LocalizationKit';
- import { pinyin4js } from '@ohos/pinyin4js';
- const context = getContext(this) as common.UIAbilityContext;
- @Preview
- @Component
- @Entry
- export struct VipPage{
- @State bundleName:string =''
- // @State titleBarModel: TitleBar.Model = new TitleBar.Model()
- // .setTitleTextStyle(FontStyle.Normal)
- // .setTitleBarStyle(TitleBar.BarStyle.TRANSPARENT)
- // .setLeftIcon($r('app.media.left_back_white'))
- // .setTitleName('赞助中心')
- // .setTitleFontColor(Color.White)
- // .setTitleBarBackground($r('app.color.title_bar_bg'))
- // .setLeftTitleBackground($r('app.color.title_bar_bg'))
- // .setTitleBarBottomLineColor($r('app.color.title_bar_bg'))
- // .setOnLeftClickListener(() => {
- // router.back()
- //
- // })
- @State isShowDutySheetView: boolean = false;
- @State isAgree: boolean = false;
- static readonly IS_AGREE: string = 'isAgree';
- static readonly FOREVER_DATE: string = 'forever';
- @State params: object = router.getParams()
- @State payPrice:number = 29.88 //9是一个 19是一年 19是永久赞助
- static readonly TYPE_MONTH: number = 9.8;
- static readonly TYPE_YEAR: number = 19
- static readonly TYPE_FOREVER: number = 29.88
- // static readonly VIP_FILEPATH: string = '.vv'
- @State appName:string = ''
- @State expireDate:string = ''
- @State filePath:string = ''
- @State payType:number = 0
- private wxApi = WXApi
- private wxEventHandler = WXEventHandler
- @State resultText: string = ''
- /** 当前断点类型(如大屏/小屏) */
- @StorageProp('currentBreakpoint') currentBreakpoint: string = BreakpointTypeEnum.MD;
- @StorageProp('topRectHeight') topRectHeight: number = px2vp(AppUtil.getStatusBarHeight());
- static readonly WX_NOTIFY_URL: string = 'https://webhook.ss5.xyz/wechat_notify.php'
- @StorageProp('themeColor') themeColor: string = CommonConstants.DEFAULT_THEME_COLOR;
- @State isDarkMode: boolean = false
- @StorageProp('currentColorMode') @Watch('onColorModeChange') currentMode: number =
- ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT;
- onColorModeChange() {
- this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
- }
- // 组件生命周期
- async aboutToAppear() {
- this.topRectHeight = px2vp(AppUtil.getStatusBarHeight());
- this.isAgree = PreferencesUtil.getBooleanSync(VipPage.IS_AGREE,false)
- Utility.getAppName(getContext(this)).then((appName:string)=>{
- this.appName = appName
- })
- let themeColor = PreferencesUtil.getStringSync('THEME_COLOR', CommonConstants.DEFAULT_THEME_COLOR);
- AppStorage.setOrCreate('themeColor', themeColor);
- this.themeColor = themeColor;
- this.isDarkMode = this.currentMode === ConfigurationConstant.ColorMode.COLOR_MODE_DARK
- const documentViewPicker = new picker.DocumentViewPicker()
- let documentSaveResult = await documentViewPicker.save({ pickerMode: picker.DocumentPickerMode.DOWNLOAD })
- let download_path = new fileUri.FileUri(documentSaveResult[0]).path + '/'
- this.filePath = download_path + STR_LOCK_VIDEO+ '/' + VIP_FILEPATH
- this.expireDate = this.readDataFromFile(this.filePath)
- this.bundleName = await AppUtil.getBundleName()
- this.doCheckHao()
- this.wxEventHandler.registerOnWXRespCallback(this.onWXResp)
- }
- private onWXResp: OnWXResp = (resp) => {
- if (resp.errCode === ErrCode.ERR_OK) {
- ToastUtil.showToast('支付成功!')
- let expireDate = this.getExpireDate(this.payPrice)
- this.saveDataToFile(expireDate,this.filePath,false )
- }else {
- ToastUtil.showToast('支付失败!')
- }
- // this.resultText = JSON.stringify(resp ?? {}, null, 2)
- }
- // 组件消失生命周期
- aboutToDisappear() {
- console.info(' aboutToDisappear');
- this.wxEventHandler.unregisterOnWXRespCallback(this.onWXResp)
- }
- build() {
- Column() {
- // 顶部安全区和自定义标题栏
- Column() {
- // 顶部安全区
- Blank()
- .height(this.topRectHeight)
- .backgroundColor(this.isDarkMode?$r('app.color.title_bar_bg'):this.themeColor)
- .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
- // 自定义标题栏(Stack实现绝对居中)
- Stack() {
- // 居中标题
- Text('赞助中心')
- .fontSize(18)
- .fontColor(Color.White)
- .align(Alignment.Center)
- // 左右按钮
- Row() {
- Image($r('app.media.left_back_white'))
- .width(24)
- .height(24)
- .margin({ left: 12, right: 8 })
- .onClick(() => {
- router.back();
- })
- Blank().flexGrow(1)
- Blank().width(32)
- }
- .height(48)
- .width('100%')
- .alignItems(VerticalAlign.Center)
- }
- .height(48)
- .width('100%')
- .backgroundColor(this.isDarkMode?$r('app.color.title_bar_bg'):this.themeColor)
- }
- Scroll() {
- Column() {
- Column() {
- Column() {
- Image($r('app.media.icon'))
- .visibility(Visibility.Visible)
- .borderRadius('100%')
- .clip(true)
- .width(38)
- .height(38)
- Row(){
- Text(Utility.isNoble()?'欢迎尊敬的赞助用户 ':'欢迎尊敬的用户 ')
- .margin({top:15,bottom:8})
- .fontSize(15)
- .maxLines(1)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Text(this.expireDate===VipPage.FOREVER_DATE ?'永久赞助':this.expireDate)
- .margin({top:15,bottom:8})
- .fontSize(15)
- .maxLines(1)
- .fontColor(Color.Gray)
- .fontWeight(480)
- }
- }
- .justifyContent(FlexAlign.Center)
- .width('100%')
- .height(72)
- .borderRadius(30)
- }
- .height(72)
- .margin({
- left: 15,
- right: 15,
- top: 15,
- bottom: 0
- })
- Column() {
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Image($r('app.media.vip'))
- .width(18)
- .height(18)
- .fillColor(this.themeColor)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 22 })
- Text(`赞助特权\n1、跳过片头片尾\n2、纯净无广告\n3、更多功能开发中`)
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- }
- .width('100%')
- .height(98)
- .onClick(() => {
- this.isShowDutySheetView = !this.isShowDutySheetView;
- })
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Image($r('app.media.icon_person2'))
- .width(16)
- .height(16)
- .fillColor(this.themeColor)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 22 })
- Text(`客服邮箱:${CommonConstants.CONTACT_MAIL}`)
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .maxLines(2)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- }
- .width('100%')
- .height(45)
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .onClick(()=>{
- ToastUtil.showToast('复制邮件地址成功!')
- Utility.copyText(CommonConstants.CONTACT_MAIL)
- })
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Image($r('app.media.selected'))
- .width(16)
- .height(16)
- .alignSelf(ItemAlign.Center)
- .fillColor(this.themeColor)
- .margin({ left: 22 })
- Text('选择赞助时间')
- .margin({ left: 10, right: 20 })
- .fontSize(12)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- }
- .width('100%')
- .height(38)
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- .visibility(Utility.isNoble()?Visibility.None:Visibility.Visible)
- Row() {
- Text()
- .width(10)
- .height(10)
- .borderRadius('100%')
- .clip(true)
- .backgroundColor(this.themeColor)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 25 })
- Text('一个月赞助:'+VipPage.TYPE_MONTH+'元')
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- Checkbox()
- .select(this.payPrice===VipPage.TYPE_MONTH?true:false)
- .selectedColor(this.themeColor)
- .shape(CheckBoxShape.CIRCLE)
- .onChange((checked: boolean)=>{
- if(checked){
- this.payPrice = VipPage.TYPE_MONTH
- }
- })
- .margin({ left: 20, top: 8, bottom: 8,right:20 })
- .width(22)
- .height(22)
- }
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .visibility(Utility.isNoble()?Visibility.None:Visibility.Visible)
- .onClick(() => {
- this.payPrice = VipPage.TYPE_MONTH
- })
- .width('100%')
- .height(50)
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Text()
- .width(10)
- .height(10)
- .borderRadius('100%')
- .clip(true)
- .backgroundColor(this.themeColor)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 25 })
- Text('永久赞助:'+VipPage.TYPE_FOREVER+'元 ')
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- .visibility(Utility.isNoble()?Visibility.None:Visibility.Visible)
- Text('您还可以继续赞助支持我们:'+VipPage.TYPE_FOREVER+'元 ')
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- .visibility(Utility.isNoble()?Visibility.Visible:Visibility.None)
- Text('(原价¥49.8)')
- .fontSize(14)
- .fontColor(Color.Gray)
- .decoration({ type: TextDecorationType.LineThrough })
- .visibility(Utility.isNoble()?Visibility.None:Visibility.Visible)
- Blank()
- Checkbox()
- .select(this.payPrice===VipPage.TYPE_FOREVER?true:false)
- .selectedColor(this.themeColor)
- .onChange((checked: boolean)=>{
- if(checked){
- this.payPrice = VipPage.TYPE_FOREVER
- }
- })
- .shape(CheckBoxShape.CIRCLE)
- .margin({ left: 20, top: 8, bottom: 8,right:20 })
- .width(22)
- .height(22)
- }
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .width('100%')
- .height(50)
- .onClick(() => {
- this.payPrice = VipPage.TYPE_FOREVER
- })
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Image($r('app.media.selected'))
- .width(16)
- .height(16)
- .fillColor(this.themeColor)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 22 })
- Text('选择支付方式')
- .margin({ left: 10, right: 20 })
- .fontSize(12)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- }
- .width('100%')
- .height(38)
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Image($r('app.media.wx_logo'))
- .width(22)
- .height(22)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 25 })
- Text('微信支付')
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- Checkbox()
- .select(this.payType===0?true:false)
- .selectedColor(this.themeColor)
- .onChange((checked: boolean)=>{
- if(checked){
- this.payType =0
- }else{
- this.payType =1
- }
- })
- .shape(CheckBoxShape.CIRCLE)
- .margin({ left: 20, top: 8, bottom: 8,right:20 })
- .width(22)
- .height(22)
- }
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .onClick(() => {
- this.payType =0
- })
- .width('100%')
- .height(50)
- // .visibility(Visibility.None)
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- // .visibility(Visibility.None)
- Row() {
- Image($r('app.media.alipay'))
- .width(22)
- .height(22)
- .alignSelf(ItemAlign.Center)
- .margin({ left: 25 })
- Text('支付宝')
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- Blank()
- Checkbox()
- .select(this.payType===1?true:false)
- .selectedColor(this.themeColor)
- .onChange((checked: boolean)=>{
- if(checked){
- this.payType =1
- }else{
- this.payType =0
- }
- })
- .shape(CheckBoxShape.CIRCLE)
- .margin({ left: 20, top: 8, bottom: 8,right:20 })
- .width(22)
- .height(22)
- }
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .onClick(() => {
- this.payType =1
- })
- .width('100%')
- .height(50)
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- Row() {
- Checkbox()
- .select(this.isAgree)
- .selectedColor(this.themeColor)
- .shape(CheckBoxShape.CIRCLE)
- .onChange((checked: boolean)=>{
- this.isAgree = checked
- })
- .margin({ left: 20, top: 8, bottom: 8 })
- .width(22)
- .height(22)
- Text('请同意用户协议')
- .margin({ left: 10, right: 20 })
- .fontSize(15)
- .fontColor(Color.Gray)
- .fontWeight(480)
- .id('text_update')
- Blank()
- Image($r('app.media.arrow_right'))
- .width(22)
- .height(22)
- .margin({ left: 20, right: 20 })
- .align(Alignment.Center)
- }
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .width('100%')
- .height(45)
- .bindSheet($$this.isShowDutySheetView, this.DutySheet(), {
- height:'85%',
- dragBar: true,
- showClose: true,
- preferType: this.currentBreakpoint!==BreakpointTypeEnum.SM?SheetType.CENTER:SheetType.BOTTOM,
- backgroundColor: this.themeColor,
- title: { title: $r('app.string.persion_duty') }
- })
- .onClick(() => {
- this.isShowDutySheetView = !this.isShowDutySheetView;
- })
- Line().width('100%').height(0.3).backgroundColor($r('app.color.index_tab_unselected_font_color'))
- }
- .margin({top:20,bottom:15})
- Row(){
- Button('开始赞助')
- .fontColor(Color.White)
- .layoutWeight(1)
- .height(50)
- .backgroundColor(this.themeColor)
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .margin({left:10,right:25})
- .onClick(()=>{
- this.doPay()
- })
- }
- .margin({top:15,bottom:66})
- .width(this.currentBreakpoint !== BreakpointTypeEnum.SM?'25%':'60%')
- }
- .layoutWeight(1)
- .margin({ left: this.currentBreakpoint !== BreakpointTypeEnum.SM?15:0,
- right: this.currentBreakpoint !== BreakpointTypeEnum.SM?15:0 })
- }
- .transition(TransitionEffect.move(TransitionEdge.BOTTOM)
- .animation({ duration: 380, curve: Curve.Ease,delay:50 }))
- .scrollBar(BarState.Auto)
- .height(px2vp(DisplayUtil.getHeight()-AppUtil.getStatusBarHeight()-AppUtil.getNavigationIndicatorHeight()))
- .alignSelf(ItemAlign.Start)
- .width('100%')
- }
- }
- doPay(){
- if(this.isAgree){
- if(this.payType ===0){
- this.doWxPay()
- }else{
- this.goToAliPay()
- }
- }else{
- this.isShowDutySheetView = true
- }
- }
- doWxPay = () => {
- isHasWX().then((result:boolean) =>{
- if(!result){
- ToastUtil.showToast("没有安装微信")
- return
- }
- //需要德本的服务端支持,德本的接口返回prepayId
- createWeChatOrder(CommonConstants.WX_PAY_APPID, CommonConstants.WX_PAY_MCHID,
- this.appName, this.payPrice*100,pinyin4js.getShortPinyin(this.appName))
- .then((prepayId: string) => {
- this.wechatPay(prepayId)
- // console.log('onecold Prepay ID:', prepayId);
- })
- .catch((error: Error) => {
- console.error('onecold Error:', error);
- });
- // createWeChatOrderInfo(CommonConstants.WX_PAY_APPID, CommonConstants.WX_PAY_MCHID,
- // this.appName, this.payPrice*100,getOutTradeNo())
- // .then((prepayId: string) => {
- // this.wechatPay(prepayId)
- // })
- // .catch((error: Error) => {
- // console.error('onecold Error:', error);
- // });
- })
- }
- //微信支付
- async wechatPay(prepayId: string) {
- console.log('onecold Prepay ID:', prepayId);
- let nonceStr = RandomUtil.getRandomStr(16,'abcdefghijklmnopqrstuvwxyz')
- const timestamp: number = Math.floor(Date.now() / 1000);
- const signString = constructSignatureString(CommonConstants.WX_PAY_APPID,timestamp+'',nonceStr,prepayId)
- // const signString = `${CommonConstants.WX_PAY_APPID}\n${timestamp}\n${nonceStr}\n${prepayId}\n`;
- console.log("onecold rsasignRSA ", 'signString: ' + signString);
- let signStr = await rsaSign2048(signString);
- let signStrBase64 = Base64Util.encodeToStrSync(signStr)
- console.log("onecold rsasignRSA ", 'signStr: ' + signStr);
- console.log("onecold rsasignRSA ", 'signStrBase64: ' + signStrBase64);
- let req = new wxOpenSdk.PayReq
- req.partnerId = CommonConstants.WX_PAY_MCHID //剑虾的商户号mchid对应的值。
- req.appId =CommonConstants.WX_PAY_APPID //微信开放平台审核通过的移动应用AppID 。
- req.packageValue = 'Sign=WXPay' //填写固定值Sign=WXPay
- req.prepayId = prepayId //调用微信支付下单接口返回的支付交易会话ID,该值有效期为2小时。
- req.nonceStr = nonceStr //随机字符串,不长于32位。推荐随机数生成算法。
- req.timeStamp = timestamp+'' //时间戳,标准北京时间
- req.sign = signStrBase64
- req.extData = 'extData'
- let finished = await this.wxApi.sendReq(getContext(this) as common.UIAbilityContext, req)
- hilog.info(0x0000,'onecold','send request finished: ', finished)
- }
- goToAliPay(){
- /*
- * 支付宝支付:这里只是为了方便直接向商户展示支付宝的整个支付流程;所以Demo中加签过程直接放在客户端完成;
- * 真实App里,privateKey等数据严禁放在客户端,加签过程务必要放在服务端完成;
- * 防止商户私密数据泄露,造成不必要的资金损失,及面临各种安全风险;
- *
- * orderInfo 的获取必须来自服务端;
- */
- OrderInfoUtil.getOrderInfo(this.payPrice,this.appName,0,"0").then((orderInfo) => {
- new Pay().pay(orderInfo, true).then(async (result) => {
- let message =
- `resultStatus: ${result.get('resultStatus')} memo: ${result.get('memo')} result: ${result.get('result')}`;
- // console.log(message);
- if(result.get('resultStatus') === '9000'){//9000支付成功,6001取消支付
- ToastUtil.showToast('支付成功!')
- let expireDate = this.getExpireDate(this.payPrice)
- this.saveDataToFile(expireDate,this.filePath,false )
- }else{
- ToastUtil.showToast('取消支付!')
- }
- }).catch((error: BusinessError) => {
- console.log(error.message);
- ToastUtil.showToast('支付失败!'+error.message)
- });
- });
- }
- getExpireDate(payPrice:number){
- const now = new Date();
- if(payPrice == VipPage.TYPE_MONTH){
- // 返回一个月后的时间
- now.setMonth(now.getMonth() + 1);
- }else if(payPrice === VipPage.TYPE_YEAR){
- // 返回一年后的时间
- now.setFullYear(now.getFullYear() + 1);
- }else if(payPrice === VipPage.TYPE_FOREVER){
- return VipPage.FOREVER_DATE
- }
- return DateUtil.getFormatDateStr(now,'yyyy-MM-dd HH:mm');
- }
- readDataFromFile(filePath:string){
- if(!FileUtil.accessSync(filePath)){
- return ''
- }
- let readTextOptions: ReadTextOptions = {
- offset: 0,
- length: 0,
- encoding: 'utf-8'
- };
- let stat = fileIo.statSync(filePath);
- readTextOptions.length = stat.size;
- let str = fileIo.readTextSync(filePath, readTextOptions);
- const parsedData:VipData = JSON.parse(str) as VipData;
- // LogUtil.info('onecold parsedData.expireDate = ' + parsedData.expireDate)
- let result = Base64Util.decodeSync( parsedData.expireDate)
- // LogUtil.info('onecold 解密的result = ' +StrUtil.unit8ArrayToStr(result))
- return StrUtil.unit8ArrayToStr(result);
- }
- async saveDataToFile(expireDate:string, filePath:string,isHao:boolean) {
- let newExpireDate = expireDate
- if(expireDate!==VipPage.FOREVER_DATE){
- if(FileUtil.accessSync(filePath)&&!isHao){
- let readDate = this.readDataFromFile(filePath)
- let currentDate = new Date();
- if(readDate === VipPage.FOREVER_DATE){
- newExpireDate = VipPage.FOREVER_DATE
- }else{
- //如果里面有值,直接把日期相加
- if(DateUtil.getFormatDate(readDate) > currentDate){
- let iDate = DateUtil.compareDays(currentDate,readDate)
- // LogUtil.info('onecold iDate = ' + iDate)
- let itemDate = DateUtil.getFormatDate(expireDate);
- newExpireDate =DateUtil.getFormatDateStr(Utility.addDays(itemDate,iDate),'yyyy-MM-dd HH:mm')
- // LogUtil.info('onecold newExpireDate = ' + newExpireDate)
- }
- }
- }
- }else{
- newExpireDate = VipPage.FOREVER_DATE
- }
- this.expireDate = newExpireDate
- Utility.setNoble(this.expireDate)
- //将newExpireDate进行加密
- newExpireDate = Base64Util.encodeToStrSync(StrUtil.strToUint8Array(newExpireDate))
- // LogUtil.info('onecold 加密后的newExpireDate = ' + newExpireDate)
- let newItem = new VipData(newExpireDate,'',true)
- try {
- let jsonData = JSON.stringify(newItem);
- const file = await fileIo.open(filePath, fileIo.OpenMode.CREATE | fileIo.OpenMode.READ_WRITE);
- // 清空文件内容
- await fileIo.truncate(file.fd, 0);
- await fileIo.write(file.fd, jsonData);
- await fileIo.close(file);
- console.log('Data saved successfully.');
- } catch (error) {
- console.error('Failed to save data:', error);
- }
- }
- @Builder
- DutySheet() {
- Column(){
- this.DutyView()
- }
- .width('100%')
- .height('100%')
- }
- private webController: WebviewController = new webview.WebviewController();
- ports: webview.WebMessagePort[] = [];
- @State webUrl: string = CommonConstants.NEW_DUTY
- @State
- progressValue: number = 0
- @Builder
- DutyView(){
- Progress({ value: 0, total: 100, type: ProgressType.Linear })
- .backgroundColor(0xFFFFFF)
- .color(0x414AFF)
- .value(this.progressValue)
- .width('%100')
- .height(2)
- // .visibility(this.progressIsVisible)
- .visibility(this.progressValue!=100 ? Visibility.Visible : Visibility.None)
- Column(){
- Web({
- src: this.webUrl,
- controller: this.webController
- })
- .width("100%")
- .height("100%")
- .layoutWeight(1)
- .domStorageAccess(true)
- .onProgressChange((event)=>{
- if (event) {
- console.log('newProgress:' + event.newProgress);
- this.progressValue = event.newProgress
- }
- })
- Row(){
- Button('不同意')
- .fontColor(Color.White)
- // .backgroundColor(this.themeColor)
- .height(50)
- .layoutWeight(1)
- .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .margin({left:25,right:10})
- .onClick(()=>{
- this.isAgree = false
- PreferencesUtil.putSync(VipPage.IS_AGREE,this.isAgree)
- this.isShowDutySheetView = false
- })
- Button('同意')
- .fontColor(Color.White)
- .linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
- .layoutWeight(1)
- .height(50)
- // .backgroundColor(this.themeColor)
- .clickEffect({level:ClickEffectLevel.HEAVY})
- .margin({left:10,right:25})
- .onClick(()=>{
- this.isAgree = true
- PreferencesUtil.putSync(VipPage.IS_AGREE,this.isAgree)
- this.isShowDutySheetView = false
- })
- }
- .margin({top:20,bottom:30})
- }
- }
- doCheckHao(){
- if(Utility.isHaoOpenTime()){
- let isHao:boolean = PreferencesUtil.getBooleanSync('is_vhaoping');
- if(!isHao){
- this.showHaopingDialog()
- return
- }
- }
- }
- showHaopingDialog(){
- setTimeout(()=>{
- DialogHelper.showCustomContentDialog({
- dialogId:'haoping',
- title: "好评福利",
- autoCancel: false, //点击遮障层时,不关闭弹窗
- backCancel: true, //点击返回键,不关闭弹窗
- contentBuilder: () => {
- this.customHaoPingBuilder("好消息!好评可以返一个月无广告特权!\n\n如果您觉得好用可以给个好评吗?谢谢!\n\n给个好评吧,非常感谢您的支持!")
- },
- buttons: [],
- })
- },3000)
- }
- //好评的自定义内容
- @Builder
- customHaoPingBuilder(content: string) {
- Column() {
- Text(content)
- .fontColor(Color.Gray)
- .fontSize(16)
- .alignSelf(ItemAlign.Start)
- .margin({bottom:15})
- .fontSize(16)
- Row(){
- Button('取消')
- .fontColor(Color.White)
- .backgroundColor($r('app.color.title_bar_bg'))
- //.linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
- .height(50)
- .layoutWeight(1)
- .stateEffect(true)
- .margin({right:6})
- .onClick(()=>{
- DialogHelper.closeDialog('haoping'); //关闭弹框
- })
- Button('好评')
- .fontColor(Color.White)
- //.linearGradient( { direction: GradientDirection.Right, colors:[['#ff37a0fc',0.0],['#67e667',0.5],['#f5856e',1.0]]})
- .layoutWeight(1)
- .height(50)
- .backgroundColor($r('app.color.title_bar_bg'))
- .stateEffect(true)
- .margin({left:6})
- .onClick(()=>{
- DialogHelper.closeDialog('haoping'); //关闭弹框
- Utility.gotoMarket(context,this.bundleName)
- PreferencesUtil.putSync("is_vhaoping", true);
- setTimeout(()=>{
- let expireDate = this.getExpireDate(VipPage.TYPE_MONTH)
- this.saveDataToFile(expireDate,this.filePath,true )
- },360000)
- })
- }
- }
- .width("100%")
- .padding(10)
- }
- }
- // 定义响应数据的类型
- interface WeChatOrderResponse {
- prepay_id: string;
- }
- interface Amount {
- total: number;
- currency: string;
- }
- //调用服务端接口,用户在商户APP端选择微信支付后,商户需调用该接口在微信支付下单,生成用于调起支付的预支付交易会话标识(prepay_id)。
- async function createWeChatOrder(
- app_id: string,
- mch_id: string,
- description: string,
- amount: number,
- out_trade_no_pre: 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)
- + '&out_trade_no_pre=' + encodeURIComponent(out_trade_no_pre)
- LogUtil.debug("onecold 微信支付 requestUrl=" + requestUrl)
- 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: WeChatOrderResponse;
- LogUtil.debug("onecold 微信支付 response.result=" + response.result)
- if (typeof response.result === 'string') {
- responseData = JSON.parse(response.result) as WeChatOrderResponse;
- } else if (response.result instanceof Object) {
- responseData = response.result as WeChatOrderResponse;
- } else {
- throw new Error('onecold Unexpected response format');
- }
- const prepayId: string = responseData.prepay_id;
- console.log('onecold WeChat Order Created, prepay_id:', prepayId);
- return prepayId;
- } else {
- console.error('Failed to create WeChat order:', response.responseCode, response.result);
- throw new Error(`HTTP Error: ${response.responseCode}`);
- }
- } catch (error) {
- console.error('Error creating WeChat order:', error);
- return '';
- }
- }
- async function isHasWX(): Promise<boolean>{
- try {
- let link = 'weixin://';
- let data = bundleManager.canOpenLink(link);
- if (data) {
- return true
- }else {
- promptAction.showToast({message:'微信未安装'})
- return false
- }
- } catch (err) {
- let message = (err as BusinessError).message;
- console.error('canOpenLink failed: %{public}s', message);
- return false
- }
- }
- // 微信支付构造签名串
- function constructSignatureString(appId: string, timestamp: string, nonceStr: string, prepayId: string): string {
- return `${appId}\n${timestamp}\n${nonceStr}\n${prepayId}\n`;
- }
- // 微信支付RSA2048|PKCS1|SHA256 APP调起支付签名
- async function 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()
- }
- }
- // 定义接口请求参数类型
- interface WeChatOrderRequest {
- appid: string;
- mchid: string;
- description: string;
- out_trade_no: string;
- notify_url: string;
- amount: Amount;
- }
- function generateSignatureInfo(timestamp: string,nonceStr: string,body:string): string {
- const httpMethod = 'POST';
- const url = '/v3/pay/transactions/jsapi';
- // const timestamp = Math.floor(Date.now() / 1000).toString();
- // const body = '{"appid":"wxd678efh567hg6787","mchid":"1900007291","description":"Image形象店-深圳腾大-QQ公仔","out_trade_no":"1217752501201407033233368018","notify_url":"https://www.weixin.qq.com/wxpay/pay.php","amount":{"total":100,"currency":"CNY"},"payer":{"openid":"oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"}}';
- console.log("onecold rsasignRSA ", 'body: ' + body);
- const signatureString = `${httpMethod}\n${url}\n${timestamp}\n${nonceStr}\n${body}\n`;
- return signatureString
- }
- function getOutTradeNo(): string {
- const timestamp = Date.now().toString(); // 获取当前时间戳
- const randomPart = Math.floor(Math.random() * 1e16).toString().padStart(16, '0'); // 生成16位随机数
- const orderNumber = (timestamp + randomPart).slice(0, 32); // 确保长度为32位
- return orderNumber;
- }
- // 构造Authorization头
- function constructAuthorizationHeader(mchid: string,nonceStr:string,signature: string,
- timestamp:string,serialNo:string): string {
- return `WECHATPAY2-SHA256-RSA2048 mchid="${mchid}",nonce_str="${nonceStr}",signature="${signature}",timestamp="${timestamp}",serial_no="${serialNo}"`;
- }
- async function createWeChatOrderInfo(appid: string, mchid: string, description: string,amount: number,
- outTradeNo: string): Promise<string> {
- const url: string = 'https://api.mch.weixin.qq.com/v3/pay/transactions/app';
- let nonceStr = RandomUtil.getRandomStr(16,'abcdefghijklmnopqrstuvwxyz')
- const timestamp: number = Math.floor(Date.now() / 1000);
- // 构建请求体
- const body: WeChatOrderRequest = { appid: appid, mchid: mchid, description: description, out_trade_no: outTradeNo, notify_url: VipPage.WX_NOTIFY_URL, amount: { total: amount, currency: 'CNY'} };
- let generateSign:string= generateSignatureInfo(timestamp+'',nonceStr, JSON.stringify(body))
- console.log("onecold rsasignRSA ", 'generateSign: ' + generateSign);
- let signStr = await rsaSign2048(generateSign);
- let signStrBase64 = Base64Util.encodeToStrSync(signStr)
- let authorizationHeader = constructAuthorizationHeader(mchid,nonceStr,signStrBase64,timestamp+'',CommonConstants.WX_PAY_SERIALNO)
- console.log("onecold rsasignRSA ", 'signStr: ' + signStr);
- console.log("onecold rsasignRSA ", 'signStrBase64: ' + signStrBase64);
- console.log("onecold rsasignRSA ", 'authorizationHeader: ' + authorizationHeader);
- // 构建请求头
- const headers: Record<string, string> = {
- 'Authorization': authorizationHeader, // 替换为你的授权信息
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
- };
- const httpRequest: http.HttpRequest = http.createHttp();
- const options: http.HttpRequestOptions = {
- method: http.RequestMethod.POST,
- header: headers,
- extraData: JSON.stringify(body),
- readTimeout: 6000,
- connectTimeout: 6000,
- };
- try {
- const response: http.HttpResponse = await httpRequest.request(url, options);
- LogUtil.debug("onecold 微信支付 response.result=" + response.result)
- if (response.responseCode === 200) {
- // LogUtil.debug("onecold 微信支付 response.result=" + response.result)
- let responseData: WeChatOrderResponse;
- if (typeof response.result === 'string') {
- responseData = JSON.parse(response.result) as WeChatOrderResponse;
- } else if (response.result instanceof Object) {
- responseData = response.result as WeChatOrderResponse;
- } else {
- throw new Error('Unexpected response format');
- }
- const prepayId: string = responseData.prepay_id;
- console.log('WeChat Order Created, prepay_id:', prepayId);
- return prepayId;
- } else {
- console.error('Failed to create WeChat order:', response.responseCode, response.result);
- throw new Error(`HTTP Error: ${response.responseCode}`);
- }
- } catch (error) {
- console.error('Error creating WeChat order:', error);
- return '';
- }
- }
|