Explorar el Código

feat: "Airwallex退款"

ritchie hace 2 años
padre
commit
d0d0e45312

+ 1 - 0
src/main/java/com/szwl/common/AccessTokenCommon.java

@@ -15,6 +15,7 @@ import java.util.Map;
 
 public class AccessTokenCommon {
     public final static String ACCESS_TOKEN_URL = "https://api-demo.airwallex.com/api/v1/authentication/login";
+
     public final static String CLIENT_ID = "IBi-pVO4SSGzXIDHRYfVOA";
 
     public final static String API_KEY = "7eb2be388987ae27ae80c904bed93f89ddd08437debb2692c364da07deba1502a279e388d0c3e732f16ebbb8787d1a14";

+ 148 - 29
src/main/java/com/szwl/controller/AirwallexPayController.java

@@ -5,32 +5,36 @@ import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.szwl.common.AccessTokenCommon;
+import com.szwl.constant.AirwallexConstant;
 import com.szwl.model.bean.PaymentIntentRequestBody;
 import com.szwl.model.bean.RefundRequestBody;
 import com.szwl.model.bo.R;
 import com.szwl.model.bo.ResponseModel;
 import com.szwl.model.entity.TOrderAbroad;
+import com.szwl.model.utils.AccessTokenThreadUtil;
 import com.szwl.service.AirwallexService;
 import com.szwl.service.TAdminService;
 import com.szwl.service.TOrderAbroadService;
 import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiModelProperty;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
-import java.util.Date;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
 
 import static com.szwl.constant.ResponseCodesEnum.L0006;
 
@@ -49,14 +53,18 @@ public class AirwallexPayController {
     @Resource
     TOrderAbroadService tOrderAbroadService;
 
+//    @GetMapping("/getAccessToken")
+//    public ResponseModel<?> getAccessToken() {
+//        String accessToken = airwallexService.getAccessToken();
+//        //获取到的accessToken可以放入内存或者存到数据库中,不用每次都获取
+//        return R.ok(accessToken);
+//    }
 
     @ApiOperation(value = "获取token")
     @GetMapping("/getAccessToken")
-    @Scheduled(cron = "0 0/20 * * * ?") // 每20分钟执行一次,我删了入参String id
-    public ResponseModel<?> getAccessToken() {
-        String accessToken = airwallexService.getAccessToken();
-        //获取到的accessToken可以放入内存或者存到数据库中,不用每次都获取
-        return R.ok(accessToken);
+    @Scheduled(cron = "0 0/20 * * * ?")
+    public void getAccessToken() {
+        AccessTokenCommon.ACCESS_TOKEN = AccessTokenThreadUtil.getAccessToken();
     }
 
     @ApiOperation(value = "Create a PaymentIntent")
@@ -64,11 +72,14 @@ public class AirwallexPayController {
     public R createAPaymentIntent(@RequestBody PaymentIntentRequestBody paymentIntentRequestBody) {
         log.info("发起支付请求");
         // 先获取token
-        String accessToken = airwallexService.getAccessToken();
-        // TODO: 创建订单
-        if(accessToken == null || "".equals(accessToken)) {
-            return R.fail(L0006);
-        }
+//        String accessToken = airwallexService.getAccessToken();
+//        new AccessTokenThreadUtil().run();
+//        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+//
+//        if(accessToken == null || "".equals(accessToken)) {
+//            accessToken = new AccessTokenThreadUtil().getAccessToken();
+//            return R.fail(L0006);
+//        }
 
         BigDecimal amount = paymentIntentRequestBody.getAmount();
         String currency = paymentIntentRequestBody.getCurrency();
@@ -78,7 +89,7 @@ public class AirwallexPayController {
         String productName = paymentIntentRequestBody.getProductName();
         String clientId = paymentIntentRequestBody.getClientId();
         Long equipmentId = paymentIntentRequestBody.getEquipmentId();
-
+        // 创建订单
         TOrderAbroad tOrderAbroad = new TOrderAbroad();
         tOrderAbroad.setAmount(amount);
         tOrderAbroad.setCurrency(currency);
@@ -90,12 +101,26 @@ public class AirwallexPayController {
         tOrderAbroad.setEquipmentId(equipmentId);
         // 设置订单支付状态,0未支付,1已支付,3已退款。
         tOrderAbroad.setPayStatus(0);
+
+        // 返回payment intent id和client secret
+        Map<String, Object> responseMap = airwallexService.caPaymentIntent(amount, currency, requestId, merchantOrderId);
+
+        String paymentIntentId = (String) responseMap.get("id");
+        String clientSecret = (String) responseMap.get("client_secret");
+
+        // 把 paymentIntentId 保存到数据库
+        tOrderAbroad.setPaymentIntentId(paymentIntentId);
         // 将订单存入数据库
         boolean save = tOrderAbroadService.save(tOrderAbroad);
         System.out.println("将订单存入数据库:" + save);
 
-        // 返回payment intent id和client secret,拼接二维码链接给前端
-        String QR = airwallexService.caPaymentIntent(amount, currency, requestId, merchantOrderId);
+        // 拼接二维码链接给前端
+//        String env = AirwallexConstant.ENV;
+//        String mode = AirwallexConstant.MODE;
+//        String locale = "it";
+        String qrUrl = AirwallexConstant.QR_URL;
+
+        String QR = qrUrl + "?intent_id=" + paymentIntentId + "&client_secret=" + clientSecret + "&currency=" + currency;
 
         // TODO: 设置分销
 
@@ -103,18 +128,44 @@ public class AirwallexPayController {
     }
 
     @ApiOperation(value = "获取支付订单的信息,订单状态")
-    @GetMapping("/retrieveAPaymentIntent/{intId}")
-    public String retrieveAPaymentIntent(@PathVariable Long intId) {
+    @GetMapping("/retrieveAPaymentIntent")
+    public JSON retrieveAPaymentIntent(@RequestParam String id) {
         log.info("查询支付订单信息");
-
-        String retrieve = airwallexService.retrieveAPaymentIntent(intId);
-        JSONObject jsonObject = JSON.parseObject(retrieve);
+        // 这里的intId指的是paymentIntendId,也是id
+        String intentResp = airwallexService.retrieveAPaymentIntent(id);
+        JSONObject jsonObject = JSON.parseObject(intentResp);
         // 取消订单的原因
 //        String cancellationReason = jsonObject.getString("cancellation_reason");
-        // 订单状态
+        // 支付信息
+        String amount = jsonObject.getString("amount");
+        String currency = jsonObject.getString("currency");
+        String createdAt = jsonObject.getString("created_at");
+        String updatedAt = jsonObject.getString("updated_at");
         String status = jsonObject.getString("status");
+//        String customer = jsonObject.getString("customer");
+//        JSONObject customerObj = JSON.parseObject(customer);
+//        String address = customerObj.getString("address");
 
-        return status;
+        JSONObject state = Optional.ofNullable(jsonObject)
+                .flatMap(jsonObject1 -> Optional.ofNullable(jsonObject.getJSONObject("customer")))
+                .flatMap(jsonObject1 -> Optional.ofNullable(jsonObject.getJSONObject("address")))
+                .flatMap(jsonObject1 -> Optional.ofNullable(jsonObject.getJSONObject("state")))
+                .orElse(null);
+        JSONObject city = Optional.ofNullable(jsonObject)
+                .flatMap(jsonObject1 -> Optional.ofNullable(jsonObject.getJSONObject("customer")))
+                .flatMap(jsonObject1 -> Optional.ofNullable(jsonObject.getJSONObject("address")))
+                .flatMap(jsonObject1 -> Optional.ofNullable(jsonObject.getJSONObject("city")))
+                .orElse(null);
+
+        Map<String, Object> intentDetails = new HashMap<>();
+        intentDetails.put("amount",amount);
+        intentDetails.put("currency",currency);
+        intentDetails.put("state",state);
+        intentDetails.put("city",city);
+        intentDetails.put("createdAt",createdAt);
+        intentDetails.put("status",status);
+
+        return new JSONObject(intentDetails);
     }
 
 
@@ -122,19 +173,26 @@ public class AirwallexPayController {
     @PostMapping("/createARefund")
     ResponseModel<String> createARefund(@RequestBody RefundRequestBody refundRequestBody) {
         log.info("发起退款");
-        String requestId = refundRequestBody.getRequestId();
+        String requestId = UUID.randomUUID().toString().trim().replaceAll("-", "");
+
+//        String requestId = refundRequestBody.getRequestId();
         String paymentIntentId = refundRequestBody.getPaymentIntentId();
+//        String reason = refundRequestBody.getReason();
+
 //        QueryWrapper<TOrderAbroad> tOrderAbroadQueryWrapper = new QueryWrapper<>();
 //        tOrderAbroadQueryWrapper.eq("request_id", requestId);
 //        TOrderAbroad orderAbroad = tOrderAbroadService.getOne(tOrderAbroadQueryWrapper);
 
         LambdaQueryWrapper<TOrderAbroad> lambdaQueryWrapper = Wrappers.lambdaQuery();
-        lambdaQueryWrapper.eq(TOrderAbroad::getRequestId, requestId);
+        lambdaQueryWrapper.eq(TOrderAbroad::getPaymentIntentId, paymentIntentId);
         TOrderAbroad orderAbroad = tOrderAbroadService.getOne(lambdaQueryWrapper);
 
         if(orderAbroad == null) {
             return R.fail("订单为空/error");
         }
+
+        // 支付状态:退款中
+        orderAbroad.setPayStatus(2);
         // 修改订单表
 //        SimpleDateFormat sdf = new SimpleDateFormat();
 //        sdf.applyPattern("yyyy-MM-dd HH:mm:ss");
@@ -145,19 +203,80 @@ public class AirwallexPayController {
 //        String format = localDateTime.format(dtf);
         // 退款发起时间
         orderAbroad.setRefundDate(new Date());
+        tOrderAbroadService.updateById(orderAbroad);
 
 
         // 发起退款
+//        String refund = airwallexService.createARefund(requestId, paymentIntentId, reason);
         String refund = airwallexService.createARefund(requestId, paymentIntentId);
 
+        System.out.println(refund);
+
         JSONObject jsonObject = JSON.parseObject(refund);
         String status = jsonObject.getString("status");
+//        orderAbroad.set;
+//        tOrderAbroadService.updateById(orderAbroad);
+//        switch (status) {
+//            case "RECEIVED" :
+//                System.out.println("退款被接收");
+//                break;
+//            case "ACCEPTED" :
+//                System.out.println("退款被接受");
+//                break;
+//            case "SUCCEEDED" :
+//                System.out.println("退款成功");
+//                break;
+//            case "FAILED" :
+//                System.out.println("退款失败");
+//                break;
+//        }
+
+//        if (!status.equals("FAILED")) {
+        if (status.equals("RECEIVED") || status.equals("ACCEPTED") || status.equals("SUCCEEDED")) {
+            String refundId = jsonObject.getString("id");
+            orderAbroad.setRefundId(refundId);
+            tOrderAbroadService.updateById(orderAbroad);
+            return R.ok("退款处理中,请稍候查询");
+        }
+        return R.fail("退款失败");
+//        if (Objects.equals(status, "SUCCEEDED")) {
+//            String refundId = jsonObject.getString("id");
+//            orderAbroad.setRefundId(refundId);
+////            orderAbroad.setPayStatus(3);
+//            tOrderAbroadService.updateById(orderAbroad);
+//            return R.ok("退款申请中,请稍候查询");
+//        } else {
+//            return R.ok("退款失败");
+//        }
+    }
+
+    @ApiOperation(value = "查询某笔退款详情")
+    @GetMapping("/retrieveARefund/{id}")
+    public String retrieveARefund(@PathVariable("id") String refundId) {
+        log.info("根据rfd_查询某笔退款详情");
+
+        String refundResp = airwallexService.retrieveARefund(refundId);
+        JSONObject jsonObject = JSON.parseObject(refundResp);
+        String status = jsonObject.getString("status");
+
+        if (status.equals("SUCCEEDED")) {
 
-        if (Objects.equals(status, "SUCCEEDED")) {
-            return R.ok("退款申请中,请稍候查询");
-        } else {
-            return R.ok("退款失败");
+            LambdaQueryWrapper<TOrderAbroad> lambdaQueryWrapper = Wrappers.lambdaQuery();
+            lambdaQueryWrapper.eq(TOrderAbroad::getRefundId, refundId);
+            TOrderAbroad orderAbroad = tOrderAbroadService.getOne(lambdaQueryWrapper);
+
+//            if (orderAbroad == null ) {
+//                return "订单为空/error";
+//            }
+            if (Objects.isNull(orderAbroad)) {
+                return "订单为空/error";
+            }
+            // 设置支付状态为 3已退款
+            orderAbroad.setPayStatus(3);
+            tOrderAbroadService.updateById(orderAbroad);
         }
+        return status;
+
     }
 
 }

+ 1 - 1
src/main/java/com/szwl/controller/TOrderAbroadController.java

@@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
  * </p>
  *
  * @author wuhs
- * @since 2023-04-17
+ * @since 2023-04-26
  */
 @RestController
 @RequestMapping("/tOrderAbroad")

+ 24 - 0
src/main/java/com/szwl/controller/WebhookController.java

@@ -3,7 +3,9 @@ package com.szwl.controller;
 import cn.com.sand.third.org.apache.commons.codec.digest.HmacUtils;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.szwl.model.bo.R;
 import com.szwl.model.bo.ResponseModel;
 import com.szwl.model.entity.TOrderAbroad;
@@ -78,6 +80,28 @@ public class WebhookController {
 // Do something with event
 
             response.setStatus(HttpServletResponse.SC_OK);
+
+
+            JSONObject jsonObject = JSON.parseObject(payload);
+            String data = jsonObject.getString("data");
+            JSONObject jsonObject1 = JSON.parseObject(data);
+            String dataObject = jsonObject1.getString("object");
+            JSONObject jsonObject2 = JSON.parseObject(dataObject);
+            String refundId = jsonObject2.getString("id");
+            String status = jsonObject2.getString("status");
+
+            // 如果退款成功
+            if (status.equals("RECEIVED") || status.equals("ACCEPTED") || status.equals("SUCCEEDED")) {
+
+                LambdaQueryWrapper<TOrderAbroad> lambdaQueryWrapper = Wrappers.lambdaQuery();
+                lambdaQueryWrapper.eq(TOrderAbroad::getRefundId, refundId);
+                TOrderAbroad orderAbroad = tOrderAbroadService.getOne(lambdaQueryWrapper);
+
+                // 设置订单支付状态为 已退款
+                orderAbroad.setPayStatus(3);
+                tOrderAbroadService.updateById(orderAbroad);
+            }
+
         } else {
 // Invalid signature
             response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

+ 1 - 1
src/main/java/com/szwl/mapper/TOrderAbroadMapper.java

@@ -9,7 +9,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  * </p>
  *
  * @author wuhs
- * @since 2023-04-17
+ * @since 2023-04-26
  */
 public interface TOrderAbroadMapper extends BaseMapper<TOrderAbroad> {
 

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 3 - 2
src/main/java/com/szwl/mapper/xml/TOrderAbroadMapper.xml


+ 4 - 1
src/main/java/com/szwl/model/bean/RefundRequestBody.java

@@ -1,5 +1,6 @@
 package com.szwl.model.bean;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.Data;
 
 import java.math.BigDecimal;
@@ -9,8 +10,10 @@ public class RefundRequestBody {
 
     private BigDecimal amount;
 
-    private String requestId;
+//    @JsonProperty("request_id")
+//    private String requestId;
 
+    @JsonProperty("payment_intent_id")
     private String paymentIntentId;
 
     private String reason;

+ 10 - 10
src/main/java/com/szwl/model/entity/TOrderAbroad.java

@@ -10,15 +10,13 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
-import javax.persistence.Column;
-
 /**
  * <p>
  * 
  * </p>
  *
  * @author wuhs
- * @since 2023-04-17
+ * @since 2023-04-26
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -30,8 +28,6 @@ public class TOrderAbroad implements Serializable {
     @TableId(value = "id", type = IdType.AUTO)
     private Long id;
 
-//    @CreationTimestamp
-    @Column(nullable = false, updatable = false, columnDefinition="TIMESTAMP default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP")
     @ApiModelProperty(value = "订单创建时间")
     private Date createDate;
 
@@ -98,7 +94,7 @@ public class TOrderAbroad implements Serializable {
     @ApiModelProperty(value = "商品描述,{xxx,1个;xxx,2个}")
     private String productDesc;
 
-    @ApiModelProperty(value = "支付状态")
+    @ApiModelProperty(value = "支付状态, 0: 未支付, 1: 已付款, 2: 退款中, 3: 已退款")
     private Integer payStatus;
 
     @ApiModelProperty(value = "分账方类型,0:分账方2个,1:分账方3个,3:分账方4个,3:分账方超4个;")
@@ -107,8 +103,8 @@ public class TOrderAbroad implements Serializable {
     @ApiModelProperty(value = "支付流水号")
     private String trxNo;
 
-    @ApiModelProperty(value = "退款流水号")
-    private String refundTrxNo;
+    @ApiModelProperty(value = "退款编号rfd")
+    private String refundId;
 
     @ApiModelProperty(value = "是否发送es")
     private String es;
@@ -137,10 +133,14 @@ public class TOrderAbroad implements Serializable {
     @ApiModelProperty(value = "货币")
     private String currency;
 
-    @ApiModelProperty(value = "商户订单id,唯一订单编号,类似于order的sn")
+    @ApiModelProperty(value = "订单号,商户唯一订单id,类似于order的sn")
     private String merchantOrderId;
 
-    @ApiModelProperty(value = "商户唯一请求id")
+    @ApiModelProperty(value = "请求编号,商户唯一支付请求编号id")
     private String requestId;
 
+    @ApiModelProperty(value = "交易编号")
+    private String paymentIntentId;
+
+
 }

+ 0 - 17
src/main/java/com/szwl/model/utils/AccessTokenListener.java

@@ -1,17 +0,0 @@
-package com.szwl.model.utils;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-
-public class AccessTokenListener implements ServletContextListener {
-    @Override
-    public void contextInitialized(ServletContextEvent sce) {
-        // 开启servlet
-        new AccessTokenThreadUtil().start();
-    }
-
-    @Override
-    public void contextDestroyed(ServletContextEvent sce) {
-        // 关闭servlet
-    }
-}

+ 7 - 25
src/main/java/com/szwl/model/utils/AccessTokenThreadUtil.java

@@ -12,43 +12,25 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-public class AccessTokenThreadUtil extends Thread{
+public class AccessTokenThreadUtil{
+//    获取access_token方法
+    public static String getAccessToken() {
 
-    @Override
-    public void run() {
-        while (true) {
-            this.getAccessToken();
-            try {
-                Thread.sleep(20 * 60 * 1000);//休眠20分钟
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-        }
-
-    }
-
-    //获取access_token方法
-    public String getAccessToken() {
-
-//        String requestUrl = AccessTokenCommon.ACCESS_TOKEN_URL.replace("CLIENT_ID", AccessTokenCommon.CLIENT_ID).replace("API_KEY", AccessTokenCommon.API_KEY);
-//        jsonObject = WeixinUtil.httpRequest(requestUrl, "GET", null);
-//        AccessTokenCommon.ACCESS_TOKEN  = jsonObject.getString("access_token");
-//        System.out.println(AccessTokenCommon.ACCESS_TOKEN );
         String url = AccessTokenCommon.ACCESS_TOKEN_URL;
         List<BasicHeader> headers = new ArrayList<>();
-        BasicHeader header1 = new BasicHeader("CLIENT_ID", AccessTokenCommon.CLIENT_ID);
-        BasicHeader header2 = new BasicHeader("API_KEY", AccessTokenCommon.API_KEY);
+        BasicHeader header1 = new BasicHeader("x-client-id", AccessTokenCommon.CLIENT_ID);
+        BasicHeader header2 = new BasicHeader("x-api-key", AccessTokenCommon.API_KEY);
         headers.add(header1);
         headers.add(header2);
         Map<String,String> map = new HashMap<>();
         String data = JSON.toJSONString(map);
         String response = null;
         try {
-            response = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON,headers);
+            response = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
             JSONObject resultJson = JSONObject.parseObject(response);
             AccessTokenCommon.ACCESS_TOKEN = resultJson.getString("token");
             if(StringUtils.isNotEmpty(AccessTokenCommon.ACCESS_TOKEN)){
-                System.out.println("token="+AccessTokenCommon.ACCESS_TOKEN);
+                System.out.println("token =" + AccessTokenCommon.ACCESS_TOKEN);
                 return AccessTokenCommon.ACCESS_TOKEN;
             }
         } catch (Exception e) {

+ 11 - 8
src/main/java/com/szwl/service/AirwallexService.java

@@ -9,18 +9,18 @@ import java.util.Map;
 public interface AirwallexService  {
 
 
-    /**
-     * 获取 access token
-     * 30分钟过期
-     */
-    String getAccessToken();
+//    /**
+//     * 获取 access token
+//     * 30分钟过期
+//     */
+//    String getAccessToken();
 
     /**
      * 获取某一笔订单的信息 Retrieve a PaymentIntent
-     * @param intId
+     * @param id
      * @return
      */
-    String retrieveAPaymentIntent(Long intId);
+    String retrieveAPaymentIntent(String id);
 
 
     R getFormSchema();
@@ -33,7 +33,7 @@ public interface AirwallexService  {
 
     R getPaymentById(String paymentId);
 
-    String caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId);
+    Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId);
 
     /**
      * 创建一笔退款 Create a Refund
@@ -42,8 +42,11 @@ public interface AirwallexService  {
      * @param paymentIntentId
      * @return
      */
+//    String createARefund(String requestId, String paymentIntentId, String reason);
     String createARefund(String requestId, String paymentIntentId);
 
+    String retrieveARefund(String refundId);
+
 //    /**
 //     * 退款结果回调
 //     * @param request

+ 1 - 5
src/main/java/com/szwl/service/TOrderAbroadService.java

@@ -3,18 +3,14 @@ package com.szwl.service;
 import com.szwl.model.entity.TOrderAbroad;
 import com.baomidou.mybatisplus.extension.service.IService;
 
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 /**
  * <p>
  *  服务类
  * </p>
  *
  * @author wuhs
- * @since 2023-04-17
+ * @since 2023-04-26
  */
 public interface TOrderAbroadService extends IService<TOrderAbroad> {
 
-//    boolean updatePayStatusById(TOrderAbroad tOrderAbroad);
 }

+ 121 - 67
src/main/java/com/szwl/service/impl/AirwallexServiceImpl.java

@@ -2,8 +2,10 @@ package com.szwl.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
+import com.szwl.common.AccessTokenCommon;
 import com.szwl.constant.AirwallexConstant;
 import com.szwl.model.bo.R;
+import com.szwl.model.utils.AccessTokenThreadUtil;
 import com.szwl.model.utils.HttpClientSslUtils;
 import com.szwl.service.AirwallexService;
 import com.szwl.service.TOrderAbroadService;
@@ -20,6 +22,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static com.szwl.constant.ResponseCodesEnum.L0006;
+
 /**
  * <p>
  *  服务实现类
@@ -35,46 +39,59 @@ public class AirwallexServiceImpl implements AirwallexService {
     @Resource
     TOrderAbroadService tOrderAbroadService;
 
-
-    @Override
-    public String getAccessToken() {
-//        HttpResponse<String> response = Unirest.post("https://api-demo.airwallex.com/api/v1/authentication/login")
-//                .header("Content-Type", "application/json")
-//                .header("x-client-id", "W_ORsgAFTiuA9k2KuqZt8A")
-//                .header("x-api-key", "8ac97c856c6d6cae7eb8fd05511f7a165be798d032381cb8026de7b4aa9aaee2e6312a8888a3474d783a40913ab6b55d")
-//                .body("{
-//    }").asString();
-        String url = AirwallexConstant.url+"/api/v1/authentication/login";
-        List<BasicHeader> headers = new ArrayList<>();
-        BasicHeader header1 = new BasicHeader("x-client-id",AirwallexConstant.clientid);
-        BasicHeader header2 = new BasicHeader("x-api-key",AirwallexConstant.apiKey);
-        headers.add(header1);
-        headers.add(header2);
-        Map<String,String> map = new HashMap<>();
-        String data = JSON.toJSONString(map);
-        String response=null;
-        try {
-            response = HttpClientSslUtils.doPost(url, data,ContentType.APPLICATION_JSON,headers);
-            JSONObject resultJson = JSONObject.parseObject(response);
-            String token = resultJson.getString("token");
-            if(StringUtils.isNotEmpty(token)){
-                System.out.println("token="+token);
-                return token;
-            }
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
-        return response;
-    }
+//    @Override
+//    public String getAccessToken() {
+////        HttpResponse<String> response = Unirest.post("https://api-demo.airwallex.com/api/v1/authentication/login")
+////                .header("Content-Type", "application/json")
+////                .header("x-client-id", "W_ORsgAFTiuA9k2KuqZt8A")
+////                .header("x-api-key", "8ac97c856c6d6cae7eb8fd05511f7a165be798d032381cb8026de7b4aa9aaee2e6312a8888a3474d783a40913ab6b55d")
+////                .body("{
+////    }").asString();
+//        String url = AirwallexConstant.url+"/api/v1/authentication/login";
+//        List<BasicHeader> headers = new ArrayList<>();
+//        BasicHeader header1 = new BasicHeader("x-client-id",AirwallexConstant.clientid);
+//        BasicHeader header2 = new BasicHeader("x-api-key",AirwallexConstant.apiKey);
+//        headers.add(header1);
+//        headers.add(header2);
+//        Map<String,String> map = new HashMap<>();
+//        String data = JSON.toJSONString(map);
+//        String response=null;
+//        try {
+//            response = HttpClientSslUtils.doPost(url, data,ContentType.APPLICATION_JSON,headers);
+//            JSONObject resultJson = JSONObject.parseObject(response);
+//            String token = resultJson.getString("token");
+//            if(StringUtils.isNotEmpty(token)){
+//                System.out.println("token="+token);
+//                return token;
+//            }
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//        return response;
+//    }
 
 
+    /**
+     * 创建支付意向
+     * @param amount
+     * @param currency
+     * @param requestId
+     * @param merchantOrderId
+     * @return
+     */
     @Override
-    public String caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId) {
+    public Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId) {
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
         // 调用付款意向 api,返回payment intent id和client secret
         // 请求头
         String url = AirwallexConstant.url+"/api/v1/pa/payment_intents/create";
         List<BasicHeader> headers = new ArrayList<>();
-        BasicHeader header1 = new BasicHeader("Authorization",AirwallexConstant.BEARER + this.getAccessToken());
+//        new BasicHeader("Authorization", AirwallexConstant.BEARER + this.getAccessToken());
+        BasicHeader header1 = new BasicHeader("Authorization",AirwallexConstant.BEARER + accessToken);
         headers.add(header1);
         // body参数
         Map<String, Object> bodyMap = new HashMap<>();
@@ -89,90 +106,127 @@ public class AirwallexServiceImpl implements AirwallexService {
         Map<String, Object> responseMap = new HashMap<>();
         String resp = null;
         try {
-            // 发送请求,获取响应结果
             resp = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
-            System.out.println(resp);
-
             responseMap = JSON.parseObject(resp);
-//            return resp;
         } catch (Exception e) {
             e.printStackTrace();
         }
 
-        String paymentIntentId = (String) responseMap.get("id");
-        String clientSecret = (String) responseMap.get("client_secret");
+        return responseMap;
 
-        // 把 paymentIntentId 保存到数据库
+    }
+
+    /**
+     * 获取某笔支付订单的信息
+     * @param id
+     * @return
+     */
+    @Override
+    public String retrieveAPaymentIntent(String id) {
 
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
 
-        String env = AirwallexConstant.ENV;
-        String mode = AirwallexConstant.MODE;
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/pa/payment_intents/" + id;
+        // 请求头
+        List<BasicHeader> headers = new ArrayList<>();
+        BasicHeader header = new BasicHeader("Authorization", AirwallexConstant.BEARER + accessToken);
+        headers.add(header);
+
+        // 请求体
+//        Map<String, Object> bodyMap = new HashMap<>();
+//        String data = JSON.toJSONString(bodyMap);
+
+        String resp = null;
+        try {
+            resp = HttpClientSslUtils.doGet(url, ContentType.APPLICATION_JSON, headers);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
 
-//        String locale = "it";
-        String qrUrl = AirwallexConstant.QR_URL;
-        return qrUrl + "?intent_id=" + paymentIntentId + "&client_secret=" + clientSecret + "&currency=" + currency;
+        return resp;
     }
 
+    /**
+     * 创建一笔退款
+     * @param requestId
+     * @param paymentIntentId
+     * @return
+     */
     @Override
     public String createARefund(String requestId, String paymentIntentId) {
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
 
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+//
         // 请求头
         String url = AirwallexConstant.url + "/api/v1/pa/refunds/create";
         List<BasicHeader> headers = new ArrayList<>();
-        BasicHeader header1 = new BasicHeader("Authorization", AirwallexConstant.BEARER + this.getAccessToken());
+        BasicHeader header1 = new BasicHeader("Authorization", AirwallexConstant.BEARER + accessToken);
         headers.add(header1);
 
         // body参数
         Map<String, Object> bodyMap = new HashMap<>();
         bodyMap.put("request_id", requestId);
-//        bodyMap.put("amount", amount); // 退款金额
-//        bodyMap.put("reason", reason); // 退款原因
         bodyMap.put("payment_intent_id", paymentIntentId);
+//        bodyMap.put("amount", amount); // 退款金额
+//        reason = "退款原因-测试";
+//        bodyMap.put("reason", reason);
         String data = JSON.toJSONString(bodyMap);
 
         String resp = null;
         try {
-            HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
+            resp = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            e.printStackTrace();
         }
-
         return resp;
     }
 
-//    @Override
-//    public String refundWebhooks(HttpServletRequest request, HttpServletResponse response) {
-//        return null;
-//    }
-
-
     /**
-     * 获取某笔支付订单的信息
-     * @param intId
+     * 获取某笔退款的详情
+     * @param refundId
      * @return
      */
     @Override
-    public String retrieveAPaymentIntent(Long intId) {
+    public String retrieveARefund(String refundId) {
+
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
 
-        String url = AirwallexConstant.url + "/api/v1/pa/payment_intents/{id}";
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/pa/refunds/" + refundId;
         // 请求头
         List<BasicHeader> headers = new ArrayList<>();
-        new BasicHeader("Authorization", AirwallexConstant.BEARER + this.getAccessToken());
-        // 请求体
-//        Map<String, Object> bodyMap = new HashMap<>();
-//        String data = JSON.toJSONString(bodyMap);
+        BasicHeader header = new BasicHeader("Authorization", AirwallexConstant.BEARER + accessToken);
+        headers.add(header);
 
         String resp = null;
+
         try {
             resp = HttpClientSslUtils.doGet(url, ContentType.APPLICATION_JSON, headers);
-
         } catch (Exception e) {
             throw new RuntimeException(e);
         }
-
         return resp;
     }
 
+
+//    @Override
+//    public String refundWebhooks(HttpServletRequest request, HttpServletResponse response) {
+//        return null;
+//    }
+
+
+
+
     @Override
     public R getFormSchema() {
         // POST /api/v1/beneficiary_form_schemas/generate 根据国家/付款方式查询表单字段,返回前端所需表单信息(对接付款国较多)

+ 1 - 12
src/main/java/com/szwl/service/impl/TOrderAbroadServiceImpl.java

@@ -12,20 +12,9 @@ import org.springframework.stereotype.Service;
  * </p>
  *
  * @author wuhs
- * @since 2023-04-17
+ * @since 2023-04-26
  */
 @Service
 public class TOrderAbroadServiceImpl extends ServiceImpl<TOrderAbroadMapper, TOrderAbroad> implements TOrderAbroadService {
 
-    /**
-     * 根据 erquestId 将订单的支付状态 payStatus 改成1
-     *
-     * @return
-     */
-//    @Override
-//    public boolean updatePayStatusById(TOrderAbroad tOrderAbroad) {
-//
-//
-//        return false;
-//    }
 }