【金融项目】尚融宝项目(九)

18、账户绑定

18.1、需求介绍

18.1.1、运行汇付宝

1、数据库

hfb.sql

2、程序

hfb

3、数据库配置

application-dev.yml 中修改数据库配置

4、启动程序

端口:9999

18.1.2、参考文档

1、传入参数

参考《汇付宝商户账户技术文档》业务接口3.1参数说明

2、返回结果

参考《汇付宝商户账户技术文档》业务接口3.2返回/通知结果

3、数据接口

参考《汇付宝商户账户技术文档》业务接口3.3账户绑定

18.1.3、账户绑定

18.1.3.1、账户绑定流程

尚融宝应该在网站引导客户在“资金托管平台“开设账户。也就是说投资人和借款人必须在资金托管平台页面上自主开户,与尚融宝建立对应的账户体系。

以后所有的资金操作都会到“资金托管平台”进行,绑定账户流程如图:

【金融项目】尚融宝项目(九)_第1张图片

18.1.3.2、相关数据库表

【金融项目】尚融宝项目(九)_第2张图片

18.2、调用汇付宝实现账户创建

18.2.1、准备

18.2.1.1、引入HttpUtils

guigu-common中引入HttpUtils工具类

这个工具类使用了另一个常见的远程连接工具:java.net.HttpURLConnection

18.2.1.2、添加依赖

service-base中添加依赖


<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>fastjsonartifactId>
dependency>

18.2.1.3、添加辅助类

service-core中添加FormHelper:构建表单工具

service-core中添加HfbConst:常量定义

service-core中添加RequestHelper:签名工具

【金融项目】尚融宝项目(九)_第3张图片

18.2.1.4、定义UserBindVO

service-core中添加

package com.atguigu.srb.core.pojo.vo;

@Data
@ApiModel(description = "账户绑定")
public class UserBindVO {
    @ApiModelProperty(value = "身份证号")
    private String idCard;
    @ApiModelProperty(value = "用户姓名")
    private String name;
    @ApiModelProperty(value = "银行类型")
    private String bankType;
    @ApiModelProperty(value = "银行卡号")
    private String bankNo;
    @ApiModelProperty(value = "手机号")
    private String mobile;
}

18.2.1.5、创建枚举

service-core中创建包enums,创建枚举UserBindEnum

package com.atguigu.srb.core.enums;

@AllArgsConstructor
@Getter
public enum UserBindEnum {
    NO_BIND(0, "未绑定"),
    BIND_OK(1, "绑定成功"),
    BIND_FAIL(-1, "绑定失败"),
    ;
    private Integer status;
    private String msg;
}

完整的枚举源代码:资料中 java代码\service-core\enums目录

18.2.2、后端接口实现

18.2.2.1、要动态构建的表单模板

DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  <head> head>
  <body>
    <form name="form" action="远程地址" method="post">
      
      <input type="text" name="mobile" value="13900000000" />
      <input type="text" name="sign" value="123456" />
    form>
    <script>
      document.form.submit()
    script>
  body>
html>

18.2.2.2、Controller

UserBindController

package com.atguigu.srb.core.controller.api;

@Api(tags = "会员账号绑定")
@RestController
@RequestMapping("/api/core/userBind")
@Slf4j
public class UserBindController {
    @Resource
    private UserBindService userBindService;
    @ApiOperation("账户绑定提交数据")
    @PostMapping("/auth/bind")
    public R bind(@RequestBody UserBindVO userBindVO, HttpServletRequest request) {
        String token = request.getHeader("token");
        Long userId = JwtUtils.getUserId(token);
        String formStr = userBindService.commitBindUser(userBindVO, userId);
        return R.ok().data("formStr", formStr);
    }
}

18.2.2.3、Service

接口:UserBindService

/**
     * 账户绑定提交到托管平台的数据
     */
String commitBindUser(UserBindVO userBindVO, Long userId);

相关常量:HfbConst

/**
* 用户绑定
*/
//用户绑定汇付宝平台url地址
public static final String USERBIND_URL = "http://localhost:9999/userBind/BindAgreeUserV2";
//用户绑定异步回调
public static final String USERBIND_NOTIFY_URL = "http://localhost/api/core/userBind/notify";
//用户绑定同步回调
public static final String USERBIND_RETURN_URL = "http://localhost:3000/user";

实现:UserBindServiceImpl

@Override
public String commitBindUser(UserBindVO userBindVO, Long userId) {
    //查询身份证号码是否绑定
    QueryWrapper<UserBind> userBindQueryWrapper = new QueryWrapper<>();
    userBindQueryWrapper
        .eq("id_card", userBindVO.getIdCard())
        .ne("user_id", userId);
    UserBind userBind = baseMapper.selectOne(userBindQueryWrapper);
    //USER_BIND_IDCARD_EXIST_ERROR(-301, "身份证号码已绑定"),
    Assert.isNull(userBind, ResponseEnum.USER_BIND_IDCARD_EXIST_ERROR);
    //查询用户绑定信息
    userBindQueryWrapper = new QueryWrapper<>();
    userBindQueryWrapper.eq("user_id", userId);
    userBind = baseMapper.selectOne(userBindQueryWrapper);
    //判断是否有绑定记录
    if(userBind == null) {
        //如果未创建绑定记录,则创建一条记录
        userBind = new UserBind();
        BeanUtils.copyProperties(userBindVO, userBind);
        userBind.setUserId(userId);
        userBind.setStatus(UserBindEnum.NO_BIND.getStatus());
        baseMapper.insert(userBind);
    } else {
        //曾经跳转到托管平台,但是未操作完成,此时将用户最新填写的数据同步到userBind对象
        BeanUtils.copyProperties(userBindVO, userBind);
        baseMapper.updateById(userBind);
    }
    Map<String, Object> paramMap = new HashMap<>();
    paramMap.put("agentId", HfbConst.AGENT_ID);
    paramMap.put("agentUserId", userId);
    paramMap.put("idCard",userBindVO.getIdCard());
    paramMap.put("personalName", userBindVO.getName());
    paramMap.put("bankType", userBindVO.getBankType());
    paramMap.put("bankNo", userBindVO.getBankNo());
    paramMap.put("mobile", userBindVO.getMobile());
    paramMap.put("returnUrl", HfbConst.USERBIND_RETURN_URL);
    paramMap.put("notifyUrl", HfbConst.USERBIND_NOTIFY_URL);
    paramMap.put("timestamp", RequestHelper.getTimestamp());
    paramMap.put("sign", RequestHelper.getSign(paramMap));
    //构建充值自动提交表单
    String formStr = FormHelper.buildForm(HfbConst.USERBIND_URL, paramMap);
    return formStr;
}

18.2.3、前端整合

pages/user/bind.vue

commitBind() {
      this.$alert(
        '
您即将前往汇付宝绑定账号
'
, '前往汇付宝资金托管平台', { dangerouslyUseHTMLString: true, confirmButtonText: '立即前往', callback: (action) => { if (action === 'confirm') { this.$axios .$post('/api/core/userBind/auth/bind', this.userBind) .then((response) => { document.write(response.data.formStr) }) } }, } ) },

18.2.4、测试

1、登录

使用借款人账号登录

2、测试

访问 http://127.0.0.1:3000/user/bind

3、结果

尚融宝数据库中创建了user_bind记录

汇付宝数据库中创建了user_bind 和 user_account两条数据记录

18.3、回调接口实现账户绑定

18.3.1、绑定步骤总结

step1:用户在个人中心点击 “立即开通” (http://localhost:3000/user/bind)

step2:尚融宝展示账户绑定页面

【金融项目】尚融宝项目(九)_第4张图片

step3:用户填写基本信息(注意:身份证必须是尚未开户),点击“开户”按钮

step4:尚融宝后台创建用户绑定信息(新建user_bind记录)

step5:跳转到汇付宝页面(资金托管接口调用)

【金融项目】尚融宝项目(九)_第5张图片

step6:汇付宝验证用户身份、用户设置交易密码

【金融项目】尚融宝项目(九)_第6张图片

step7:汇付宝创建绑定账号(新建user_bind和user_account记录)

step8:异步回调:

尚融宝user_bind表更新bind_code字段、status字段

尚融宝user_info表更新 bind_code字段、name字段、idCard字段、bind_status字段

step9:用户点击“返回平台”,返回尚融宝

【金融项目】尚融宝项目(九)_第7张图片

18.3.2、尚融宝回调接口

18.3.2.1、controller

UserBindController中创建回调方法

@ApiOperation("账户绑定异步回调")
@PostMapping("/notify")
public String notify(HttpServletRequest request) {
    Map<String, Object> paramMap = RequestHelper.switchMap(request.getParameterMap());
    log.info("用户账号绑定异步回调:" + JSON.toJSONString(paramMap));
    //校验签名
    if(!RequestHelper.isSignEquals(paramMap)) {
        log.error("用户账号绑定异步回调签名错误:" + JSON.toJSONString(paramMap));
        return "fail";
    }
    //修改绑定状态
    userBindService.notify(paramMap);
    return "success";
}

18.3.2.2、service

接口:UserBindService

void notify(Map<String, Object> paramMap);

实现:UserBindServiceImpl

@Resource
private UserInfoMapper userInfoMapper;

@Override
@Transactional(rollbackFor = Exception.class)
public void notify(Map<String, Object> paramMap) {
    // 校验是否绑定成功
    String resultCode = (String) paramMap.get("resultCode");
    if (!"0001".equals(resultCode)) {
        throw new BusinessException("用户绑定失败");
    }
    
    String bindCode = (String)paramMap.get("bindCode");
    //会员id
    String agentUserId = (String)paramMap.get("agentUserId");
    //根据user_id查询user_bind记录
    QueryWrapper<UserBind> userBindQueryWrapper = new QueryWrapper<>();
    userBindQueryWrapper.eq("user_id", agentUserId);
    //更新用户绑定表
    UserBind userBind = baseMapper.selectOne(userBindQueryWrapper);
    userBind.setBindCode(bindCode);
    userBind.setStatus(UserBindEnum.BIND_OK.getStatus());
    baseMapper.updateById(userBind);
    //更新用户表
    UserInfo userInfo = userInfoMapper.selectById(agentUserId);
    userInfo.setBindCode(bindCode);
    userInfo.setName(userBind.getName());
    userInfo.setIdCard(userBind.getIdCard());
    userInfo.setBindStatus(UserBindEnum.BIND_OK.getStatus());
    userInfoMapper.updateById(userInfo);
}

本文章参考B站 尚硅谷《尚融宝》Java微服务分布式金融项目,仅供个人学习使用,部分内容为本人自己见解,与尚硅谷无关。

你可能感兴趣的:(Java项目,金融,java,spring,boot,vue.js)