Browse Source

feat: "Airwallex Payment"

wangzeyu@tom.com 2 years ago
parent
commit
e416b3bc91

+ 2 - 0
src/main/java/com/szwl/constant/AirwallexConstant.java

@@ -40,6 +40,8 @@ public class AirwallexConstant {
      *
      */
     public final static String url = "https://api-demo.airwallex.com";
+    // 正式环境是 https://api.airwallex.com
+
     /**
      * 商户密钥 : MD5
      */

+ 98 - 34
src/main/java/com/szwl/controller/AirwallexPayController.java

@@ -3,56 +3,91 @@ package com.szwl.controller;
 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.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 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.dto.*;
 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.*;
 
-import static com.szwl.constant.ResponseCodesEnum.L0006;
-
 //@CrossOrigin
-@Api(value = "/api/airwallexPay", tags = {"空中云汇" })
+@Api(value = "/api/airwallexPay", tags = {"空中云汇"})
 @RestController
 @RequestMapping("/api/airwallexPay")
 @Slf4j
 public class AirwallexPayController {
     @Value("${test.value:bbb}")
     private String testValue;
-    @Autowired
+
     TAdminService tAdminService;
-    @Autowired
+
     AirwallexService airwallexService;
-    @Resource
+
     TOrderAbroadService tOrderAbroadService;
 
+    public AirwallexPayController(TAdminService tAdminService, AirwallexService airwallexService, TOrderAbroadService tOrderAbroadService) {
+        this.tAdminService = tAdminService;
+        this.airwallexService = airwallexService;
+        this.tOrderAbroadService = tOrderAbroadService;
+    }
+
+    @ApiOperation(value = "创建收款人")
+    @PostMapping("/caBeneficiary")
+    public JsonNode caBeneficiary(@RequestBody CaBeneficiaryRequestDTO requestDTO) {
+
+        BeneficiaryDTO beneficiary = requestDTO.getBeneficiary();
+        List<String> paymentMethods = requestDTO.getPaymentMethods();
+        String nickname = requestDTO.getNickname();
+        String resp = airwallexService.caBeneficiary(beneficiary, nickname, paymentMethods);
+
+        try {
+            JsonNode jsonNode = new ObjectMapper().readTree(resp);
+            return jsonNode;
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+//        JSONObject jsonObject = JSON.parseObject(resp);
+//        String beneficiaryId = jsonObject.getString("beneficiary_id");
+
+        return null;
+    }
+
+    @ApiOperation(value = "获取authCode")
+    @PostMapping("/getAuthCode")
+    public JsonNode getAuthCode(@RequestBody GetAuthCodeDTO getAuthCodeDTO) {
+        String codeChallenge = getAuthCodeDTO.getCodeChallenge();
+        String[] scope = getAuthCodeDTO.getScope();
+        String resp = airwallexService.getAuthCode(codeChallenge, scope);
+        try {
+            JsonNode jsonNode = new ObjectMapper().readTree(resp);
+            return jsonNode;
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
 //    @GetMapping("/getAccessToken")
 //    public ResponseModel<?> getAccessToken() {
 //        String accessToken = airwallexService.getAccessToken();
@@ -81,6 +116,9 @@ public class AirwallexPayController {
 //            return R.fail(L0006);
 //        }
 
+        // 如果是海外客户,使用的是 Airwallex ,就要判断他有没有设置分销
+        // 在 Airwallex 支付之前,要先判断
+
         BigDecimal amount = paymentIntentRequestBody.getAmount();
         String currency = paymentIntentRequestBody.getCurrency();
         String merchantOrderId = paymentIntentRequestBody.getMerchantOrderId();
@@ -178,12 +216,12 @@ public class AirwallexPayController {
 //        String city = JSON.toJSONString(cityJson);
 
         Map<String, Object> intentDetails = new HashMap<>();
-        intentDetails.put("amount",amount);
-        intentDetails.put("currency",currency);
+        intentDetails.put("amount", amount);
+        intentDetails.put("currency", currency);
 //        intentDetails.put("state",state);
-        intentDetails.put("type",type);
-        intentDetails.put("createdAt",createdAt);
-        intentDetails.put("status",status);
+        intentDetails.put("type", type);
+        intentDetails.put("createdAt", createdAt);
+        intentDetails.put("status", status);
 
         return new JSONObject(intentDetails);
     }
@@ -191,7 +229,7 @@ public class AirwallexPayController {
 
     @ApiOperation(value = "发起退款")
     @PostMapping("/createARefund")
-    ResponseModel<String> createARefund(@RequestBody RefundRequestBody refundRequestBody) {
+    public ResponseModel<String> createARefund(@RequestBody RefundRequestBody refundRequestBody) {
         log.info("发起退款");
         String requestId = UUID.randomUUID().toString().trim().replaceAll("-", "");
 
@@ -207,7 +245,7 @@ public class AirwallexPayController {
         lambdaQueryWrapper.eq(TOrderAbroad::getPaymentIntentId, paymentIntentId);
         TOrderAbroad orderAbroad = tOrderAbroadService.getOne(lambdaQueryWrapper);
 
-        if(orderAbroad == null) {
+        if (orderAbroad == null) {
             return R.fail("订单为空/error");
         }
 
@@ -311,17 +349,43 @@ public class AirwallexPayController {
 
     }
 
-//    @ApiOperation(value = "新建一笔转账")
-//    @PostMapping()
-//    public R caPayment(@RequestBody PaymentRequestBody paymentRequestBody) {
-//        log.info("发起一笔转账");
-//
-//
-//        airwallexService.caPayment()
-//
-//
-//        return R.ok();
-//    }
+    @ApiOperation(value = "新建一笔付款")
+    @PostMapping("/caPayment")
+    public R caPayment(@RequestBody CaPaymentRequestDTO caPaymentRequestDTO) {
+
+        String resp = airwallexService.caPayment(caPaymentRequestDTO);
+
+        ObjectMapper objectMapper = new ObjectMapper();
+        JsonNode jsonNode = null;
+        try {
+            jsonNode = objectMapper.readTree(resp);
+        } catch (JsonProcessingException e) {
+            e.printStackTrace();
+        }
+        // 断言确保 jsonNode 不为 null
+        assert jsonNode != null;
+        String paymentId = jsonNode.get("payment_id").asText();
+
+        // 返回 payment_id
+        return R.ok(paymentId);
+    }
 
-}
 
+    @ApiOperation(value = "查询支付结果")
+    @GetMapping("/getPaymentById/{payment_id}")
+    public R getPaymentById(@PathVariable("payment_id") String paymentId) {
+
+        String resp = airwallexService.getPaymentById(paymentId);
+
+        return R.ok(resp);
+    }
+
+    @ApiOperation(value = "查询当前账户余额")
+    @GetMapping("/getCurrentBalances")
+    public R getCurrentBalances() {
+
+        String resp = airwallexService.getCurrentBalances();
+
+        return R.ok(resp);
+    }
+}

+ 21 - 0
src/main/java/com/szwl/controller/TAirwallexMchController.java

@@ -0,0 +1,21 @@
+package com.szwl.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author wuhs
+ * @since 2023-07-06
+ */
+@RestController
+@RequestMapping("/tAirwallexMch")
+public class TAirwallexMchController {
+
+}
+

+ 16 - 0
src/main/java/com/szwl/mapper/TAirwallexMchMapper.java

@@ -0,0 +1,16 @@
+package com.szwl.mapper;
+
+import com.szwl.model.entity.TAirwallexMch;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author wuhs
+ * @since 2023-07-06
+ */
+public interface TAirwallexMchMapper extends BaseMapper<TAirwallexMch> {
+
+}

+ 35 - 0
src/main/java/com/szwl/mapper/xml/TAirwallexMchMapper.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.szwl.mapper.TAirwallexMchMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.szwl.model.entity.TAirwallexMch">
+        <id column="id" property="id" />
+        <result column="beneficiary_id" property="beneficiaryId" />
+        <result column="payer_entity_type" property="payerEntityType" />
+        <result column="payment_methods" property="paymentMethods" />
+        <result column="company_name" property="companyName" />
+        <result column="entity_type" property="entityType" />
+        <result column="account_currency" property="accountCurrency" />
+        <result column="account_name" property="accountName" />
+        <result column="account_number" property="accountNumber" />
+        <result column="bank_country_code" property="bankCountryCode" />
+        <result column="bank_name" property="bankName" />
+        <result column="swift_code" property="swiftCode" />
+        <result column="address_city" property="addressCity" />
+        <result column="address_country_code" property="addressCountryCode" />
+        <result column="address_postcode" property="addressPostcode" />
+        <result column="address_state" property="addressState" />
+        <result column="address_street_address" property="addressStreetAddress" />
+        <result column="create_date" property="createDate" />
+        <result column="modify_date" property="modifyDate" />
+        <result column="admin_id" property="adminId" />
+        <result column="account_balance_available" property="accountBalanceAvailable" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, beneficiary_id, payer_entity_type, payment_methods, company_name, entity_type, account_currency, account_name, account_number, bank_country_code, bank_name, swift_code, address_city, address_country_code, address_postcode, address_state, address_street_address, create_date, modify_date, admin_id, account_balance_available
+    </sql>
+
+</mapper>

+ 10 - 0
src/main/java/com/szwl/model/dto/AdditionalInfoDTO.java

@@ -0,0 +1,10 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class AdditionalInfoDTO {
+//    @JsonProperty("personal_email")
+    private String personal_email;
+}

+ 19 - 0
src/main/java/com/szwl/model/dto/AddressDTO.java

@@ -0,0 +1,19 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class AddressDTO {
+    private String city;
+
+//    @JsonProperty("country_code")
+    private String country_code;
+
+    private String postcode;
+
+    private String state;
+
+//    @JsonProperty("street_address")
+    private String street_address;
+}

+ 34 - 0
src/main/java/com/szwl/model/dto/BankDetailsDTO.java

@@ -0,0 +1,34 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class BankDetailsDTO {
+//    @JsonProperty("account_currency")
+    private String account_currency;
+
+//    @JsonProperty("account_name")
+    private String account_name;
+
+//    @JsonProperty("account_number")
+    private String account_number;
+
+//    @JsonProperty("account_routing_type1")
+    private String account_routing_type1;
+
+//    @JsonProperty("account_routing_value1")
+    private String account_routing_value1;
+
+//    @JsonProperty("bank_country_code")
+    private String bank_country_code;
+
+//    @JsonProperty("bank_name")
+    private String bank_name;
+
+//    @JsonProperty("local_clearing_system")
+    private String local_clearing_system;
+
+//    @JsonProperty("swift_code")
+    private String swift_code;
+}

+ 22 - 0
src/main/java/com/szwl/model/dto/BeneficiaryDTO.java

@@ -0,0 +1,22 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class BeneficiaryDTO {
+
+//    @JsonProperty("additional_info")
+    private AdditionalInfoDTO additional_info;
+
+    private AddressDTO address;
+
+//    @JsonProperty("bank_details")
+    private BankDetailsDTO bank_details;
+
+//    @JsonProperty("company_name")
+    private String company_name;
+
+//    @JsonProperty("entity_type")
+    private String entity_type;
+}

+ 19 - 0
src/main/java/com/szwl/model/dto/CaBeneficiaryRequestDTO.java

@@ -0,0 +1,19 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(value="CaBeneficiaryRequestDTO", description="创建收款人 caBeneficiary 请求体")
+public class CaBeneficiaryRequestDTO {
+
+    private BeneficiaryDTO beneficiary;
+
+    private String nickname;
+
+    @JsonProperty("payment_methods")
+    private List<String> paymentMethods;
+}

+ 23 - 0
src/main/java/com/szwl/model/dto/CaBeneficiaryResponseDTO.java

@@ -0,0 +1,23 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel(value="CaBeneficiaryResponseDTO", description="创建收款人 caBeneficiary 响应体")
+public class CaBeneficiaryResponseDTO {
+    private BeneficiaryDTO beneficiary;
+
+    @JsonProperty("beneficiary_id")
+    private String beneficiaryId;
+    private String nickname;
+
+    @JsonProperty("payer_entity_type")
+    private String payerEntityType;
+
+    @JsonProperty("payment_methods")
+    private List<String> paymentMethods;
+}

+ 38 - 0
src/main/java/com/szwl/model/dto/CaPaymentRequestDTO.java

@@ -0,0 +1,38 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel(value="CaPaymentRequestDTO", description="创建一笔付款,返回 Payment ID")
+public class CaPaymentRequestDTO {
+
+    @JsonProperty("beneficiary_id")
+    private String beneficiaryId;
+
+    @JsonProperty("payment_amount")
+    private double paymentAmount;
+
+    @JsonProperty("payment_currency")
+    private String paymentCurrency;
+
+    @JsonProperty("payment_method")
+    private String paymentMethod;
+
+    private String reason;
+
+    private String reference;
+
+//    @JsonProperty("request_id")
+//    private String requestId;
+
+    @JsonProperty("source_amount")
+    private String sourceAmount;
+
+    @JsonProperty("source_currency")
+    private String sourceCurrency;
+
+    @JsonProperty("swift_charge_option")
+    private String swiftChargeOption;
+}

+ 19 - 0
src/main/java/com/szwl/model/dto/GetAuthCodeDTO.java

@@ -0,0 +1,19 @@
+package com.szwl.model.dto;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@ApiModel(value="GetAuthCodeDTO", description="获取 AuthCode 请求体")
+public class GetAuthCodeDTO {
+
+    @ApiModelProperty(value="质询令牌")
+    @JsonProperty("code_challenge")
+    private String codeChallenge;
+
+    @ApiModelProperty(value="允许访问范围")
+    private String[] scope;
+}

+ 93 - 0
src/main/java/com/szwl/model/entity/TAirwallexMch.java

@@ -0,0 +1,93 @@
+package com.szwl.model.entity;
+
+import java.math.BigDecimal;
+import com.baomidou.mybatisplus.annotation.IdType;
+import java.util.Date;
+import com.baomidou.mybatisplus.annotation.TableId;
+import java.io.Serializable;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author wuhs
+ * @since 2023-07-06
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel(value="TAirwallexMch对象", description="空中云汇收款信息表")
+public class TAirwallexMch implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "自增ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "受益人ID")
+    private String beneficiaryId;
+
+    @ApiModelProperty(value = "付款方实体类型")
+    private String payerEntityType;
+
+    @ApiModelProperty(value = "支付方式")
+    private String paymentMethods;
+
+    @ApiModelProperty(value = "公司名称")
+    private String companyName;
+
+    @ApiModelProperty(value = "实体类型")
+    private String entityType;
+
+    @ApiModelProperty(value = "账户币种")
+    private String accountCurrency;
+
+    @ApiModelProperty(value = "账户名称")
+    private String accountName;
+
+    @ApiModelProperty(value = "账户号码")
+    private String accountNumber;
+
+    @ApiModelProperty(value = "银行国家代码")
+    private String bankCountryCode;
+
+    @ApiModelProperty(value = "银行名称")
+    private String bankName;
+
+    @ApiModelProperty(value = "SWIFT代码")
+    private String swiftCode;
+
+    @ApiModelProperty(value = "地址城市")
+    private String addressCity;
+
+    @ApiModelProperty(value = "地址国家代码")
+    private String addressCountryCode;
+
+    @ApiModelProperty(value = "地址邮编")
+    private String addressPostcode;
+
+    @ApiModelProperty(value = "地址州")
+    private String addressState;
+
+    @ApiModelProperty(value = "地址街道")
+    private String addressStreetAddress;
+
+    @ApiModelProperty(value = "创建日期")
+    private Date createDate;
+
+    @ApiModelProperty(value = "修改日期")
+    private Date modifyDate;
+
+    @ApiModelProperty(value = "管理员ID")
+    private Integer adminId;
+
+    @ApiModelProperty(value = "可用账户余额")
+    private BigDecimal accountBalanceAvailable;
+
+
+}

+ 62 - 3
src/main/java/com/szwl/service/AirwallexService.java

@@ -1,14 +1,16 @@
 package com.szwl.service;
 
 import com.szwl.model.bo.R;
+import com.szwl.model.dto.BeneficiaryDTO;
+import com.szwl.model.dto.CaPaymentRequestDTO;
 
 import java.math.BigDecimal;
+import java.util.List;
 import java.util.Map;
 
 
 public interface AirwallexService  {
 
-
 //    /**
 //     * 获取 access token
 //     * 30分钟过期
@@ -27,12 +29,30 @@ public interface AirwallexService  {
 
     R getAPISchema();
 
+    /**
+     * 创建收款人
+     * @param requestBody
+     * @return
+     */
     String createBeneficiary(Map<String, Object> requestBody);
 
     String createPayout();
 
-    R getPaymentById(String paymentId);
+    /**
+     * 查询支付结果
+     * @param paymentId
+     * @return
+     */
+    String getPaymentById(String paymentId);
 
+    /**
+     * 创建支付意向
+     * @param amount
+     * @param currency
+     * @param requestId
+     * @param merchantOrderId
+     * @return
+     */
     Map<String, Object> caPaymentIntent(BigDecimal amount, String currency, String requestId, String merchantOrderId);
 
     /**
@@ -45,8 +65,45 @@ public interface AirwallexService  {
 //    String createARefund(String requestId, String paymentIntentId, String reason);
     String createARefund(String requestId, String paymentIntentId);
 
+    /**
+     * 获取某笔退款的详情
+     * @param refundId
+     * @return
+     */
     String retrieveARefund(String refundId);
 
+    /**
+     * 获取 authorization_code
+     * 30 秒后过期
+     * @param codeChallenge
+     * @param scope
+     * @return
+     */
+    String getAuthCode(String codeChallenge, String[] scope);
+
+    /**
+     * 创建收款人
+     * @param beneficiary
+     * @param nickname
+     * @param paymentMethods
+     * @return
+     */
+    String caBeneficiary(BeneficiaryDTO beneficiary, String nickname, List<String> paymentMethods);
+
+    /**
+     * 创建一笔订单
+     * @param caPaymentRequestDTO
+     * @return
+     */
+    String caPayment(CaPaymentRequestDTO caPaymentRequestDTO);
+
+
+    /**
+     * 查询当前用户的余额:申泽账户
+     * @return
+     */
+    String getCurrentBalances();
+
 //    /**
 //     * 退款结果回调
 //     * @param request
@@ -56,4 +113,6 @@ public interface AirwallexService  {
 //    String refundWebhooks(HttpServletRequest request, HttpServletResponse response);
 
 //    void caWebhook(String[] envents, String requiredId, String url, String version);
-}
+
+
+}

+ 16 - 0
src/main/java/com/szwl/service/TAirwallexMchService.java

@@ -0,0 +1,16 @@
+package com.szwl.service;
+
+import com.szwl.model.entity.TAirwallexMch;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author wuhs
+ * @since 2023-07-06
+ */
+public interface TAirwallexMchService extends IService<TAirwallexMch> {
+
+}

+ 210 - 9
src/main/java/com/szwl/service/impl/AirwallexServiceImpl.java

@@ -4,6 +4,8 @@ import com.alibaba.fastjson.JSON;
 import com.szwl.common.AccessTokenCommon;
 import com.szwl.constant.AirwallexConstant;
 import com.szwl.model.bo.R;
+import com.szwl.model.dto.BeneficiaryDTO;
+import com.szwl.model.dto.CaPaymentRequestDTO;
 import com.szwl.model.utils.AccessTokenThreadUtil;
 import com.szwl.model.utils.HttpClientSslUtils;
 import com.szwl.service.AirwallexService;
@@ -15,10 +17,7 @@ import org.springframework.stereotype.Service;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 /**
  * <p>
@@ -216,14 +215,187 @@ public class AirwallexServiceImpl implements AirwallexService {
     }
 
 
+    /**
+     * 获取 authorization_code
+     * @param codeChallenge
+     * @param scope
+     * @return
+     */
+    @Override
+    public String getAuthCode(String codeChallenge, String[] scope) {
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/authentication/authorize";
+        // 请求头
+        List<BasicHeader> headers = new ArrayList<>();
+        BasicHeader header1 = new BasicHeader("Authorization", AirwallexConstant.BEARER + accessToken);
+//        BasicHeader header2 = new BasicHeader("x-on-behalf-of", "string");
+        headers.add(header1);
+//        headers.add(header2);
+
+        // 请求体
+        Map<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put("code_challenge", codeChallenge);
+        bodyMap.put("scope", scope);
+
+        String data = JSON.toJSONString(bodyMap);
+
+        String resp = null;
+        try {
+            resp = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return resp;
+    }
+
+
+    /**
+     * 创建收款人
+     * @param beneficiary
+     * @param nickname
+     * @param paymentMethods
+     * @return
+     */
+    @Override
+    public String caBeneficiary(BeneficiaryDTO beneficiary, String nickname, List<String> paymentMethods) {
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/beneficiaries/create/";
+        // 请求头
+        List<BasicHeader> headers = new ArrayList<>();
+        BasicHeader header = new BasicHeader("Authorization", AirwallexConstant.BEARER + accessToken);
+        headers.add(header);
+
+        // 请求体
+        Map<String, Object> bodyMap = new HashMap<>();
+        bodyMap.put("beneficiary", beneficiary);
+        bodyMap.put("nickname", nickname);
+        bodyMap.put("payment_methods", paymentMethods);
+
+        String data = JSON.toJSONString(bodyMap);
+
+        String resp = null;
+
+        try {
+            resp = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return resp;
+    }
+
+
+    /**
+     * 创建一笔付款
+     * @param caPaymentRequestDTO
+     * @return
+     */
+    @Override
+    public String caPayment(CaPaymentRequestDTO caPaymentRequestDTO) {
+
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/payments/create/";
+        // 请求头
+        List<BasicHeader> headers = new ArrayList<>();
+        BasicHeader header = new BasicHeader("Authorization", AirwallexConstant.BEARER + accessToken);
+        headers.add(header);
+
+        // 请求体
+        Map<String, Object> bodyMap = new HashMap<>();
+
+        String beneficiaryId = caPaymentRequestDTO.getBeneficiaryId();
+        double paymentAmount = caPaymentRequestDTO.getPaymentAmount();
+        String paymentCurrency = caPaymentRequestDTO.getPaymentCurrency();
+        String paymentMethod = caPaymentRequestDTO.getPaymentMethod();
+        String reason = caPaymentRequestDTO.getReason();
+        String reference = caPaymentRequestDTO.getReference();
+        String requestId;
+        requestId = UUID.randomUUID().toString().trim();
+//        String sourceAmount = caPaymentRequestDTO.getSourceAmount();
+        String sourceCurrency = caPaymentRequestDTO.getSourceCurrency();
+        String swiftChargeOption = caPaymentRequestDTO.getSwiftChargeOption();
+
+        bodyMap.put("beneficiary_id", beneficiaryId);
+        bodyMap.put("payment_amount", paymentAmount);
+        bodyMap.put("payment_currency", paymentCurrency);
+        bodyMap.put("payment_method", paymentMethod);
+        bodyMap.put("reason", reason);
+        bodyMap.put("reference", reference);
+        bodyMap.put("request_id", requestId);
+//        bodyMap.put("source_amount", sourceAmount);
+        bodyMap.put("source_currency", sourceCurrency);
+        bodyMap.put("swift_charge_option", swiftChargeOption);
+
+        String data = JSON.toJSONString(bodyMap);
+
+        String resp = null;
+
+        try {
+            resp = HttpClientSslUtils.doPost(url, data, ContentType.APPLICATION_JSON, headers);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return resp;
+
+    }
+
+
+    /**
+     * 查询申泽钱包余额
+     * @return
+     */
+    @Override
+    public String getCurrentBalances() {
+
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/balances/current";
+        // 请求头
+        List<BasicHeader> headers = new ArrayList<>();
+        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;
 //    }
 
 
-
-
+    /**
+     * 根据国家/付款方式查询表单字段
+     *
+     * @return
+     */
     @Override
     public R getFormSchema() {
         // POST /api/v1/beneficiary_form_schemas/generate 根据国家/付款方式查询表单字段,返回前端所需表单信息(对接付款国较多)
@@ -251,6 +423,11 @@ public class AirwallexServiceImpl implements AirwallexService {
         return null;
     }
 
+    /**
+     * 创建收款人,返回收款人ID
+     * @param requestBody
+     * @return
+     */
     @Override
     public String createBeneficiary (Map<String, Object> requestBody) {
         // POST /api/v1/beneficiaries/create 创建收款人,返回收款人ID
@@ -274,13 +451,37 @@ public class AirwallexServiceImpl implements AirwallexService {
 
 
     @Override
-    public R getPaymentById(String paymentId) {
+    public String getPaymentById(String paymentId) {
         // GET /api/v1/payments/{payment_id} 查询支付结果,返回支付结果状态
 //        https://www.airwallex.com/docs/api#/Payouts/Payments/_api_v1_payments__payment_id_/get
-        return null;
+        String accessToken = AccessTokenCommon.ACCESS_TOKEN;
+
+        if(accessToken == null || "".equals(accessToken)) {
+            accessToken = AccessTokenThreadUtil.getAccessToken();
+        }
+
+        String url = AirwallexConstant.url + "/api/v1/payments/" + paymentId;
+        // 请求头
+        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);
+        }
+
+        return resp;
+
     }
 
 
     // Cancel、Retry
 
-}
+}

+ 20 - 0
src/main/java/com/szwl/service/impl/TAirwallexMchServiceImpl.java

@@ -0,0 +1,20 @@
+package com.szwl.service.impl;
+
+import com.szwl.model.entity.TAirwallexMch;
+import com.szwl.mapper.TAirwallexMchMapper;
+import com.szwl.service.TAirwallexMchService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author wuhs
+ * @since 2023-07-06
+ */
+@Service
+public class TAirwallexMchServiceImpl extends ServiceImpl<TAirwallexMchMapper, TAirwallexMch> implements TAirwallexMchService {
+
+}

+ 1 - 0
src/main/resources/bootstrap.yml

@@ -47,6 +47,7 @@ eureka:
     serviceUrl:
       defaultZone: http://120.25.151.99:49001/eureka/
     register-with-eureka: true
+#    register-with-eureka: false
   instance:
     prefer-ip-address: true
     ip-address: 120.25.151.99

+ 4 - 3
src/test/java/com/szwl/AutoGeneratorTests.java

@@ -36,18 +36,19 @@ class AutoGeneratorTests {
 				.setControllerName("%sController");
 
 		//配置数据源
-		//配置数据源
+		//TODO:配置数据源
 		DataSourceConfig dataSourceConfig = new DataSourceConfig();
 		dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver")
-				.setUrl("jdbc:mysql://rm-wz995mu26a1479kz0so.mysql.rds.aliyuncs.com:3306/orderdb")
+				.setUrl("jdbc:mysql://rm-wz995mu26a1479kz0so.mysql.rds.aliyuncs.com:3306/szwl-test")
 				.setUsername("root").setPassword("sunzee@020");
 
 		//策略配置
+		//TODO:配置表名
 		StrategyConfig strategyConfig = new StrategyConfig();
 		strategyConfig
 //				.setCapitalMode(true)//设置全局大写命名
 				.setInclude(new String[]{
-						""
+						"t_airwallex_mch"
 				})//只会生成该表
 				.setEntityLombokModel(true)//实体类生成之后自动添加lombok注解
 				.setNaming(NamingStrategy.underline_to_camel)//数据库表映射到实体的命名策略