1 应用内支付
开发步骤
步骤一:判断当前登录的华为账号所在服务地是否支持应用内支付
在使用应用内支付之前,您的应用需要向IAP Kit发送queryEnvironmentStatus请求,以此判断用户当前登录的华为帐号所在的服务地是否在IAP Kit支持结算的国家/地区中。
// pages/Index.ets
/**
* @description 应用内支付服务示例-消耗型商品
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-01
*/
import { common } from '@kit.AbilityKit'
import { iap } from '@kit.IAPKit';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = {} as common.UIAbilityContext;
@State querying: boolean = true;
@State queryingFailed: boolean = false;
@State productInfoArray: iap.Product[] = [];
@State queryFailedText: string = "查询失败!";
showLoadingPage() {
this.queryingFailed = false;
this.querying = true;
}
showFailedPage(failedText?: string) {
if (failedText) {
this.queryFailedText = failedText;
}
this.queryingFailed = true;
this.querying = false;
}
showNormalPage() {
this.queryingFailed = false;
this.querying = false;
}
aboutToAppear(): void {
this.showLoadingPage();
this.context = getContext(this) as common.UIAbilityContext;
this.onCase();
}
async onCase() {
this.showLoadingPage();
const queryEnvCode = await this.queryEnv();
if (queryEnvCode !== 0) {
let queryEnvFailedText = "当前应用不支持IAP Kit服务!";
if (queryEnvCode === iap.IAPErrorCode.ACCOUNT_NOT_LOGGED_IN) {
queryEnvFailedText = "请通过桌面设置入口登录华为账号后再次尝试!";
}
this.showFailedPage(queryEnvFailedText);
return;
}
}
// 判断当前登录的华为账号所在服务地是否支持应用内支付。
async queryEnv(): Promise<number> {
try {
console.log("IAPKitDemo queryEnvironmentStatus begin.");
await iap.queryEnvironmentStatus(this.context);
return 0;
} catch (error) {
promptAction.showToast({
message: "IAPKitDemo queryEnvironmentStatus failed. Cause: " + JSON.stringify(error)
})
return error.code;
}
}
build() {...}
}
步骤二:确保权益发放
用户购买商品后,开发者需要及时发放相关权益。但实际应用场景中,若出现异常(网络错误、进程被中止等)将导致应用无法知道用户实际是否支付成功,从而无法及时发放权益,即出现掉单情况。为了确保权益发放,您需要在以下场景检查用户是否存在已购未发货的商品:
- 应用启动时。
- 购买请求返回1001860001时。
- 购买请求返回1001860051时。
如果存在已购未发货商品,则发放相关权益,然后向IAP Kit确认发货,完成购买。
// pages/Index.ets
/**
* @description 应用内支付服务示例-消耗型商品
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-01
*/
import { common } from '@kit.AbilityKit'
import { iap } from '@kit.IAPKit';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = {} as common.UIAbilityContext;
@State querying: boolean = true;
@State queryingFailed: boolean = false;
@State productInfoArray: iap.Product[] = [];
@State queryFailedText: string = "查询失败!";
showLoadingPage() {...}
showFailedPage(failedText?: string) {...}
showNormalPage() {...}
aboutToAppear(): void {...}
async onCase() {
...
await this.queryPurchase();
}
// 判断当前登录的华为账号所在服务地是否支持应用内支付。
async queryEnv(): Promise<number> {...}
async queryPurchase() {
console.log("IAPKitDemo queryPurchase begin.");
const queryPurchaseParam: iap.QueryPurchasesParameter = {
productType: iap.ProductType.CONSUMABLE,
queryType: iap.PurchaseQueryType.UNFINISHED
};
const result: iap.QueryPurchaseResult = await iap.queryPurchases(this.context, queryPurchaseParam);
// 处理订单信息
if (result) {
const purchaseDataList: string[] = result.purchaseDataList;
if (purchaseDataList === undefined || purchaseDataList.length <= 0) {
console.log("IAPKitDemo queryPurchase, list empty.");
return;
}
for (let i = 0; i < purchaseDataList.length; i++) {
const purchaseData = purchaseDataList[i];
const jwsPurchaseOrder = (JSON.parse(purchaseData) as PurchaseData).jwsPurchaseOrder;
if (!jwsPurchaseOrder) {
console.log("IAPKitDemo queryPurchase, jwsPurchaseOrder invalid.");
continue;
}
const purchaseStr = JWTUtil.decodeJwtObj(jwsPurchaseOrder);
const purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload;
}
}
}
build() {...}
}
步骤三:查询商品信息
通过queryProducts来获取在AppGallery Connect上配置的商品信息。发起请求时,开发者需在请求参数QueryProductsParameter中携带相关的商品ID,并根据实际配置指定其productType。
当接口请求成功时,IAP Kit将返回商品信息Product的列表。 您可以使用Product包含的商品价格、名称和描述等信息,向用户展示可供购买的商品列表。
// pages/Index.ets
/**
* @description 应用内支付服务示例-消耗型商品
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-01
*/
import { common } from '@kit.AbilityKit'
import { iap } from '@kit.IAPKit';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = {} as common.UIAbilityContext;
@State querying: boolean = true;
@State queryingFailed: boolean = false;
@State productInfoArray: iap.Product[] = [];
@State queryFailedText: string = "查询失败!";
showLoadingPage() {...}
showFailedPage(failedText?: string) {...}
showNormalPage() {...}
aboutToAppear(): void {...}
async onCase() {
...
await this.queryProducts();
}
// 判断当前登录的华为账号所在服务地是否支持应用内支付。
async queryEnv(): Promise<number> {...}
// 查询商品信息
async queryProducts() {
try {
console.log("IAPKitDemo queryProducts begin.");
const queryProductParam: iap.QueryProductsParameter = {
productType: iap.ProductType.CONSUMABLE,
productIds: ['nutpi_course_1']
};
const result: iap.Product[] = await iap.queryProducts(this.context, queryProductParam);
this.productInfoArray = result;
this.showNormalPage();
} catch (error) {
this.showFailedPage();
}
}
async queryPurchase() {...}
build() {...}
}
步骤四:构建商品列表UI
// pages/Index.ets
/**
* @description 应用内支付服务示例-消耗型商品
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-01
*/
import { common } from '@kit.AbilityKit'
import { iap } from '@kit.IAPKit';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = {} as common.UIAbilityContext;
@State querying: boolean = true;
@State queryingFailed: boolean = false;
@State productInfoArray: iap.Product[] = [];
@State queryFailedText: string = "查询失败!";
showLoadingPage() {...}
showFailedPage(failedText?: string) {...}
showNormalPage() {...}
aboutToAppear(): void {...}
async onCase() {...}
// 判断当前登录的华为账号所在服务地是否支持应用内支付。
async queryEnv(): Promise<number> {...}
// 查询商品信息
async queryProducts() {...}
async queryPurchase() {...}
build() {
Column() {
Column() {
Text('应用内支付服务示例-消耗型')
.fontSize(18)
.fontWeight(FontWeight.Bolder)
}
.width('100%')
.height(54)
.justifyContent(FlexAlign.Center)
.backgroundColor(Color.White)
Column() {
Column() {
Row() {
Text('Consumables')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.margin({ left: 24, right: 24 })
}
.margin({ top: 16, bottom: 12 })
.height(48)
.justifyContent(FlexAlign.Start)
.width('100%')
// 商品列表信息
List({ space: 0, initialIndex: 0 }) {
ForEach(this.productInfoArray, (item: iap.Product) => {
ListItem() {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
Image($r('app.media.app_icon'))
.height(48)
.width(48)
.objectFit(ImageFit.Contain)
Text(item.name)
.width('100%')
.height(48)
.fontSize(16)
.textAlign(TextAlign.Start)
.padding({ left: 12, right: 12 })
Button(item.localPrice)
.width(200)
.fontSize(16)
.height(30)
.onClick(() => {
this.createPurchase(item.id, item.type)
})
.stateEffect(true)
}
.borderRadius(16)
.backgroundColor('#FFFFFF')
.alignSelf(ItemAlign.Auto)
}
})
}
.divider({ strokeWidth: 1, startMargin: 2, endMargin: 2 })
.padding({ left: 12, right: 12 })
.margin({ left: 12, right: 12 })
.borderRadius(16)
.backgroundColor('#FFFFFF')
.alignSelf(ItemAlign.Auto)
}
.backgroundColor('#F1F3F5')
.width('100%')
.height('100%')
.visibility(this.querying || this.queryingFailed ? Visibility.None : Visibility.Visible)
// 加载进度组件
Stack() {
LoadingProgress()
.width(96)
.height(96)
}
.backgroundColor('#F1F3F5')
.width('100%')
.height('100%')
.visibility(this.querying ? Visibility.Visible : Visibility.None)
// 异常文本提示
Stack({ alignContent: Alignment.Center }) {
Text(this.queryFailedText)
.fontSize(28)
.fontWeight(FontWeight.Bold)
.margin({ left: 24, right: 24 })
}
.backgroundColor('#F1F3F5')
.width('100%')
.height('100%')
.visibility(this.queryingFailed ? Visibility.Visible : Visibility.None)
.onClick(() => {
this.onCase();
})
}
.width('100%')
.layoutWeight(1)
}
.width('100%')
.height('100%')
.backgroundColor(0xF1F3F5)
}
}
步骤五:发起购买
用户发起购买时,开发者的应用可通过向IAP Kit发送createPurchase请求来拉起IAP Kit收银台。发起请求时,需在请求参数PurchaseParameter中携带开发者此前已在华为AppGallery Connect网站上配置并生效的商品ID,并根据实际配置指定其productType。
// pages/Index.ets
/**
* @description 应用内支付服务示例-消耗型商品
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-01
*/
import { common } from '@kit.AbilityKit'
import { iap } from '@kit.IAPKit';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = {} as common.UIAbilityContext;
@State querying: boolean = true;
@State queryingFailed: boolean = false;
@State productInfoArray: iap.Product[] = [];
@State queryFailedText: string = "查询失败!";
showLoadingPage() {...}
showFailedPage(failedText?: string) {...}
showNormalPage() {...}
aboutToAppear(): void {...}
async onCase() {...}
// 判断当前登录的华为账号所在服务地是否支持应用内支付。
async queryEnv(): Promise<number> {...}
// 查询商品信息
async queryProducts() {...}
async queryPurchase() {...}
/**
* 发起购买
* @param id AppGallery Connect控制台配置的商品ID
* @param type 商品类型
*/
createPurchase(id: string, type: iap.ProductType) {
console.log("IAPKitDemo createPurchase begin.");
try {
const createPurchaseParam: iap.PurchaseParameter = {
productId: id,
productType: type
};
iap.createPurchase(this.context, createPurchaseParam).then(async (result) => {
console.log("IAPKitDemo createPurchase success. Data: " + JSON.stringify(result));
// 获取PurchaseOrderPayload的JSON字符串
const purchaseData: PurchaseData = JSON.parse(result.purchaseData) as PurchaseData;
const jwsPurchaseOrder: string = purchaseData.jwsPurchaseOrder;
// 解码 JWTUtil为自定义类,可参见Sample Code工程
const purchaseStr = JWTUtil.decodeJwtObj(jwsPurchaseOrder);
const purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload;
// 处理发货
}).catch((error: BusinessError) => {
promptAction.showToast({
message: "IAPKitDemo createPurchase failed. Cause: " + JSON.stringify(error)
})
if (error.code === iap.IAPErrorCode.PRODUCT_OWNED || error.code === iap.IAPErrorCode.SYSTEM_ERROR) {
// 参考权益发放检查是否需要补发货,确保权益发放
this.queryPurchase();
}
})
} catch (err) {
promptAction.showToast({
message: "IAPKitDemo createPurchase failed. Error: " + JSON.stringify(err)
})
}
}
build() {...}
}
步骤六:完成购买
对PurchaseData.jwsPurchaseOrder解码验签成功后,如果PurchaseOrderPayload.purchaseOrderRevocationReasonCode为空,则代表购买成功,即可发放相关权益。
发货成功后,开发者需在应用中发送finishPurchase请求确认发货,以此通知IAP服务器更新商品的发货状态,完成购买流程。发送finishPurchase请求时,需在请求参数FinishPurchaseParameter中携带PurchaseOrderPayload中的productType、purchaseToken、purchaseOrderId。请求成功后,IAP服务器会将相应商品标记为已发货。
对于消耗型商品,应用成功执行finishPurchase之后,IAP服务器会将相应商品重新设置为可购买状态,用户即可再次购买该商品。
// pages/Index.ets
/**
* @description 应用内支付服务示例-消耗型商品
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-01
*/
import { common } from '@kit.AbilityKit'
import { iap } from '@kit.IAPKit';
import { JSON } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { promptAction } from '@kit.ArkUI';
@Entry
@Component
struct Index {
private context: common.UIAbilityContext = {} as common.UIAbilityContext;
@State querying: boolean = true;
@State queryingFailed: boolean = false;
@State productInfoArray: iap.Product[] = [];
@State queryFailedText: string = "查询失败!";
showLoadingPage() {...}
showFailedPage(failedText?: string) {...}
showNormalPage() {...}
aboutToAppear(): void {...}
async onCase() {...}
// 判断当前登录的华为账号所在服务地是否支持应用内支付。
async queryEnv(): Promise<number> {...}
// 查询商品信息
async queryProducts() {...}
async queryPurchase() {...}
/**
* 发起购买
* @param id AppGallery Connect控制台配置的商品ID
* @param type 商品类型
*/
createPurchase(id: string, type: iap.ProductType) {
console.log("IAPKitDemo createPurchase begin.");
try {
const createPurchaseParam: iap.PurchaseParameter = {
productId: id,
productType: type
};
iap.createPurchase(this.context, createPurchaseParam).then(async (result) => {
console.log("IAPKitDemo createPurchase success. Data: " + JSON.stringify(result));
// 获取PurchaseOrderPayload的JSON字符串
const purchaseData: PurchaseData = JSON.parse(result.purchaseData) as PurchaseData;
const jwsPurchaseOrder: string = purchaseData.jwsPurchaseOrder;
// 解码 JWTUtil为自定义类,可参见Sample Code工程
const purchaseStr = JWTUtil.decodeJwtObj(jwsPurchaseOrder);
const purchaseOrderPayload = JSON.parse(purchaseStr) as PurchaseOrderPayload;
// 处理发货
this.finishPurchase(purchaseOrderPayload);
}).catch((error: BusinessError) => {
promptAction.showToast({
message: "IAPKitDemo createPurchase failed. Cause: " + JSON.stringify(error)
})
if (error.code === iap.IAPErrorCode.PRODUCT_OWNED || error.code === iap.IAPErrorCode.SYSTEM_ERROR) {
// 参考权益发放检查是否需要补发货,确保权益发放
this.queryPurchase();
}
})
} catch (err) {
promptAction.showToast({
message: "IAPKitDemo createPurchase failed. Error: " + JSON.stringify(err)
})
}
}
finishPurchase(purchaseOrder: PurchaseOrderPayload) {
console.log("IAPKitDemo finishPurchase begin.");
const finishPurchaseParam: iap.FinishPurchaseParameter = {
productType: purchaseOrder.productType,
purchaseToken: purchaseOrder.purchaseToken,
purchaseOrderId: purchaseOrder.purchaseOrderId
};
iap.finishPurchase(this.context, finishPurchaseParam).then((result) => {
console.log("IAPKitDemo finishPurchase success");
}).catch((error: BusinessError) => {
promptAction.showToast({
message: "IAPKitDemo finishPurchase failed. Cause: " + JSON.stringify(error)
})
})
}
build() {...}
}
2 推送服务
开发步骤
步骤一:请求通知授权
为确保应用可正常收到消息,建议应用发送通知前调用requestEnableNotification()方法弹出提醒,告知用户需要允许接收通知消息。
// entryability/EntryAbility.ets
/**
* @description 应用入口
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-13
*/
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { window } from '@kit.ArkUI';
import { BusinessError } from '@kit.BasicServicesKit';
import { JSON } from '@kit.ArkTS';
import { notificationManager } from '@kit.NotificationKit';
export default class EntryAbility extends UIAbility {
async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
// 请求通知授权
await this.requestNotification();
}
async requestNotification() {
try {
console.info("requestNotification: 请求通知授权开始。");
// 查询通知是否授权
const notificationEnabled: boolean = await notificationManager.isNotificationEnabled();
console.info("requestNotification: " + (notificationEnabled ? '已' : '未') + "授权");
if (!notificationEnabled) {
// 请求通知授权
await notificationManager.requestEnableNotification();
}
} catch (error) {
const e: BusinessError = error as BusinessError;
console.error("requestNotification failed. Cause: " + JSON.stringify(e));
}
}
}
步骤二:获取Push Token
导入pushService模块。建议在应用的UIAbility(例如EntryAbility)的onCreate()方法中调用getToken()接口获取Push Token并上报到开发者的服务端,方便开发者的服务端向终端推送消息。本示例便于应用端测试发送通知消息请求,将Push Token获取放置在Index.ets页面。
// pages/Index.ets
import { pushService } from '@kit.PushKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { JSON } from '@kit.ArkTS';
import { http } from '@kit.NetworkKit';
import { promptAction } from '@kit.ArkUI';
/**
* @description 推送服务示例
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-13
*/
@Entry
@Component
struct Index {
@State pushToken: string = "";
async aboutToAppear(): Promise<void> {
try {
// 获取Push Token
const pushToken: string = await pushService.getToken();
console.log("getToken succeed. Token: " + pushToken);
const now = new Date();
const timestamp = now.getTime();
console.log("getToken succeed. Time: " + Math.floor(timestamp / 1000));
console.log("getToken succeed. Time: " + (Math.floor(timestamp / 1000) + 3600));
this.pushToken = pushToken;
// 此处需要上报Push Token到应用服务端
} catch (error) {
const e: BusinessError = error as BusinessError;
console.error("getToken failed. Cause: " + JSON.stringify(e));
}
}
build() {...}
}
步骤三:获取项目ID
登录AppGallery Connect控制台,选择“我的项目”,在项目列表中选择对应的项目,左侧导航栏选择“项目设置”,拷贝项目ID。
步骤四:创建服务账号密钥文件
- 开发者需要在华为开发者联盟的API Console上创建并下载推送服务API的服务账号密钥文件。点击“管理中心 > API服务 > API库”,在API库页面选择“项目名称”,在展开的App Services列表中点击“推送服务”。
- 点击推送服务页面中的“启用”,完成API添加。
- 点击“管理中心 > API服务 > 凭证”,在凭证页面点击“服务账号密钥”卡片中的“创建凭证”按钮。
- 在“创建服务账号密钥”页面输入信息并点击“生成公私钥”,点击“创建并下载JSON”,完成“服务账号密钥”凭证创建,需要开发者保存“支付公钥”,用于后期生成JWT鉴权令牌。
步骤五:生成JWT Token
开发者在正式开发前调试功能,可使用在线生成工具获取JWT Token,需要注意生成JWT Token时Algorithm请选择RS256或PS256。若用于正式环境,为了方便开发者生成服务账号鉴权令牌,华为提供了JWT开源组件,可根据开发者使用的开发语言选择进行开发。
- HEADER中的kid指下载的服务账号密钥文件中key_id字段。
- PAYLOAD数据中iss指下载的的服务账号密钥文件中sub_account字段。
- VERIFY SIGNATURE中复制粘贴公钥和私钥。
步骤六:调用推送服务REST API
该模块需要开发者在应用服务端自行开发,需要结合用户信息留存设备Token,本课程中该功能位于应用端仅用于学习,不推荐该方法。应用服务端调用Push Kit服务端的REST API推送通知消息,需要传递的参数说明如下所示:
- [projectId]:项目ID。
- Authorization:JWT格式字符串,JWT Token前加“Bearer ”,需注意“Bearer”和JWT格式字符串中间的空格不能丢。
- push-type:0表示Alert消息,此处为通知消息场景。
- category:表示通知消息自分类的类别,MARKETING为资讯营销类消息。
- actionType:0表示点击消息打开应用首页。
- token:Push Token。
- testMessage:测试消息标识,true标识测试消息。
- notifyId:(选填)自定义消息标识字段,仅支持数字,范围[0, 2147483647],若要用于消息撤回则必填。
在应用端按钮组件Button的点击事件onClick中通过数据请求API实现发送通知消息。
// pages/Index.ets
import { pushService } from '@kit.PushKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { JSON } from '@kit.ArkTS';
import { http } from '@kit.NetworkKit';
import { promptAction } from '@kit.ArkUI';
/**
* @description 推送服务示例
* @author 白晓明
* @organization 坚果派
* @website: nutpi.com.cn
* @date 2024-06-13
*/
@Entry
@Component
struct Index {
@State pushToken: string = "";
@State isLoading: boolean = false;
// 步骤五生成的JWT Token
authorization: string = "Bearer ****";
async aboutToAppear(): Promise<void> {
try {
// 获取Push Token
const pushToken: string = await pushService.getToken();
console.log("getToken succeed. Token: " + pushToken);
const now = new Date();
const timestamp = now.getTime();
console.log("getToken succeed. Time: " + Math.floor(timestamp / 1000));
console.log("getToken succeed. Time: " + (Math.floor(timestamp / 1000) + 3600));
this.pushToken = pushToken;
// 上报Push Token
} catch (error) {
const e: BusinessError = error as BusinessError;
console.error("getToken failed. Cause: " + JSON.stringify(e));
}
}
async deletePushTokenFunc() {
try {
await pushService.deleteToken();
} catch (error) {
const e: BusinessError = error as BusinessError;
console.error("deleteToken failed. Cause: " + JSON.stringify(e));
}
}
build() {
Column() {
Row() {
Text('推送服务示例')
.fontSize(18)
.fontWeight(FontWeight.Bolder)
}
.width('100%')
.height(54)
.justifyContent(FlexAlign.Center)
.alignItems(VerticalAlign.Center)
Column({ space: 16 }) {
Row() {
LoadingProgress()
Text('等待通知发送完成')
.fontSize(16)
}
.width('100%')
.height(64)
.justifyContent(FlexAlign.Center)
.visibility(this.isLoading ? Visibility.Visible : Visibility.Hidden)
Button('发送通知消息')
.type(ButtonType.Normal)
.borderRadius(8)
.enabled(!this.isLoading)
.onClick(async () => {
try {
this.isLoading = true;
const url = "https://push-api.cloud.huawei.com/v3/388421841222199046/messages:send";
const httpRequest = http.createHttp();
const response: http.HttpResponse = await httpRequest.request(url, {
header: {
"Content-Type": "application/json",
"Authorization": this.authorization,
"push-type": 0
},
method: http.RequestMethod.POST,
extraData: {
"payload": {
"notification": {
"category": "MARKETING",
"title": "普通通知标题",
"body": "普通通知内容",
"clickAction": {
"actionType": 0
},
"notifyId": 12345
}
},
"target": {
"token": [this.pushToken]
},
"pushOptions": {
"testMessage": true
}
}
})
if (response.responseCode === 200) {
const result = response.result as string;
const data = JSON.parse(result) as ResultData;
promptAction.showToast({
message: data.msg
})
}
} catch (error) {
const e: BusinessError = error as BusinessError;
console.error("getToken failed. Cause: " + JSON.stringify(e));
} finally {
this.isLoading = false;
}
})
}
.width('100%')
.layoutWeight(1)
}
.height('100%')
.width('100%')
}
}
// 接口返回数据类
interface ResultData {
code: string;
msg: string;
requestId: string;
}