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

        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);
    }

}

        笔记:
完整的微信支付代码,不会的进来拿走直接用_第1张图片

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

你可能感兴趣的:(第三方技术,微信,java,开发语言,微信开放平台,微信支付)