微信支付与支付宝支付(Java)

1、微信jsapi支付

微信JSPAI文档地址:[https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1](%E5%BE%AE%E4%BF%A1JSPAI%E6%96%87%E6%A1%A3%E5%9C%B0%E5%9D%80%EF%BC%9Ahttps://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
(1)生成统一下单信息
private Map<String, Object> createOrder(String openId,String body,Integer orderPrice,Integer appType,
										    String orderNum,HttpServletRequest request) throws UnsupportedEncodingException {
		
		//定义随机数
		Map packageParams = new LinkedHashMap<>();
		//使用小程序的统一下单
		if(appType==1) {
			packageParams.put("appid",Constant.Applet_AppId);//微信小程序的APPID
		} else {
            //微信内调起H5支付需要使用公众号的APPID
			packageParams.put("appid",Constant.APPID);
		}
		packageParams.put("mch_id", Constant.Trade_NO);	//商户号
		packageParams.put("nonce_str", WXPayUtil.generateNonceStr());	//随机数
		packageParams.put("body", body);	//支付主体参数
		packageParams.put("out_trade_no",orderNum);	//订单号
		packageParams.put("total_fee",orderPrice);	//订单金额
		packageParams.put("spbill_create_ip",PayUtil.getLocalIp(request));	//终端IP
		packageParams.put("notify_url", remoteAddr+notifyUrl);	//微信回调地址
		packageParams.put("trade_type", "JSAPI");	//支付方式
		packageParams.put("openid", openId);	//传openId参数
		//获取sign(第一次签名)
		String sign;
		try {
            //签名规则最好下载微信提供的demo,使用其中的工具类
			sign = WXPayUtil.generateSignature(packageParams, Constant.MAH_PASSWORD);
			packageParams.put("sign", sign);
			log.info("生成的签名数据为:"+sign); 
		} catch (Exception e) {
			e.printStackTrace();
		}		
		return packageParams;
	}

(2)请求微信服务器之后需要进行二次签名认证,将数据返回给客户端,由JS拉起支付

public Map<Object,Object> payResult(String openId,String body,Integer orderPrice,Integer appType,String orderNum,HttpServletRequest request) {
	    Map packageP = new LinkedHashMap();
		try {
			String requestXML = WXPayUtil.mapToXml(createOrder(openId,body,orderPrice,appType,orderNum,request));
			log.info("转成XML的数据为:"+requestXML);
			//得到含有prepay_id的XML
			String resXml=HttpClientUtil.doPostCarryJson(Constant.Unifiedorder, requestXML);
			log.info("含有prepay_id的XML为:"+resXml);
			Map map2 = null;
		    try {
		       map2 = WXPayUtil.xmlToMap(resXml);
		    } catch (Exception e) {
		       e.printStackTrace();
		    }		    
		    //得到返回状态码
		    String returnCode=(String) map2.get("return_code");
		    //得到prepay_id 进行二次签名
		    if(returnCode.equals("SUCCESS")) {
				String prepay_id = (String) map2.get("prepay_id");
				//使用小程序的二次签名
				if(appType==1) {
					packageP.put("appId",Constant.Applet_AppId);//微信小程序的APPID
				} else {
					packageP.put("appId",Constant.APPID);
				}
				packageP.put("nonceStr", WXPayUtil.generateNonceStr());//时间戳 
				packageP.put("package", "prepay_id=" + prepay_id);//必须把package写成 "prepay_id="+prepay_id这种形式
				packageP.put("signType", "MD5");
				//paySign加密 
				packageP.put("timeStamp", WXPayUtil.getCurrentTimestampMs()); 
				//得到paySign 用于请求微信 /*String payStr = PayUtil.createLinkString(packageP); 
				String paySign = WXPayUtil.generateSignature(packageP, Constant.MAH_PASSWORD);
				packageP.put("paySign", paySign); 
				packageP.put("msg", "操作成功");	
		    } else {
		    	packageP.put("msg", getMsgByCode(returnCode));
		    }
		   } catch (Exception e) {
			   log.error("解析密码错误");
			   e.printStackTrace();
		   }
		return packageP;
	}

(3)签名生成方法

 /**
     * 生成签名. 注意,若含有sign_type字段,必须和signType参数保持一致。
     *
     * @param data 待签名数据
     * @param key API密钥
     * @param signType 签名方式
     * @return 签名
     */
    public static String generateSignature(final Map<String, Object> data, String key, SignType signType) throws Exception {
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);
        StringBuilder sb = new StringBuilder();
        for (String k : keyArray) {
            if (k.equals(WXPayConstants.FIELD_SIGN)) {
                continue;
            }
            if (data.get(k)!=null) // 参数值为空,则不参与签名
                sb.append(k).append("=").append(data.get(k)).append("&");
        }
        sb.append("key=").append(key);
        if (SignType.MD5.equals(signType)) {
            return MD5(sb.toString()).toUpperCase();
        }
        else if (SignType.HMACSHA256.equals(signType)) {
            return HMACSHA256(sb.toString(), key);
        }
        else {
            throw new Exception(String.format("Invalid sign_type: %s", signType));
        }
    }
    注意:商户密钥重置以后十五分钟生效

**

2、微信扫码支付

**
文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
(1)生成下单请求

private Map<String, Object> createScanOrder(String body,Integer orderPrice,String orderNum,HttpServletRequest request) throws UnsupportedEncodingException {
	
	//定义随机数
	Map packageParams = new LinkedHashMap<>();
	packageParams.put("appid",Constant.APPID);//微信公众号的APPID
	packageParams.put("mch_id", Constant.Trade_NO);	//商户号
	packageParams.put("nonce_str", WXPayUtil.generateNonceStr());	//随机数
	packageParams.put("body", body);	//支付主体参数
	packageParams.put("out_trade_no",orderNum);	//订单号
	packageParams.put("total_fee",orderPrice);	//订单金额
	packageParams.put("spbill_create_ip",PayUtil.getLocalIp(request));	//终端IP
	packageParams.put("notify_url", remoteAddr+notifyUrl);	//微信回调地址
	packageParams.put("trade_type", "NATIVE");	//支付方式
	//获取sign(第一次签名)
	String sign;
	try {
		sign = WXPayUtil.generateSignature(packageParams, Constant.MAH_PASSWORD);
		packageParams.put("sign", sign);
		log.info("生成的签名数据为:"+sign); 
	} catch (Exception e) {
		e.printStackTrace();`在这里插入代码片`
	}		
	return packageParams;
}

(2)发起支付请求,返回支付链接

 public String payScan(String body, Integer orderPrice, String orderNum, HttpServletRequest request) {
		String urlCode=null;
		try {
			String requestXML = WXPayUtil.mapToXml(createScanOrder(body,orderPrice,orderNum,request));
			log.info("转成XML的数据为:"+requestXML);
			//得到含有prepay_id的XML
			String resXml=HttpClientUtil.doPostCarryJson(Constant.Unifiedorder, requestXML);
			log.info("含有prepay_id的XML为:"+resXml);
			Map map = WXPayUtil.xmlToMap(resXml);
			// 返回微信支付的二维码连接
	        urlCode = (String) map.get("code_url");
	        log.info("微信二维码为:"+urlCode);
	    } catch (Exception e) {
	    	log.error("微信扫码支付异常", e);
	    }
		return urlCode;
	}

**

3、微信退款

**
文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_4
注意:退款需要双向证书文件,Java建议使用第一个证书文件,其它语言使用其它文件
(1)生成退款订单参数

private Map<String,Object> createRefundOrder(int refundFee,int orderPrice,String orderNo,int orderType) throws UnsupportedEncodingException {
	Map packageParams = new HashMap<>();
	//如果支付方式为小程序,则创建jsapi退款订单
	if(orderType==PayStatus.JsapiPay.getCode()) {
		packageParams.put("appid",Constant.Applet_AppId);//微信小程序ID
	} else {
		packageParams.put("appid",Constant.APPID);	//微信公众号ID
	}
	packageParams.put("mch_id", Constant.Trade_NO);	//商户号
	packageParams.put("nonce_str", WXPayUtil.generateNonceStr());	//随机数
	packageParams.put("out_trade_no",orderNo);	//订单号
	packageParams.put("out_refund_no", DateTimeUtil.gens("L"));	//退款订单号
	packageParams.put("total_fee", orderPrice);	//订单金额
	packageParams.put("refund_fee", refundFee);
	//获取sign(第一次签名)
	String sign;
	try {
		sign = WXPayUtil.generateSignature(packageParams, Constant.MAH_PASSWORD);
		packageParams.put("sign", sign);
		log.info("生成的签名数据为:"+sign);
	} catch (Exception e) {
		log.error("生成退款异常:{}",e.getMessage());
	}	
	return packageParams;
}

(2)发起退款请求

public DataOutResponse refund(Integer refundFee,String type,Long orderId) {
	SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式
	//获取支付订单号
	String orderNum=orderPayDao.findOrdedrById(orderId).getPayNo();
    try {
		OrderInfo order=OrderInfoDao.findById(orderId);
		NavigationBar navigationbar=navigationBarDao.findById(order.getNavigationbarId());
		//判断是否需要进行时间条件判断
		if(ParameterEnum.ON.getText().equals(type)) {
			//当前时间大于退费时间则无法退费
			if(df.format(new Date()).compareTo(navigationbar.getRemark())>0) {
				//如果已经配送,将无法进行退费
				return ReturnFomart.retParam(2025,order);
			}
		}
		//该笔订单金额
		int orderPrice=(int) (orderPayDao.findOrderPrice(orderNum)*100);
		String requestXML = WXPayUtil.mapToXml(createRefundOrder(refundFee,orderPrice,orderNum,order.getOrderType()));
		log.info("解析出的XML文件信息为:"+requestXML);
		//发起退款请求
		String resXml=HttpClientUtil.doRefund(Constant.RefundOrder, requestXML,filePath);
		log.info("返回信息为:"+resXml);
		Map map =WXPayUtil.xmlToMap(resXml);
		String returnCode=(String) map.get("return_code");
		if("SUCCESS".equals(returnCode)) {
			String resultCode = map.get("result_code").toString();
			if("SUCCESS".equals(resultCode)) {
				String refundNo=map.get("out_refund_no").toString();
				//计算订单金额
				List<DishInfoDto> dishInfo=dishDao.getDishInfo(orderId,order.getNavigationbarId());
				Double totalPrice=0d;  //该笔订单消费的总金额
				for(DishInfoDto dish:dishInfo) {
					totalPrice+=dish.getDiningSum()*dish.getDishPrice();
				}
				//将订单中的状态进行更新
				order.setOrderStatus(2);
				//将消费明细表中的状态进行更新
				ConfirmOrderBill confirmOrderBill=confirmOrderDao.findConsumeByOrderId(orderId);
				confirmOrderBill.setOrderStatus(2);
				//存入退费明细表当中
				patientReturnDao.addPatientReturn(confirmOrderBill, totalPrice,refundNo,order.getCustomerName(),order.getAreaCode());
				return ReturnFomart.retParam(200, order);
			}				
		} 
		return ReturnFomart.retParam(2028, order);
	} catch (Exception e) {
		log.error("map转XML文件出错:{}",e.getMessage());
		return ReturnFomart.retParam(1000, orderNum);
	}
    
}
**(3)HttpClientUtil**
 public static String doRefund(String url, String data,String filePath) throws Exception { 
		KeyStore keyStore = KeyStore.getInstance("PKCS12");
        //windows下的文件路径和Linux下的文件路径转换方式不同
	    FileInputStream is = new FileInputStream(new File(filePath));
	    try { 
	    	keyStore.load(is, Constant.Trade_NO.toCharArray());
	    } finally { 
	    	is.close();
	    } 
	    // Trust own CA and all self-signed certs
	    SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial( keyStore,
	    		Constant.Trade_NO.toCharArray()) .build();
	    // Allow TLSv1 protocol only
	    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslcontext,
	            new String[]{"TLSv1"},
	            null,
	            SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER
	    );
	    CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
	    try { 
	    	HttpPost httpost = new HttpPost(url); // 设置响应头信息
	        httpost.addHeader("Connection", "keep-alive");
	        httpost.addHeader("Accept", "*/*");
	        httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
	        httpost.addHeader("Host", "api.mch.weixin.qq.com");
	        httpost.addHeader("X-Requested-With", "XMLHttpRequest");
	        httpost.addHeader("Cache-Control", "max-age=0");
	        httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
	        httpost.setEntity(new StringEntity(data, "UTF-8"));
	        CloseableHttpResponse response = httpclient.execute(httpost);
	        try { 
	        	HttpEntity entity = response.getEntity();
	            String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
	            EntityUtils.consume(entity);
	            return jsonStr;
	        } finally { 
	        	response.close();
	        } 
	        } finally { 
	        	httpclient.close();
	        } 
	  }

**

1、支付宝手机网站支付

**
文档地址:https://docs.open.alipay.com/203/107090/
先去支付文档下载支付所需要的jar包,放入自己的maven私服当中
(1)支付主体对象:

@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class AlipayVo implements Serializable {
    
    private static final long serialVersionUID = 1L;
    /**
    * 支付主题
    */
    private String subject;
    /**
    * 订单号
    */
    private String out_trade_no;
    /**
    * 支付金额(以元为单位)
    */
    private double total_amount;
    /**
    * 产品编码
    */
    private String product_code;
}
(2)发起支付请求
 public String aliPayOrder(String orderNum, double orderPrice, String body) {
		log.info("订单号:",orderNum,"订单金额:",orderPrice,"支付主体:",body);
		AlipayVo vo = new AlipayVo();
		vo.setOut_trade_no(orderNum);
		vo.setTotal_amount(orderPrice);
		vo.setSubject(body);
		vo.setProduct_code(Constant.Project_Code);
		String json=JsonUtils.getBeanToJson(vo);
		AlipayClient alipayClient =new DefaultAlipayClient(Constant.AliPay_Server,Constant.AliPay_AppId,Constant.AliPay_PrivateKey,
				   										   "json","UTF-8",Constant.AliPay_PublicKey,Constant.AliPay_Sign);
		AlipayTradeWapPayRequest alipayRequest = new AlipayTradeWapPayRequest();
		alipayRequest.setReturnUrl(Constant.AliPay_Return_Url);
		alipayRequest.setNotifyUrl(Constant.AliPay_Notify_Url);
		alipayRequest.setBizContent(json);
		String result = null;
		log.info("调用支付宝支付的参数为:"+JSON.toJSONString(alipayRequest));
		try {
			result = alipayClient.pageExecute(alipayRequest,"GET").getBody();
		}
		catch (AlipayApiException e) {
			log.error("统一下单出错",e);
		}
		log.info("支付返回的参数为:" + result);
		return result;
	}
(3)退款请求
文档地址:https://docs.open.alipay.com/api_1/alipay.trade.refund/
(1)退款对象
 public class AlipayRefund {
    
        private String out_trade_no;	//特殊可选 商户订单号
        private String trade_no;	//特殊可选 支付宝交易号
        private double refund_amount;	//必须 退款金额


        public String getOut_trade_no() {
            return out_trade_no;
        }

        public void setOut_trade_no(String out_trade_no) {
            this.out_trade_no = out_trade_no;
        }

        public String getTrade_no() {
            return trade_no;
        }

        public void setTrade_no(String trade_no) {
            this.trade_no = trade_no;
        }

        public double getRefund_amount() {
            return refund_amount;
        }

        public void setRefund_amount(double refund_amount) {
            this.refund_amount = refund_amount;
        }

    }
(2)发起退款请求
 public DataOutResponse aliRefund(String orderNum, double refundAmount,String type) {
		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");	//设置日期格式
		log.info("退款订单号{}:",orderNum,"退款金额{}:",refundAmount);
		AlipayRefund refund=new AlipayRefund();
		refund.setOut_trade_no(orderNum);
		refund.setRefund_amount(refundAmount);
		String json=JsonUtils.getBeanToJson(refund);
		AlipayTradeRefundResponse response=null;
		OrderInfo orderInfo=OrderInfoDao.findOrderInfoByNo(orderNum);
		NavigationBar navigationbar=navigationBarDao.findById(orderInfo.getNavigationbarId());
		try {
			//判断是否需要进行时间条件判断
			if(ParameterEnum.ON.getText().equals(type)) {
				//当前时间大于退费时间则无法退费
				if(df.format(new Date()).compareTo(navigationbar.getRemark())>=0) {
					//已经到备餐时间,将无法进行退费
					return ReturnFomart.retParam(2025,orderInfo);
				}
			}
			AlipayClient alipayClient =new DefaultAlipayClient(Constant.AliPay_Server,Constant.AliPay_AppId,Constant.AliPay_PrivateKey,
					   										   "json","UTF-8",Constant.AliPay_PublicKey,Constant.AliPay_Sign);
			AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
			request.setBizContent(json);
			//发起退款请求
			response = alipayClient.execute(request);
			//退款成功则改变订单状态
			if ("10000".equals(response.getCode())) {
				//将订单中的状态进行更新
				orderInfo.setOrderStatus(2);
				//将消费明细表中的状态进行更新
				ConfirmOrderBill confirmOrderBill=confirmOrderDao.findConsumeByOrderId(orderInfo.getOrderId());
				confirmOrderBill.setOrderStatus(2);
				//如果已经存入,不要重复存储
				if(CompareUtil.isEmpty(patientReturnDao.findReturnInfoByOrderId(orderInfo.getOrderId()))) {
					//存入退费明细表当中
					patientReturnDao.addPatientReturn(confirmOrderBill, refundAmount,orderNum,orderInfo.getCustomerName(),orderInfo.getAreaCode());
				}
                return ReturnFomart.retParam(200, response.getMsg());
            }
		} catch (AlipayApiException e) {
			log.error("支付宝退款异常{}:", e);
		}
		return ReturnFomart.retParam(4001, response.getSubMsg());
	}
**注意:支付宝的支付和退款都是走异步回调的,而且会回调两次,所以需要判断回调次数,防止消费记录中出现重复的记录**
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值