如何使用支付宝账号授权登录网站

本周在项目开发中使用到了支付宝授权登录(一键登录)我们的网站,周末做一下总结:

0.总体思路

为防止各位朋友看迷糊,先说一下整体执行流程:用户在我们网站点击一个“支付宝授权登录”按钮,请求到了java后台,完成跳转至支付宝之前的字符串拼接(包括回调地址,appid,scope,state),后台将这个地址处理完成之后返回给前端,前端通过window.href=”url”的形式跳转至支付宝登录页面,用户通过输入密码或者扫码,支付宝判断如果正确就会携带支付宝用户id和access_token跳转至我写的回调地址里面(这个回调地址是我们自己写的,让支付宝调用的,需要在支付宝页面配置,下面会说),我根据alipay_user_id查自己的库,看用户是否存在,如果存在说明已经与我们平台的用户系统进行绑定,将其重定向至成功页,否则重定向至绑定用户信息页,完善信息。需要明白的是我们平台也有自己的用户系统,必须将从支付宝拿过来的alipay_user_id与我们平台的用户系统进行绑定,否则区分不出哪个是哪个用户,绑定就是在这个完善用户信息页面进行的。

1.开通蚂蚁金服开发服务并配置完成。

上面只说了思路,下面说具体的操作流程。既然需要调用支付宝的接口,那就要开通蚂蚁金服的服务,通过下面地址开通:https://openhome.alipay.com/platform/appManage.htm ,需要营业执照或者身份证信息,审核通过后创建应用,并在功能选项中选择要使用的服务,比如我这里使用“获取会员信息”,点击“继续添加”可以添加其他的,如下图:
这里写图片描述
点击概览下面的应用信息,配置回调地址和公钥,密钥,如下图:
这里写图片描述
随后下载支付宝sdk的jar,已经集成了非常简单的调用方法。
参考文档如下:
https://docs.open.alipay.com/289/105656#s3

2.代码开发

代码开发不太难,有点绕的是怎么传参。我是通过state传递的。从官方文档中可以看到:state参数不是必须参数,属于商户自定义参数,用户授权后,重定向到redirect_uri时会原样回传给商户,而且最大长度只能是100,最好是做到既不可预测,又可以证明客户端和当前第三方网站的登录认证状态存在关联,那我们就可以通过state参数进行传递,比如我这里通过1_0,2_500这种形式拼接的,前面的数代表操作类型,比如我这里1代表登录,2代表修改支付宝账号,0代表无上级id,大于0表示那就是上级id,如500代表上级id,然后拿到传递过来的参数之后使用split参数进行分割、解析、判断不同情况,部分示例代码如下:

    /**
     * @Description 登录接口
     * @Author 刘俊重
     */
    @NoLogin
    @RequestMapping("/supplierLogin")
    public R supplierLogin(@RequestBody Map<String, Object> map) throws Exception {
        //获取核心企业id,0表示不是通过核心企业邀请链接登录
        Object coreId = map.get("coreId");
        if (null == coreId || coreId == "") {
            coreId = 0;
        }

        String s = DbEnum.CallBack.Type.LOGIN+"_"+coreId;
        logger.info(">>>>>>>>>>>>>>>>>>>>s"+s);
        /***重定向至支付宝授权登录页*/
        String encode = URLEncoder.encode(SystemVar.REDIRECT_URL,"UTF-8");
        return R.ok().put("visitUrl", SystemVar.ALIPAY_URL+"?app_id=" + SystemVar.APP_ID + "&scope=auth_user&redirect_uri=" + encode + "&state=" + s);
    }

回调函数部分代码如下:

/**
     * @Description 支付宝登录成功之后的回调函数,供支付宝调用
     * @Author 刘俊重
     */
    @NoLogin
    @RequestMapping("/callBackLogin")
    @ResponseBody
    public R callBackLogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String authCode = request.getParameter("auth_code");
        String state = request.getParameter("state");   /***我们需要的参数,拿到之后以下划线分割*/

        if(null==state || state==""){
            return R.error("获取支付宝授权失败");
        }
        AlipaySystemOauthTokenResponse authToken = getAuthToken(authCode);
        if (null == authToken) {
            return R.error("获取支付宝授权失败");
        }
        String userId = authToken.getUserId();
        String accessToken = authToken.getAccessToken();

        String[] split = state.split("_");
        String type = split[0];
        if(DbEnum.CallBack.Type.LOGIN.equals(type)){
            String coreId = split[1];
            //登录
            /***根据支付宝用户id查询供应商是否存在*/
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("alipayUserId", userId);
            SuppliersInfo suppliersInfo = suppliersInfoService.look(map);
            if (null == suppliersInfo) {
                if("0".equals(coreId)){
                    //说明没有注册而且没有带核心企业id,跳转至错误提示页面
                    response.sendRedirect(SystemVar.WEBSITE + "/#/error?userId=" + userId + "&coreId=" + coreId);
                    return R.ok();
                }

                //根据上级id查询是否确实存在,避免乱注册
                Map<String, Object> param = new HashMap<String, Object>();
                param.put("finmallId", coreId);
                CoreCorpInfo coreCorpInfo = coreCorpInfoService.look(param);
                if (null == coreCorpInfo) {
                    response.sendRedirect(SystemVar.WEBSITE + "/#/error?userId=" + userId + "&coreId=" + coreId);
                    return R.ok();
                }

                logger.info(">>>>>>>>>>>>>>>>完善信息地址"+SystemVar.WEBSITE + "/#/fillCompMess?userId=" + userId + "&coreId=" + coreId);
                //信息不存在,说明没有注册,去完善信息页
                response.sendRedirect(SystemVar.WEBSITE + "/#/fillCompMess?userId=" + userId + "&coreId=" + coreId);
                return R.ok();
            }

            String auditState = suppliersInfo.getAuditState();
            if (SuppliersInfo.AuditState.WAIT.equals(auditState)) {
                logger.info(">>>>>>>>>>>>>>>>待审核地址"+SystemVar.WEBSITE + "/#/waitExam?userId=" + userId + "&coreId=" + coreId);
                //待审核,进待审核提示页
                response.sendRedirect(SystemVar.WEBSITE + "/#/waitExam?userId=" + userId + "&coreId=" + coreId);
                return R.ok();
            } else if (SuppliersInfo.AuditState.UNPASSED.equals(auditState)) {
                logger.info(">>>>>>>>>>>>>>>>审核拒绝地址"+SystemVar.WEBSITE + "/#/refuse?userId=" + userId + "&coreId=" + coreId);
                //审核拒绝,进审核拒绝提示页
                response.sendRedirect(SystemVar.WEBSITE + "/#/refuse?userId=" + userId + "&coreId=" + coreId);
                return R.ok();
            } else if (SuppliersInfo.AuditState.PASSED.equals(auditState)) {
                //审核通过,把用户信息放session中
                String token = TokenUtils.getToken();
                cacheManager.getCache(SysCache.SESSION_CACHE_NAME).put(token, suppliersInfo);
                //往cookie中添加token
                CookieUtils.setCookie(request, response, CookieName.SCM_TOKEN, token);

                logger.info(">>>>>>>>>>>>>>>>审核通过地址"+SystemVar.WEBSITE + "/#/alipay?userId=" + userId + "&coreId=" + coreId + "&token=" + token);
                response.sendRedirect(SystemVar.WEBSITE + "/#/alipay?userId=" + userId + "&coreId=" + coreId + "&token=" + token);
                return R.ok();
            }
        }

        return null;
    }

支付宝获取获取authToken方法如下(支付宝中也有示例):

    /**
     * @Description 获取支付宝authToken
     * @Author 刘俊重
     * @Date 2017/11/27
     */
    private AlipaySystemOauthTokenResponse getAuthToken(String authCode) {

        AlipayClient alipayClient = new DefaultAlipayClient(SystemVar.ALIPAY_GATEWAY, SystemVar.APP_ID, SystemVar.PRIVATE_KEY, "json", CHARSET_UTF8, SystemVar.ALIPAY_PUBLIC_KEY, "RSA2");
        AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
        request.setCode(authCode);
        request.setGrantType("authorization_code");
        AlipaySystemOauthTokenResponse oauthTokenResponse = null;
        try {
            oauthTokenResponse = alipayClient.execute(request);
            System.out.println(oauthTokenResponse.getAccessToken());
        } catch (AlipayApiException e) {
            //处理异常
            e.printStackTrace();
        }
        return oauthTokenResponse;
    }

到这里已经可以获取到alipay_user_id供我们使用了,如果还想获取其它信息,可以使用accessToken换取用户信息,文档中有,这里不再赘述。

3.如何配置支付宝沙箱测试

支付宝的回调地址只能填写一个,如果项目已经上线了,那总不能一会把回调地址配置成生产的,一会配置成测试的吧,好在支付宝提供了一套供测试使用的沙箱环境,沙箱环境的文档地址如下:
https://docs.open.alipay.com/200/105311 ,也可以看我下面说的这些:
首先进入如下地址:https://openhome.alipay.com/platform/appDaily.htm?tab=info 配置沙箱环境,包括沙箱的网关,授权url,appid,公钥,密钥,均跟生产的都不同,需要重新配置,其中授权url如下:
https://openauth.alipaydev.com/oauth2/publicAppAuthorize.htm 。沙箱环境使用正常的支付宝账号也无法登录,必须要使用沙箱环境分配的账号,可以在下面地址中找到沙箱测试账号:https://openhome.alipay.com/platform/appDaily.htm?tab=account ,以上便是支付宝授权登录网站的开发流程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值