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

news2024/11/24 7:20:01

介绍

华为支付云侧接口 Java SDK Sample。

官方 Java 语言开发库pay-javacoreservice 组成:

  • core 为基础库。包含自动签名和验签的 HTTP 客户端、回调处理、加解密库。
  • service 为业务服务。基于业务场景提供不同的业务类,其下的方法为对应的http接口。

本示例展示通过pay-java使用华为支付服务提供的预下单预签约API接口并对回调通知敏感信息加解密等其他内容进行说明。

需要使用华为支付服务接口:

  1. 预下单:/api/v2/aggr/preorder/create/app (参考[直连商户-预下单])
  2. 预签约:/api/v2/contract/presign/app (参考[直连商户-预签约])
  3. 更多接口详细查看:[华为支付服务API参考]

效果预览

运行成功日志输出

1

demo工程的配置与使用

配置demo工程的步骤如下

  1. 配置好java环境:JDK 1.8及以上。
  2. 配置好Maven集成环境。
  3. 获取商户配置后将配置添加到配置文件petalpayconfig.properties。
  4. 启动demo工程:src/main/java/com.huawei.petalpay.paymentservice.example/ExampleApplication.java

具体实现

预下单:

  • 商户服务器按照商户模型调用华为支付提供的[直连商户预下单]或[服务商/平台类商户预下单]接口。
  • 获取预下单号(prepayId),然后组建orderStr返回给客户端。

使用示例如下:

/** Native 支付下单为例 */
public class PrepayQuickStart {
    public static PreOrderCreateRequest getRequest() {
        return PreOrderCreateRequestV2.builder()
            .mercOrderNo("pay-example-" + System.currentTimeMillis()) // 每次订单号都要变,请将pay-example-修改为商户自己的订单前缀
            .appId(MercConfigUtil.APP_ID)  // appId,需要配置为与商户绑定的正确的appId
            .mercNo(MercConfigUtil.MERC_NO) // 商户的商户号
            .tradeSummary("请修改为对应的商品简称") // 请修改为商品简称
            .bizType("100002") // (100001:虚拟商品购买,100002:实物商品购买,100003:预付类账号充值,100004:航旅交通服务,100005:活动票务订购,100006:商业服务消费,100007:生活服务消费,100008:租金缴纳,100009:会员费缴纳,100011:其他商家消费,100037:公共便民服务)
            .totalAmount(2L)
            .callbackUrl("https://www.xxxxxx.com/hw/pay/callback") //回调通知地址,通知URL必须为直接可访问的URL,要求为https地址。最大长度为512。请替换为格式正确的结果通知回调地址。
            .build();
    }

    public static void main(String[] args) {
        DefaultPetalPayClient payClient = new DefaultPetalPayClient(MercConfigUtil.getMercConfig());
        // 配置请求参数
        AggrPay aggrPay = new AggrPay(payClient);
        // 组装对象
        PreOrderCreateRequest preOrderReq = getRequest();
        PreOrderCreateResponse response = null;
        try {
            response = aggrPay.aggrPreOrderForApp(preOrderReq);
        } catch (Exception e) {
            System.out.println(e);
        }
        System.out.println(JsonUtils.obj2Json(response));
    }
}

预签约:

  • 商户服务器按照商户模型调用华为支付提供的[直连商户预签约]接口。
  • 获取预下单号(preSignNo),构建contractStr参数,然后返回给客户端。

使用示例如下:

import com.huawei.petalpay.paymentservice.core.tools.JsonUtils;

public class PrepayQuickStart {
   public static void main(String[] args) {
      System.out.println(JsonUtils.obj2Json(contractPreSignAppV2()));
   }
   public CommonResponse contractPreSignAppV2() {
      DefaultPetalPayClient payClient = new DefaultPetalPayClient(MercConfigUtil.getMercConfig());
      // 组装对象
      PreSignRequestV2 preSignReq = getPreSignRequestV2();
      PreSignResponse response = null;
      try {
         response = payClient.execute("POST", "/api/v2/contract/presign/app", PreSignResponse.class, preSignReq);
      } catch (Exception e) {
         // todo 异常处理
         log.error("request error ", e);
         return CommonResponse.buildErrorRsp(e.getMessage());
      }
      if (!validResponse(response)) {
         // todo 异常处理
         log.error("response is invalid ", response);
         return CommonResponse.buildFailRsp(response);
      }
      return CommonResponse.buildSuccessRsp(payClient.buildContractStr(response.getPreSignNo()));
   }
   
   public static boolean validResponse(BaseGwRspWithSign rsp) {
      return rsp != null || "000000".equals(rsp.getResultCode());
   }
   
   private PreSignRequestV2 getPreSignRequestV2() {
      return PreSignRequestV2.builder().appId(MercConfigUtil.APP_ID) // appId,需要配置为与商户绑定的正确的appId
              .mercContractCode("pay-example-" + System.currentTimeMillis()) // 签约协议号,每次请求都要变,请将pay-example-修改为商户自己的订单前缀
              .mercNo(MercConfigUtil.MERC_NO) // 商户号
              .planId("100") // 协议模板ID,该模板ID是商户在向华为支付提交代扣权限申请时由华为支付生成。请填写正确的协议模板ID。
              .callbackUrl("https://www.xxxxxx.com/hw/sign/callback") //回调通知地址,通知URL必须为直接可访问的URL,要求为https地址。最大长度为512。请替换为格式正确的结果通知回调地址。
              .build();
   }
}

从示例可见,使用 SDK 不需要计算请求签名和验证应答签名。

参考:

  1. pay-example/src/main/java/com.huawei.petalpay.paymentservice.example/controller/MercApiController.java

回调通知

  • 开发者需要在开发者的服务器上创建一个公开的 HTTP 端点,接受来自华为支付的回调通知。
  • 接收到回调通知,使用VerifyTools.getCallbackResult方法来验证回调通知并实现CallBackHandleInterface接口来处理回调结果。

使用示例如下:

public class CallbackController {
    /**
     * 华为支付通知回调签名公钥
     */
    public static final String HW_PAY_PUBLIC_KEY_FOR_CALLBACK = "";

    /**
     * 支付回调模拟接口(不同的场景,用不同的接口处理)
     *
     * @param request 入参
     * @return CallBackBaseResponse
     */
    @PostMapping(value = "/v1/transation/result", produces = MediaType.APPLICATION_JSON_VALUE)
    public CallBackBaseResponse transationResultNotify(HttpServletRequest request) {
        // TransResultCallbackReq-支付回调实体类
        return VerifyTools.getCallbackResult(request, HW_PAY_PUBLIC_KEY_FOR_CALLBACK, reqString -> {
            NotifyPaymentReq callbackReq = JSONObject.parseObject(reqString, NotifyPaymentReq.class);
            // 商户自行业务处理
            doProcess(callbackReq);
        });
    }

    /**
     * 业务处理
     *
     * @param reqBody
     */
    private void doProcess(Object reqBody) {
        log.info("Please write merchant business process here");
    }
}

目前不同通知业务结果的通知类存在差异,对应的映射关系如下:

  • NotifyPaymentReq: 支付及代扣结果回调
  • NotifyRefundReq: 退款结果回调
  • NotifyContractReq: 签约结果回调
  • NotifyAllocReq: 分账结果回调
  • NotifyReclaimAllocReq: 分账回收结果回调
  • NotifyCombinedTransactionReq: 合单支付结果回调

敏感信息加解密

为了保证通信过程中敏感信息字段(如用户的住址、银行卡号、手机号码等)的机密性, 华为支付要求加密上送的敏感信息。对应的字段在api接口文档中标注。 使用示例如下:

static class RegisterSubmercReq {
   private String message;
   public RegisterSubmercReq(String message) {
      this.message = message;
   }
}
public static void main(String[] args) {
   PetalPayClient payClient = new DefaultPetalPayClient(MercConfigUtil.getMercConfig());
   String sessionKey = SM4Util.getSM4GCMSessionKey();
   String message = "xxxx";
   RegisterSubmercReq req = new RegisterSubmercReq(SM4Util.getSM4GCMContent(sessionKey, message));
   RequestConfig config = RequestConfig.builder()
           .publicKeyForSessionKey(MercConfigUtil.HW_PUBLIC_KEY_FOR_SESSIONKEY)
           .sessionKey(sessionKey)
           .build();
   try {
      MgmtSubmercRsp response = payClient.execute(
              "POST", "/api/v1/partner/mgmt/submerc/register", MgmtSubmercRsp.class, config, req);
   } catch (Exception e) {
      System.out.println(e);
   }
   System.out.println(JsonUtils.obj2Json(response));
}

自定义httpClient

SDK 使用 [HttpClient] 作为默认的 HTTP 客户端。 开发者可以直接使用 DefaultPetalPayClient来发起http请求。

开发者如果需要自定义接口请求的client以做请求中的日志打印等操作,可以通过继承PetalpayClient来实现:

public class MercPetalPayClient extends PetalPayClient {
    public MercPetalPayClient(PetalPayConfig petalPayConfig) {
        super(petalPayConfig);
    }

    @Override
    public String doPost(String url, Map<String, String> headers, String requestBody) throws Exception {
        // todo
    }

    @Override
    public String doGet(String url, Map<String, String> headers, String requestBody) throws Exception {
        // todo
    }
}

新增或拓展业务接口

开发者如果未及时更新SDK,需要使用最新的http接口,可直接调用petalpayClient的execute方法,进行接口请求。

对应的方法示例如下:

    execute(String httpMethod,String apiUrl,Class<T> rspType);
    execute(String httpMethod,String apiUrl,Class<T> rspType, Object requestObj);
    execute(String httpMethod,String apiUrl,Class<T> rspType, RequestConfig requestConfig, Object requestObj);

依赖

  • 仓库地址
<mirror>
  <id>central</id>
  <mirrorOf>central</mirrorOf>
  <url>https://developer.huawei.com/repo/</url>
</mirror>
  • Maven依赖
<dependency>
    <groupId>com.huawei.petalpay</groupId>
    <artifactId>pay-java</artifactId>
    <version>1.0.0.295</version>
</dependency>

约束与限制

通知回调接口

  • 对于回调通知,如果华为支付未收到application/json类型响应的数据,或收到应答数据不是{“resultCode”:“000000”,“resultDesc”:“Success.”} ,华为支付会通过一定的周期定期重新发起通知,但不保证通知最终能成功。

  • 相同通知可能多次重复发送给商户服务器,商户服务器需要正确实现以应对重复请求,处理建议:

    • 在商户服务器收到通知进行业务处理前先检查对应业务状态,对于未处理过的场景才进行业务处理。已处理的场景则直接返回成功。
    • 在业务处理时,合理设计同步机制防止并发问题。
  • 如果在预期时间内未收到Payment Kit的回调请求,请排查提供的callbackUrl网络是否连通。如排除网络连通性问题,请调用同步查询接口确认订单状态。排查建议:

    • 确认callbackUrl为商户系统真实地址,保证url中的域名或IP是外网可以正常访问的。不能填写localhost、127.0.0.1、192.168.x.x、10.xx.xx.xx等。
    • callbackUrl必须为[https://开头的完整地址。]
  • 对于收到的异步回调请求,请务必进行验签处理并在验签通过后进行后续业务流程。否则可能因为信息泄露导致对商户潜在的攻击,造成资金损失。

  • 因商户自身系统实现问题导致的业务异常,资金损失,由商户自行承担。

  • 如商户对支付回调地址有IP防火墙策略限制,需要对以下网段开通允许名单,后续有变动时会在此处更新。

    • 124.70.118.0/24
    • 139.159.166.0/24
  • 商户系统收到回调通知时,需要在3秒内返回应答响应,否则华为支付会认为通知失败,会触发重试机制。

  • 商户系统收到异步通知并返回{“resultCode”:“000000”,“resultDesc”:“Success.”} 时,服务器异步通知参数 callbackId 才会失效。同一个异步通知请求的多次重试callbackId是不变的。

接口约束

  • 请勿将开发者的服务器的IP允许清单设置成用于限制华为的出口IP地址。IP允许清单本身并不能提高安全性且会给业务发展带来约束,在消息层面已有更安全的RSA签名机制条件下,没有存在价值。若开发者不遵守此约定带来的后果将由开发者自行承担。

  • 地址必须支持HTTPS协议且具有合法商用证书,否则无法正常接收通知消息。

  • 支持的TLS协议版本:1.2 / 1.3。

  • 支持的加密套件列表:

    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_DSS_WITH_AES_128_GCM_SHA256,TLS_DHE_DSS_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256

以上就是本篇文章所带来的鸿蒙开发中一小部分技术讲解;想要学习完整的鸿蒙全栈技术。可以在结尾找我可全部拿到!
下面是鸿蒙的完整学习路线,展示如下:
1

除此之外,根据这个学习鸿蒙全栈学习路线,也附带一整套完整的学习【文档+视频】,内容包含如下

内容包含了:(ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

鸿蒙【北向应用开发+南向系统层开发】文档

鸿蒙【基础+实战项目】视频

鸿蒙面经

在这里插入图片描述

为了避免大家在学习过程中产生更多的时间成本,对比我把以上内容全部放在了↓↓↓想要的可以自拿喔!谢谢大家观看!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1983594.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

openai-dotnet:OpenAI官方提供的.NET SDK库!

自从ChatGPT大火以来&#xff0c;针对OpenaAI提供的API接口&#xff0c;封装的SDK库非常多。 之前也推荐过几个.Net版本&#xff0c;今天推荐下OpenAI官方提供的.NET 库&#xff01; 01 项目简介 openai-dotnet是OpenAI 官方提供的 .NET库&#xff0c;用于方便.NET应用程序中…

【Java数据结构】---初始数据结构

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 前言 从今天开始我们就要学习Java…

搭建基于树莓派的Linux学习环境(TODO)

主要是想学一下Linux内核&#xff0c;所以搭一套环境&#xff0c;其实有几个选择&#xff0c;都是我买了板子的。 首先是正点原子的RK3568&#xff0c;最早是想弄安卓&#xff0c;但是SDK的大小真的把我劝退了&#xff0c;动不动几百个G的空间&#xff0c;还有就是保底16个G的…

108 将有序数组转换为二叉搜索树

解题思路&#xff1a; 平衡二叉树&#xff0c;又称自平衡二叉搜索树&#xff08;简称AVL树&#xff09;&#xff0c;其特点如下: 每个子树都为平衡二叉树高度平衡&#xff1a;任意节左子树与右子树高度差不超过1排序树&#xff1a;左子树的所有节点的值小于该节点&#xff0c;…

算法回忆录(3)

11. 假设有7个物品&#xff0c;它们的重量和价值如下表所示。若这些物品均不能被分割&#xff0c;且背包容量M&#xff1d;150&#xff0c;设计算法求解怎么装才能使得获取的价值最大&#xff1f;请写出伪代码。 #include <stdio.h>#define MAX_ITEMS 100 #define …

怎么读取FRM、MYD、MYI数据文件

一、介绍frm、MYD、MYI文件 在MySQL中&#xff0c;使用MyISAM存储引擎时&#xff0c;数据库表会被分割成几个不同的文件文件描述功能扩展名FRM 文件表结构定义文件存储表的结构信息&#xff0c;字段、索引等.FRMMYD 文件数据文件包含表的实际数据.MYD&#xff08;MYData&#x…

Vue3安装ffmpeg做视频截取报错

通过 yarn 安装 ffmpeg 时报错。 即&#xff0c;执行以下指令时报错&#xff1a; yarn add ffmpeg/ffmpeg^0.10.0 yarn add ffmpeg/core^0.10.0错误信息&#xff1a; node_modules\pngquant-bin: Command failed. Error: pngquant failed to build, make sure that libpng-d…

Unity强化工程 之 SpriteRender

本文仅作笔记学习和分享&#xff0c;不用做任何商业用途 本文包括但不限于unity官方手册&#xff0c;unity唐老狮等教程知识&#xff0c;如有不足还请斧正 1.SpriteRenderer是什么 渲染精灵用的&#xff0c;是渲染的核心组件&#xff0c;有许多重要参数所以要详细讲一讲 Spri…

从数据孤岛到一体化平台:PLM系统的变革之路

在当今快速变化的商业环境中&#xff0c;产品生命周期管理&#xff08;Product Lifecycle Management, PLM&#xff09;系统已成为企业提升竞争力、加速产品创新、优化资源配置的关键工具。相较于传统的产品数据管理&#xff08;Product Data Management, PDM&#xff09;系统和…

WPF MVVM模式图片占用问题

在很久以前就遇到这个问题&#xff0c;当时解决了&#xff0c;这过了几年&#xff0c;又遇到这个问题&#xff0c;这里做个总结&#xff0c;防止下次再踩坑了&#xff0c;也顺便帮助一下同样遇到这个问题的朋友 。 出现这个问题的原因是&#xff1a;将文件路径绑定到Image的Sou…

BUUCTF [安洵杯 2019]easy_serialize_php 1

打开题目&#xff0c;看到一串php代码&#xff0c;试着代码审计一下&#xff0c;看一下有用信息 可以看出是通过$_SESSION[img]来读取文件 extract可以将数组中的变量导入当前变量表 也就是说我们可以伪造$_SESSION 数组中的所有数据 这里传递一个参数fphpinfo 先用hackbar进…

软件工程课程实习报告(仅供参考)

一&#xff1a;实习内容设计与实现&#xff1a; 实习一&#xff1a;Git分布式版本控制 本实验的主要目的是学习和掌握Git作为版本控制工具的基本使用方法&#xff0c;特别是在团队协作开发中的重要性。具体目标包括&#xff1a; 1. 理解Git的基本概念和工作原理&#xff0c;…

【AI】可变形卷积Deformable Conv

卷积对大家来说并不陌生了&#xff0c;这里主要描述Deformable Conv。其在论文中也是常见的一个术语&#xff0c;Deformable Convolutional Networks(DCN) 还可以细分成可变形卷积、对候选区域的池化等。 传统卷积操作 将特征图分成一个个与卷积核大小相同的部分&#xff0c;…

k8s—部署dashboard可视化界面

1、下载recommended.yaml配置文件 1&#xff09;根据自己安装的kubernetes版本安装适配的dashboard 我安装的kubernetes是1.24.2版本的&#xff0c;需要安装v:2.6.1版本的dashboard 2&#xff09;下载地址&#xff1a;https://raw.githubusercontent.com/kubernetes/dashboa…

【机器学习】神经网络的无限可能:从基础到前沿

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 引言 在当今人工智能的浪潮中&#xff0c;神经网络作为其核心驱动力之一&#xff0c;正以前所未有的速度改变着我们的世界。从图像识别到自然语言处理&#xff0c;从自动驾驶到医疗诊断&#xff0c;神经网络的…

electron 配置、打包 -报错解决

目录 一、配置途中遇到的问题&#xff1a; 二、 make 配置好后开始打包 三、Electron-builder 打包报错 一、配置途中遇到的问题&#xff1a; 1. 安装 yarn add electron -D 一直卡在这里失败 一直卡可以使用下面这个&#xff0c;然后再重新装依赖 1. 采用新的镜像地址 npm …

proteus仿真c51单片机(二)中断控制流水灯(电路设计及代码)

实验要求 8路流水灯&#xff0c;K1和K2都未按下时&#xff0c;主程序执行LED流水灯程序&#xff0c;K1按下时&#xff0c;左右4只LED交替闪烁&#xff0c;K2按下时8只LED全部闪烁4次&#xff0c;设置外部中断1为高优先级。 实验步骤 1、打开PROTEUS软件选取元件&#xff0c…

未授权访问漏洞(重点版─=≡Σ(((つ•̀ω•́)つ)

1.* Redis 搭建靶场环境&#xff1a; 进入目录:cd/vulhub-master/redis/4-unacc 启动:docker-compose up-d 检查:docker-compose ps vi docker-compose.yml //查看端口和版本号 安装redis工具 在kali上安装redis进行服务链接 #安装redis apt-get install redis #redi…

GD 32 IIC 驱动代码

前言&#xff1a; 学会IIC驱动的原理&#xff0c;时序和代码实现 1.0 GPIO初始化 从原理图中可以看出IIC对应的时钟线和数据线在PB端口&#xff0c;因此需要初始化GPIOB的时钟&#xff0c;同时初始化GPIOB_PIN_6 | 7,的引脚&#xff0c;设置为开漏输出模式。 什么事开漏&…

构建二叉树并后序遍历

题目来源&#xff1a;牛客网清华考研oj题 http://www.nowcoder.com/questionTerminal/4b91205483694f449f94c179883c1fef 题目&#xff1a;如下图 答案&#xff1a;如下图 #include<stdio.h> #include<stdlib.h>typedef struct TreeNode{char val;struct TreeNod…