//config public class AlipayRefundConfig { private final String charset = "UTF-8"; //参数编码字符集 private final String signType = "MD5"; //签名方式 private String service = "refund_fastpay_by_platform_nopwd"; //接口名称 private String gatewayUrl = "https://mapi.alipay.com/gateway.do"; //支付宝网关 private String partner; //合作者身份ID private String notifyUrl; //服务器异步通知页面路径 private String sellerId; //收款支付宝账号,以2088开头由16位纯数字组成的字符串,一般情况下收款账号就是签约账号 private String signKey; // MD5密钥,安全检验码,由数字和字母组成的32位字符串,查看地址 public void setService(String service) { this.service = service; } public String getService() { return service; } public String getCharset() { return charset; } public String getSignType() { return signType; } public String getGatewayUrl() { return gatewayUrl; } public void setGatewayUrl(String gatewayUrl) { this.gatewayUrl = gatewayUrl; } public String getPartner() { return partner; } public void setPartner(String partner) { this.partner = partner; } public String getNotifyUrl() { return notifyUrl; } public void setNotifyUrl(String notifyUrl) { this.notifyUrl = notifyUrl; } public String getSellerId() { return sellerId; } public void setSellerId(String sellerId) { this.sellerId = sellerId; } public String getSignKey() { return signKey; } public void setSignKey(String signKey) { this.signKey = signKey; } } //?????? public class AlipayRefundRequest { private String refundDate; // 退款请求时间 yyyy-MM-dd HH:mm:ss private String batchNo; // 退款批次号,退款日期(8位)+流水号(3~24位) private String tradeNo; // 原付款支付宝交易号 private BigDecimal amount; // 退款总金额 private String reason; // 退款理由 private String notifyUrl; //服务器异步通知页面路径,优先使用 public String getRefundDate() { return refundDate; } public void setRefundDate(String refundDate) { this.refundDate = refundDate; } public String getBatchNo() { return batchNo; } public void setBatchNo(String batchNo) { this.batchNo = batchNo; } public String getTradeNo() { return tradeNo; } public void setTradeNo(String tradeNo) { this.tradeNo = tradeNo; } public BigDecimal getAmount() { return amount; } public void setAmount(BigDecimal amount) { this.amount = amount; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public String getNotifyUrl() { return notifyUrl; } public void setNotifyUrl(String notifyUrl) { this.notifyUrl = notifyUrl; } } //?????? public class AlipayRefundHelper { public static String createGateway(AlipayRefundConfig config, AlipayRefundRequest request) { TreeMap<String, String> parameter = new TreeMap<>(); parameter.put("_input_charset", config.getCharset()); parameter.put("notify_url", request.getNotifyUrl() == null ? config.getNotifyUrl() : request.getNotifyUrl()); parameter.put("partner", config.getPartner()); parameter.put("seller_id", config.getSellerId()); parameter.put("service", config.getService()); parameter.put("sign_type", config.getSignType()); parameter.put("batch_no", request.getBatchNo()); parameter.put("refund_date", request.getRefundDate()); parameter.put("batch_num", "1"); StringBuilder sb = new StringBuilder(80); sb.append(request.getTradeNo()).append("^"); sb.append(request.getAmount()).append("^"); sb.append(request.getReason()); parameter.put("detail_data", sb.toString()); String queryString = AlipayUtil.buildQueryString(parameter, config.getSignKey()); return config.getGatewayUrl() + queryString; } public static AlipayRefundReturn parseReturn(String xml) { AlipayRefundReturn r = new AlipayRefundReturn(); r.setIsSuccess(extractXml(xml, "is_success")); r.setError(extractXml(xml, "error")); return r; } private static String extractXml(String xml, String tag) { int p = xml.indexOf(tag); if (p < 0) return null; int p1 = -1; int p2 = -1; for (int i = p + tag.length(); i < xml.length(); i++) { char c = xml.charAt(i); if (c == ‘ ‘ || c == ‘\t‘) continue; if (c != ‘>‘) return null; p1 = i + 1; p2 = xml.indexOf(‘<‘, p1); break; } if (p1 < 0 || p2 < 0 || p2 < p1) return null; return xml.substring(p1, p2); } } /** */ public class AlipayUtil { public static boolean isSuccess(String str) { return str != null && "T".equalsIgnoreCase(str.trim()); } public static boolean isFailed(String str) { return str != null && "F".equalsIgnoreCase(str.trim()); } public static boolean isProcess(String str) { return str != null && "P".equalsIgnoreCase(str.trim()); } public static boolean signSkip(String k, String v) { return v == null || v.length() == 0 || k == null || "sign_type".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k); } public static String buildQueryString(TreeMap<String, String> parameter, String signKey) { StringBuilder sign = new StringBuilder(); StringBuilder query = new StringBuilder(); for (Map.Entry<String, String> entry : parameter.entrySet()) { String k = entry.getKey(); String v = entry.getValue(); if (!AlipayUtil.signSkip(k, v)) { sign.append("&").append(k).append("=").append(v); try { v = URLEncoder.encode(v, "UTF8"); } catch (Exception e) { // ignore } query.append("&").append(k).append("=").append(v); } } sign.append(signKey); String digest = Md5Util.sumUtf8(sign.substring(1)); query.append("&sign=").append(digest); query.setCharAt(0, ‘?‘); return query.toString(); } /** * @return */ public enum VerifyResult { UNSUPPORTED, NOT_PASS, MD5_PASS, ALL_PASS }; public static VerifyResult verifyNotifyMd5(TreeMap<String, String> params, String signKey, String partnerId) { if (params == null || params.isEmpty()) return VerifyResult.UNSUPPORTED; if (!"md5".equalsIgnoreCase(params.get("sign_type"))) return VerifyResult.UNSUPPORTED; StringBuilder sign = new StringBuilder(300); for (Map.Entry<String, String> entry : params.entrySet()) { String k = entry.getKey(); if ("sign".equalsIgnoreCase(k) || "sign_type".equalsIgnoreCase(k)) { continue; } sign.append("&").append(k).append("=").append(entry.getValue()); } sign.append(signKey); String signStr = sign.substring(1); String signMd5 = Md5Util.sumUtf8(signStr); String paraMd5 = params.get("sign"); if (!signMd5.equalsIgnoreCase(paraMd5)) { return VerifyResult.NOT_PASS; } // chick notify_id String verifyUrl = "https://mapi.alipay.com/gateway.do?service=notify_verify&partner="; StringBuilder queryUrl = new StringBuilder(100); queryUrl.append(verifyUrl); queryUrl.append(partnerId); queryUrl.append("¬ify_id="); queryUrl.append(params.get("notify_id")); BufferedReader in = null; try { URL url = new URL(queryUrl.toString()); URLConnection urlConnection = url.openConnection(); in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); String inputLine = in.readLine(); if (inputLine.equalsIgnoreCase("true")) { return VerifyResult.ALL_PASS; } else { return VerifyResult.MD5_PASS; } } catch (Exception e) { return VerifyResult.MD5_PASS; } finally { if (in != null) { try { in.close(); } catch (IOException e) { // ignore } } } } }
/** * 生成支付宝批次号 * * @return */public String getRandomBatchNum() { SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); String format = dateFormat.format(new Date()); int max = 24; int min = 3; Random random = new Random(); int s = random.nextInt(max) % (max - min + 1) + min; StringBuffer buffer = new StringBuffer(); for (int i = 0; i < s; i++) { Integer val = (int) (Math.random() * 9 + 1); buffer.append(val.toString()); } return format + buffer.toString();}
//测试 public static void main(String[] args) { AlipayRefundConfig config = new AlipayRefundConfig(); config.setNotifyUrl("http://127.0.0.1:9966/alipay.html"); config.setPartner(PayConstants.PARTNER_ID); config.setSellerId(PayConstants.PARTNER_ID); config.setSignKey(PayConstants.SECURITY_KEY); AlipayRefundRequest req = new AlipayRefundRequest(); req.setBatchNo(getRandomBatchNum()); //退款流水号 SimpleDateFormat dt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); req.setRefundDate(dt.format(new Date())); //退款请求时间 req.setAmount(new BigDecimal("0.01")); req.setReason("测试"); req.setTradeNo("888888888"); //交易号 String payUrl = AlipayRefundHelper.createGateway(config, req); System.out.println(payUrl); String xml = PayUtil.request(payUrl); AlipayRefundReturn r = AlipayRefundHelper.parseReturn(xml); System.out.println(xml); System.out.println(r.getIsSuccess()); System.out.println(r.getError()); }
原文地址:https://www.cnblogs.com/dreammyone/p/8575104.html
时间: 2024-10-24 22:02:49