Alipay.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. package com.nuliji.tools.pay;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alipay.api.AlipayApiException;
  4. import com.alipay.api.AlipayClient;
  5. import com.alipay.api.AlipayConstants;
  6. import com.alipay.api.DefaultAlipayClient;
  7. import com.alipay.api.domain.AlipayTradeAppPayModel;
  8. import com.alipay.api.domain.AlipayTradePrecreateModel;
  9. import com.alipay.api.internal.util.AlipaySignature;
  10. import com.alipay.api.request.AlipayTradeAppPayRequest;
  11. import com.alipay.api.request.AlipayTradePrecreateRequest;
  12. import com.alipay.api.request.AlipayTradeQueryRequest;
  13. import com.alipay.api.response.AlipayTradeAppPayResponse;
  14. import com.alipay.api.response.AlipayTradePrecreateResponse;
  15. import com.alipay.api.response.AlipayTradeQueryResponse;
  16. import com.nuliji.tools.pay.common.PayInfo;
  17. import com.nuliji.tools.pay.common.ResultInfo;
  18. import org.slf4j.Logger;
  19. import org.slf4j.LoggerFactory;
  20. import javax.servlet.http.HttpServletRequest;
  21. import java.math.BigDecimal;
  22. import java.util.HashMap;
  23. import java.util.Iterator;
  24. import java.util.Map;
  25. import java.util.Objects;
  26. /**
  27. * Created by gaojie on 2017/5/10.
  28. */
  29. public class Alipay implements PaySource{
  30. //添加一个日志器
  31. private static final Logger logger = LoggerFactory.getLogger(Alipay.class);
  32. private AlipayClient alipayClient = null;
  33. private String appId = "";
  34. private String appKey = "";
  35. private String appPublicKey = "";
  36. public Alipay(String appId, String appKey, String appPublicKey){
  37. this.appId = appId;
  38. this.appKey = appKey;
  39. this.appPublicKey = appPublicKey;
  40. logger.debug("alipay=>{},{}", appKey, appPublicKey);
  41. alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do", appId, appKey, "json", "utf-8", appPublicKey, AlipayConstants.SIGN_TYPE_RSA2);
  42. }
  43. @Override
  44. public ResultInfo notifyTrade(HttpServletRequest request) throws Exception{
  45. //获取支付宝POST过来反馈信息
  46. Map<String,String> params = new HashMap<String,String>();
  47. Map requestParams = request.getParameterMap();
  48. for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
  49. String name = (String) iter.next();
  50. String[] values = (String[]) requestParams.get(name);
  51. String valueStr = "";
  52. for (int i = 0; i < values.length; i++) {
  53. valueStr = (i == values.length - 1) ? valueStr + values[i]
  54. : valueStr + values[i] + ",";
  55. }
  56. //乱码解决,这段代码在出现乱码时使用。
  57. //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
  58. params.put(name, valueStr);
  59. }
  60. logger.debug("notify:"+params.toString());
  61. //切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
  62. //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
  63. boolean flag = AlipaySignature.rsaCheckV1(params, appPublicKey, "utf-8", "RSA2");
  64. ResultInfo info = new ResultInfo();
  65. info.setResponse(params);
  66. if(!flag){
  67. info.setStatus("system");
  68. info.setMessage("签名校验错误");
  69. return info;
  70. }
  71. String status = params.get("trade_status");
  72. if(Objects.equals(status, "WAIT_BUYER_PAY")){
  73. info.setStatus("wait");
  74. }else if(Objects.equals(status, "TRADE_CLOSE")){
  75. info.setStatus("close");
  76. }else if(Objects.equals(status, "TRADE_SUCCESS")){
  77. info.setStatus("success");
  78. }else if(Objects.equals(status, "TRADE_FINISHED")){
  79. info.setStatus("finish");
  80. }
  81. info.setNo(params.get("out_trade_no"));
  82. info.setTransaction_no(params.get("trade_no"));
  83. info.setMoney(BigDecimal.valueOf(Float.valueOf(params.get("total_amount"))));
  84. info.setOpenId(params.get("buyer_user_id"));
  85. info.setMessage("success");
  86. info.setAppId(appId);
  87. info.setPid(params.get("seller_id"));
  88. return info;
  89. }
  90. @Override
  91. public ResultInfo returnTrade(ResultInfo info) {
  92. Map<String,String> response = (Map)info.getResponse();
  93. if(response.get("code").isEmpty()){
  94. // 手机返回
  95. // let {out_trade_no, trade_no, app_id, total_amount, seller_id, msg, charset, timestamp, code} = content;
  96. switch(response.get("code")){
  97. case "9000":
  98. info.setStatus("wait");
  99. info.setNo(response.get("out_trade_no"));
  100. info.setTransaction_no(response.get("trade_no"));
  101. info.setMoney(BigDecimal.valueOf(Float.valueOf(response.get("total_amount"))));
  102. break;
  103. case "6004":
  104. case "8000":
  105. info.setStatus("wait");
  106. info.setMessage("支付处理中");
  107. break;
  108. case "4000":
  109. info.setStatus("error");
  110. info.setMessage("支付失败");
  111. break;
  112. case "6001":
  113. info.setStatus("system");
  114. info.setMessage("用户取消支付");
  115. break;
  116. case "6002":
  117. info.setStatus("system");
  118. info.setMessage("网络链接错误");
  119. break;
  120. case "5000":
  121. default:
  122. info.setStatus("system");
  123. info.setMessage("请联系管理员");
  124. }
  125. }else{
  126. // wap返回
  127. // let {app_id, method, sign_type, sign, charset, timestamp, version, out_trade_no, trade_no, total_amount, seller_id} = content;
  128. info.setNo(response.get("out_trade_no"));
  129. info.setTransaction_no(response.get("trade_no"));
  130. info.setMoney(BigDecimal.valueOf(Float.valueOf(response.get("total_amount"))));
  131. info.setMessage("success");
  132. info.setStatus("wait");
  133. }
  134. return info;
  135. }
  136. @Override
  137. public boolean validTrade(ResultInfo info, PayInfo payInfo) {
  138. if(info.getAppId() != payInfo.getAppId()) return false;
  139. // if(info.getPid() != payInfo.getPid()) return false;
  140. return true;
  141. }
  142. public PayInfo appTrade(String payNo, String pid, BigDecimal money, String subject, String body, String notifyUrl, String ip) throws Exception{
  143. AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
  144. //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
  145. AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
  146. model.setBody(body);
  147. model.setSubject(subject);
  148. model.setOutTradeNo(payNo);
  149. model.setTimeoutExpress("30m");
  150. model.setTotalAmount(money.toString());
  151. model.setProductCode("QUICK_MSECURITY_PAY");
  152. request.setBizModel(model);
  153. request.setNotifyUrl(notifyUrl);
  154. PayInfo payInfo = new PayInfo();
  155. payInfo.setPid(pid);
  156. payInfo.setAppId(appId);
  157. payInfo.setMoney(money);
  158. try {
  159. //这里和普通的接口调用不同,使用的是sdkExecute
  160. AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
  161. // System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
  162. payInfo.setRequest(response.getBody());
  163. payInfo.setStatus("ok");
  164. } catch (AlipayApiException e) {
  165. e.printStackTrace();
  166. payInfo.setStatus("fail");
  167. payInfo.setRequest(request);
  168. }
  169. return payInfo;
  170. }
  171. public PayInfo preTrade(String payNo, String pid, BigDecimal money, String subject, String body, String notifyUrl, String ip) throws Exception{
  172. AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
  173. //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
  174. AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
  175. model.setBody(body);
  176. model.setSubject(subject);
  177. model.setOutTradeNo(payNo);
  178. model.setTimeoutExpress("30m");
  179. model.setTotalAmount(money.toString());
  180. model.setProductCode("FACE_TO_FACE_PAYMENT");
  181. request.setBizModel(model);
  182. request.setNotifyUrl(notifyUrl);
  183. PayInfo payInfo = new PayInfo();
  184. payInfo.setPid(pid);
  185. payInfo.setAppId(appId);
  186. payInfo.setMoney(money);
  187. try {
  188. //这里和普通的接口调用不同,使用的是sdkExecute
  189. AlipayTradePrecreateResponse response = alipayClient.sdkExecute(request);
  190. // System.out.println(response.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
  191. payInfo.setRequest(response.getBody());
  192. payInfo.setStatus("ok");
  193. } catch (AlipayApiException e) {
  194. e.printStackTrace();
  195. payInfo.setStatus("fail");
  196. payInfo.setRequest(request);
  197. }
  198. return payInfo;
  199. }
  200. @Override
  201. public ResultInfo getTrade(String payNo, String transactionNo, String pid) throws Exception {
  202. AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
  203. request.setBizContent("{" +
  204. " \"out_trade_no\":\""+payNo+"\"," +
  205. " \"trade_no\":\""+transactionNo+"\"" +
  206. " }");
  207. AlipayTradeQueryResponse response = alipayClient.execute(request);
  208. logger.debug("getTrade:"+ JSON.toJSONString(response));
  209. ResultInfo info = parseResult(response, "ok");
  210. String status = info.getStatus();
  211. if(Objects.equals(status, "ok")) {
  212. String trade_status = response.getTradeStatus();
  213. logger.debug(trade_status);
  214. // 交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
  215. if(Objects.equals(trade_status, "WAIT_BUYER_PAY")){
  216. info.setStatus("wait");
  217. }else if(Objects.equals(trade_status, "TRADE_CLOSE")){
  218. info.setStatus("close");
  219. }else if(Objects.equals(trade_status, "TRADE_SUCCESS")){
  220. info.setStatus("success");
  221. }else if(Objects.equals(trade_status, "TRADE_FINISHED")){
  222. info.setStatus("finish");
  223. }
  224. logger.debug(info.getStatus());
  225. }
  226. logger.debug("getTrade:"+ JSON.toJSONString(info));
  227. return info;
  228. }
  229. private ResultInfo parseResult(AlipayTradeQueryResponse response, String status){
  230. ResultInfo info = new ResultInfo();
  231. info.setAppId(appId);
  232. info.setResponse(response);
  233. info.setNo(response.getOutTradeNo());
  234. info.setMoney(BigDecimal.valueOf(Float.valueOf(response.getTotalAmount())));
  235. info.setOpenId(response.getOpenId());
  236. info.setTransaction_no(response.getTradeNo());
  237. if (response == null || response.getCode() == null) {
  238. return formatInfo(info, "system", "请求错误");
  239. }
  240. switch(response.getCode()){
  241. case "10000": // 调用接口成功
  242. return formatInfo(info, status, "");
  243. case "40004": // 业务处理失败
  244. switch(response.getSubCode()){
  245. case "ACQ.EXIST_FORBIDDEN_WORD":
  246. return formatInfo(info, "error", response.getSubMsg());
  247. case "ACQ.TRADE_HAS_SUCCESS":
  248. return formatInfo(info, "success", "");
  249. case "ACQ.TRADE_HAS_CLOSE":
  250. return formatInfo(info, "close", "当前订单已关闭,请重新支付");
  251. case "ACQ.BUYER_BALANCE_NOT_ENOUGH":
  252. return formatInfo(info, "error", "用户余额不足");
  253. case "ACQ.BUYER_BANKCARD_BALANCE_NOT_ENOUGH":
  254. return formatInfo(info, "error", "用户余额不足");
  255. case "ACQ.ERROR_BALANCE_PAYMENT_DISABLE":
  256. return formatInfo(info, "error", "余额支付需开启");
  257. case "ACQ.BUYER_SELLER_EQUAL":
  258. return formatInfo(info, "error", "买卖家不能相同");
  259. case "ACQ.TRADE_BUYER_NOT_MATCH":
  260. return formatInfo(info, "error", "交易买家不匹配");
  261. case "ACQ.BUYER_ENABLE_STATUS_FORBID":
  262. return formatInfo(info, "error", "用户状态非法");
  263. case "ACQ.PULL_MOBILE_CASHIER_FAIL":
  264. return formatInfo(info, "error", "请重新支付");
  265. case "ACQ.MOBILE_PAYMENT_SWITCH_OFF":
  266. return formatInfo(info, "error", "请开启无线支付功能");
  267. case "ACQ.PAYMENT_FAIL":
  268. return formatInfo(info, "error", "系统错误,请重新支付");
  269. case "ACQ.BUYER_PAYMENT_AMOUNT_DAY_LIMIT_ERROR":
  270. return formatInfo(info, "error", "买家付款日限额超限");
  271. case "ACQ.BEYOND_PAY_RESTRICTION":
  272. return formatInfo(info, "error", "商家收款额度超限");
  273. case "ACQ.BEYOND_PER_RECEIPT_RESTRICTION":
  274. return formatInfo(info, "error", "商家月收款额度超限");
  275. case "ACQ.BUYER_PAYMENT_AMOUNT_MONTH_LIMIT_ERROR":
  276. return formatInfo(info, "error", "买家月支付额度超限");
  277. case "ACQ.SELLER_BEEN_BLOCKED":
  278. return formatInfo(info, "error", "商家账号被冻结");
  279. case "ACQ.ERROR_BUYER_CERTIFY_LEVEL_LIMIT":
  280. return formatInfo(info, "error", "买家未通过人行认证");
  281. case "ACQ.PAYMENT_REQUEST_HAS_RISK":
  282. return formatInfo(info, "error", "支付方式存在风险");
  283. case "ACQ.NO_PAYMENT_INSTRUMENTS_AVAILABLE":
  284. return formatInfo(info, "error", "没有可用的支付工具");
  285. case "ACQ.USER_FACE_PAYMENT_SWITCH_OFF":
  286. return formatInfo(info, "error", "请开启当面付款开关");
  287. case "ACQ.SELLER_BALANCE_NOT_ENOUGH":
  288. return formatInfo(info, "error", "商户的支付宝账户中无足够的资金进行撤销");
  289. case "ACQ.REASON_TRADE_BEEN_FREEZEN":
  290. return formatInfo(info, "exception", "当前交易被冻结,不允许进行撤销");
  291. case "ACQ.TRADE_NOT_EXIST"://query
  292. return formatInfo(info, "close", "查询的交易不存在,请重新支付");
  293. default:
  294. return formatInfo(info, "system", response.getSubMsg());
  295. }
  296. case "20000":// 服务不可用
  297. return formatInfo(info, "wait", "等待支付处理");
  298. case "20001":// 授权权限不足
  299. case "40001":// 缺少必要参数
  300. case "40002":// 非法参数
  301. case "40006":// 权限不足
  302. default:
  303. return formatInfo(info, "system", response.getMsg());
  304. }
  305. }
  306. private ResultInfo formatInfo(ResultInfo info, String status, String message){
  307. info.setStatus(status);
  308. info.setMessage(message);
  309. return info;
  310. }
  311. }