完整的微信支付代码,不会的进来拿走直接用

本文阅读 7 分钟
首页 代码,Java 正文

        hello,大家好呀,这次想给大家分享一下近期学习研究的技术,那就是微信支付了。提到微信支付,大家肯定熟悉的不能再熟悉了,梦梦也就不多解释了。         由于工作原因,这两天就一直在学习微信支付这方面的知识,文档、视频、SDK真的是每一样都不落下,边看边动手操作,用视频上给的参数配置创建项目写接口、写笔记等等,下面就是学习过程中记录的笔记辽。

        如果有需要笔记+代码的码友们,可以去梦梦空间搜 “微信支付(笔记和代码)”,也可以点击链接查看 微信支付(笔记+代码)

        代码:(其中一部分哈)

/** * @Decription 获取商户的私钥 * private 私有方法使私钥安全性提高 * @Param fileName 私钥文件的路径 * @Return java.security.PrivateKey * @Author lmh * @Date 2022/5/12 0:48 */
    private PrivateKey getPrivateKey(String fileName){ 
        try { 
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(
                    new FileInputStream(fileName));
            return merchantPrivateKey;
        } catch (FileNotFoundException e) { 
            //抛出异常,并把错误文件继续向上抛出
            throw new RuntimeException("私钥文件不存在",e);
        }
    }

    /** * @Decription 获取签名验证器,会定时下载和更新商户对应的平台证书 * @Param null * @Return com.wechat.pay.contrib.apache.httpclient.auth.Verifier * @Author lmh * @Date 2022/5/12 3:35 */
    @Bean    //让这个方法可以自动执行,不执行多次,应用程序启动的时候执行一次即可
    public Verifier getVerifier() { 
        log.info("获取签名验证器");
        //1,获取商户私钥
        PrivateKey merchantPrivateKey = this.getPrivateKey(privateKeyPath);
        //2,获取私钥签名对象
        PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, merchantPrivateKey);
        //3,获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        //4,获取身份认证对象
        WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);
        //5,向证书管理器增加需要自动更新平台证书的商户信息
        try { 
            certificatesManager.putMerchant(mchId, wechatPay2Credentials, apiV3Key.getBytes(StandardCharsets.UTF_8));
            // ... 若有多个商户号,可继续调用putMerchant添加商户信息
            //6,从证书管理器中获取verifier
            Verifier verifier =certificatesManager.getVerifier(mchId);
            return verifier;
        } catch (Exception e) { 
            throw new RuntimeException("获取失败",e);
        }
    }


    /** * @Decription 获取微信支付的远程请求对象 HttpClient请求对象 * @Param verifier 签名验证器 * @Return org.apache.http.impl.client.CloseableHttpClient * @Author lmh * @Date 2022/5/12 3:22 */
    @Bean(name = "wxPayClient")  //配置类中加@bean 表示项目启动的时候就会加载bean
    public CloseableHttpClient getWxPayClient(Verifier verifier){ 
        log.info("获取httpclient对象");
        //1,获取商户私钥
        PrivateKey merchantPrivateKey = this.getPrivateKey(privateKeyPath);
        //获取WechatPayHttpClientBuilder对象
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(mchId, mchSerialNo, merchantPrivateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient

        // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }

    /** * 获取HttpClient,无需进行应答签名验证,跳过验签的流程 */
    @Bean(name = "wxPayNoSignClient")
    public CloseableHttpClient getWxPayNoSignClient(){ 

        //获取商户私钥
        PrivateKey privateKey = getPrivateKey(privateKeyPath);

        //用于构造HttpClient
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                //设置商户信息
                .withMerchant(mchId, mchSerialNo, privateKey)
                //无需进行签名验证、通过withValidator((response) -> true)实现
                .withValidator((response) -> true);

        // 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();

        log.info("== getWxPayNoSignClient END ==");

        return httpClient;
    }
/** * @program: payment_demo * @description: 微信支付 * @author: lmh * @create: 2022-05-12 14:11 **/
@CrossOrigin   //跨域
@RestController
@RequestMapping("/api/wx-pay")
@Api(tags = "网站微信支付API")
@Slf4j
public class WxPayController { 
    @Resource
    private WxPayService wxPayService;
    @Resource
    private Verifier varifier;

    /** * @Decription 传入商品ID,调用Native下单接口,生成支付二维码 * API V3 版本要使用RESTful风格 * @Param null * @Return com.payment.vo.R * @Author lmh * @Date 2022/5/12 14:18 */
    @ApiOperation(value = "调用Native下单接口,生成支付二维码")
    @PostMapping("/native/{productId}")
    public R nativePay(@PathVariable Long productId) throws Exception{ 
        log.info("发起支付请求,支付订单号是:"+productId);
        //1,返回支付二维码链接和订单号
        Map<String,Object> map = wxPayService.nativePay(productId);
        return R.ok().setData(map);
    }

    /** * @Decription 接收通知 * 这个地址要和我们下单的时候设置的notify_url 地址是一样的,这样的话当我们调用下单接口给微信发送请求的时候, * 微信是根据我们的notify_url参数中的地址给我们通知、应答的 * @Param null * @Return java.lang.String * @Author lmh * @Date 2022/5/13 13:46 */
    @PostMapping("/native/notify")
    public String nativeNotify(HttpServletRequest request, HttpServletResponse response){ 
        Gson gson = new Gson();
        Map<String,Object> bodyMap;  //通知对象,JSON格式的
        Map<String,Object> responseMap = new HashMap<>();   //给应答对象
        try { 
            //1,处理通知参数,即处理微信给我们发出的请求
            String body = HttpUtils.readData(request);
            //2,将请求体转化为JSON
            bodyMap = gson.fromJson(body, HashMap.class);
            String requestId = (String) bodyMap.get("id");
            log.info("支付通知的ID:{}",requestId);
            log.info("支付通知的完整数据:{}",bodyMap);
            //int i = 9/0;
            //3,通知签名验证
            //针对微信通知(给我们请求)的签名验证,需要自己编写;但针对微信应答(给我们响应)的签名验证,封装在SDK中,不需要我们编写
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(varifier, body, requestId);
            if (!wechatPay2ValidatorForRequest.validate(request)){ 
                log.error("通知签名验证失败");
                response.setStatus(500);
                responseMap.put("code", "FAIL");
                responseMap.put("message","通知签名验证失败");
                return gson.toJson(responseMap);
            }
            log.info("验签成功");
            //4,处理订单(订单状态,记录日志等等)
            wxPayService.processOrder(bodyMap);

            //模拟应答超时5秒,微信会按照频次重复的给我们发通知
            //TimeUnit.SECONDS.sleep(5);

            //发送成功应答
            response.setStatus(200);
            responseMap.put("code", "SUCCESS");
            responseMap.put("message","成功");
            return gson.toJson(responseMap);
        } catch (Exception e) { 
            e.printStackTrace();
            //发送失败应答
            response.setStatus(500);
            responseMap.put("code", "FAIL");
            responseMap.put("message","失败");
            return gson.toJson(responseMap);
        }
    }

    /** * @Decription 取消订单 * @Param null * @Return com.payment.vo.R * @Author lmh * @Date 2022/5/14 23:59 */
    @ApiOperation(value = "用户取消订单")
    @PostMapping("/cancel/{orderNo}")
    public R cancel(@PathVariable String orderNo) throws Exception { 
        log.info("用户取消订单");
        wxPayService.cancelOrder(orderNo);
        return R.ok().setMessage("订单已经取消");
    }

    /** * @Decription 查单接口 实际业务中不需要写controller,是写在定时任务中的, * 写controller只是方便我们测试 * @Param null * @Return com.payment.vo.R * @Author lmh * @Date 2022/5/15 0:40 */
    @ApiOperation(value = "查询订单 : 测试使用")
    @GetMapping("/query/{orderNo}")
    public R queryOrder(@PathVariable String orderNo) throws Exception { 
        log.info("查询订单");
        String result = wxPayService.queryOrder(orderNo);
        return R.ok().setMessage("查询成功").data("result",result);
    }

    /** * @Decription 申请退款 * @Param orderNo :订单编号; reason : 退款原因 * @Return com.payment.vo.R * @Author lmh * @Date 2022/5/15 21:48 */
    @ApiOperation(value = "申请退款")
    @ApiImplicitParams({ @ApiImplicitParam(name = "orderNo",value = "订单编号"),
    @ApiImplicitParam(name = "reason",value = "退款原因")})
    @PostMapping("/refunds/{orderNo}/{reason}")
    public R refunds(@PathVariable String orderNo,@PathVariable String reason) throws Exception{ 
        log.info("申请退款");
        wxPayService.refund(orderNo,reason);
        return R.ok();
    }

    /** * @Decription * @Param request 微信通知的请求 * @param response 我们给微信的应答响应 * @Return java.lang.String * @Author lmh * @Date 2022/5/15 23:47 */
    @PostMapping("/refunds/notify")
    public String refundsNotify(HttpServletRequest request,HttpServletResponse response){ 
        log.info("退款通知");
        Gson gson = new Gson();
        Map<String,Object> bodyMap;  //通知对象,JSON格式的
        Map<String,String> responseMap = new HashMap<>();  //应答对象
        try { 
            //1,处理通知参数
            String body = HttpUtils.readData(request);
            bodyMap = gson.fromJson(body,HashMap.class);
            String requestId = (String) bodyMap.get("id");  //通知ID,唯一的
            log.info("退款通知的id:{}",requestId);
            log.info("退款通知完整的数据:{}",bodyMap);
            //2,通知签名的验证
            //针对微信通知(给我们请求)的签名验证,需要自己编写;但针对微信应答(给我们响应)的签名验证,封装在SDK中,不需要我们编写
            WechatPay2ValidatorForRequest wechatPay2ValidatorForRequest = new WechatPay2ValidatorForRequest(varifier, body, requestId);
            if (!wechatPay2ValidatorForRequest.validate(request)){ 
                log.error("退款通知验签失败");
                //失败的应答
                response.setStatus(500);
                responseMap.put("code","FAIL");
                responseMap.put("message","退款通知验签失败");
                return gson.toJson(responseMap);
            }
            log.info("退款通知验签成功");
            //3,处理退款订单
            wxPayService.processRefund(bodyMap);
            //4,成功应答
            response.setStatus(200);
            responseMap.put("code","SUCCESS");
            responseMap.put("message","退款通知验签成功");
            return gson.toJson(responseMap);
        } catch (Exception e) { 
            e.printStackTrace();
            //失败的应答
            response.setStatus(500);
            responseMap.put("code","FAIL");
            responseMap.put("message","退款通知验签失败");
            return gson.toJson(responseMap);
        }
    }

    /** * @Decription 实际业务中我们是不用对外提供接口的,写在定时任务中的 * @Param refundNo 退款单号 * @Return com.payment.vo.R * @Author lmh * @Date 2022/5/15 23:28 */
    @ApiOperation(value = "查询退款 : 测试使用")
    @GetMapping("/query-refund/{refundNo}")
    public R queryRefund(@PathVariable String refundNo) throws Exception{ 
        log.info("查询退款");
        String result = wxPayService.queryRefund(refundNo);
        return R.ok().setMessage("查询成功").data("result",result);
    }

    /** * @Decription 获取账单url * @Param billDate 账单日期 * @param type 账单类型(交易账单 tradebill ; 资金账单 fundflowbill) * @Return com.payment.vo.R * @Author lmh * @Date 2022/5/16 1:29 */
    @ApiOperation(value = "获取账单URL:测试使用")
    @GetMapping("/querybill/{billDate}/{type}")
    public R quryTradeBill(@PathVariable String billDate,@PathVariable String type) throws Exception{ 
        log.info("获取账单url");
        String downloadUrl = wxPayService.queryBill(billDate,type);
        return R.ok().setMessage("获取账单url成功").data("downloadUrl",downloadUrl);
    }

    @ApiOperation("下载账单")
    @GetMapping("/downloadbill/{billDate}/{type}")
    public R downloadBill(@PathVariable String billDate, @PathVariable String type) throws Exception { 

        log.info("下载账单");
        String result = wxPayService.downloadBill(billDate, type);

        return R.ok().data("result", result);
    }

}

        笔记: img

        如果有需要笔记+代码的码友们,可以去梦梦空间搜 “微信支付(笔记和代码)”,也可以点击链接查看 微信支付(笔记+代码)         好了,就不多聊了哈,现在已经很晚了,去碎觉了,拜拜

本文为互联网自动采集或经作者授权后发布,本文观点不代表立场,若侵权下架请联系我们删帖处理!文章出自:https://blog.csdn.net/qq_46540738/article/details/124792096
-- 展开阅读全文 --
安全面试之XSS(跨站脚本攻击)
« 上一篇 07-24

发表评论

成为第一个评论的人

热门文章

标签TAG

最近回复