web项目web接入微信登录

最近写了一个简单的微信第三方登录功能,存粹分享下心得和体会

        首先需要APPID和SCRECT还有回调域(第三方地址,一般是公司的域名)(域名解析),

获取步骤是:

a.在微信开放平台https://open.weixin.qq.com/经过注册成为开发者。

b.在“管理中心”中创建一个移动应用来提交审核

之后是微信登录流程:

简单用例子来说就是:首先要分辨是第一次登录还是不是第一次登录,是前端传过来的授权临时票据code和appid和secrect来进行操作,
再在wxuser表中根据openid能否查询到对象,并且对象的userid是否存在,有的话不是第一次登录,没有就是第一次登录,
如果不是第一次登录,那么就是免密登录,重置token的有效时间,然后再设置盐值和密码的logininfo为空,就可以返回并且加上
集合就ok,如果是第一次登录,就需要写入三张表并且绑定,具体是首先非空校验,之后判断验证码是否过期,之后再验证验证码
是否正确,之后再验证是否根据手机号能查询到用户,能查到的话就可以只添加wxuser,否则要添加logininfo,user,最后是wxuser,
最后放入redis中,并把密码和盐值设置为空,最后在前端跳转首页。

经过整理流程就是:

前端:

1.在前端的登录页准备微信登录的按钮
2.当用户点击微信扫码登录,前端接缪按向微信发起获取授权的请求    
3.微信直接展示扫描二维码给用户(询问用户要不要给我们web项目授权)
4.用户扫码,确认授权我们的项目可以获取微信用户信息
5.微信收到确认,生成code(授权码),通过回调域)拼接code返回
6.我们的web项目在前台页面上就可以获取授权码了

微信登录流程
1.在前端页面中,我们定义钩子函数。
   从请求栏中获取code,并且触发调用后端的微信登录接口,将code传送到后端
2.后端接口收到请求,交给service处理
3.service业务流
4.code不能为空
5.根据code从微信获取token  使用httpClient  
6.拿到token+openId
7.判断openId是已经存在(查询t_wxUser),
   7.1.如果已经有了并且userid不为空,直接免密登录
   7.2 如果为空,需要让用户绑定个人用户信息
      返回token+openId 前端帮我们跳转到绑定页面
 
二:微信绑定流程
1.在前端页面的钩子函数中
2.接收微信登录流程的返回值,
3.跳转到绑定页面
4.绑定页面解析地址栏参数并且接收用户输入的参数
5.发起微信绑定流程
6.后端接收参数交给service处理
7.service业务流
  一:校验
   1.空校验
   2.判断验证码
  二:判断phone是否被注册 user
   1.如果注册了,那么我们可以直接绑定微信用户了
   2.如果没有注册过,要生成t_user + t_loginInfo
  三:通过 token+openId 查询微信信息 wxuser       
     生成t_wxuser
  四:绑定user和wxuser
  五:免密登录

/*微信登录*/
@Override
public AjaxResult wechat(Map<String, String> map) {
    String code = map.get("code");
    if (StringUtils.isEmpty(code)){//为空
        throw new MyException("系统异常。。。");
    }

    //通过code,appid,secret获取token令牌
    String url = WxConstants.GET_TOKEN_URL.replace("APPID",WxConstants.APPID)
            .replace("SECRET",WxConstants.SECRET)
            .replace("CODE",code);
    //发送请求,获取token
    String obj = HttpClientUtils.httpGet(url);
    //把json字符串转成json对象
    JSONObject jsonObject = JSONObject.parseObject(obj);
    //获取token和openid
    String token = jsonObject.getString("access_token");
    String openid = jsonObject.getString("openid");
    //通过openid和userid查询,如果不为空,说明登录过,免密登录
    WxUser wxUser = wxUserMapper.loadByOpenId(openid);

    String param = "?token=" + token + "&openId=" + openid;
    if (wxUser != null && wxUser.getUser_id() != null){//之前扫描过,直接放行
        //查询对应的logininfo信息,
        LoginInfo loginInfo = loginInfoMapper.loadByUserId(wxUser.getUser_id());
        //4.1获取token
        String token1 = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token1,loginInfo,30, TimeUnit.MINUTES);
        Map<String, Object> map1 = new HashMap<>();
        map1.put("token",token1);

        //把盐值名和密码设置为空
        loginInfo.setPassword("");
        loginInfo.setSalt("");
        map1.put("loginInfo",loginInfo);//对象 存对象要序列化
       return AjaxResult.me().setResultObj(map1);
    }else {
        //第一次登录
        return AjaxResult.me().setSuccess(false).setResultObj(param);
    }
}

/*
* 微信绑定
*     phone:"13330964748",
   verifyCode:"",
   token:"",
                openId:""
* */
@Override
public Map<String, Object> binder(Map<String, String> map) {
    String phone = map.get("phone");
    System.out.println(phone);
    String verifyCode = map.get("verifyCode");
    System.out.println(verifyCode);
    String token = map.get("token");
    System.out.println(token);
    String openId = map.get("openId");
    System.out.println(openId);
    //1.空校验
    if (StringUtils.isEmpty(phone)
            || StringUtils.isEmpty(verifyCode)
            || StringUtils.isEmpty(token)
            || StringUtils.isEmpty(openId)
            ){
        throw new MyException("参数不能为空");
    }
    //2.验证码校验
    //验证码对否过期
    Object o = redisTemplate.opsForValue().get("binder:" + phone);
    //端输入的验证码和发送的是否一致 不区分
    //获取验证码
    String code = o.toString().split(":")[0];
    if (!verifyCode.equalsIgnoreCase(code)){
        throw new MyException("验证码错误,请重新输入!!");
    }
    //3.判断手机号是否被注册
    User user = userMapper.loadByPhone(phone);
    LoginInfo loginInfo = null;
    User userTemplate = null;
    if (user != null){//之前注册过了
        System.out.println(111);
            userTemplate  = user;
        loginInfo = loginInfoMapper.loadByUserId(userTemplate.getId());
    }else {//没有注册,重新保存三张表
        System.out.println(222);
        User user1 = initUser(phone);
        userTemplate = user1;
        //设置logininfo_id
        loginInfo = initLoginInfo(userTemplate);
        //设置类型为1用户
        loginInfo.setType(1);
        //添加登录信息
        loginInfoMapper.add(loginInfo);
        System.out.println(loginInfo.getId());
        userTemplate.setLogininfo_id(loginInfo.getId());

        //添加logininfo_id
        user1.setLogininfo_id(loginInfo.getId());
        //添加用户
        userMapper.add(user1);
    }
    //获取用户信息,保存在wxuser
    String obj = HttpClientUtils.httpGet(WxConstants.GET_USER_URL)
            .replace("ACCESS_TOKEN", token)
            .replace("OPENID", openId);
    WxUser wxUser = initWxuser(obj);
    //绑定
    wxUser.setUser_id(userTemplate.getId());
    //保存wxuser中的信息
    wxUser.setOpenid(openId);
    wxUserMapper.add(wxUser);

    //4.把用户信息放入redis中
    //4.1获取token
    redisTemplate.opsForValue().set(token,loginInfo,30, TimeUnit.MINUTES);
    Map<String, Object> map1 = new HashMap<>();
    map1.put("token",token);

    //把用户名和密码设置为空
    loginInfo.setPassword("");
    loginInfo.setSalt("");
    map1.put("loginInfo",loginInfo);//对象 存对象要序列化
    return map1;
}

//通过obj生成wxUser对象
private WxUser initWxuser(String obj) {
    JSONObject jsonObject = JSONObject.parseObject(obj);
    WxUser wxUser = new WxUser();
    wxUser.setOpenid(jsonObject.getString("openid"));
    wxUser.setNickname(jsonObject.getString("nickname"));
    wxUser.setSex(jsonObject.getInteger("sex"));
    wxUser.setAddress(null);
    wxUser.setHeadimgurl(jsonObject.getString("headimgurl"));
    wxUser.setUnionid(jsonObject.getString("unionid"));
    return wxUser;
}

//通过user生成logininfo对象
private LoginInfo initLoginInfo(User userTemplate) {
    LoginInfo info = new LoginInfo();
    BeanUtils.copyProperties(userTemplate,info); //按照同名原则拷贝属性
    return info;
}

//通过手机号生成user对象
private User initUser(String phone) {
    User user = new User();
    user.setUsername(phone);
    user.setPhone(phone);
    user.setEmail(null);
    //给一个随机密码
    String salt = UUID.randomUUID().toString();
    String password = MD5Utils.encrypByMd5("1"+salt);
    user.setPassword(password);
    user.setSalt(salt);
    user.setState(1);
    user.setCreatetime(new Date());
    return user;
}
ASP.NET Core Web 可以通过微信支付提供的 API 进行扫码支付的接入。下面是实现步骤: 1. 申请微信支付账号和开通扫码支付功能。在申请过程中,需要提供商户信息和开户银行信息等。 2. 在 ASP.NET Core Web 中引入微信支付 SDK,可以通过 NuGet 包管理器安装。 ``` Install-Package Senparc.Weixin.MP.Pay ``` 3. 在 ASP.NET Core Web 项目中添加配置文件 appsettings.json,用于存储微信支付相关的配置参数,如下所示: ``` { "WeixinPay": { "MchId": "微信支付分配的商户号", "AppId": "应用ID", "Key": "商户支付密钥" } } ``` 4. 在 ASP.NET Core Web 项目中创建一个控制器,用于处理扫码支付的请求。控制器代码如下所示: ``` [Route("api/[controller]")] [ApiController] public class WeixinPayController : ControllerBase { private readonly IOptions<WeixinPayOptions> _options; public WeixinPayController(IOptions<WeixinPayOptions> options) { _options = options; } [HttpPost("unifiedorder")] public async Task<IActionResult> UnifiedOrder([FromBody]UnifiedorderRequest request) { // 设置请求参数 var data = new TenPayV3UnifiedorderRequestData( body: request.Body, outTradeNo: request.OutTradeNo, totalFee: request.TotalFee, spbillCreateIp: request.SpbillCreateIp, notifyUrl: request.NotifyUrl, tradeType: "NATIVE", productId: request.ProductId ); // 调用统一下单 API 进行支付 var result = await TenPayV3.UnifiedorderAsync(_options.Value.AppId, _options.Value.MchId, _options.Value.Key, data); // 处理返回结果 if (result.ReturnCode == "SUCCESS" && result.ResultCode == "SUCCESS") { // 生成二维码图片 var url = result.CodeUrl; var qrCode = new QRCodeGenerator().CreateQrCode(url, QRCodeGenerator.ECCLevel.Q); // 返回二维码图片 return File(qrCode.GetGraphic(20), "image/png"); } // 返回错误信息 return BadRequest(result.ReturnMsg); } } ``` 5. 创建一个模型类,用于保存扫码支付的请求参数。 ``` public class UnifiedorderRequest { public string Body { get; set; } public string OutTradeNo { get; set; } public int TotalFee { get; set; } public string SpbillCreateIp { get; set; } public string NotifyUrl { get; set; } public string ProductId { get; set; } } ``` 6. 在 Startup.cs 文件中添加微信支付相关的配置,代码如下所示: ``` services.Configure<WeixinPayOptions>(Configuration.GetSection(nameof(WeixinPayOptions))); ``` 7. 启动 ASP.NET Core Web 项目,使用 Postman 或其他工具向接口发送扫码支付的请求,请求参数包括:商品描述、商户订单号、总金额、终端 IP、通知地址、商品 ID 等。 ``` POST /api/weixinpay/unifiedorder HTTP/1.1 Host: localhost:5000 Content-Type: application/json { "body": "测试商品", "outTradeNo": "123456", "totalFee": 1, "spbillCreateIp": "127.0.0.1", "notifyUrl": "http://localhost:5000/api/weixinpay/notify", "productId": "123456" } ``` 8. 如果请求成功,将返回一个二维码图片,可以使用扫码工具扫描该二维码进行支付。如果请求失败,将返回错误信息。 以上就是 ASP.NET Core Web 支付功能接入微信扫码支付的实现步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值