Authored by tanling

跨境支付

  1 +package com.yohoufo.common.utils;
  2 +
  3 +import java.io.FileNotFoundException;
  4 +import java.io.FileReader;
  5 +import java.io.FileWriter;
  6 +import java.io.IOException;
  7 +import java.io.StringReader;
  8 +import java.io.StringWriter;
  9 +
  10 +import javax.xml.bind.JAXBContext;
  11 +import javax.xml.bind.JAXBException;
  12 +import javax.xml.bind.Marshaller;
  13 +import javax.xml.bind.Unmarshaller;
  14 +
  15 +/**
  16 + * 封装了XML转换成object,object转换成XML的代码
  17 + *
  18 + * @author Steven
  19 + *
  20 + */
  21 +public class XMLUtil {
  22 + /**
  23 + * 将对象直接转换成String类型的 XML输出
  24 + *
  25 + * @param obj
  26 + * @return
  27 + */
  28 + public static String convertToXml(Object obj) {
  29 + // 创建输出流
  30 + StringWriter sw = new StringWriter();
  31 + try {
  32 + // 利用jdk中自带的转换类实现
  33 + JAXBContext context = JAXBContext.newInstance(obj.getClass());
  34 +
  35 + Marshaller marshaller = context.createMarshaller();
  36 + // 格式化xml输出的格式
  37 + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
  38 + Boolean.TRUE);
  39 + // 将对象转换成输出流形式的xml
  40 + marshaller.marshal(obj, sw);
  41 + } catch (JAXBException e) {
  42 + e.printStackTrace();
  43 + }
  44 + return sw.toString();
  45 + }
  46 +
  47 + /**
  48 + * 将对象根据路径转换成xml文件
  49 + *
  50 + * @param obj
  51 + * @param path
  52 + * @return
  53 + */
  54 + public static void convertToXml(Object obj, String path) {
  55 + try {
  56 + // 利用jdk中自带的转换类实现
  57 + JAXBContext context = JAXBContext.newInstance(obj.getClass());
  58 +
  59 + Marshaller marshaller = context.createMarshaller();
  60 + // 格式化xml输出的格式
  61 + marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
  62 + Boolean.TRUE);
  63 + // 将对象转换成输出流形式的xml
  64 + // 创建输出流
  65 + FileWriter fw = null;
  66 + try {
  67 + fw = new FileWriter(path);
  68 + } catch (IOException e) {
  69 + e.printStackTrace();
  70 + }
  71 + marshaller.marshal(obj, fw);
  72 + } catch (JAXBException e) {
  73 + e.printStackTrace();
  74 + }
  75 + }
  76 +
  77 + @SuppressWarnings("unchecked")
  78 + /**
  79 + * 将String类型的xml转换成对象
  80 + */
  81 + public static Object convertXmlStrToObject(Class clazz, String xmlStr) {
  82 + Object xmlObject = null;
  83 + try {
  84 + JAXBContext context = JAXBContext.newInstance(clazz);
  85 + // 进行将Xml转成对象的核心接口
  86 + Unmarshaller unmarshaller = context.createUnmarshaller();
  87 + StringReader sr = new StringReader(xmlStr);
  88 + xmlObject = unmarshaller.unmarshal(sr);
  89 + } catch (JAXBException e) {
  90 + e.printStackTrace();
  91 + }
  92 + return xmlObject;
  93 + }
  94 +
  95 + @SuppressWarnings("unchecked")
  96 + /**
  97 + * 将file类型的xml转换成对象
  98 + */
  99 + public static Object convertXmlFileToObject(Class clazz, String xmlPath) {
  100 + Object xmlObject = null;
  101 + try {
  102 + JAXBContext context = JAXBContext.newInstance(clazz);
  103 + Unmarshaller unmarshaller = context.createUnmarshaller();
  104 + FileReader fr = null;
  105 + try {
  106 + fr = new FileReader(xmlPath);
  107 + } catch (FileNotFoundException e) {
  108 + e.printStackTrace();
  109 + }
  110 + xmlObject = unmarshaller.unmarshal(fr);
  111 + } catch (JAXBException e) {
  112 + e.printStackTrace();
  113 + }
  114 + return xmlObject;
  115 + }
  116 +}
  117 +
@@ -5,14 +5,22 @@ import com.alibaba.fastjson.JSONObject; @@ -5,14 +5,22 @@ import com.alibaba.fastjson.JSONObject;
5 import com.yohobuy.ufo.model.order.bo.OrderInfo; 5 import com.yohobuy.ufo.model.order.bo.OrderInfo;
6 import com.yohoufo.common.utils.DateUtil; 6 import com.yohoufo.common.utils.DateUtil;
7 import com.yohoufo.common.utils.RSAUtils; 7 import com.yohoufo.common.utils.RSAUtils;
  8 +import com.yohoufo.common.utils.XMLUtil;
8 import com.yohoufo.order.config.AlipayConfig; 9 import com.yohoufo.order.config.AlipayConfig;
  10 +import com.yohoufo.order.constants.RefundContant;
9 import com.yohoufo.order.model.PayQueryBo; 11 import com.yohoufo.order.model.PayQueryBo;
10 import com.yohoufo.order.model.PayRefundBo; 12 import com.yohoufo.order.model.PayRefundBo;
  13 +import com.yohoufo.order.service.pay.alipay.bean.AlipayQueryResponse;
  14 +import com.yohoufo.order.service.pay.alipay.bean.AlipayRefundResponse;
  15 +import org.apache.commons.lang3.StringUtils;
  16 +import org.apache.http.client.utils.DateUtils;
11 import org.slf4j.Logger; 17 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory; 18 import org.slf4j.LoggerFactory;
  19 +import org.springframework.beans.factory.annotation.Value;
13 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
14 import java.math.BigDecimal; 21 import java.math.BigDecimal;
15 import java.net.URLEncoder; 22 import java.net.URLEncoder;
  23 +import java.util.Date;
16 import java.util.HashMap; 24 import java.util.HashMap;
17 import java.util.Map; 25 import java.util.Map;
18 26
@@ -51,7 +59,6 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract { @@ -51,7 +59,6 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract {
51 return "zfbgj@yoho.cn"; 59 return "zfbgj@yoho.cn";
52 } 60 }
53 61
54 -  
55 /** 62 /**
56 * OpenApi退款 63 * OpenApi退款
57 * @param refundBo 64 * @param refundBo
@@ -60,13 +67,30 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract { @@ -60,13 +67,30 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract {
60 public PayRefundBo refundOpenApi(PayRefundBo refundBo) { 67 public PayRefundBo refundOpenApi(PayRefundBo refundBo) {
61 logger.info("enter AliPayRefunder to refund tradeNo {}, amount {}", refundBo.getRefundOrderCode(), refundBo.getAmount()); 68 logger.info("enter AliPayRefunder to refund tradeNo {}, amount {}", refundBo.getRefundOrderCode(), refundBo.getAmount());
62 Map<String, String> refundParams = buildOpenApiRefundParams(refundBo.getPayOrderCode(), refundBo.getRefundOrderCode(), refundBo.getAmount()); 69 Map<String, String> refundParams = buildOpenApiRefundParams(refundBo.getPayOrderCode(), refundBo.getRefundOrderCode(), refundBo.getAmount());
63 - String respTxt = sendOpenApiRequest(String.valueOf(refundBo.getPayOrderCode()), refundParams, AlipayConfig.OPENAPI_URL); 70 + String respTxt = sendOpenApiRequest(String.valueOf(refundBo.getPayOrderCode()), refundParams, AlipayConfig.CROSS_BORDER_OPENAPI_URL);
  71 +
64 PayRefundBo bo = refundOpenApiConvert(respTxt, refundBo); 72 PayRefundBo bo = refundOpenApiConvert(respTxt, refundBo);
65 logger.info("exit AliPayRefunder refund, refundStatus: {}, refundMsg", bo.getRefundStatus(), bo.getRefundMsg()); 73 logger.info("exit AliPayRefunder refund, refundStatus: {}, refundMsg", bo.getRefundStatus(), bo.getRefundMsg());
66 return bo; 74 return bo;
67 } 75 }
68 76
69 77
  78 + public PayRefundBo refundOpenApiConvert(String respText, PayRefundBo bo) {
  79 + AlipayRefundResponse refundResponse = (AlipayRefundResponse)XMLUtil.convertXmlStrToObject(AlipayRefundResponse.class, respText);
  80 +
  81 + if ("T".equalsIgnoreCase(refundResponse.getIs_success())){
  82 + bo.setRefundStatus(RefundContant.PAYMENT_REFUND_RESULTCODE_SUCCESS);
  83 + bo.setRefundMsg("退款申请成功");
  84 + return bo;
  85 + }
  86 +
  87 + bo.setRefundStatus(RefundContant.PAYMENT_REFUND_RESULTCODE_FAIL);
  88 + bo.setRefundMsg(refundResponse.getError());
  89 +
  90 + return bo;
  91 + }
  92 +
  93 +
70 /** 94 /**
71 * openapi退款参数 95 * openapi退款参数
72 * @param tradeNo 96 * @param tradeNo
@@ -86,21 +110,8 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract { @@ -86,21 +110,8 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract {
86 params.put("out_trade_no", tradeNo); 110 params.put("out_trade_no", tradeNo);
87 params.put("return_rmb_amount", String.valueOf(amount)); 111 params.put("return_rmb_amount", String.valueOf(amount));
88 params.put("currency", "HKD"); 112 params.put("currency", "HKD");
89 -  
90 -  
91 -  
92 - params.put("app_id", getAppId());  
93 - params.put("method", "alipay.trade.refund");  
94 - params.put("charset", AlipayConfig.input_charset);  
95 - params.put("sign_type", "RSA");  
96 - params.put("timestamp", DateUtil.getCurrentTime());  
97 - params.put("version", "1.0");  
98 -  
99 - JSONObject bizJson = new JSONObject();  
100 - bizJson.put("out_trade_no", tradeNo);  
101 - bizJson.put("refund_amount", amount);  
102 - bizJson.put("out_request_no", refundNo);  
103 - params.put("biz_content", bizJson.toJSONString()); 113 + params.put("gmt_return", DateUtil.formatDate(DateUtil.getCurrentTimeSecond(), DateUtil.yyyyMMddHHmmss));
  114 + params.put("product_code", "NEW_WAP_OVERSEAS_SELLER");
104 115
105 String preSignStr = getOpenApiSignString(params, true); 116 String preSignStr = getOpenApiSignString(params, true);
106 params.put("sign", RSAUtils.sign(preSignStr, getRsaPrivateKey(), AlipayConfig.input_charset)); 117 params.put("sign", RSAUtils.sign(preSignStr, getRsaPrivateKey(), AlipayConfig.input_charset));
@@ -115,37 +126,22 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract { @@ -115,37 +126,22 @@ public class AlipayCrossBorderService extends AlipayServiceAbstract {
115 * @return 126 * @return
116 */ 127 */
117 public PayQueryBo payQuery(String tradeNo, int orderCreateTime) { 128 public PayQueryBo payQuery(String tradeNo, int orderCreateTime) {
118 - // TODO 临时吃掉异常,否则无法取消  
119 - try{  
120 Map<String, String> queryParams = buildOpenApiQueryParams(tradeNo); 129 Map<String, String> queryParams = buildOpenApiQueryParams(tradeNo);
121 String respTxt = sendOpenApiRequest(tradeNo, queryParams, AlipayConfig.CROSS_BORDER_OPENAPI_URL); 130 String respTxt = sendOpenApiRequest(tradeNo, queryParams, AlipayConfig.CROSS_BORDER_OPENAPI_URL);
122 - QueryBo queryBo = JSON.parseObject(JSONObject.toJSONString(JSON.parseObject(respTxt).getJSONObject("alipay_trade_query_response")), QueryBo.class);  
123 -  
124 - // 查询结果转换成 共通的对象  
125 - PayQueryBo payQueryBo = new PayQueryBo();  
126 131
127 - if ("10000".equals(queryBo.getCode())){  
128 - // 订单支付时的商户号  
129 - payQueryBo.setPayOrderCode(queryBo.getOut_trade_no());  
130 - payQueryBo.setTradeNo(queryBo.getTrade_no()); 132 + AlipayQueryResponse alipayQueryResponse = (AlipayQueryResponse) XMLUtil.convertXmlStrToObject(AlipayQueryResponse.class, respTxt);
131 133
132 - if ("TRADE_SUCCESS".equals(queryBo.getTrade_status())) { 134 + PayQueryBo payQueryBo = new PayQueryBo();
  135 + if ("T".equalsIgnoreCase(alipayQueryResponse.getIs_success())){
  136 + AlipayQueryResponse.Trade trade =alipayQueryResponse.getResponse().getTrade();
  137 + payQueryBo.setPayOrderCode(trade.getOut_trade_no());
  138 + payQueryBo.setTradeNo(trade.getTrade_no());
133 payQueryBo.setPayStatus(true); 139 payQueryBo.setPayStatus(true);
134 -  
135 - }else if("TRADE_CLOSED".equals(queryBo.getTrade_status())){  
136 - payQueryBo.setRefundStatus(true);  
137 - }  
138 -  
139 - payQueryBo.setAmount(Double.parseDouble(queryBo.getTotal_amount()));  
140 - payQueryBo.setBuyerId(queryBo.getBuyer_user_id()); 140 + payQueryBo.setAmount(Double.parseDouble(trade.getTotal_fee()));
  141 + payQueryBo.setBuyerId(trade.getBuyer_id());
141 } 142 }
142 143
143 return payQueryBo; 144 return payQueryBo;
144 - }catch (Exception e){  
145 - e.printStackTrace();  
146 - }  
147 -  
148 - return new PayQueryBo();  
149 } 145 }
150 146
151 147
  1 +package com.yohoufo.order.service.pay.alipay.bean;
  2 +
  3 +import javax.xml.bind.annotation.XmlAccessType;
  4 +import javax.xml.bind.annotation.XmlAccessorType;
  5 +import javax.xml.bind.annotation.XmlRootElement;
  6 +
  7 +@XmlAccessorType(XmlAccessType.FIELD)
  8 +@XmlRootElement(name = "alipay")
  9 +public class AlipayQueryResponse {
  10 +
  11 + /**
  12 + * 是否成功
  13 + * T:成功, F:失败
  14 + */
  15 + private String is_success;
  16 +
  17 + /**
  18 + * 错误消息
  19 + */
  20 + private String error;
  21 +
  22 + private AlipayResponse response;
  23 +
  24 + public String getIs_success() {
  25 + return is_success;
  26 + }
  27 +
  28 + public void setIs_success(String is_success) {
  29 + this.is_success = is_success;
  30 + }
  31 +
  32 + public String getError() {
  33 + return error;
  34 + }
  35 +
  36 + public void setError(String error) {
  37 + this.error = error;
  38 + }
  39 +
  40 + public AlipayResponse getResponse() {
  41 + return response;
  42 + }
  43 +
  44 + public void setResponse(AlipayResponse response) {
  45 + this.response = response;
  46 + }
  47 +
  48 + public static class AlipayResponse{
  49 + private Trade trade;
  50 +
  51 + public Trade getTrade() {
  52 + return trade;
  53 + }
  54 +
  55 + public void setTrade(Trade trade) {
  56 + this.trade = trade;
  57 + }
  58 + }
  59 +
  60 + public static class Trade{
  61 + private String buyer_email;
  62 + private String buyer_id;
  63 + private String discount;
  64 + private String out_trade_no;
  65 + private String trade_status;
  66 + private String trade_no;
  67 + private String total_fee;
  68 +
  69 + public String getBuyer_email() {
  70 + return buyer_email;
  71 + }
  72 +
  73 + public void setBuyer_email(String buyer_email) {
  74 + this.buyer_email = buyer_email;
  75 + }
  76 +
  77 + public String getBuyer_id() {
  78 + return buyer_id;
  79 + }
  80 +
  81 + public void setBuyer_id(String buyer_id) {
  82 + this.buyer_id = buyer_id;
  83 + }
  84 +
  85 + public String getDiscount() {
  86 + return discount;
  87 + }
  88 +
  89 + public void setDiscount(String discount) {
  90 + this.discount = discount;
  91 + }
  92 +
  93 + public String getOut_trade_no() {
  94 + return out_trade_no;
  95 + }
  96 +
  97 + public void setOut_trade_no(String out_trade_no) {
  98 + this.out_trade_no = out_trade_no;
  99 + }
  100 +
  101 + public String getTrade_status() {
  102 + return trade_status;
  103 + }
  104 +
  105 + public void setTrade_status(String trade_status) {
  106 + this.trade_status = trade_status;
  107 + }
  108 +
  109 + public String getTrade_no() {
  110 + return trade_no;
  111 + }
  112 +
  113 + public void setTrade_no(String trade_no) {
  114 + this.trade_no = trade_no;
  115 + }
  116 +
  117 + public String getTotal_fee() {
  118 + return total_fee;
  119 + }
  120 +
  121 + public void setTotal_fee(String total_fee) {
  122 + this.total_fee = total_fee;
  123 + }
  124 + }
  125 +
  126 +
  127 +}
  1 +package com.yohoufo.order.service.pay.alipay.bean;
  2 +
  3 +import javax.xml.bind.annotation.XmlAccessType;
  4 +import javax.xml.bind.annotation.XmlAccessorType;
  5 +import javax.xml.bind.annotation.XmlRootElement;
  6 +
  7 +@XmlAccessorType(XmlAccessType.FIELD)
  8 +@XmlRootElement(name = "alipay")
  9 +public class AlipayRefundResponse {
  10 +
  11 + /**
  12 + * 是否成功
  13 + * T:成功, F:失败
  14 + */
  15 + private String is_success;
  16 +
  17 +
  18 + private String error;
  19 +
  20 + public String getError() {
  21 + return error;
  22 + }
  23 +
  24 + public void setError(String error) {
  25 + this.error = error;
  26 + }
  27 +
  28 + public String getIs_success() {
  29 + return is_success;
  30 + }
  31 +
  32 + public void setIs_success(String is_success) {
  33 + this.is_success = is_success;
  34 + }
  35 +}
@@ -78,6 +78,8 @@ wechat.notifyurl=http://testapi.yohops.com/payment/weixin_notify @@ -78,6 +78,8 @@ wechat.notifyurl=http://testapi.yohops.com/payment/weixin_notify
78 78
79 alipay.notifyurl=http://testapi.yohops.com/payment/alipay_notify 79 alipay.notifyurl=http://testapi.yohops.com/payment/alipay_notify
80 80
  81 +alipay.cross.border.notifyurl=http://testapi.yohops.com/payment/alipay_notify
  82 +
81 alipay.transfer.notifyurl=http://testapi.yohops.com/payment/alipay_transfer_notify 83 alipay.transfer.notifyurl=http://testapi.yohops.com/payment/alipay_transfer_notify
82 84
83 erp-gateway.url=http://java-yoho-erp-gateway.test3.ingress.dev.yohocorp.com/erp-gateway 85 erp-gateway.url=http://java-yoho-erp-gateway.test3.ingress.dev.yohocorp.com/erp-gateway