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

介绍

华为支付云侧接口 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内核、鸿蒙南向开发、鸿蒙项目实战)等技术知识点。帮助大家在学习鸿蒙路上快速成长!

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

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

鸿蒙面经

在这里插入图片描述

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

  • 26
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值