宠物之家

宠物之家

前言

本项目是一个o2o项目,以宠物为核心,提供宠物领养,宠物收购,宠物寻主,产品购买,服务购买等相关业务。前端用的vue技术栈,后端用的spring,springMVC,springboot,mybatis。

负责模块

用户模块
宠物模块
支付模块
##主要运用技术
1.redis
2.发送短信技术
3.微信三方登录技术
4.md5加密技术
5.RSA加密技术
6.支付宝三方支付技术
7.百度地图定位技术
8.quartz定时器
9.docker
##用户模块
需求:用户注册,用户登录,用户店铺收藏,用户浏览足迹

注册

在这里插入图片描述##表的设计注册方面我们设计了两张表,一张user用户信息表,和loginInfo登录信息表,把用户注册成功后的信息先存放在loginInfo表再存放在user表
在这里插入图片描述

后端代码实现

  public AjaxResult getVerifyCode(Map<String, String> params) {
        String phone = params.get("phone");
        //获取前台传来的手机号判断是否为空
        if (!StringUtils.hasLength(phone)){
            return AjaxResult.ajax().setSuccess(false).setMessage("请输入正确手机号!");
        }
        //判断手机号是否已经存在
        User user = mapper.findOneUser(phone);
        if(user!=null){
            return AjaxResult.ajax().setSuccess(false).setMessage("该手机号已经被注册");
        }
        //不存在,就判断redis里面是否有未过期的验证码,从redis获取短信验证码
        String key="register"+phone;
        String value=(String) redisTemplate.opsForValue().get(key);//code:time
        //判断value是否为空
        String code="";
        //为空
        if(!StringUtils.hasLength(value)){
            code = StrUtils.getComplexRandomString(4);
        }else {
            //不为空就判断是否过了重复发短信的时间
            long times = Long.valueOf(value.split(":")[1]);
            long millis = System.currentTimeMillis();
            if(millis-times<1000*60*1){
                return AjaxResult.ajax().setSuccess(false).setMessage("请不要重复发送短信");
            }else {
                code=value.split(":")[0];
            }
        }
        //把value放入redis
        redisTemplate.opsForValue().set(key,code+":"+System.currentTimeMillis(),3, TimeUnit.MINUTES);
        //发送短信
      //  Smsutil.sendSms(phone,code);
        System.out.println("发送的验证码为:"+code);
        return AjaxResult.ajax();
    }

登录

设计流程图
在这里插入图片描述##表的设计
在登录方面我们设计了三张表,user用户信息表,employee员工信息表,loginInfo登录信息表,我们把user表和employ表中所有信息都放在了loginInfo表中,并用type字段来进行区分,在前后台登录实现的时候只需要调用一个接口查询一张表
在这里插入图片描述

后端实现代码

账号密码登录

public AjaxResult loginInfo(LoginDto loginDto) {
        //判断用户信息是否完善
        String password1 = loginDto.getPassword();
        if (StringUtils.isEmpty(loginDto.getUsername()) || StringUtils.isEmpty(password1) || StringUtils.isEmpty(loginDto.getType())) {
            return AjaxResult.ajax().setSuccess(false).setMessage("请输入完整信息");
        }
        //判断账号是否存在
        LoginInfo loginInfo1 = mapper.loadByUsername(loginDto);
        if (loginInfo1 == null) {
            return AjaxResult.ajax().setSuccess(false).setMessage("账号或密码错误1");
        }
        //判断该账号是否可用
        Integer disable = loginInfo1.getDisable();
        if (disable == 0) {
            return AjaxResult.ajax().setMessage("该账号不可用").setSuccess(false);
        }
        //判断密码是否正确
        String password = loginInfo1.getPassword();

        String salt = loginInfo1.getSalt();

        String md5 = MD5Utils.encrypByMd5(password1 + salt);

        if (!md5.equals(password)) {
            return AjaxResult.ajax().setSuccess(false).setMessage("账号或密码错误2");
            //密码正确
        } else {
            //生成tocken
            String tocken = UUID.randomUUID().toString();
            template.opsForValue().set(tocken, loginInfo1, 30, TimeUnit.MINUTES);
            Map<Object, Object> map = new HashMap<>();
            map.put("tocken", tocken);
            loginInfo1.setPassword("");
            map.put("user", loginInfo1);
            String checked = loginDto.getChecked();
            map.put("checked", checked);
            String pass = loginDto.getPassword();
            map.put("pass", pass);
            String name = loginDto.getUsername();
            map.put("name", name);
            return AjaxResult.ajax().setResultObj(map);

        }
    }

##微信登录
流程图设计
在这里插入图片描述##表的设计
三方登录我们还设计了一张微信用户信息表,用来保存相关的微信用户的信息
在这里插入图片描述

实现思路:
前台使用微信提供的接口,需要在其中配置回调页面–
当用户扫码后携带code授权码跳转到回调页面,封装绑定地址,授权码数据发送请求到后台–
后台通过code授权码,发送json请求获取到用户唯一标示(openid)和令牌(accessToken)–
通过openid获取用户信息,有就把用户信息放入redis返回前台,没有就返回绑定页面地址并携带
appenid和accesstoken–
用户在填完绑定信息发请求到后台–
判断用户信息是否填写完善–
通过手机号查询用户,有就通过openid拿到微信用户个人信息存入数据库–
没有,就先注册添加用户信息到loginfo表,user表再拿到微信个人信息存入数据库–
把用户信息放入redis,并返回前台,前台跳转首页

代码实现

//微信登录
 public AjaxResult loginWeixin(Map<String, String> params) {
        String code = params.get("code");

        String binderUrl = params.get("binderUrl");

        //通过授权码来获取openid和access_token令牌
        String url = WxConstants.GET_ACCESSTOKEN_URL.
                replace("APPID", WxConstants.APPID)
                .replace("SECRET", WxConstants.SECURITY)
                .replace("CODE", code);
        String JsonStr = HttpClientUtils.httpGet(url);
        JSONObject jsonObject = JSONObject.parseObject(JsonStr);
        //拿到openid和令牌access_token
        String accesstoken = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");
        //通过openid拿到user用户
        User user = userMapper.getByOpenid(openid);
        //判断如果拿到了就说明已经绑定,没拿到就跳转到绑定界面
        if (user != null) {
            //拿到loginInfo
            LoginInfo loginInfo = mapper.loadById(user.getLogininfo_id());
            //放入redis
            String tocken = UUID.randomUUID().toString();
            template.opsForValue().set(tocken, loginInfo, 30, TimeUnit.MINUTES);
            HashMap<Object, Object> map = new HashMap<>();
            map.put("tocken", tocken);
            loginInfo.setPassword("");
            map.put("user", loginInfo);
            return AjaxResult.ajax().setResultObj(map);
        } else {
            binderUrl = binderUrl + "?accessToken=" + accesstoken + "&openid=" + openid;
            return AjaxResult.ajax().setResultObj(binderUrl).setMessage("binder").setSuccess(false);
        }
    }
   //微信绑定登录
     public AjaxResult weixinBinder(LoginDto loginDto) {
        String accesstoken = loginDto.getAccesstoken();
        String openid = loginDto.getOpenid();
        System.out.println(accesstoken );
        System.out.println(openid  );
        //通过accesstoken和openid拿到用户信息
        String url = WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", accesstoken)
                .replace("OPENID", openid);
        String JsonStr = HttpClientUtils.httpGet(url);
        //通过账号判断该用户是否存在,不存在就注册加绑定,存在就绑定
        LoginInfo loginInfo = mapper.loadByUsername(loginDto);
        if (loginInfo == null) {
            loginInfo = loginDtotologinInfo(loginDto);
            mapper.insert(loginInfo);
            //拿到自增loginInfo的id
            User user = UserServiceImpl.LoginInfotoUser(loginInfo);
            //返回自增id
            userMapper.insert(user);
            //拿到user的id放入wxUser的
            WxUser wxUser = usertoWxUser(user, JsonStr);
            wxUserMapper.save(wxUser);
        } else {
            //存在就判断密码直接绑定
            String salt = loginInfo.getSalt();

            String password = loginDto.getPassword();
            String md5 = MD5Utils.encrypByMd5(password + salt);
            if (!md5.equals(loginInfo.getPassword())) {
                return AjaxResult.ajax().setSuccess(false).setMessage("账号或密码错误");
            }
            String username = loginInfo.getUsername();
            User user = userMapper.findOneUser(username);
            WxUser wxUser = usertoWxUser(user, JsonStr);
            wxUserMapper.save(wxUser);

        }
        //放入redis
        String tocken = UUID.randomUUID().toString();
        template.opsForValue().set(tocken, loginInfo, 30, TimeUnit.MINUTES);
        HashMap<Object, Object> map = new HashMap<>();
        map.put("tocken", tocken);
        loginInfo.setPassword("");
        map.put("user", loginInfo);
        return AjaxResult.ajax().setResultObj(map);
    }

其他收藏,足迹

宠物模块

##表的设计
宠物模块我们一共设计了四张表,宠物信息表,宠物表,宠物详情表,
宠物类型表
在这里插入图片描述

实现思路:
寻主:
用户发布寻主消息,存放寻主消息,把消息发送给最近的一家店铺,
店铺处理生成相关宠物信息以及收购订单。
领养:用户点击领养,后台生成订单,支付单。
后台代码:

 @Override
    public void save(SeachMasterMsg msg, LoginInfo loginInfo) {
        //通过loginInfoid拿到user对象;
        User user = mapper.getById(loginInfo.getId());
        //拿到userId放入SeachMasterMsg
        msg.setUser_id(user.getId());
        //拿到用户地址经纬度
        Point point = DistanceUtil.getPoint(msg.getAddress());
        //拿到所有店铺地址
        List<Shop> shops = shopMapper.findAll();
        Shop nearestShop = DistanceUtil.getNearestShop(point, shops);
        if (nearestShop==null){
            throw new RuntimeException("抱歉附近没有门店!") ;
        }
        //拿到最近的shop放入SeachMasterMsg,并给店铺管理员发信息
        msg.setShop_id(nearestShop.getId());
        Smsutil.sendSms(nearestShop.getAdmin().getPhone(),"老板附近有宠物可领取哦!" );
        msgMapper.save(msg);
    }
     @Override//将信息转换成宠物
    public void insert(Pet pet,LoginInfo loginIonf) {
        //将消息改为已处理
        Long id = pet.getSeachmastermsg_id();
        SeachMasterMsg seachMasterMsg = msgMapper.loadById(id);
        seachMasterMsg.setState(1);
        msgMapper.update(seachMasterMsg);
        //保存宠物信息(处理后的信息前台传来)
        petService.insert(pet);
        //生成订单
        PetAcquisitionOrder petAcquisitionOrder = petto2order(pet,loginIonf,seachMasterMsg);
        petAcquisitionOrderMapper.save(petAcquisitionOrder);
    }
      @Override
    public void updateAdopt(Long id, LoginInfo loginInfo) {
        //拿到用户确认是谁领养的
        User user = userMapper.getById(loginInfo.getId());
        Pet pet = petMapper.loadById(id);
        pet.setUser_id(user.getId());
        //修改为被领养状态
        pet.setState(2);
        petMapper.update(pet);
    }

其他 宠物详情的展示crud

支付模块(支付宝支付为例)

支付宝流程
在这里插入图片描述##表的设计
对于这个业务我们设计了三张表,支付表,支付流水表,支付宝支付信息表
在这里插入图片描述

实现思路:
后台封装了支付宝提供的接口–
当用户交订单就会生成支付订单,然后调用支付接口–
需要传入支付宝公钥,商家的私钥,统一支付单号,支付价格等信息–
支付宝返回一个支付数据包,把数据包返回前台–
前台解析数据包,拿到form表单,界面弹出支付二维码–
用户扫码之后同步回调到我们指定的页面,并异步回调后台指定的接口–
在接口修改相关订单及支付单的状态,并添加支付流水
设置定时器30分钟未支付就取消订单
实现代码

 public AjaxResult productOrder(LoginInfo loginInfo, OrderDto dto) {
        Long id = dto.getAddress_id();
        UserAddress userAddress = userAddressMapper.loadById(id);
        //添加主表ProductOrder
       ProductOrder productOrder = OrderDto2ProductOrder(loginInfo,dto,userAddress);
        String paySn = CodeGenerateUtils.generateUnionPaySn();
       productOrder.setPaySn(paySn);
       productOrderMapper.save(productOrder);
       //添加到其他关联表,订单地址表
        OrderAddress orderAddress=userAddressto2orderAddress(userAddress,productOrder);
        orderAddressMapper.save(orderAddress);
        //订单详情表
        Long product_id = dto.getProduct_id();
        Product product = productMapper.loadById(product_id);
        ProductOrderDetail productOrderDetail = productto2productDetail(product,productOrder);
        productOrderDetailMapper.save(productOrderDetail);
        //生成支付表单;
        PayBill payBill = productOrderto2payBill(productOrder,dto);
        payBill.setUnionPaySn(paySn);
        //保存单据
        payBillMapper.save(payBill);
        //返回一个支付宝数据包会form表单返回给前台
        String result = payBillService.pay(payBill);
        //设置订单超时取消
        QuartzJobInfo info = new QuartzJobInfo();
        info.setType(JobContstants.PRODUCT_ORDER_CANCEL);
        info.setJobName("product_order_cancel_"+productOrder.getId());
        //会调用set方法转成conj形式
        info.setFireDate(productOrder.getLastPayTime());
        HashMap<String, Object> map = new HashMap<>();
        map.put("orderId", productOrder.getId());
        info.setParams(map);
        quartzService.addObj(info);
        return AjaxResult.ajax().setResultObj(result);

    }
支付宝工具类
public static String aliPay(AlipayInfo alipayInfo, PayBill payBill){
        try {
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(Alipayconfig.gatewayUrl,alipayInfo.getAppid(), alipayInfo.getMerchant_private_key(), "json", Alipayconfig.charset, alipayInfo.getAlipay_public_key(), Alipayconfig.sign_type);
            //设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(Alipayconfig.return_url);
            alipayRequest.setNotifyUrl(Alipayconfig.notify_url);
            //商户订单号,商户网站订单系统中唯一订单号,必填
            String out_trade_no = new String(payBill.getUnionPaySn());
            //付款金额,必填
            String total_amount = new String(payBill.getMoney().toString());
            //订单名称,必填
            String subject = new String(payBill.getDigest());
            //商品描述,可空
            String body = new String("服务订单");

            alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                    + "\"total_amount\":\""+ total_amount +"\","
                    + "\"subject\":\""+ subject +"\","
                    + "\"body\":\""+ body +"\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
            //请求
            String result = alipayClient.pageExecute(alipayRequest).getBody();
            return result;
            //输出
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }




     /* *
     *类名:AlipayConfig
     *功能:基础配置类
     *详细:设置帐户有关信息及返回路径
     *修改日期:2017-04-05
     *说明:
     *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
     *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
     */
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

        // 服务器异步通知页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
        public static String notify_url = "http://syupi2.natappfree.cc/notify";
        // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
        public static String return_url = "http://localhost/success.html";
        // 支付宝网关
        public static String gatewayUrl = "https://openapi.alipaydev.com/gateway.do";
        public static String sign_type = "RSA2";
        public static String charset = "utf-8";

微信,余额支付实现思路差不多

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值