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


    华为支付服务

    介绍

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

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

    效果预览

    1

    Sample工程的配置与使用

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

    1. [创建项目]及[应用]。
    2. 打开Sample应用,使用[AppGallery Connect]应用的包名替换app.json5文件中的bundleName属性值。
    3. 使用[AppGallery Connect]应用的配置更新module.json5文件相关配置,配置client_id及app_id属性值。
    4. 详细可参见指南[开发准备]。

    具体实现

    单次支付:

    • 商户服务器按照商户模型调用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 应用页面

    2

    配置内容为:

    ```
    {
        "module": {
            // ...
            "metadata": [
                {
                    "name": "app_id",
                    "value": "***"
                },
                {
                    "name": "client_id",
                    "value": "***"
                }
           ]
        }
    }
    ```
    
    1. Index组件中的orderStr需要替换成自己的订单数据,contractStr需要替换成自己的签约信息数据。
  • 相关阅读:
    AIGC:python 文生图代码(python + stable-diffusion+ cuda)
    git如何拉去某个tag的代码
    uniapp 滑动页面至某个元素或顶部
    Linux 进程信号
    Supervisor监控Go程序
    Excel中文本数字单元格批量转换(不影响公式单元格)
    MySQL(五) 数据恢复
    python爬虫基础-response响应头
    【HDFS】ResponseProcessor线程详解以及客户端backoff反压
    MyBatis-Plus 和swagger
  • 原文地址:https://blog.csdn.net/2301_76813281/article/details/140954719