鸿蒙应用服务开发【华为支付服务】客户端

华为支付服务

介绍

本示例展示了使用华为支付服务提供的单次支付,签约代扣。

需要使用华为支付服务接口 @kit.PaymentKit

效果预览

Sample工程的配置与使用

在DevEco中配置Sample工程的步骤如下

  1. 创建项目\]及\[应用\]。

  2. 使用[AppGallery Connect]应用的配置更新module.json5文件相关配置,配置client_id及app_id属性值。
  3. 详细可参见指南[开发准备]。

具体实现

单次支付:

  • 商户服务器按照商户模型调用Payment Kit提供的[直连商户预下单]或[服务商/平台类商户预下单]接口获取预下单号(prepayId),然后组建orderStr返回给客户端。
  • 商户客户端调用requestPayment接口调起Payment Kit客户端收银台。
  • 用户在Payment Kit客户端收银台完成支付操作后,Payment Kit客户端会收到支付结果信息。
  • Payment Kit客户端展示支付结果页,用户关闭支付结果页后Payment Kit客户端会返回支付状态给商户客户端。

签约代扣:

  • 商户服务器按照商户模型调用Payment Kit提供的[预签约接口]获取预下单号(preSignNo),然后返回给客户端。
  • 商户客户端构建contractStr参数,调用requestContract接口调起Payment Kit客户端签约收银台。
  • 用户在Payment Kit客户端签约收银台完成签约操作后,Payment Kit客户端会收到签约结果信息。
  • Payment Kit客户端展示签约结果页,用户关闭签约结果页后Payment Kit客户端会返回商户客户端。
  • 签约完成后,Payment Kit服务器会调用回调接口返回签约结果信息给商户服务器。
  • 商户服务器收到签约结果回调响应后,使用SM2验签方式对签约结果进行验签。
  • 签约完成后,商户服务器可以调用Payment Kit提供的[申请免密代扣接口],完成扣款服务。

参考

复制代码
/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
 */
import { paymentService } from '@kit.PaymentKit';
import { BusinessError } from '@kit.BasicServicesKit';
import { common } from '@kit.AbilityKit';

@Entry
@Component
struct Index {
  context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;

  requestPaymentPromise() {
    // use your own orderStr
    const orderStr = '{"app_id":"***","merc_no":"***","prepay_id":"xxx","timestamp":"1680259863114","noncestr":"1487b8a60ed9f9ecc0ba759fbec23f4f","sign":"****","auth_id":"***"}';
    paymentService.requestPayment(this.context, orderStr)
      .then(() => {
        // succeeded in paying
        console.info('succeeded in paying');
      })
      .catch((error: BusinessError) => {
        // failed to pay
        console.error(`failed to pay, error.code: ${error.code}, error.message: ${error.message}`);
      });
  }

  requestPaymentCallBack() {
    // use your own orderStr
    const orderStr = '{"app_id":"***","merc_no":"***","prepay_id":"xxx","timestamp":"1680259863114","noncestr":"1487b8a60ed9f9ecc0ba759fbec23f4f","sign":"****","auth_id":"***"}';
    paymentService.requestPayment(this.context, orderStr, (error: BusinessError) => {
      if (error) {
        // failed to pay
        console.error(`failed to pay, error.code: ${error.code}, error.message: ${error.message}`);
        return;
      }
      // succeeded in paying
      console.info('succeeded in paying');
    })
  }

  requestContractPromise() {
    // use your own contractStr
    const contractStr = '{"appId":"***","preSignNo":"***"}';
    paymentService.requestContract(this.context, contractStr)
      .then(() => {
        // succeed in signing
        console.log('succeeded in signing');
      })
      .catch((error: BusinessError) => {
        // failed to sign
        console.error(`failed to sign, error.code: ${error.code}, error.message: ${error.message}`);
      });
  }

  requestContractCallBack() {
    // use your own contractStr
    const contractStr = '{"appId":"***","preSignNo":"***"}';
    paymentService.requestContract(this.context, contractStr, (error: BusinessError) => {
      if (error) {
        // failed to sign
        console.error(`failed to sign, error.code: ${error.code}, error.message: ${error.message}`);
        return;
      }
      // succeed in signing
      console.info('succeeded in signing');
    })
  }

  build() {
    Column() {
      Button('requestPaymentPromise')
        .type(ButtonType.Capsule)
        .width('50%')
        .margin(20)
        .onClick(() => {
          this.requestPaymentPromise();
        })
      Button('requestPaymentCallBack')
        .type(ButtonType.Capsule)
        .width('50%')
        .margin(20)
        .onClick(() => {
          this.requestPaymentCallBack();
        })
      Button('requestContractPromise')
        .type(ButtonType.Capsule)
        .width('50%')
        .margin(20)
        .onClick(() => {
          this.requestContractPromise();
        })
      Button('requestContractCallBack')
        .type(ButtonType.Capsule)
        .width('50%')
        .margin(20)
        .onClick(() => {
          this.requestContractCallBack();
        })
    }
    .justifyContent(FlexAlign.Center)
    .width('100%')
    .height('100%')
  }
}

依赖

  1. AppScope/app.json5下"bundleName"配置需要与您在[AppGallery Connect]中[创建应用]时的包名保持一致。

  2. 您需要更新entry/src/main/module.json5文件中的[module -> metadata]配置项:

    • 其中app_id的"value"的值为开发者的APP ID(在AppGallery Connect网站点击"我的项目",在项目列表中找到您的项目,在"项目设置 > 常规"页面的"应用"区域获取"APP ID"的值),详见下图的标号1处。
    • 其中client_id的"value"的值为开发者的OAuth 2.0客户端ID(在AppGallery Connect网站点击"我的项目",在项目列表中找到您的项目,在"项目设置 > 常规"页面的"应用"区域获取"OAuth 2.0客户端ID(凭据):Client ID"的值),详见下图的标号2处。

AppGallery Connect 应用页面

配置内容为:

复制代码
```
{
    "module": {
        // ...
        "metadata": [
            {
                "name": "app_id",
                "value": "***"
            },
            {
                "name": "client_id",
                "value": "***"
            }
       ]
    }
}
```
  1. Index组件中的orderStr需要替换成自己的订单数据,contractStr需要替换成自己的签约信息数据。
相关推荐
在人间耕耘5 小时前
HarmonyOS Vision Kit 视觉AI实战:把官方 Demo 改造成一套能长期复用的组件库
人工智能·深度学习·harmonyos
王码码20357 小时前
Flutter for OpenHarmony:socket_io_client 实时通信的事实标准(Node.js 后端的最佳拍档) 深度解析与鸿蒙适配指南
android·flutter·ui·华为·node.js·harmonyos
HarmonyOS_SDK7 小时前
【FAQ】HarmonyOS SDK 闭源开放能力 — Ads Kit
harmonyos
Swift社区9 小时前
如何利用 ArkUI 框架优化鸿蒙应用的渲染性能
华为·harmonyos
特立独行的猫a10 小时前
uni-app x跨平台开发实战:开发鸿蒙HarmonyOS影视票房榜组件完整实现过程
华为·uni-app·harmonyos·轮播图·uniapp-x
盐焗西兰花12 小时前
鸿蒙学习实战之路-STG系列(5/11)-守护策略管理-添加与修改策略
服务器·学习·harmonyos
盐焗西兰花13 小时前
鸿蒙学习实战之路-STG系列(4/11)-应用选择页功能详解
服务器·学习·harmonyos
lbb 小魔仙15 小时前
鸿蒙跨平台项目实战篇03:React Native Bundle增量更新详解
react native·react.js·harmonyos
特立独行的猫a15 小时前
uni-app x跨平台开发实战:开发鸿蒙HarmonyOS滚动卡片组件,scroll-view无法滚动踩坑全记录
华为·uni-app·harmonyos·uniapp-x
不爱吃糖的程序媛15 小时前
Flutter Orientation 插件在鸿蒙平台的使用指南
flutter·华为·harmonyos