小程序微信支付v3版java代码,支付与退款

支付功能

首先需要自己在微信平台申请账户,将openid与key放入配置文件中进行读取,在公众平台配置支付回调地址,还需要下载好加密的证书,对信息进行加密

编写代码按照微信提供的文档进行拼接自己的参数,进行加密处理后请求微信提供的地址,因为我写的是小程序,在登陆时候就保存用户的openid了,直接获取即可。同时配置的回调地址需要外网能够访问。

 

 @RequestMapping(value = "do", method = RequestMethod.POST)
    public R payVip(@RequestBody WxVo vo) throws Exception {
        User user = userService.getById(vo.getUserid());
        String userOpenid = user.getOpenid();
        if (StringUtils.isEmpty(userOpenid)){
            StringBuffer baseAccessTokenUrl = new StringBuffer()
                    .append("https://api.weixin.qq.com/sns/jscode2session")
                    .append("?appid=%s")
                    .append("&secret=%s")
                    .append("&js_code=%s")
                    .append("&grant_type=authorization_code");
            String accessTokenUrl = String.format(baseAccessTokenUrl.toString(),
                    ConstantPropertiesUtil.WX_OPEN_APP_ID,
                    ConstantPropertiesUtil.WX_OPEN_APP_SECRET,
                    vo.getCode());
            OkHttpClient client = new OkHttpClient();
            Request request = new Request.Builder().url(accessTokenUrl).build();
            Response response = client.newCall(request).execute();
            if (response.isSuccessful()) {
                String body = response.body().string();
                JSONObject jsonObject = JSONObject.parseObject(body);
                String session_key = jsonObject.getString("session_key");
                String openid = jsonObject.getString("openid");
                userOpenid=openid;
            }else {
                return R.error().message("微信授权失败");
            }

        }
       //判断自己的业务逻辑
        //开始支付,创建数据体
        JSONObject order = new JSONObject();
        order.put("appid", ConstantPropertiesUtil.WX_OPEN_APP_ID);
        order.put("mchid",ConstantPropertiesUtil.PARTNER);
        order.put("description","支付");
        String str_no = new DateTime().toString("yyyyMMddHHmmssSSS");
        order.put("out_trade_no",str_no);
        System.out.println(str_no);
        order.put("notify_url","https://www.dsxssd.com/api/dsxs/wx/payNotice");
        JSONObject amount =  new JSONObject();
        amount.put("total",(long)(companyClass.getMoney()*100));
        amount.put("currency","CNY");
        order.put("amount",amount);
        JSONObject payer = new JSONObject();
        payer.put("openid",userOpenid);
        order.put("payer",payer);
//放在服务器上的v3证书
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(ResourceUtils.getFile("/www/zs/apiclient_key.pem")));
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
                new WechatPay2Credentials(ConstantPropertiesUtil.PARTNER,new PrivateKeySigner(ConstantPropertiesUtil.NUM,merchantPrivateKey)),
                ConstantPropertiesUtil.MY.getBytes(StandardCharsets.UTF_8));

        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(ConstantPropertiesUtil.PARTNER, ConstantPropertiesUtil.NUM, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier));
        HttpClient httpClient = builder.build();
        HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
        httpPost.addHeader("Accept","application/json");
        httpPost.addHeader("Content-type","application/json;charset=utf-8");
        httpPost.setEntity(new StringEntity(order.toJSONString(),"UTF-8"));
        HttpResponse response = httpClient.execute(httpPost);
        String body = EntityUtils.toString(response.getEntity());
        JSONObject jsonObject = JSONObject.parseObject(body);
        if(jsonObject.containsKey("code")) {
            System.out.println(jsonObject.getString("message"));
            return null;
        }
        final String prepay_id = jsonObject.getString("prepay_id");

        final String timeStamp = System.currentTimeMillis()+"";

        final String nonceStr = RandomStringGenerator.getRandomStringByLength(32);

        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append(ConstantPropertiesUtil.WX_OPEN_APP_ID+"\n");
        stringBuffer.append(timeStamp+"\n");
        stringBuffer.append(nonceStr+"\n");
        stringBuffer.append("prepay_id="+prepay_id+"\n");

            Signature signature = Signature.getInstance("SHA256withRSA");
            signature.initSign(merchantPrivateKey);
            signature.update(stringBuffer.toString().getBytes(StandardCharsets.UTF_8));
        byte[] signBytes = signature.sign();
        String paySign = Base64.encodeBytes(signBytes);

        //处理自己业务逻辑
        corderService.saveCorder(user,companyClass,str_no);

        JSONObject params = new JSONObject();
        params.put("appId",ConstantPropertiesUtil.WX_OPEN_APP_ID);
        params.put("timeStamp",timeStamp);
        params.put("nonceStr",nonceStr);
        params.put("package","prepay_id="+prepay_id);
        params.put("signType","RSA");
        params.put("paySign",paySign);

        return R.ok().data("weixinMap",params);
    }
    /**
     * 买课支付通知(api)
     */
    @RequestMapping(value = "payNotice", method = RequestMethod.POST)
    public R payNotice(
            HttpServletRequest request,
            HttpServletResponse response){
        System.out.println("支付回调执行");
        try {
            String reqParams = StreamUtil.read(request.getInputStream());
            logger.info("-------支付结果:"+reqParams);
            JSONObject json = JSONObject.parseObject(reqParams);
            if(json.getString("event_type").equals("TRANSACTION.SUCCESS")){
                logger.info("-------支付成功");

            }
            String ciphertext = json.getJSONObject("resource").getString("ciphertext");
            final String associated_data = json.getJSONObject("resource").getString("associated_data");
            final String nonce = json.getJSONObject("resource").getString("nonce");
            AesUtil aesUtil = new AesUtil(ConstantPropertiesUtil.MY.getBytes(StandardCharsets.UTF_8));
            ciphertext = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
            logger.info(JSONObject.parseObject(ciphertext).getString("out_trade_no"));
            //商户单号
            String out_trade_no =  JSONObject.parseObject(ciphertext).getString("out_trade_no");
            //交易单号
            String transaction_id = JSONObject.parseObject(ciphertext).getString("transaction_id");
            //金额
            String total =JSONObject.parseObject(ciphertext).getString("total");
            String openid =JSONObject.parseObject(ciphertext).getString("openid");
            System.out.println("更新数据库");
                UpdateWrapper<Corder> wrapper = new UpdateWrapper<>();
                wrapper.eq("orderid",out_trade_no).set("status",1).set("paytype",2);
            boolean b = corderService.update(wrapper);
            System.out.println(b+"=============");


        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
        }
        return R.ok();
    }

由于服务器上的jre对v3秘钥进行加密解密的长度超过128,会报异常需要我们自己下载jrc将其中的jar覆盖掉原有的。

退款

 @RequestMapping(value="/refund")
    public void refund(
            String out_trade_no,
            String reason){
        System.out.println("退款接口执行");
        Integer totalFee = 1;
        Integer total = 1;
        Orderr orderr = orderrService.getById(out_trade_no);
        if (!StringUtils.isEmpty(orderr)){
            total = orderr.getPayment();
            totalFee = orderr.getPayment();
        }else {
            Corder corder = corderService.getCorderByNo(out_trade_no);
            totalFee = corder.getPayment();
            total = corder.getPayment();
        }
        String out_refund_no = new DateTime().toString("yyyyMMddHHmmssSSS");
        try {

            JSONObject order = new JSONObject();
            order.put("out_trade_no", out_trade_no);//商户订单号
            order.put("out_refund_no", out_refund_no);//商户退款单号
            order.put("reason", reason);//退款原因
            order.put("notify_url","https://www.dsxssd.com/api/dsxs/wx/refundNotice/");//退款通知

            JSONObject amount = new JSONObject();
            amount.put("refund", (long)(totalFee*100));//退款金额
            amount.put("currency", "CNY");
            amount.put("total", (long)(total*100));//原订单金额
            order.put("amount", amount);

            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(ResourceUtils.getFile("/www/zs/apiclient_key.pem")));

            // 使用定时更新的签名验证器,不需要传入证书
            ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
                    new WechatPay2Credentials(ConstantPropertiesUtil.PARTNER, new PrivateKeySigner( ConstantPropertiesUtil.NUM, merchantPrivateKey)),
                    ConstantPropertiesUtil.MY.getBytes(StandardCharsets.UTF_8));
            WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                    .withMerchant(ConstantPropertiesUtil.PARTNER, ConstantPropertiesUtil.NUM, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(verifier));
            // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient

            // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
            HttpClient httpClient = builder.build();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/refund/domestic/refunds");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type","application/json; charset=utf-8");
            httpPost.setEntity(new StringEntity(order.toJSONString(), "UTF-8"));
            // 后面跟使用Apache HttpClient一样

            HttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());

            JSONObject bodyAsJSON = JSONObject.parseObject(bodyAsString);

            logger.info(bodyAsJSON.toJSONString());

            final String status = bodyAsJSON.getString("status");
            if(status.equals("SUCCESS")){
                logger.info("退款成功");
            }else if(status.equals("CLOSED")){
                logger.info("退款关闭");
            }else if(status.equals("PROCESSING")){
                logger.info("退款处理中");
            }else if(status.equals("ABNORMAL")){
                logger.info("退款异常");
            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            logger.info(e.toString());
            e.printStackTrace();
        }
    }


    /**
     * 买课退款通知(api)
     */
    @RequestMapping(value="/refundNotice")
    public void refundNotice(
            HttpServletRequest request,
            HttpServletResponse response){
        try {
            String reqParams = StreamUtil.read(request.getInputStream());
            logger.info("-------退款回调结果:"+reqParams);
            JSONObject json = JSONObject.parseObject(reqParams);
            final String event_type = json.getString("event_type");
            if(event_type.equals("REFUND.SUCCESS")){
                logger.info("-------退款成功");
            }else if(event_type.equals("REFUND.ABNORMAL")){
                logger.info("-------退款异常");
            }else if(event_type.equals("REFUND.CLOSED")){
                logger.info("-------退款关闭");
            }
            String ciphertext = json.getJSONObject("resource").getString("ciphertext");
            final String associated_data = json.getJSONObject("resource").getString("associated_data");
            final String nonce = json.getJSONObject("resource").getString("nonce");
            AesUtil aesUtil = new AesUtil(ConstantPropertiesUtil.MY.getBytes());
            ciphertext = aesUtil.decryptToString(associated_data.getBytes(), nonce.getBytes(), ciphertext);
            logger.info("-------ciphertext:"+ciphertext);
            String out_trade_no =  JSONObject.parseObject(ciphertext).getString("out_trade_no");

      
           //处理自己的业务逻辑
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.toString());
        }
    }

复制改改就能用

猜你喜欢

转载自blog.csdn.net/weixin_52210557/article/details/125125451