欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

vue springboot 接入支付宝 微信 银联

程序员文章站 2024-01-22 11:11:10
...

需要:支付宝商户号,微信商户号,银联商户号

支付宝

  1. 进入支付宝开放平台,我用的公钥证书方式,参考文档… 把需要的6个文件弄到,vue springboot 接入支付宝 微信 银联
    2.弄到文件后,后台yml配置文件中配置支付宝的一些参数和路径:
    vue springboot 接入支付宝 微信 银联
    3.Controller 那边接收参数传给Service就行 自己写吧
    4.Service:
  //pom.xml引入支付宝sdk
 <dependency> 
      <groupId>com.alipay.sdk</groupId>
      <artifactId>alipay-sdk-java</artifactId>
      <version>4.8.62.ALL</version>
 </dependency>
 =====================================================================================
 //支付
  public String Alipay(FinalParma finalParma,int isMobile) {
      try{CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
          certAlipayRequest.setServerUrl(gaturl);
          certAlipayRequest.setAppId(appid);
          certAlipayRequest.setPrivateKey(app_private_key);
          certAlipayRequest.setFormat("json");
          certAlipayRequest.setCharset(charset);
          certAlipayRequest.setSignType(sign_type);
          certAlipayRequest.setCertPath(app_cert_path);
          certAlipayRequest.setAlipayPublicCertPath(ali_cert_path);
          certAlipayRequest.setRootCertPath(ali_root_cert_path);
          AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
          if(isMobile==1){
              AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
              request.setReturnUrl(ali_return_url); //前台通知地址
              request.setNotifyUrl(natapp + ali_notify_url); //异步地址
              request.setBizContent(GsonUtil.getgson().toJson(finalParma));//这个就不解释了
              AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
              if(response.isSuccess()){
                  System.out.println("调用手机支付成功");
                  return response.getBody();  //返回的是html文本
              }else {
                  System.out.println("调用手机支付失败");
              }
          }else {
              AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
              request.setReturnUrl(ali_return_url);
              request.setNotifyUrl(natapp + ali_notify_url);
              request.setBizContent(GsonUtil.getgson().toJson(finalParma));
              AlipayTradePagePayResponse response = alipayClient.pageExecute(request);
              if(response.isSuccess()){
                  System.out.println("调用电脑支付成功");
                  return response.getBody();
              }else {
                  System.out.println("调用电脑支付失败");
              }
          }
      }catch (Exception e){
          e.printStackTrace();
      }
      return null;
  }

  //异步通知
  public String ali_notify(HttpServletRequest request){
      try{Map<String, String> params = new HashMap<>();
          Map requestParams = request.getParameterMap();
          for (Object o : requestParams.keySet()) {
              String name = (String) o;
              String[] values = (String[]) requestParams.get(name);
              String valueStr = "";
              for (int i = 0; i < values.length; i++) {
                  valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
              }
              params.put(name, valueStr);
          }
          
          boolean signVerified = AlipaySignature.rsaCertCheckV1(params, ali_cert_path, charset,sign_type);
          if(!signVerified) {
              System.out.println("校验失败");
              return "fail";
          }

          String trade_status = params.get("trade_status");
          String order_ids = URLDecoder.decode(params.get("passback_params"), "UTF-8"); //传过来的业务参数
          if (trade_status.equals("TRADE_SUCCESS")){
              System.out.println("支付成功:"+trade_status);
              //业务逻辑...
              return "success";
          }
      }catch (Exception e){
          e.printStackTrace();
      }
      return "fail";
  }

  //退款
  public String ali_refund(Order order){
      try{CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
          certAlipayRequest.setServerUrl(gaturl);
          certAlipayRequest.setAppId(appid);
          certAlipayRequest.setPrivateKey(app_private_key);
          certAlipayRequest.setFormat("json");
          certAlipayRequest.setCharset(charset);
          certAlipayRequest.setSignType(sign_type);
          certAlipayRequest.setCertPath(app_cert_path);
          certAlipayRequest.setAlipayPublicCertPath(ali_cert_path);
          certAlipayRequest.setRootCertPath(ali_root_cert_path);
          AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
          AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

          RefundPar refundPar = new RefundPar();
          refundPar.setOut_trade_no(order.getOut_trade_no());
          refundPar.setTrade_no(order.getTrade_no());
          refundPar.setOut_request_no(order.getOrder_sn());
          refundPar.setRefund_amount(order.getPay_amount());
          request.setBizContent(GsonUtil.getgson().toJson(refundPar));
          AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);

          if(response.isSuccess()){
              System.out.println("调用退款成功");
              //业务逻辑
              return response.getBody();
          } else {
              System.out.println("调用退款失败");
          }
      }catch (Exception e){
          e.printStackTrace();
      }
      return null;
  }
======================================================================================
 //支付宝同步跳转接口
 @RequestMapping("/ali_return_url")
 public String ali_return_url(HttpServletRequest request){
     return "<html>\n" +
           "<head>\n" +
           "</head>\n" +
           "<body>\n" +
           "<div style=\"display: flex\">\n" +
           "    <b style=\"margin: 100px auto;color: red;font-size: 50px;\"> 支付成功:"+request.getParameter("total_amount") +"元 </b>\n" +
           "</div>\n" +
           "</body>\n" +
           "</html>";
 }
 //支付宝基本接口ok.拿去即用

微信

1.搞到微信需要的一些证书文件后,yml配置:
vue springboot 接入支付宝 微信 银联
2.再来一个配置类:
vue springboot 接入支付宝 微信 银联
3.Controller自己写, Service:

     <!--pom.xml文件引入微信sdk-->
     <dependency>
         <groupId>com.github.wxpay</groupId>
         <artifactId>wxpay-sdk</artifactId>
         <version>0.0.3</version>
     </dependency>
  =============================================================================
  
    @Resource
    WxPayAppConfig myWXPayConfig;

    //wx支付
    public String WeChat(FinalParma finalParma){
        Map<String, String> returnMap = new HashMap<>();
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        try {
            WXPay wxpay = new WXPay(myWXPayConfig);
            requestMap.put("body", finalParma.getSubject());                        // 商品描述
            requestMap.put("out_trade_no", "1415659990");                           // 商户订单号
            requestMap.put("total_fee", "855");                                     // 总金额
            requestMap.put("spbill_create_ip", "123.123.123.123");                  // 终端IP
            requestMap.put("trade_type", "NATIVE");                                 // 支付类型
            requestMap.put("notify_url", myWXPayConfig.getWx_notify_url());         // 接收微信支付异步通知回调地址

            Map<String, String> resultMap = wxpay.unifiedOrder(requestMap);
            System.out.println(resultMap);

            String returnCode = resultMap.get("return_code");
            String returnMsg = resultMap.get("return_msg");
            if ("SUCCESS".equals(returnCode)) {
                String resultCode = resultMap.get("result_code");
                String errCodeDes = resultMap.get("err_code_des");
                if ("SUCCESS".equals(resultCode)) {
                    responseMap = resultMap;
                }
            }
            if (responseMap.isEmpty()) {
                System.out.println("结果为空");
                return "结果为空";
            }
            // 3、签名生成算法
            Long time = System.currentTimeMillis() / 1000;
            String timestamp = time.toString();
            returnMap.put("appid", myWXPayConfig.getAppID());
            returnMap.put("partnerid", myWXPayConfig.getMchID());
            returnMap.put("prepayid", responseMap.get("prepay_id"));
            returnMap.put("noncestr", responseMap.get("nonce_str"));
            returnMap.put("timestamp", timestamp);
            returnMap.put("package", "Sign=WXPay");
            returnMap.put("sign", WXPayUtil.generateSignature(returnMap, myWXPayConfig.getKey())); //微信支付签名

            System.out.println("调用微信支付成功");
            return "ok";
        } catch (Exception e) {
            e.printStackTrace();
            return "微信支付统一下单异常";
        }

    }
    //异步通知
    public String wx_notify(String notifyStr) {
        String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
        try {
            // 转换成map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(notifyStr);
            WXPay wxpayApp = new WXPay(myWXPayConfig);
            if (wxpayApp.isPayResultNotifySignatureValid(resultMap)) {
                String returnCode = resultMap.get("return_code");  //状态
                String outTradeNo = resultMap.get("out_trade_no");//商户订单号
                String transactionId = resultMap.get("transaction_id");
                if (returnCode.equals("SUCCESS")) {
                    if (StringUtils.isNotBlank(outTradeNo)) {
                        System.out.println("成功");
                        xmlBack = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return xmlBack;
    }

    //退款
    public String wx_refund(Order order){
        Map<String, String> responseMap = new HashMap<>();
        Map<String, String> requestMap = new HashMap<>();
        WXPay wxpay = new WXPay(myWXPayConfig);
//        requestMap.put("out_trade_no", orderNo);
//        requestMap.put("out_refund_no", UUIDGenerator.getOrderNo());
//        requestMap.put("total_fee", "订单支付时的总金额,需要从数据库查");
//        requestMap.put("refund_fee", String.valueOf((int)(amount*100)));//所需退款金额
//        requestMap.put("refund_desc", refundReason);
        try {
            responseMap = wxpay.refund(requestMap);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String return_code = responseMap.get("return_code");   //返回状态码
        String return_msg = responseMap.get("return_msg");     //返回信息
        if ("SUCCESS".equals(return_code)) {
            String result_code = responseMap.get("result_code");       //业务结果
            String err_code_des = responseMap.get("err_code_des");     //错误代码描述
            if ("SUCCESS".equals(result_code)) {
                //表示退款申请接受成功,结果通过退款查询接口查询
                return "退款申请成功";
            } else {
                return "错误";
            }
        } else {
            return "错误";
        }
    }

=====================================================================================
    //微信异步接口
    @RequestMapping("/wx_notify_url")
    public String wx_notify_url(HttpServletRequest request){
        System.out.println("微信异步通知");
        InputStream is = null;
        String xmlBack = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
        try {
            is = request.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            xmlBack = service_weChat.wx_notify(sb.toString());
        } catch (Exception e) {
            System.out.println("微信手机支付回调通知失败");
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return xmlBack;
    }
OK

银联

1.打开银联开发平台,找到开发包 下载:
vue springboot 接入支付宝 微信 银联
解压找到这几个文件,配置文件就拷贝到项目里,配置一下证书文件的路径就可以:vue springboot 接入支付宝 微信 银联
3.拷贝开发包中的sdk, 把sdk里面的所有类搞到项目里:
vue springboot 接入支付宝 微信 银联
4.再把demo文件里面的这个类搞到项目里,改个名,我改成UnionpayBese:
vue springboot 接入支付宝 微信 银联
5.再搞一个类:

@Component
public class InitUnionPayProject implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        SDKConfig.getConfig().loadPropertiesFromSrc();
    }
}

6.一共有这些东西:

vue springboot 接入支付宝 微信 银联
vue springboot 接入支付宝 微信 银联vue springboot 接入支付宝 微信 银联
vue springboot 接入支付宝 微信 银联
7.Service:

    //银联支付
    public String UnionPay(FinalParma finalParma,int isMobile){
        try
        {
            Map<String, String> requestData = new HashMap<String, String>();
            requestData.put("version", UnionpayBese.version);
            requestData.put("encoding", UnionpayBese.encoding);            //字符集编码
            requestData.put("signMethod", SDKConfig.getConfig().getSignMethod());
            requestData.put("txnType", "01");                             //交易类型 ,01:消费
            requestData.put("txnSubType", "01");                          //交易子类型, 01:自助消费
            requestData.put("bizType", "000201");                         //业务类型,B2C网关支付,手机wap支付
            requestData.put("frontUrl", frontUrl);   //前台跳转地址
            requestData.put("backUrl", natapp + backUrl);  //异步通知地址

            requestData.put("merId", merID);
            requestData.put("accessType", "0");
            System.out.println("订单号:" +finalParma.getOut_trade_no());
            requestData.put("orderId", finalParma.getOut_trade_no());
            requestData.put("txnTime", TimeUtils.getDate("yyyyMMddHHmmss"));
            requestData.put("currencyCode", "156");
            requestData.put("txnAmt", changeBranch(finalParma.getTotal_amount()));
            if(isMobile==1){
                System.out.println("手机网页");
                requestData.put("channelType", "08");
            }else{
                System.out.println("pc网页");
                requestData.put("channelType", "07");
            }
            requestData.put("reqReserved", finalParma.getPassback_params()); //穿透域,传业务参数
            requestData.put("riskRateInfo", "{commodityName="+finalParma.getSubject()+"}"); 
            Map<String, String> submitFromData = AcpService.sign(requestData, UnionpayBese.encoding);
            String requestFrontUrl = SDKConfig.getConfig().getFrontRequestUrl();
            String html = AcpService.createAutoFormHtml(requestFrontUrl, submitFromData, UnionpayBese.encoding);
            return html;
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }

    //元转分
    String changeBranch(String amount) {
        String currency = amount.replaceAll("\\$|\\¥|\\,", "");
        int index = currency.indexOf(".");
        int length = currency.length();
        Long amLong;
        if (index == -1) {
            amLong = Long.valueOf(currency + "00");
        } else if (length - index >= 3) {
            amLong = Long.valueOf((currency.substring(0, index + 3)).replace(".", ""));
        } else if (length - index == 2) {
            amLong = Long.valueOf((currency.substring(0, index + 2)).replace(".", "") + 0);
        } else {
            amLong = Long.valueOf((currency.substring(0, index + 1)).replace(".", "") + "00");
        }
        return amLong.toString();
    }

    //银联异步通知
    public boolean unionpay_notify(HttpServletRequest request){
        try{
            String encoding = request.getParameter(SDKConstants.param_encoding);
            Map<String, String> reqParam = new HashMap<String, String>();
            Enumeration<?> temp = request.getParameterNames();
            if (null != temp) {
                while (temp.hasMoreElements()) {
                    String en = (String) temp.nextElement();
                    String value = request.getParameter(en);
                    reqParam.put(en, value);
                    if (reqParam.get(en) == null || "".equals(reqParam.get(en))) {
                        reqParam.remove(en);
                    }
                }
            }
            Map<String, String> valideData = null;
            if (null != reqParam && !reqParam.isEmpty()) {
                Iterator<Map.Entry<String, String>> it = reqParam.entrySet().iterator();
                valideData = new HashMap<String, String>(reqParam.size());
                while (it.hasNext()) {
                    Map.Entry<String, String> e = it.next();
                    String key = (String) e.getKey();
                    String value = (String) e.getValue();
                    valideData.put(key, value);
                }
            }

            if (!AcpService.validate(valideData, encoding)) {
                System.out.println("验签失败,需解决验签问题!");
            } else {
                String order_ids = valideData.get("reqReserved");
                String[] idArr = order_ids.split(",");
                List<Order> orders = service_order.GetOrder(idArr,"","");
                for (Order order: orders){
                    if(order.getStatus()==0){ //如果没支付,就处理业务逻辑
//                        order.setOut_trade_no(valideData.get("orderId"));
//                        order.setTrade_no(valideData.get("queryId"));  queryId这个比较重要
                    }
                }
                return true;
            }
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return false;
    }

    //银联退款
    public String unionpay_refund(Order order){
        Map<String, String> data = new HashMap<String, String>();
        data.put("version", UnionpayBese.version);
        data.put("encoding", UnionpayBese.encoding);         //字符集编码 可以使用UTF-8,GBK两种方式
        data.put("signMethod", SDKConfig.getConfig().getSignMethod()); //签名方法
        data.put("txnType", "04");                           //交易类型 04-退货
        data.put("txnSubType", "00");                        //交易子类型  默认00
        data.put("bizType", "000301");                       //业务类型 B2C网关支付,手机wap支付
        data.put("channelType", "07");                       //渠道类型,07-PC,08-手机
        data.put("merId", merID);
        data.put("accessType", "0");
        data.put("orderId", "T"+order.getOut_trade_no()); //不能一样哦
        data.put("txnTime", TimeUtils.getDate("yyyyMMddHHmmss"));
        data.put("currencyCode", "156");
        data.put("txnAmt", changeBranch(order.getPay_amount().toString()));
        data.put("backUrl", "http://www.specialUrl.com"); //不需要通知
        data.put("origQryId", order.getTrade_no());
        
        Map<String, String> reqData  = AcpService.sign(data,UnionpayBese.encoding);
        Map<String, String> rspData = AcpService.post(reqData,SDKConfig.getConfig().getBackRequestUrl(),UnionpayBese.encoding);
        
        try{
            System.out.println("rspData: "+ rspData);
            if (AcpService.validate(rspData, UnionpayBese.encoding)) {
                String respCode = rspData.get("respCode");
                if ("00".equals(respCode)) {
                	//.....
                    return "退款成功";
                }
            }
        }catch (Exception e){
            e.printStackTrace();
            return null;
        }
        return null;

// 分转元:
String y = request.getParameter("txnAmt");
BigDecimal.valueOf(Long.valueOf(y)).divide(new BigDecimal(100)).toString();

三个支付基本集成了, 测试可以正式就改改就可以,银联的最麻烦
银联有个坑,异步通知会发长报文过来,要停止异步通知只能回应200,但会先回应100,导致无限异步通知, 没想到解决方法

VUE

打开后台传的html文本就可以支付了
vue springboot 接入支付宝 微信 银联
vue springboot 接入支付宝 微信 银联
借鉴了一些文章,感谢各位前辈

相关标签: java vue 支付