微信扫码登录

微信扫码登录

1.准备工作

1.需要appid 
     商户号
     app秘钥
     key  发送给微信官方对参数进行校验的key
     回调地址  
     4大基础配置
2.申请开通微信扫码支付

2.大体流程

1.拿着组装好的参数去微信发送请求,拿到返回的code_url(就是二维码中的链接)
2.用谷歌的工具生成的二维码响应给前端
3.回调函数中处理业务逻辑,支付以后修改状态等
4.前端查询支付结果,拿着生成订单的订单号轮询访问接口,获取他的状态,根据状态修改对应的逻辑    
5.微信的金额为分,建议数据库存储分    
6.微信回调函数中,该方法头上必须为   @RequestMapping("/xyNavicatCallback") 

3.代码实现

1.微信扫码统一下单请求

 /**
     * 统一下单方法
     * @return
     */
    private String unfiedOrder(XyOrder order,HttpServletRequest request,String goodBodyName) throws Exception {
        BigDecimal ordPrice = order.getOrderPrice();

        //BigDecimal bigPrice = YuanByFenUtil.yuanByFen(new Double(ordPrice.doubleValue()),"100",2);
       // String price = bigPrice.toString();
        //生成签名
        SortedMap<String,String> PARAMS = new TreeMap<>();
        PARAMS.put("appid", ConfigUtil.APPID);   //公众号的appid
        PARAMS.put("mch_id",ConfigUtil.MCH_ID);    //商户号appid
        PARAMS.put("nonce_str", CommonUtilsYpl.generateUUID());
        PARAMS.put("body",goodBodyName);     //订单的内容
        PARAMS.put("out_trade_no",order.getOrderNumber()); //商品订单号
        PARAMS.put("total_fee","1");  //订单的钱数
        String ip =  IpUtils.getIpAddr(request);
        log.info("我是ip地址"+ip);



        PARAMS.put("spbill_create_ip",ip); //用户的ip
        PARAMS.put("notify_url",ConfigUtil.NOTIFY_URL);  //回调地址
        PARAMS.put("trade_type", "NATIVE");  //支付类型
        PARAMS.put("attach", ip);  //支付类型


        //生成签名
        String sign  = WXPayUtil.createSign(PARAMS,ConfigUtil.API_KEY);
        PARAMS.put("sign",sign);

        //map转xml
        String payXml  =  WXPayUtil.mapToXml(PARAMS);
        System.out.println("我是发送的xml"+payXml);


        //统一下单 发起请求下单,得到微信返回结果
        String orderStr  = HttpUtilsYpl.doPost("https://api.mch.weixin.qq.com/pay/unifiedorder",payXml,4000);

        String s2 = new String(orderStr.getBytes(ISO_8859_1),"utf-8");
        log.info("我是微信返回的数据"+s2);


        if(null == orderStr){
            return  null;
        }
        Map<String,String> unifiedOrderMap = WXPayUtil.xmlToMap(orderStr);
        System.out.println("我是xml转换成map的返回值:"+unifiedOrderMap);

        if (unifiedOrderMap!=null){
            return unifiedOrderMap.get("code_url");
        }
        return null;
    }

2.微信回调结果

 /**
     * 微信扫码支付回调接口
     * @return
     */
    @RequestMapping("/xyNavicatCallback")
    public Object xyCallBack(HttpServletResponse response, HttpServletRequest request) throws Exception {
        //微信回调都是通过流发送的
        InputStream inputStream = request.getInputStream();
        BufferedReader in  = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
        StringBuffer sb = new StringBuffer();
        String line;
        while ((line = in.readLine())!=null){
            sb.append(line);
        }
        in.close();
        inputStream.close();
        //以上拿到微信回发的所有数据

        //拿到转换后的数据
        Map<String,String> callbackMap = WXPayUtil.xmlToMap(sb.toString());
       log.info("我是转换后的数据" +callbackMap.toString());

        //我是排序后的数据
        SortedMap<String, String> sortedMap = WXPayUtil.getSortedMap(callbackMap);

        //1.签名校验
        if (WXPayUtil.isCorrectSign(sortedMap,ConfigUtil.API_KEY)){
            //如果签名对了再判断微信返回的是不是成功
            if ("SUCCESS".equals(sortedMap.get("result_code"))){
                //2.更新订单状态
                String outTradeNo = sortedMap.get("out_trade_no");
                String ip = sortedMap.get("attach");

                String payNum = sortedMap.get("transaction_id");
                log.info("走回调了");
                //拿着上面的订单号去数据库把订单查出来
                List<XyOrder> list = xyOrderService.selectXyOrderByOrderNo(outTradeNo);
                //判断订单号是否存在
                if (!list.isEmpty())
                {
                    int row = 0;
                    //遍历该订单号列表并将状态改变
                    for (XyOrder order : list)
                    {
                        //查出来以后判断状态是否为0(未支付状态)
                        if(order!=null && order.getStatus() ==0){
                            //更新订单的状态
                            order.setIp(ip);
                            order.setPayNum(payNum);
                            order.setOpenId(sortedMap.get("openid"));
                            order.setStatus(1);
                            order.setPayTime(new Date()); //支付时间
                            row = xyOrderService.updateXyOrder(order);
                        }
                    }
                    //3.影响行数 row==1 或者row==0 响应微信成功或失败
                    if (row >=1){  //修改成功
                        response.setContentType("text/html");
                        response.getWriter().print("success");
                        return null;
                    }
                }
            }
        }
        response.setContentType("text/html");
        response.getWriter().print("fail");
       return  null;
    }

3.生成前端需要扫码的二维码

 @GetMapping("/add")
    public void order(Long orderId, String goodBodyName, HttpServletResponse response, HttpServletRequest request) throws Exception {
       //拿到订单id对应的订单
        XyOrder order = xyOrderService.selectXyOrderById(orderId);

        //拿到一个code_url 扫码的地址
        String code_url = unfiedOrder(order,request,goodBodyName);
        if (code_url == null){
            throw new LogicException("没有拿微信的code_url");
        }
        try{
            //生成二维码
            Map<EncodeHintType,Object> hints = new HashMap<>();
            //设置纠错等级
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
            hints.put(EncodeHintType.CHARACTER_SET,"UTF-8");



            //生成二维码的格式 参数1为路径code_url 为格式 3,4为宽高,5为二维码的配置
            BitMatrix bitMatrix = new MultiFormatWriter()
                    .encode(code_url,
                            BarcodeFormat.QR_CODE,400,400,hints);
            OutputStream outputStream =  response.getOutputStream();

            MatrixToImageWriter.writeToStream(bitMatrix,"png",outputStream);

        }catch (Exception e){
            e.printStackTrace();
        }



    }

4.前端轮询查询支付结果的接口

   /**
     * 根据订单号查询订单状态
     * @param orderNumber
     * @return
     */
    @GetMapping("/selectByStatus")
    public Object selectByStatus(String orderNumber){
      List<XyOrder> xyOrders =   xyOrderService.selectByStatus(orderNumber);
      return xyOrders.get(0).getStatus();
    }


微信扫码登录Angular是一种基于微信开放平台提供的二维码扫描技术,在Angular应用中实现场景化认证的过程。这种方式使得用户可以通过微信扫码的方式快速完成身份验证并登录到应用程序中,无需手动输入用户名和密码。 ### 实现步骤: #### 1. 注册微信开放平台账号 首先需要在微信公众平台上注册一个账号,并创建一个小程序或公众号,获取AppID和AppSecret。 #### 2. 配置Angular项目 在Angular项目中引入微信支付和授权的相关依赖库,如`ngx-wechat-login`等。这通常涉及安装相应的npm包。 ```bash # 使用 npm 安装示例 npm install ngx-wechat-login --save ``` #### 3. 引入服务 在 Angular 应用中引入微信登录相关的服务,并注入到需要使用此功能的组件中。 ```typescript import { WechatLoginService } from 'ngx-wechat-login'; constructor(private wechatLoginService: WechatLoginService) {} ``` #### 4. 创建登录功能 在组件中创建微信扫码登录的功能实现。通常包括调用微信登录接口、处理回调结果以及展示加载状态。 ```typescript export class LoginPage { loading = false; constructor(private wechatLoginService: WechatLoginService) {} startWechatLogin() { this.loading = true; // 调用微信登录API,此处假设调用的是wechatLoginService.startLogin() this.wechatLoginService.startLogin().subscribe( (response) => { console.log('成功响应', response); this.handleSuccess(response); }, (error) => { console.error('登录失败', error); this.handleFailure(error); } ); } handleSuccess(data) { // 处理成功的回调数据,可能包含用户信息等 console.log('登录成功', data); // 根据实际情况,可以跳转至主页面或其他操作 } handleFailure(err) { // 处理错误情况 console.log('登录失败', err); } } ``` #### 5. 显示二维码界面 在前端渲染界面中,添加一个按钮触发微信登录请求,然后展示一个二维码供用户扫码。 ```html <button (click)="startWechatLogin()">微信扫码登录</button> <div #qrCode></div> <!-- 添加模板引用 --> <ng-template #qrCode> <!-- 渲染二维码图片 --> <img src="{{ qrCodeUrl }}" alt="二维码"> </ng-template> ``` #### 6. 后端对接 后端需要设置好路由和控制器,用于接收来自微信的回调数据,验证用户身份并返回对应的信息给前端。 #### 7. 用户权限管理 根据用户通过微信登录获得的信息,更新或创建用户的会话状态和相关信息存储于数据库中。 ### 相关问题: 1. **如何优化微信扫码登录的用户体验?** 提高加载速度、简化交互流程、增强安全防护措施、提供反馈提示等都是优化体验的关键点。 2. **Angular中如何处理微信扫码登录的异常情况?** 对应的错误处理逻辑应该覆盖所有可能发生的异常场景,比如网络错误、服务器响应延迟、用户取消扫码等,避免应用崩溃。 3. **为什么选择微信扫码登录而非其他第三方登录方式?** 主要考虑的因素有安全性、用户基数大、易于集成、用户体验良好等。微信作为中国的主流社交软件之一,拥有庞大的用户群体和良好的品牌认知度,适合多种应用场景。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

是汤圆丫

怎么 给1分?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值