人脸实名认证实现方案(微信H5百度云篇)

学习目标:

配置实名认证服务、实现实名认证


学习内容:

  1. 百度智能云实名认证对接
  2. 平台化提供可配置、解耦百度实名认证服务
  3. 封装统一业务服务接口


首先这里的接入方案是标准H5方案,目前看来,微信还没有对百度智能云的这个实名认证服务做技术壁垒,但是不排除LM的小马哥做这种骚操作。如果微信浏览器里要跳到外置浏览器做这个实名认证过程,那就体验不爽了。

一、流程说明

官方的接入步骤与文档地址自行百度。
官方时序图:
在这里插入图片描述
我这边进行的封装与解耦时序图。各个公司可以有自己的配置,我们的平台仅仅是做服务抽象与解耦,只需要各公司提供配置即可。
在这里插入图片描述

二、思路剖析

这里先要看百度云的接入步骤,理解它的设计思路,然后才能在它的思路上做服务封装(任何第三方服务想要平台化都是这个思路)
这边是希望各个公司自行申请百度云服务授权,然后我们再业务系统记录授权信息。公司业务在做服务请求时,通过配置的授权信息与百度云做交互,作为一个中间的纽带。我这边是springCloud微服务架构,对业务模块做了拆解,剖析分析提供以下服务支持,
第三方服务模块提供直接接口

  1. 获取AccesToken
  2. 获取VerifyToken
  3. 指定用户实名认证信息
  4. 获取实名认证url
  5. 查询实名认证结果
    用户服务模块
  6. 用户发起实名认证
  7. 用户获取实名认证结果

三、部分core代码分享

第三方服务service层接口代码


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.net.URLEncodeUtil;
import cn.hutool.json.JSONUtil;
import com.baidubce.http.ApiExplorerClient;
import com.baidubce.http.HttpMethodName;
import com.baidubce.model.ApiExplorerRequest;
import com.baidubce.model.ApiExplorerResponse;
import com.fillersmart.fsihouse.data.common.api.ResponseCodeI18n;
import com.fillersmart.fsihouse.data.core.Result;
import com.fillersmart.fsihouse.data.core.ResultGenerator;
import com.fillersmart.fsihouse.data.vo.thirdapi.face.request.BaiduVerifyRequest;
import com.fillersmart.fsihouse.data.vo.thirdapi.face.verfity.FaceVerifyVo;
import com.fillersmart.fsihouse.thirdservice.controller.util.BaiduFaceUtil;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhengwen
 **/
@Slf4j
@RestController
@RequestMapping("/faceVerfity")
public class FaceVerfityController {
    
    

  /**
   * 获取AccessToken
   *
   * @param baiduVerifyRequest 百度实名request
   * @return 统一出参
   */
  @PostMapping(value = "/getBaiduAccessToken")
  public Result<?> getBaiduAccessToken(@RequestBody BaiduVerifyRequest baiduVerifyRequest) {
    
    
    //参数校验
    Result<?> res = BaiduFaceUtil.checkGetAccessTokenParam(baiduVerifyRequest);
    if (res != null) {
    
    
      return res;
    }

    String path = "https://aip.baidubce.com/oauth/2.0/token";
    ApiExplorerRequest request = new ApiExplorerRequest(HttpMethodName.POST, path);

    // 设置header参数
    request.addHeaderParameter("Content-Type", "application/json;charset=UTF-8");

    // 设置query参数
    request.addQueryParameter("client_id", baiduVerifyRequest.getApiKey());
    request.addQueryParameter("client_secret", baiduVerifyRequest.getSecretKey());
    request.addQueryParameter("grant_type", "client_credentials");

    // 设置jsonBody参数
    String jsonBody = "{}";
    if (MapUtil.isNotEmpty(baiduVerifyRequest.getJsonBody())) {
    
    
      jsonBody = JSONUtil.toJsonStr(baiduVerifyRequest.getJsonBody());
    }
    request.setJsonBody(jsonBody);

    ApiExplorerClient client = new ApiExplorerClient();

    try {
    
    
      ApiExplorerResponse response = client.sendRequest(request);
      // 返回结果格式为Json字符串
      return ResultGenerator.genSuccessResult(response.getResult());
    } catch (Exception e) {
    
    
      log.error("百度智能云获取AccessToken异常,原因:{}", e.getMessage(), e);
      return ResultGenerator.genFailResult(ResponseCodeI18n.GET_TOKEN_FAILED.getMsg());
    }
  }

  /**
   * 获取验证token
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/getBaiduVerifyToken")
  public Result<?> getBaiduVerifyToken(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    String path = "https://aip.baidubce.com/rpc/2.0/brain/solution/faceprint/verifyToken/generate";
    ApiExplorerRequest request = new ApiExplorerRequest(HttpMethodName.POST, path);

    // 设置header参数
    request.addHeaderParameter("Content-Type", "application/json;charset=UTF-8");

    //转换百度请求request
    Result<?> res = BaiduFaceUtil.checkAndAddVerifyTokenParam(faceVerifyVo, request);
    if (res != null) {
    
    
      return res;
    }

    ApiExplorerClient client = new ApiExplorerClient();

    try {
    
    
      ApiExplorerResponse response = client.sendRequest(request);
      // 返回结果格式为Json字符串
      return ResultGenerator.genSuccessResult(response.getResult());
    } catch (Exception e) {
    
    
      log.error("--获取百度人脸verifyToken异常,原因:{}", e.getMessage(), e);
      return ResultGenerator.genFailResult(ResponseCodeI18n.GET_TOKEN_FAILED.getMsg());
    }

  }

  /**
   * 指定用户认证(指定用户信息上报)
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/appointUserCertBaidu")
  public Result<?> appointUserCertBaidu(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    //String path = "https://aip.baidubce.com/solution/faceprint/idcard/submit";
    String path = "https://brain.baidu.com/solution/faceprint/idcard/submit";
    ApiExplorerRequest request = new ApiExplorerRequest(HttpMethodName.POST, path);

    //转换百度请求request
    Result<?> res = BaiduFaceUtil.checkAppointUserCertParam(faceVerifyVo, request);
    if (res != null) {
    
    
      return res;
    }

    // 设置header参数
    request.addHeaderParameter("Content-Type", "application/json;charset=UTF-8");

    ApiExplorerClient client = new ApiExplorerClient();

    try {
    
    
      ApiExplorerResponse response = client.sendRequest(request);
      // 返回结果格式为Json字符串
      return ResultGenerator.genSuccessResult(response.getResult());
    } catch (Exception e) {
    
    
      log.error("--指定用户认证信息异常,原因:{}", e.getMessage(), e);
      return ResultGenerator.genFailResult(ResponseCodeI18n.USER_CERT_FAIL.getMsg());
    }
  }

  /**
   * 获取实名认证url
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/getFaceCertUrlBaidu")
  public Result<?> getFaceCertUrlBaidu(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    //参数校验
    Result<?> res = BaiduFaceUtil.checkGetFaceCertUrlParam(faceVerifyVo);
    if (res != null) {
    
    
      return res;
    }
    String verifyToken = faceVerifyVo.getVerifyToken();
    if (StringUtils.isBlank(verifyToken)) {
    
    
      //accessToken
      String accessToken = faceVerifyVo.getAccessToken();
      if (StringUtils.isBlank(accessToken)) {
    
    
        BaiduVerifyRequest baiduVerifyRequest = BaiduFaceUtil.initBaiduVerifyRequest(faceVerifyVo);
        res = getBaiduAccessToken(baiduVerifyRequest);
        res = BaiduFaceUtil.transSetAccessToken(res, faceVerifyVo);
        if (res != null) {
    
    
          return res;
        }
      }
      //verifyToken
      //先取verifyToken
      res = getBaiduVerifyToken(faceVerifyVo);
      res = BaiduFaceUtil.transSetVerityToken(res, faceVerifyVo);
      if (res != null) {
    
    
        return res;
      }
      verifyToken = faceVerifyVo.getVerifyToken();

      //指定用户认证
      res = appointUserCertBaidu(faceVerifyVo);
      res = BaiduFaceUtil.transSetAppointUserResult(res, faceVerifyVo);
      if (res != null) {
    
    
        return res;
      }

    }

    Map<String, String> certAfterInfo = faceVerifyVo.getCertAfterInfo();
    String successUrl = certAfterInfo.get("successUrl");
    String failUrl = certAfterInfo.get("failUrl");
    StringBuffer urlSbf = new StringBuffer();
    urlSbf.append("https://brain.baidu.com/face/print/?token=");
    urlSbf.append(verifyToken);
    urlSbf.append("&successUrl=").append(URLEncodeUtil.encodeAll(successUrl));
    urlSbf.append("&failedUrl=").append(URLEncodeUtil.encodeAll(failUrl));
    faceVerifyVo.setCertUrl(urlSbf.toString());

    //TODO 是否要避免重复请求呢?是否需要存库呢?

    return ResultGenerator.genSuccessResult(faceVerifyVo);
  }

  /**
   * 获取实名认证结果
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/getFaceCertResultBaidu")
  public Result<?> getFaceCertResultBaidu(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    //参数校验
    String path = "https://aip.baidubce.com/rpc/2.0/brain/solution/faceprint/result/detail";
    ApiExplorerRequest request = new ApiExplorerRequest(HttpMethodName.POST, path);

    //转换百度请求request
    Result<?> res = BaiduFaceUtil.checkGetFaceCertResultParam(faceVerifyVo, request);
    if (res != null) {
    
    
      return res;
    }

    ApiExplorerClient client = new ApiExplorerClient();

    try {
    
    
      ApiExplorerResponse response = client.sendRequest(request);
      // 返回结果格式为Json字符串
      res = ResultGenerator.genSuccessResult(response.getResult());
    } catch (Exception e) {
    
    
      log.error("--获取人脸身份实名认证结果异常,原因:{}", e.getMessage(), e);
      res = ResultGenerator.genFailResult(ResponseCodeI18n.GET_CERT_RESULT_FAIL.getMsg());
    }
    return res;
  }
}

第三方接口层代码


import com.alibaba.fastjson.JSONObject;
import com.fillersmart.fsihouse.data.common.api.ResponseCodeI18n;
import com.fillersmart.fsihouse.data.constant.ConstantsEnum;
import com.fillersmart.fsihouse.data.core.RedisUtil;
import com.fillersmart.fsihouse.data.core.Result;
import com.fillersmart.fsihouse.data.core.ResultCode;
import com.fillersmart.fsihouse.data.core.ResultGenerator;
import com.fillersmart.fsihouse.data.vo.thirdapi.face.request.BaiduVerifyRequest;
import com.fillersmart.fsihouse.data.vo.thirdapi.face.verfity.FaceVerifyVo;
import com.fillersmart.fsihouse.thirdweb.controller.util.FaceVerfityUtil;
import com.fillersmart.fsihouse.thirdweb.service.FaceVerfityRpcService;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author zhengwen
 **/
@Slf4j
@RestController
@RequestMapping("/faceVerfity")
public class FaceVerfityController {
    
    

  @Resource
  private RedisUtil redisUtil;

  @Resource
  private FaceVerfityRpcService faceVerfityRpcService;

  /**
   * 获取AccessToken
   *
   * @param faceVerifyVo 人脸识别入参vo
   * @return 统一出参
   */
  @PostMapping(value = "/getAccessToken")
  public Result<?> getAccessToken(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    Result<?> res = ResultGenerator.genFailResult(ResponseCodeI18n.GET_TOKEN_FAILED.getMsg());
    String supportName = faceVerifyVo.getSupportName();
    if (StringUtils.isBlank(supportName)) {
    
    
      return ResultGenerator.genFailResult(ResponseCodeI18n.SERVICE_SUPPORT_NULL.getMsg());
    }
    ConstantsEnum.ServiceSupportType support = ConstantsEnum.ServiceSupportType.getEnum(
        supportName);
    switch (support) {
    
    
      case BAIDU:
        //先从缓存取
        res = FaceVerfityUtil.getBaiduAccessTokenFromCache(redisUtil, faceVerifyVo);
        if (res == null) {
    
    
          BaiduVerifyRequest baiduVerifyRequest = FaceVerfityUtil.transToBaiduVerfityRequest(
              faceVerifyVo);
          res = faceVerfityRpcService.getBaiduAccessToken(baiduVerifyRequest);
          res = FaceVerfityUtil.transBaiduRespToResult(res, faceVerifyVo, redisUtil);
        }
        break;
      default:

        break;
    }

    return res;
  }

  /**
   * 获取验证token
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/getVerifyToken")
  public Result<?> getVerifyToken(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    Result<?> res = ResultGenerator.genFailResult(ResponseCodeI18n.GET_TOKEN_FAILED.getMsg());
    String supportName = faceVerifyVo.getSupportName();
    if (StringUtils.isBlank(supportName)) {
    
    
      return ResultGenerator.genFailResult(ResponseCodeI18n.SERVICE_SUPPORT_NULL.getMsg());
    }
    ConstantsEnum.ServiceSupportType support = ConstantsEnum.ServiceSupportType.getEnum(
        supportName);
    switch (support) {
    
    
      case BAIDU:
        //先从缓冲取
        res = FaceVerfityUtil.getBaiduAccessTokenFromCache(redisUtil, faceVerifyVo);
        if (res == null) {
    
    
          res = getAccessToken(faceVerifyVo);
        }
        if (res != null && res.getCode().equals(ResultCode.SUCCESS.code())) {
    
    
          res = faceVerfityRpcService.getBaiduVerifyToken(faceVerifyVo);
          res = FaceVerfityUtil.transBaiduVerifyTokenResp(res, faceVerifyVo);
        }
        break;
      default:
        break;
    }
    return res;
  }

  /**
   * 指定用户认证(指定用户信息上报)
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/appointUserCert")
  public Result<?> appointUserCert(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    Result<?> res = ResultGenerator.genFailResult(ResponseCodeI18n.USER_CERT_FAIL.getMsg());
    String supportName = faceVerifyVo.getSupportName();
    if (StringUtils.isBlank(supportName)) {
    
    
      return ResultGenerator.genFailResult(ResponseCodeI18n.SERVICE_SUPPORT_NULL.getMsg());
    }
    ConstantsEnum.ServiceSupportType support = ConstantsEnum.ServiceSupportType.getEnum(
        supportName);
    switch (support) {
    
    
      case BAIDU:
        res = faceVerfityRpcService.appointUserCertBaidu(faceVerifyVo);
        //校验转换统一出参
        res = FaceVerfityUtil.transBaiduAppointUserCertResp(res, faceVerifyVo);
        break;
      default:
        break;
    }
    return res;
  }

  /**
   * 获取实名认证url
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/getFaceCertUrl")
  public Result<?> getFaceCertUrl(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    //参数校验
    Result<?> res = FaceVerfityUtil.checkGetFaceCertUrlParam(faceVerifyVo);
    if (res != null) {
    
    
      return res;
    }

    //先取verifyToken
    res = getVerifyToken(faceVerifyVo);
    if (res != null && res.getCode().equals(ResultCode.FAIL.code())) {
    
    
      return res;
    } else {
    
    
      faceVerifyVo = JSONObject.parseObject(JSONObject.toJSONString(res.getData()),
          FaceVerifyVo.class);
    }

    //指定用户认证
    res = appointUserCert(faceVerifyVo);
    if (res != null && res.getCode().equals(ResultCode.FAIL.code())) {
    
    
      return res;
    } else {
    
    
      faceVerifyVo = JSONObject.parseObject(JSONObject.toJSONString(res.getData()),
          FaceVerifyVo.class);
    }

    String supportName = faceVerifyVo.getSupportName();
    ConstantsEnum.ServiceSupportType support = ConstantsEnum.ServiceSupportType.getEnum(
        supportName);
    switch (support) {
    
    
      case BAIDU:
        res = faceVerfityRpcService.getFaceCertUrlBaidu(faceVerifyVo);
        break;
      default:
        break;
    }
    return res;
  }

  /**
   * 获取实名认证结果
   *
   * @param faceVerifyVo 人脸验证vo
   * @return 统一出参
   */
  @PostMapping(value = "/getFaceCertResult")
  public Result<?> getFaceCertResult(@RequestBody FaceVerifyVo faceVerifyVo) {
    
    
    //参数校验
    Result<?> res = FaceVerfityUtil.checkGetFaceCertResultParam(faceVerifyVo);
    if (res != null) {
    
    
      return res;
    }

    String supportName = faceVerifyVo.getSupportName();
    ConstantsEnum.ServiceSupportType support = ConstantsEnum.ServiceSupportType.getEnum(
        supportName);
    switch (support) {
    
    
      case BAIDU:
        res = faceVerfityRpcService.getFaceCertResultBaidu(faceVerifyVo);
        //转换结果
        FaceVerfityUtil.transBaiduCertResultRespToResult(res, faceVerifyVo);
        break;
      default:
        break;
    }
    return res;
  }


}

在接口层是做了将service层返回的数据做转换未业务的统一出参的,用户服务层提供的2个接口的代码就不能分享了,各位可以根据我画的时序图自行实现。实际上里面也就是做了公司配置的查询,再组合调用第三方服务模块提供的接口,postman的接口请求示例倒是可以分享下,大家可以根据入参结合时序图理解实现这2个接口。

四、postman接口请求示例分享

  1. 获取第三方服务AccessToken
    { {apiUrl}}/faceVerfity/getAccessToken
{
    
    
    "authInfo": {
    
    
        "apiKey": "百度智能云apiKey", //apiKey 必传
        "secretKey": "百度智能云secretKey" //secretKey 必传
    },
    "supportName": "baidu" //第三方服务费,必传
}
  1. 获取人脸校验verifyToken
    { {apiUrl}}/faceVerfity/getVerifyToken
{
    
    
    "authInfo": {
    
    
        "apiKey": "百度智能云apiKey", //apiKey 必传
        "secretKey": "百度智能云secretKey" //secretKey 必传
    },
    "accessToken": "", //鉴权token,非必传,不传,先取缓存,缓存没有内部会主动去取
    "planId": 新建的H5小程序方案ID, //方案ID,必传
    "supportName": "baidu" //第三方服务费,必传
}
  1. 指定用户认证(指定用户信息上报)
    { {apiUrl}}/faceVerfity/appointUserCert
{
    
    
    "authInfo": {
    
    
        "apiKey": "百度智能云apiKey", //apiKey 必传
        "secretKey": "百度智能云secretKey" //secretKey 必传
    },
    "certUserInfo": {
    
    
        "idName": "xxx", //姓名,必传
        "idNo": "42900身份证", //证件号码,必传
        "certificateType": 0 //证件类型:非必传,0大陆居民二代身份证1港澳台居民来往内地通行证2外国人永久居留证3定居国外的中国公民护照
    },
    "verifyToken":"接口2返回的verifyToken",
    "accessToken": "", //鉴权token,非必传,不传,先取缓存,缓存没有内部会主动去取
    "planId": 新建的H5小程序方案ID, //方案ID,必传
    "supportName": "baidu" //第三方服务费,必传
}
  1. 获取实名认证url
    { {apiUrl}}/faceVerfity/getFaceCertUrl
{
    
    
    "authInfo": {
    
    
        "apiKey": "xxxx", //apiKey 必传
        "secretKey": "xxxx" //secretKey 必传
    },
    "certUserInfo": {
    
    
        "idName": "xx", //姓名,必传
        "idNo": "xxx", //证件号码,必传
        "certificateType": 0 //证件类型:非必传,0大陆居民二代身份证1港澳台居民来往内地通行证2外国人永久居留证3定居国外的中国公民护照
    },
    "certAfterInfo": {
    
    
        "successUrl": "https://blog.csdn.net/", //认证成功后跳转地址,必传。这里建议传业务url,从哪里进的跳回哪里
        "failUrl": "https://blog.csdn.net/zwrlj527" //认证失败跳转地址,必传
    },
    "verifyToken": "", //验证token,非必传,不传会自行取,要自己传就通过前面的接口获取
    "accessToken": "", //鉴权token,非必传,不传,先取缓存,缓存没有内部会主动去取
    "planId": , //方案ID,必传
    "supportName": "baidu" //第三方服务费,必传
}
  1. 获取实名认证结果

{ {apiUrl}}/faceVerfity/getFaceCertResult

{
    
    
    "verifyToken": "xxx", //验证token,非必传,不传会自行取,要自己传就通过前面的接口获取
    "accessToken": "xxx", //鉴权token,非必传,不传,先取缓存,缓存没有内部会主动去取
    "supportName": "baidu" //第三方服务费,必传
}

以上每一步的入参对象都是环环相扣,上一步的出参可以作为下一步的入参。
用户模块的接口
1、 租户发起实名认证
{ {apiUrl}}/rent/user/rentUserIdCodeCert

{
    
    
    "rentUserDto": {
    
    
        "id": 1151, //租户id,必传
        "custName": "xxx", //租户姓名,必传
        "certType": 1, //认证类型,必传, 1 身份证 2 学生证 3 军官证 4 驾驶证 5护照 6港澳通行证 7外国人永久居留证
        "certCode": "xxxx", //身份号,必传
        "orgId": 60 //公司id,必传
    },
    "faceVerifyVo": {
    
    
        "certAfterInfo": {
    
    
            "successUrl": "https://blog.csdn.net/", //认证成功后跳转地址,必传。这里建议传业务url,从哪里进的跳回哪里
            "failUrl": "https://blog.csdn.net/zwrlj527" //认证失败跳转地址,必传
        }
    }
}

2、获取租户实名认证结果
{ {apiUrl}}/rent/user/getRentUserCertResult

{
    
    
    "rentUserDto": {
    
    
        "id": 1151, //租户id,必传
        "custName": "xx", //租户姓名,必传
        "certType": 1, //认证类型,必传, 1 身份证 2 学生证 3 军官证 4 驾驶证 5护照 6港澳通行证 7外国人永久居留证
        "certCode": "xxx", //身份号,必传
        "orgId": 60 //公司id,必传
    },
    "faceVerifyVo": {
    
     //获取人脸实名认证url返回的data对象
        "accessToken": "xxx",
        "authInfo": {
    
    
            "secretKey": "xxx",
            "apiKey": "xx"
        },
        "certAfterInfo": {
    
    
            "successUrl": "https://blog.csdn.net/",
            "failUrl": "https://blog.csdn.net/zwrlj527"
        },
        "certMatch": null,
        "certResult": null,
        "certUrl": "https://brain.baidu.com/face/print/?token=xxxx&successUrl=https%3A%2F%2Fblog.csdn.net%2F&failedUrl=https%3A%2F%2Fblog.csdn.net%2Fzwrlj527",
        "certUserInfo": {
    
    
            "idName": "xxx",
            "idNo": "xxxx"
        },
        "planId": xx,
        "supportName": "baidu",
        "verifyToken": "xxx"
    }
}

2个接口的入参是相扣的,接口1的出参人脸认证对象,直接可以整个在扔进去,其实也是为了方便,前端是需要做简单的组合就行了。

扫描二维码关注公众号,回复: 13771345 查看本文章

五、总结

  1. 接入还比较简单,流程清晰
  2. 官方文档也很清楚
  3. 服务方工单响应很快,过程中我们获取认证结果是遇到了报错的,但是不是我们设计的流程的问题,而是授权的问题。报错内容:
    在这里插入图片描述
    实际上上查看接口返回的message是有如下内容的
    在这里插入图片描述
  4. 在线接口调试很酸爽
    在这里插入图片描述

好了,就分享到这里,希望能帮到各位博友。最后愿世界和平,疫情早日消除,同呼吸共命运。

猜你喜欢

转载自blog.csdn.net/zwrlj527/article/details/123282613