JSAPI微信支付java

前期准备:

首先要有公众号(服务号)和商户号;在微信商户平台-->产品中心-->AppID账号管理中,关联AppID账号

1、导入maven依赖


   com.github.wxpay
   wxpay-sdk
   0.0.3

2、公众号设置(注:支付授权目录写到访问路径的controller的那一级就可以了,不要写到方法,页面支付授权路径直接配置页面的顶级域名即可)

JSAPI微信支付java_第1张图片

JSAPI微信支付java_第2张图片

3、获取openid

    @RequestMapping("/")
    public void wxlogin(HttpServletResponse response) {
        try {
        // 第一步:用户同意授权,获取code
        String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +             wxAppID +
                "&redirect_uri=" + wxUrl+"/test/wxcallback" +
                "&response_type=code" +
                "&scope=snsapi_base" +
                "&state=STATE#wechat_redirect";

            response.sendRedirect(url);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @RequestMapping("/wxcallback")
    public String wxcallback(String code){
        // 第二步:通过code换取网页授权access_token
        String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + wxAppID +
                "&secret=" + secret +
                "&code=" + code +
                "&grant_type=authorization_code";
        ResponseEntity res = restTemplate.getForEntity(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(res.getBody());
        
        return jsonObject.get("openid").toString();

4、统一下单(生成签名的顺序不要变)

public Result unifiedOrderJSAPI(Map orderMap, HttpServletRequest request) {

        Map returnMap = new HashMap<>();
        Map responseMap = new HashMap<>();
        Map data = new HashMap<>();
        String orderNo = null;
        try {
            //如果订单不为空
            if (orderMap != null){
                orderNo = orderMap.get("id").toString();
                Double amount = Double.parseDouble(orderMap.get("sfprice").toString());

                //支付参数
                WXPay wxpay = new WXPay(config);

                data.put("appid", config.getAppID());
                data.put("secret", config.getSecret());
                data.put("body", "订单支付");
                data.put("mch_id", config.getMchID());
                data.put("notify_url", config.getWxPayNotifyUrl());//异步通知地址(请注意必须是外网)
                data.put("out_trade_no", orderNo);
                data.put("spbill_create_ip", getIpAddress(request)); //自己的服务器IP地址
                data.put("openid", orderMap.get("openId").toString()); //openId

                data.put("total_fee", String.valueOf((int) (amount * 100)));
                data.put("trade_type", "JSAPI");//交易类型JSAPI支付
                String s = WXPayUtil.generateSignature(data, config.getKey());  //签名
                data.put("sign", s);//签名
                //使用官方API请求预付订单
                Map resultMap = wxpay.unifiedOrder(data);
                //获取返回码
                String returnCode = resultMap.get("return_code");
                //若返回码为SUCCESS,则会返回一个result_code,再对该result_code进行判断
                if ("SUCCESS".equals(returnCode)) {
                    String resultCode = resultMap.get("result_code");
                    if ("SUCCESS".equals(resultCode)) {
                        responseMap = resultMap;
                    }
                }
                if (responseMap == null || responseMap.isEmpty()) {
                    return ResultUtil.error("获取预支付交易会话标识失败"+responseMap);
                }
                // 3、签名生成算法
                Long time = System.currentTimeMillis() / 1000;
                String timestamp = time.toString();
                returnMap.put("appId", config.getAppID());
                returnMap.put("nonceStr", responseMap.get("nonce_str"));
                returnMap.put("package", "prepay_id="+responseMap.get("prepay_id"));
                returnMap.put("signType", "MD5");
                returnMap.put("timeStamp", timestamp);
                returnMap.put("paySign", WXPayUtil.generateSignature(returnMap, config.getKey()));//微信支付签名
            }
            return ResultUtil.success(returnMap);
        } catch (Exception e) {
            logger.error("订单号:{},错误信息:{}", orderNo, e.getStackTrace());
            return ResultUtil.error("微信支付统一下单失败");
        }
    }

5、获取jssdk配置信息

@RequestMapping("/weixinInfo")
    public Result weixinInfo( @RequestBody Map param) {
        try {
            //1、获取AccessToken jsapi_ticket
            Map tokenMap = tokenMap();
            String accessToken = tokenMap.get("accessToken");
            String jsapiTicket = tokenMap.get("ticket");
            //2、时间戳和随机字符串
            String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
            String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
            //3、获取url
            String url = config.getUrl();
            //4、将参数排序并拼接字符串
            String str = "jsapi_ticket=" + jsapiTicket + "&noncestr=" + noncestr + "×tamp=" + timestamp + "&url=" + param.get("url");
            logger.info("参数拼接的字符串:" + str);
            //5、将字符串进行sha1加密
            String signature = SHA1(str);
            logger.info("签名:" + signature);
            Map data = new HashMap<>();
            data.put("timestamp", timestamp);
            data.put("nonceStr", noncestr);
            data.put("signature", signature);
            data.put("accessToken", accessToken);
            data.put("appId", config.getAppID());
            return ResultUtil.success(data);
        } catch (Exception e) {
            logger.error("获取微信信息的错误", e);
            return ResultUtil.error("获取微信信息的错误");
        }

    }
    public String getAccessToken(){
        String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + "&appid=" + config.getAppID() + "&secret="+ config.getSecret();
        ResponseEntity res = restTemplate.getForEntity(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(res.getBody());
        String accessToken = jsonObject.getString("access_token");
        redisTemplate.opsForValue().set("accessToken",accessToken,2L, TimeUnit.HOURS);
        return  accessToken;
    }
    public String getTicket(String accessToken){
        String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";// 这个url链接和参数不能变
        ResponseEntity res = restTemplate.getForEntity(url, String.class);
        JSONObject jsonObject = JSONObject.parseObject(res.getBody());
        String ticket = jsonObject.getString("ticket");
        redisTemplate.opsForValue().set("ticket",ticket,2L, TimeUnit.HOURS);
        return  ticket;
    }
    public Map tokenMap(){
        Map tokenMap=new HashMap<>();
        String accessToken = null;
        String ticket = null;
        if (redisTemplate.opsForValue().get("access_token") != null){
            accessToken = redisTemplate.opsForValue().get("access_token").toString();
        }else{
            accessToken = getAccessToken();
        }
        if (redisTemplate.opsForValue().get("ticket") != null){
            ticket = redisTemplate.opsForValue().get("ticket").toString();
        }else{
            ticket = getTicket(accessToken);
        }
        tokenMap.put("accessToken",accessToken);
        tokenMap.put("ticket",ticket);
        return tokenMap;
    }
    public static String SHA1(String decript) {
        try {
            MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
            digest.update(decript.getBytes());
            byte messageDigest[] = digest.digest();
            // Create Hex String
            StringBuffer hexString = new StringBuffer();
            // 字节数组转换为 十六进制 数
            for (int i = 0; i < messageDigest.length; i++) {
                String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexString.append(0);
                }
                hexString.append(shaHex);
            }
            return hexString.toString();

        } catch (NoSuchAlgorithmException e) {
            logger.error("SHA1发生错误", e);
        }
        return "";
    }

6、支付页面




你可能感兴趣的:(springboot,微信支付,微信JSAPI支付)