|
|
@@ -0,0 +1,187 @@
|
|
|
+package com.nju.edu.pay.controller.api;
|
|
|
+
|
|
|
+import com.alipay.api.AlipayApiException;
|
|
|
+import com.alipay.api.AlipayClient;
|
|
|
+import com.alipay.api.DefaultAlipayClient;
|
|
|
+import com.alipay.api.domain.AlipayTradePagePayModel;
|
|
|
+import com.alipay.api.domain.AlipayTradeRefundModel;
|
|
|
+import com.alipay.api.request.AlipayTradePagePayRequest;
|
|
|
+import com.alipay.api.request.AlipayTradeRefundRequest;
|
|
|
+import com.alipay.api.response.AlipayTradePagePayResponse;
|
|
|
+import com.alipay.api.response.AlipayTradeRefundResponse;
|
|
|
+import com.nju.edu.pay.configuration.AlipayProperties;
|
|
|
+import com.nju.edu.pay.controller.dto.PayModelDTO;
|
|
|
+import com.nju.edu.pay.data.entity.Order;
|
|
|
+import com.nju.edu.pay.data.entity.Trade;
|
|
|
+import com.nju.edu.pay.service.AlipayService;
|
|
|
+import com.nju.edu.pay.service.OrderService;
|
|
|
+import com.nju.edu.pay.service.TradeService;
|
|
|
+import com.nju.edu.pay.util.enums.OrderStatus;
|
|
|
+import com.nju.edu.pay.web.response.ErrorResponse;
|
|
|
+import com.nju.edu.pay.web.response.Response;
|
|
|
+import com.nju.edu.pay.web.response.SuccessResponse;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@RestController
|
|
|
+@RequestMapping("/pay/alipay")
|
|
|
+public class AlipayController {
|
|
|
+
|
|
|
+ private final AlipayProperties alipayProperties;
|
|
|
+ private final AlipayService alipayService;
|
|
|
+ private final OrderService orderService;
|
|
|
+ private final TradeService tradeService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ public AlipayController(AlipayProperties alipayProperties, AlipayService alipayService, OrderService orderService, TradeService tradeService) {
|
|
|
+ this.alipayProperties = alipayProperties;
|
|
|
+ this.alipayService = alipayService;
|
|
|
+ this.orderService = orderService;
|
|
|
+ this.tradeService = tradeService;
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/pay")
|
|
|
+ public Response pay(@RequestBody PayModelDTO payModelDTO) throws AlipayApiException, IOException {
|
|
|
+ Order order=orderService.createOrder(payModelDTO.getUserId(),payModelDTO.getProductId(),payModelDTO.getPlatformType(),payModelDTO.getPrice());
|
|
|
+ if (order==null)
|
|
|
+ return new ErrorResponse(500,"订单创建失败");
|
|
|
+ // 订单模型
|
|
|
+ String productCode = "FAST_INSTANT_TRADE_PAY";
|
|
|
+ AlipayTradePagePayModel model = new AlipayTradePagePayModel();
|
|
|
+ model.setOutTradeNo(order.getOutTradeNo().toString());
|
|
|
+ model.setSubject(payModelDTO.getSubject());
|
|
|
+ model.setTotalAmount(String.valueOf(order.getPrice()));
|
|
|
+ model.setBody(payModelDTO.getSubject()+", 共"+payModelDTO.getPrice()+"元");
|
|
|
+ model.setProductCode(productCode);
|
|
|
+
|
|
|
+ AlipayTradePagePayRequest pagePayRequest =new AlipayTradePagePayRequest();
|
|
|
+ pagePayRequest.setReturnUrl(payModelDTO.getReturnUrl());
|
|
|
+ pagePayRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
|
|
|
+ pagePayRequest.setBizModel(model);
|
|
|
+
|
|
|
+ AlipayClient alipayClient=new DefaultAlipayClient(alipayProperties.getGatewayUrl(),alipayProperties.getAppid(),alipayProperties.getAppPrivateKey(),alipayProperties.getFormate(),alipayProperties.getCharset(),alipayProperties.getAlipayPublicKey(),alipayProperties.getSignType());
|
|
|
+ // 调用SDK生成表单, 并直接将完整的表单html输出到页面
|
|
|
+ AlipayTradePagePayResponse alipayTradePagePayResponse=alipayClient.pageExecute(pagePayRequest);
|
|
|
+ if (alipayTradePagePayResponse.isSuccess()){
|
|
|
+ return new SuccessResponse(alipayTradePagePayResponse.getBody());
|
|
|
+ }else {
|
|
|
+ order.setStatus(OrderStatus.FAILED);
|
|
|
+ orderService.updateOrder(order);
|
|
|
+ return new ErrorResponse(500,"调用支付失败");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @RequestMapping("/notify")
|
|
|
+ public String notify(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
|
|
|
+ // 一定要验签,防止黑客篡改参数
|
|
|
+ Map<String, String[]> parameterMap = request.getParameterMap();
|
|
|
+ StringBuilder notifyBuild = new StringBuilder("/****************************** alipay notify ******************************/\n");
|
|
|
+ parameterMap.forEach((key, value) -> notifyBuild.append(key + "=" + value[0] + "\n") );
|
|
|
+ log.info(notifyBuild.toString());
|
|
|
+
|
|
|
+ boolean flag = alipayService.verifySign(request);
|
|
|
+ if (flag) {
|
|
|
+ /**
|
|
|
+ * 需要严格按照如下描述校验通知数据的正确性
|
|
|
+ *
|
|
|
+ * 商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
|
|
|
+ * 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
|
|
|
+ * 同时需要校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
|
|
|
+ *
|
|
|
+ * 上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
|
|
|
+ * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
|
|
|
+ * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
|
|
|
+ */
|
|
|
+
|
|
|
+ //交易状态
|
|
|
+ String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+ // 商户订单号
|
|
|
+ String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+ //支付宝交易号
|
|
|
+ String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+ //付款金额
|
|
|
+ String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+ //商户ID
|
|
|
+ String seller_id = new String(request.getParameter("seller_id").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+
|
|
|
+ Order order=orderService.retrieveOrder(Integer.parseInt(out_trade_no));
|
|
|
+ if (order==null)
|
|
|
+ return "failed";
|
|
|
+
|
|
|
+ if (order.getPrice() == Double.parseDouble(total_amount)&& alipayProperties.getSellerId().equals(seller_id)) {
|
|
|
+ tradeService.createTrade(Integer.parseInt(out_trade_no), Integer.parseInt(trade_no));
|
|
|
+ }
|
|
|
+
|
|
|
+ if (tradeStatus.equals("TRADE_SUCCESS")||tradeStatus.equals("TRADE_FINISHED") ){
|
|
|
+
|
|
|
+ System.out.println("notify trade success called");
|
|
|
+ order.setStatus(OrderStatus.SUCCESS);
|
|
|
+ orderService.updateOrder(order);
|
|
|
+ return "success";
|
|
|
+ }else {
|
|
|
+ order.setStatus(OrderStatus.FAILED);
|
|
|
+ orderService.updateOrder(order);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return "fail";
|
|
|
+ }
|
|
|
+
|
|
|
+ @RequestMapping("/return")
|
|
|
+ public String returnUrl(HttpServletRequest request) throws UnsupportedEncodingException {
|
|
|
+
|
|
|
+ boolean verifyResult = alipayService.verifySign(request);
|
|
|
+ if(verifyResult){
|
|
|
+ //验证成功
|
|
|
+ //请在这里加上商户的业务逻辑程序代码,如保存支付宝交易号
|
|
|
+ //商户订单号
|
|
|
+ String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+ //支付宝交易号
|
|
|
+ String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
|
|
|
+
|
|
|
+ System.out.println("returnUrl called");
|
|
|
+ return "PaySuccess";
|
|
|
+
|
|
|
+ }else{
|
|
|
+ return "PayFail";
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @PostMapping("/refund/{outTradeNo}")
|
|
|
+ public Response refund(@PathVariable Integer outTradeNo) throws AlipayApiException {
|
|
|
+ AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
|
|
|
+
|
|
|
+ Order order=orderService.retrieveOrder(outTradeNo);
|
|
|
+ Trade trade=tradeService.retrieveTrade(outTradeNo);
|
|
|
+ AlipayTradeRefundModel model=new AlipayTradeRefundModel();
|
|
|
+ // 商户订单号
|
|
|
+ model.setOutTradeNo(outTradeNo.toString());
|
|
|
+ //支付宝订单号
|
|
|
+ model.setTradeNo(String.valueOf(trade.getTradeNo()));
|
|
|
+ // 退款金额
|
|
|
+ model.setRefundAmount(String.valueOf(order.getPrice()));
|
|
|
+ // 退款原因
|
|
|
+ model.setRefundReason("无理由退款");
|
|
|
+ // 退款订单号(同一个订单可以分多次部分退款,当分多次时必传)
|
|
|
+// model.setOutRequestNo(UUID.randomUUID().toString());
|
|
|
+ alipayRequest.setBizModel(model);
|
|
|
+
|
|
|
+ AlipayClient alipayClient=new DefaultAlipayClient(alipayProperties.getGatewayUrl(),alipayProperties.getAppid(),alipayProperties.getAppPrivateKey(),alipayProperties.getFormate(),alipayProperties.getCharset(),alipayProperties.getAlipayPublicKey(),alipayProperties.getSignType());
|
|
|
+ AlipayTradeRefundResponse alipayResponse = alipayClient.execute(alipayRequest);
|
|
|
+ if (alipayResponse.isSuccess()) {
|
|
|
+ order.setStatus(OrderStatus.REFUND);
|
|
|
+ orderService.updateOrder(order);
|
|
|
+ return new SuccessResponse(alipayResponse.getBody());
|
|
|
+ }
|
|
|
+
|
|
|
+ return new ErrorResponse(500,"退款失败");
|
|
|
+ }
|
|
|
+}
|