修改transaction中wip方法
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmResponse.java
index 16f744d..41e47d2 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmResponse.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmResponse.java
@@ -1,12 +1,14 @@
 package com.supwisdom.dlpay.payapi.model;
 
 import java.util.Objects;
+
 import com.fasterxml.jackson.annotation.JsonProperty;
 import com.fasterxml.jackson.annotation.JsonCreator;
 import com.supwisdom.dlpay.payapi.model.TransResult;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import org.openapitools.jackson.nullable.JsonNullable;
+
 import javax.validation.Valid;
 import javax.validation.constraints.*;
 
@@ -15,7 +17,7 @@
  */
 @javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2020-03-24T11:32:36.835+08:00[Asia/Shanghai]")
 
-public class QrcodePayConfirmResponse   {
+public class QrcodePayConfirmResponse {
   @JsonProperty("refno")
   private String refno;
 
@@ -31,6 +33,9 @@
   @JsonProperty("result")
   private TransResult result;
 
+  @JsonProperty("amount")
+  private Integer amount;
+
   public QrcodePayConfirmResponse refno(String refno) {
     this.refno = refno;
     return this;
@@ -38,11 +43,13 @@
 
   /**
    * Get refno
+   *
    * @return refno
-  */
+   */
   @ApiModelProperty(value = "")
 
-@Pattern(regexp="[0-9]*") @Size(min=16) 
+  @Pattern(regexp = "[0-9]*")
+  @Size(min = 16)
   public String getRefno() {
     return refno;
   }
@@ -58,11 +65,13 @@
 
   /**
    * Get hostDate
+   *
    * @return hostDate
-  */
+   */
   @ApiModelProperty(value = "")
 
-@Pattern(regexp="[0-9]*") @Size(min=8,max=8) 
+  @Pattern(regexp = "[0-9]*")
+  @Size(min = 8, max = 8)
   public String getHostDate() {
     return hostDate;
   }
@@ -78,11 +87,13 @@
 
   /**
    * Get hostTime
+   *
    * @return hostTime
-  */
+   */
   @ApiModelProperty(value = "")
 
-@Pattern(regexp="[0-9]*") @Size(min=6,max=6) 
+  @Pattern(regexp = "[0-9]*")
+  @Size(min = 6, max = 6)
   public String getHostTime() {
     return hostTime;
   }
@@ -98,8 +109,9 @@
 
   /**
    * Get description
+   *
    * @return description
-  */
+   */
   @ApiModelProperty(value = "")
 
 
@@ -118,8 +130,9 @@
 
   /**
    * Get result
+   *
    * @return result
-  */
+   */
   @ApiModelProperty(value = "")
 
   @Valid
@@ -132,6 +145,26 @@
     this.result = result;
   }
 
+  public QrcodePayConfirmResponse amount(Integer amount) {
+    this.amount = amount;
+    return this;
+  }
+
+  /**
+   * Get amount
+   * @return amount
+   */
+  @ApiModelProperty(value = "")
+
+
+  public Integer getAmount() {
+    return amount;
+  }
+
+  public void setAmount(Integer amount) {
+    this.amount = amount;
+  }
+
 
   @Override
   public boolean equals(java.lang.Object o) {
@@ -146,24 +179,26 @@
         Objects.equals(this.hostDate, qrcodePayConfirmResponse.hostDate) &&
         Objects.equals(this.hostTime, qrcodePayConfirmResponse.hostTime) &&
         Objects.equals(this.description, qrcodePayConfirmResponse.description) &&
-        Objects.equals(this.result, qrcodePayConfirmResponse.result);
+        Objects.equals(this.result, qrcodePayConfirmResponse.result) &&
+        Objects.equals(this.amount, qrcodePayConfirmResponse.amount);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(refno, hostDate, hostTime, description, result);
+    return Objects.hash(refno, hostDate, hostTime, description, result, amount);
   }
 
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append("class QrcodePayConfirmResponse {\n");
-    
+
     sb.append("    refno: ").append(toIndentedString(refno)).append("\n");
     sb.append("    hostDate: ").append(toIndentedString(hostDate)).append("\n");
     sb.append("    hostTime: ").append(toIndentedString(hostTime)).append("\n");
     sb.append("    description: ").append(toIndentedString(description)).append("\n");
     sb.append("    result: ").append(toIndentedString(result)).append("\n");
+    sb.append("    amount: ").append(toIndentedString(amount)).append("\n");
     sb.append("}");
     return sb.toString();
   }
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundRequest.java b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundRequest.java
index 994ebbb..2d5c958 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundRequest.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundRequest.java
@@ -1,13 +1,12 @@
 package com.supwisdom.dlpay.payapi.model;
 
-import java.util.Objects;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
-import org.openapitools.jackson.nullable.JsonNullable;
-import javax.validation.Valid;
-import javax.validation.constraints.*;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.util.Objects;
 
 /**
  * RefundRequest
@@ -30,6 +29,9 @@
   @JsonProperty("amount")
   private Integer amount;
 
+  @JsonProperty("shopaccno")
+  private String shopaccno;
+
   public RefundRequest billno(String billno) {
     this.billno = billno;
     return this;
@@ -42,7 +44,7 @@
   @ApiModelProperty(required = true, value = "")
   @NotNull
 
-@Pattern(regexp="[0-9]*") @Size(min=16) 
+@Pattern(regexp="[0-9]*") @Size(min=16)
   public String getBillno() {
     return billno;
   }
@@ -63,7 +65,7 @@
   @ApiModelProperty(required = true, value = "")
   @NotNull
 
-@Pattern(regexp="[0-9]*") @Size(min=8,max=8) 
+@Pattern(regexp="[0-9]*") @Size(min=8,max=8)
   public String getTransDate() {
     return transDate;
   }
@@ -84,7 +86,7 @@
   @ApiModelProperty(required = true, value = "")
   @NotNull
 
-@Pattern(regexp="[0-9]*") @Size(min=6,max=6) 
+@Pattern(regexp="[0-9]*") @Size(min=6,max=6)
   public String getTransTime() {
     return transTime;
   }
@@ -105,7 +107,7 @@
   @ApiModelProperty(required = true, value = "")
   @NotNull
 
-@Pattern(regexp="[0-9]*") @Size(min=16) 
+@Pattern(regexp="[0-9]*") @Size(min=16)
   public String getRefno() {
     return refno;
   }
@@ -135,6 +137,26 @@
     this.amount = amount;
   }
 
+  public RefundRequest shopaccno(String shopaccno) {
+    this.shopaccno = shopaccno;
+    return this;
+  }
+
+  /**
+   * Get shopaccno
+   * @return shopaccno
+   */
+  @ApiModelProperty(required = true, value = "")
+  @NotNull
+
+  @Pattern(regexp="[0-9]*")
+  public String getShopaccno() {
+    return shopaccno;
+  }
+
+  public void setShopaccno(String shopaccno) {
+    this.shopaccno = shopaccno;
+  }
 
   @Override
   public boolean equals(java.lang.Object o) {
@@ -149,24 +171,26 @@
         Objects.equals(this.transDate, refundRequest.transDate) &&
         Objects.equals(this.transTime, refundRequest.transTime) &&
         Objects.equals(this.refno, refundRequest.refno) &&
-        Objects.equals(this.amount, refundRequest.amount);
+        Objects.equals(this.amount, refundRequest.amount) &&
+        Objects.equals(this.shopaccno, refundRequest.shopaccno);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(billno, transDate, transTime, refno, amount);
+    return Objects.hash(billno, transDate, transTime, refno, amount, shopaccno);
   }
 
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append("class RefundRequest {\n");
-    
+
     sb.append("    billno: ").append(toIndentedString(billno)).append("\n");
     sb.append("    transDate: ").append(toIndentedString(transDate)).append("\n");
     sb.append("    transTime: ").append(toIndentedString(transTime)).append("\n");
     sb.append("    refno: ").append(toIndentedString(refno)).append("\n");
     sb.append("    amount: ").append(toIndentedString(amount)).append("\n");
+    sb.append("    shopaccno: ").append(toIndentedString(shopaccno)).append("\n");
     sb.append("}");
     return sb.toString();
   }
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundResponse.java
index bb7892c..4321f4d 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundResponse.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/RefundResponse.java
@@ -1,14 +1,13 @@
 package com.supwisdom.dlpay.payapi.model;
 
-import java.util.Objects;
 import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.supwisdom.dlpay.payapi.model.TransResult;
-import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
-import org.openapitools.jackson.nullable.JsonNullable;
+
 import javax.validation.Valid;
-import javax.validation.constraints.*;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.util.Objects;
 
 /**
  * RefundResponse
@@ -28,6 +27,12 @@
   @JsonProperty("refno")
   private String refno;
 
+  @JsonProperty("refundAmount")
+  private Integer refundAmount;
+
+  @JsonProperty("leftAmount")
+  private Integer leftAmount;
+
   @JsonProperty("result")
   private TransResult result;
 
@@ -111,6 +116,48 @@
     this.refno = refno;
   }
 
+  public RefundResponse refundAmount(Integer refundAmount) {
+    this.refundAmount = refundAmount;
+    return this;
+  }
+
+  /**
+   * Get refundAmount
+   * @return refundAmount
+   */
+  @ApiModelProperty(required = true, value = "")
+  @NotNull
+
+
+  public Integer getRefundAmount() {
+    return refundAmount;
+  }
+
+  public void setRefundAmount(Integer refundAmount) {
+    this.refundAmount = refundAmount;
+  }
+
+  public RefundResponse leftAmount(Integer leftAmount) {
+    this.leftAmount = leftAmount;
+    return this;
+  }
+
+  /**
+   * Get leftAmount
+   * @return leftAmount
+   */
+  @ApiModelProperty(required = true, value = "")
+  @NotNull
+
+
+  public Integer getLeftAmount() {
+    return leftAmount;
+  }
+
+  public void setLeftAmount(Integer leftAmount) {
+    this.leftAmount = leftAmount;
+  }
+
   public RefundResponse result(TransResult result) {
     this.result = result;
     return this;
@@ -146,12 +193,14 @@
         Objects.equals(this.hostDate, refundResponse.hostDate) &&
         Objects.equals(this.hostTime, refundResponse.hostTime) &&
         Objects.equals(this.refno, refundResponse.refno) &&
+        Objects.equals(this.refundAmount, refundResponse.refundAmount) &&
+        Objects.equals(this.leftAmount, refundResponse.leftAmount) &&
         Objects.equals(this.result, refundResponse.result);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(billno, hostDate, hostTime, refno, result);
+    return Objects.hash(billno, hostDate, hostTime, refno, refundAmount, leftAmount,result);
   }
 
   @Override
@@ -163,6 +212,8 @@
     sb.append("    hostDate: ").append(toIndentedString(hostDate)).append("\n");
     sb.append("    hostTime: ").append(toIndentedString(hostTime)).append("\n");
     sb.append("    refno: ").append(toIndentedString(refno)).append("\n");
+    sb.append("    refundAmount: ").append(toIndentedString(refundAmount)).append("\n");
+    sb.append("    leftAmount: ").append(toIndentedString(leftAmount)).append("\n");
     sb.append("    result: ").append(toIndentedString(result)).append("\n");
     sb.append("}");
     return sb.toString();
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
index fabcbbf..383ab9b 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
@@ -1,10 +1,7 @@
 package com.supwisdom.dlpay.paysdk.proxy;
 
 import com.supwisdom.dlpay.api.bean.*;
-import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmRequest;
-import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmResponse;
-import com.supwisdom.dlpay.payapi.model.QrcodePayInitRequest;
-import com.supwisdom.dlpay.payapi.model.QrcodePayInitResponse;
+import com.supwisdom.dlpay.payapi.model.*;
 import com.supwisdom.mutlitenant.client.annotations.JwtMethod;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.web.bind.annotation.*;
@@ -42,4 +39,14 @@
     @JwtMethod
     QrcodePayConfirmResponse qrcodePayQuery(@RequestHeader(name = "X-TENANT-ID") String xTenantId,
                                             @PathVariable("refno") String refno);
+
+    @RequestMapping(value = "/refund", method = RequestMethod.POST)
+    @JwtMethod
+    RefundResponse refund(@RequestHeader(name = "X-TENANT-ID") String xTenantId,
+                          @Valid @RequestBody RefundRequest refundRequest);
+
+    @RequestMapping(value = "/refundQuery", method = RequestMethod.GET)
+    @JwtMethod
+    RefundResponse refundQuery(@RequestHeader(name = "X-TENANT-ID") String xTenantId,
+                          @Valid @RequestBody RefundQueryRequest refundQueryRequest);
 }
diff --git a/payapi-spec/consumeapi.yaml b/payapi-spec/consumeapi.yaml
index b58bf96..7114293 100644
--- a/payapi-spec/consumeapi.yaml
+++ b/payapi-spec/consumeapi.yaml
@@ -86,6 +86,10 @@
         result:
           title: 交易结果
           $ref: 'definitions.yaml#/components/schemas/TransResult'
+        amount:
+          type: integer
+          format: int32
+          title: 消费金额
     RefundRequest:
       type: object
       title: 退款申请
@@ -95,6 +99,7 @@
         - transTime
         - refno
         - amount
+        - shopaccno
       properties:
         billno:
           title: 退款申请订单号
@@ -106,6 +111,8 @@
         refno:
           title: 退款申请原始订单交易参考号
           $ref: 'definitions.yaml#/components/schemas/Refno'
+        shopaccno:
+          $ref: 'definitions.yaml#/components/schemas/ShopAccNo'
         amount:
           type: integer
           title: 退款金额, 正式
@@ -123,6 +130,14 @@
         refno:
           title: 退款申请原始订单交易参考号
           $ref: 'definitions.yaml#/components/schemas/Refno'
+        refundAmount:
+          type: integer
+          format: int32
+          title: 退款金额
+        leftAmount:
+          type: integer
+          format: int32
+          title: 原流水剩余金额
         result:
           title: 退款处理结果
           $ref: 'definitions.yaml#/components/schemas/TransResult'
@@ -235,13 +250,13 @@
     refundQuery:
       parameters:
         - $ref: 'definitions.yaml#/components/headers/TenantId'
-        - name: billno
+        - name: refno
           in: path
-          description: 退款订单号
+          description: 系统交易参考号
           required: true
           schema:
             type: string
-            title: 退款订单号
+            title: 系统交易参考号
       get:
         description: 退款申请查询
         tags:
diff --git a/payapi-spec/payapi-spec.yaml b/payapi-spec/payapi-spec.yaml
index 91197ef..6a617af 100644
--- a/payapi-spec/payapi-spec.yaml
+++ b/payapi-spec/payapi-spec.yaml
@@ -13,7 +13,7 @@
     $ref: consumeapi.yaml#/components/paths/qrcodePayQuery
   /consume/refund:
     $ref: consumeapi.yaml#/components/paths/refund
-  /consume/refund/query/{billno}:
+  /consume/refund/query/{refno}:
     $ref: consumeapi.yaml#/components/paths/refundQuery
   /account/query:
     $ref: accountapi.yaml#/components/paths/accountQuery
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java
index e1cbc30..df13f9f 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/citizencard/YnrccUtil.java
@@ -42,6 +42,7 @@
   public static final String DTL_STATUS_PART_REFUND = "3"; //部分退款
 
   public static final int QUERY_MAX_COUNT = 3; //最大查询次数
+  public static final int PAY_QUERY_MAX_COUNT = 5;
 
   public static final String YNRCC_BILLS_DOWNLOAD_LASTDATE = "ynrcc.download.bills.lastdate";
 
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePayTrans.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePayTrans.java
index 4619435..4b1f742 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePayTrans.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePayTrans.java
@@ -71,6 +71,9 @@
   @Column(name = "spip", length = 20)
   private String spip;
 
+  @Transient
+  private Double leftAmount;
+
   public QrcodePayTrans() {
   }
 
@@ -193,4 +196,12 @@
   public void setSpip(String spip) {
     this.spip = spip;
   }
+
+  public Double getLeftAmount() {
+    return leftAmount;
+  }
+
+  public void setLeftAmount(Double leftAmount) {
+    this.leftAmount = leftAmount;
+  }
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/ConsumeApi.java b/payapi/src/main/java/com/supwisdom/dlpay/api/ConsumeApi.java
index ce7cf2c..850430e 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/ConsumeApi.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/ConsumeApi.java
@@ -5,34 +5,18 @@
  */
 package com.supwisdom.dlpay.api;
 
-import com.supwisdom.dlpay.payapi.model.ErrorResponse;
-import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmRequest;
-import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmResponse;
-import com.supwisdom.dlpay.payapi.model.QrcodePayInitRequest;
-import com.supwisdom.dlpay.payapi.model.QrcodePayInitResponse;
-import com.supwisdom.dlpay.payapi.model.RefundRequest;
-import com.supwisdom.dlpay.payapi.model.RefundResponse;
+import com.supwisdom.dlpay.payapi.model.*;
 import io.swagger.annotations.*;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.multipart.MultipartFile;
 
 import javax.validation.Valid;
-import javax.validation.constraints.*;
-import java.util.List;
-import java.util.Map;
 import java.util.Optional;
-@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2020-03-24T11:22:47.201+08:00[Asia/Shanghai]")
+@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", date = "2020-03-17T08:49:02.541+08:00[Asia/Shanghai]")
 
 @Validated
 @Api(value = "consume", description = "the consume API")
@@ -46,12 +30,12 @@
     @ApiResponses(value = { 
         @ApiResponse(code = 200, message = "交易成功", response = QrcodePayConfirmResponse.class),
         @ApiResponse(code = 409, message = "交易正忙,稍后重试", response = ErrorResponse.class),
-        @ApiResponse(code = 500, message = "请求失败", response = ErrorResponse.class) })
+        @ApiResponse(code = 200, message = "交易失败", response = ErrorResponse.class) })
     @RequestMapping(value = "/consume/qrcode/confirm",
         produces = { "application/json" }, 
         consumes = { "application/json" },
         method = RequestMethod.POST)
-    default ResponseEntity<QrcodePayConfirmResponse> qrcodePayConfirm(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String X_TENANT_ID,@ApiParam(value = "Qrcode确认"  )  @Valid @RequestBody QrcodePayConfirmRequest qrcodePayConfirmRequest) {
+    default ResponseEntity<QrcodePayConfirmResponse> qrcodePayConfirm(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-Tenant-Id", required=true) String xTenantId,@ApiParam(value = "Qrcode确认"  )  @Valid @RequestBody QrcodePayConfirmRequest qrcodePayConfirmRequest) {
         getRequest().ifPresent(request -> {
             for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                 if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
@@ -69,12 +53,12 @@
     @ApiOperation(value = "", nickname = "qrcodePayInit", notes = "", response = QrcodePayInitResponse.class, tags={ "pos", })
     @ApiResponses(value = { 
         @ApiResponse(code = 200, message = "初始化成功", response = QrcodePayInitResponse.class),
-        @ApiResponse(code = 500, message = "请求失败", response = ErrorResponse.class) })
+        @ApiResponse(code = 200, message = "请求错误", response = ErrorResponse.class) })
     @RequestMapping(value = "/consume/qrcode/init",
         produces = { "application/json" }, 
         consumes = { "application/json" },
         method = RequestMethod.POST)
-    default ResponseEntity<QrcodePayInitResponse> qrcodePayInit(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String X_TENANT_ID,@ApiParam(value = "QrCode 初始化"  )  @Valid @RequestBody QrcodePayInitRequest qrcodePayInitRequest) {
+    default ResponseEntity<QrcodePayInitResponse> qrcodePayInit(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String xTenantId,@ApiParam(value = "QrCode 初始化"  )  @Valid @RequestBody QrcodePayInitRequest qrcodePayInitRequest) {
         getRequest().ifPresent(request -> {
             for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                 if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
@@ -92,11 +76,11 @@
     @ApiOperation(value = "", nickname = "qrcodePayQuery", notes = "根据系统交易参考号查询流水状态", response = QrcodePayConfirmResponse.class, tags={ "pos", })
     @ApiResponses(value = { 
         @ApiResponse(code = 200, message = "查询成功", response = QrcodePayConfirmResponse.class),
-        @ApiResponse(code = 500, message = "请求失败", response = ErrorResponse.class) })
+        @ApiResponse(code = 200, message = "查询失败", response = ErrorResponse.class) })
     @RequestMapping(value = "/consume/qrcode/query/{refno}",
         produces = { "application/json" }, 
         method = RequestMethod.GET)
-    default ResponseEntity<QrcodePayConfirmResponse> qrcodePayQuery(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String X_TENANT_ID,@ApiParam(value = "系统交易参考号",required=true) @PathVariable("refno") String refno) {
+    default ResponseEntity<QrcodePayConfirmResponse> qrcodePayQuery(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String xTenantId,@ApiParam(value = "系统交易参考号",required=true) @PathVariable("refno") String refno) {
         getRequest().ifPresent(request -> {
             for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                 if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
@@ -114,13 +98,13 @@
     @ApiOperation(value = "", nickname = "refund", notes = "退款交易", response = RefundResponse.class, tags={ "pos", })
     @ApiResponses(value = { 
         @ApiResponse(code = 200, message = "退款申请成功,等待查询", response = RefundResponse.class),
-        @ApiResponse(code = 409, message = "退款申请失败,订单号已存在或正在退款中 ", response = ErrorResponse.class),
-        @ApiResponse(code = 500, message = "请求失败", response = ErrorResponse.class) })
+        @ApiResponse(code = 409, message = "退款申请失败,订单号已存在或正在退款中", response = ErrorResponse.class),
+        @ApiResponse(code = 200, message = "退款申请失败", response = ErrorResponse.class) })
     @RequestMapping(value = "/consume/refund",
         produces = { "application/json" }, 
         consumes = { "application/json" },
         method = RequestMethod.POST)
-    default ResponseEntity<RefundResponse> refund(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String X_TENANT_ID,@ApiParam(value = ""  )  @Valid @RequestBody RefundRequest refundRequest) {
+    default ResponseEntity<RefundResponse> refund(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-Tenant-Id", required=true) String xTenantId,@ApiParam(value = ""  )  @Valid @RequestBody RefundRequest refundRequest) {
         getRequest().ifPresent(request -> {
             for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                 if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
@@ -139,11 +123,11 @@
     @ApiResponses(value = { 
         @ApiResponse(code = 200, message = "退款申请查询成功", response = RefundResponse.class),
         @ApiResponse(code = 404, message = "退款申请订单不存在", response = ErrorResponse.class),
-        @ApiResponse(code = 500, message = "请求失败", response = ErrorResponse.class) })
-    @RequestMapping(value = "/consume/refund/query/{billno}",
+        @ApiResponse(code = 200, message = "退款申请失败", response = ErrorResponse.class) })
+    @RequestMapping(value = "/consume/refund/query/{refno}",
         produces = { "application/json" }, 
         method = RequestMethod.GET)
-    default ResponseEntity<RefundResponse> refundQuery(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-TENANT-ID", required=true) String X_TENANT_ID,@ApiParam(value = "退款订单号",required=true) @PathVariable("billno") String billno) {
+    default ResponseEntity<RefundResponse> refundQuery(@ApiParam(value = "租户ID" ,required=true) @RequestHeader(value="X-Tenant-Id", required=true) String xTenantId,@ApiParam(value = "系统交易参考号",required=true) @PathVariable("refno") String refno) {
         getRequest().ifPresent(request -> {
             for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                 if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java
index 9cc15b9..ab927ba 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java
@@ -2,6 +2,7 @@
 
 import com.supwisdom.dlpay.framework.util.MD5;
 import com.supwisdom.dlpay.framework.util.RandomUtils;
+import com.supwisdom.dlpay.framework.util.StringUtil;
 
 /**
  * Created by shuwei on 17/6/12.
@@ -242,9 +243,12 @@
         StringBuffer str = new StringBuffer()
                 .append("appid=").append(this.appid)
                 .append("&mch_id=").append(this.mch_id)
-                .append("&nonce_str=").append(nonce_str)
-                .append("&out_trade_no=").append(this.out_trade_no);
-        str.append("&key=").append(this.key);
+                .append("&nonce_str=").append(nonce_str);
+        if (!StringUtil.isEmpty(this.out_refund_no)) {
+            str.append("&out_refund_no=").append(this.out_refund_no);
+        }
+        str.append("&out_trade_no=").append(this.out_trade_no).
+            append("&key=").append(this.key);
         this.sign = MD5.encodeByMD5(str.toString());
         return sign;
     }
@@ -260,7 +264,14 @@
                 .append("</mch_id>")
                 .append("<nonce_str>")
                 .append(this.nonce_str)
-                .append("</nonce_str>")
+                .append("</nonce_str>");
+        if (!StringUtil.isEmpty(this.out_refund_no)) {
+            requestStr
+                .append("<out_refund_no>")
+                .append(this.out_refund_no)
+                .append("</out_refund_no>");
+        }
+        requestStr
                 .append("<out_trade_no>")
                 .append(this.out_trade_no)
                 .append("</out_trade_no>")
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/RefundDtlDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/RefundDtlDao.java
new file mode 100644
index 0000000..7f85922
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/RefundDtlDao.java
@@ -0,0 +1,10 @@
+package com.supwisdom.dlpay.api.dao;
+
+import com.supwisdom.dlpay.api.domain.TRefundDtl;
+import org.springframework.data.repository.CrudRepository;
+
+public interface RefundDtlDao extends CrudRepository<TRefundDtl,String> {
+  TRefundDtl findFirstByOriginrefnoAndTenantidOrderBySeqnoDesc(String originrefno, String tenantid);
+
+  TRefundDtl findByRefno(String refno);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java
index e6a8734..446c128 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/dao/TransactionMainDao.java
@@ -8,6 +8,7 @@
 
 import javax.persistence.LockModeType;
 import javax.persistence.QueryHint;
+import java.util.List;
 
 public interface TransactionMainDao extends CrudRepository<TTransactionMain, String> {
 
@@ -30,4 +31,6 @@
 
   @Query("select min(t.accdate) from TTransactionMain t where t.sourceType=?1 ")
   String findMinAccdateBySourcetype(String sourcetype);
+
+  List<TTransactionMain> findByReverseRefno(String refno);
 }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TRefundDtl.java b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TRefundDtl.java
new file mode 100644
index 0000000..80acea6
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/domain/TRefundDtl.java
@@ -0,0 +1,130 @@
+package com.supwisdom.dlpay.api.domain;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+
+@Entity
+@Table(name = "TB_REFUNDDTL",
+    indexes = {@Index(name = "refunddtl_idx",columnList = "originrefno,seqno,tenantid",unique = true),
+        @Index(name = "refunddtl_idx2",columnList = "outid,outtradeno,tenantid",unique = true)})
+public class TRefundDtl {
+  /**
+   * refno 退款流水交易参考号
+   */
+  @Id
+  @Column(name = "refno",length = 32)
+  private String refno;
+
+  /**
+   * originrefno 交易主表被退款流水号
+   */
+  @NotNull
+  @Column(name = "originrefno",length = 32)
+  private String originrefno;
+
+  @NotNull
+  @Column(name = "amount",precision = 9,scale = 2)
+  private Double amount;
+
+  /**
+   * afteramount 原流水退款剩余可退金额
+   */
+  @NotNull
+  @Column(name = "afteramount",precision = 9,scale = 2)
+  private Double afteramount;
+
+  /**
+   * 商户号
+   */
+  @Column(name = "outid",length = 60)
+  private String outid;
+
+  /**
+   * 退款商户billno
+   */
+  @Column(name = "outtradeno",length = 60)
+  private String outtradeno;
+
+  @Column(name = "seqno")
+  private Integer seqno;
+
+  @NotNull
+  @Column(name = "tenantid",length = 20)
+  private String tenantid;
+
+  @NotNull
+  @Column(name = "tradeflag", length = 10)
+  private String tradeflag;
+
+  public String getRefno() {
+    return refno;
+  }
+
+  public void setRefno(String refno) {
+    this.refno = refno;
+  }
+
+  public String getOriginrefno() {
+    return originrefno;
+  }
+
+  public void setOriginrefno(String originrefno) {
+    this.originrefno = originrefno;
+  }
+
+  public Double getAmount() {
+    return amount;
+  }
+
+  public void setAmount(Double amount) {
+    this.amount = amount;
+  }
+
+  public Double getAfteramount() {
+    return afteramount;
+  }
+
+  public void setAfteramount(Double afteramount) {
+    this.afteramount = afteramount;
+  }
+
+  public String getOutid() {
+    return outid;
+  }
+
+  public void setOutid(String outid) {
+    this.outid = outid;
+  }
+
+  public String getOuttradeno() {
+    return outtradeno;
+  }
+
+  public void setOuttradeno(String outtradeno) {
+    this.outtradeno = outtradeno;
+  }
+
+  public Integer getSeqno() {
+    return seqno;
+  }
+
+  public void setSeqno(Integer seqno) {
+    this.seqno = seqno;
+  }
+
+  public String getTenantid() {
+    return tenantid;
+  }
+
+  public void setTenantid(String tenantid) {
+    this.tenantid = tenantid;
+  }
+
+  public String getTradeflag() {
+    return tradeflag;
+  }
+
+  public void setTradeflag(String tradeflag) {
+    this.tradeflag = tradeflag;
+  }
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
index e32d2f8..f964872 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
@@ -50,6 +50,8 @@
 
     public static final String CFG_WECHAT_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
 
+    public static final String CFG_WECHAT_REFUND_QUERY = "https://api.mch.weixin.qq.com/pay/refundquery";
+
     public static final String CFG_WECHAT_REFUND = "https://api.mch.weixin.qq.com/secapi/pay/refund";
 
 }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt
index 6084118..55babc3 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt
@@ -12,15 +12,26 @@
 import com.supwisdom.dlpay.api.service.ConsumePayService
 import com.supwisdom.dlpay.api.service.SourceTypeService
 import com.supwisdom.dlpay.api.service.TransactionServiceProxy
+import com.supwisdom.dlpay.exception.InternalServerError
 import com.supwisdom.dlpay.framework.util.*
 import com.supwisdom.dlpay.framework.util.RandomUtils.getRandomString
 import com.supwisdom.dlpay.util.PaytypeUtil
 import mu.KotlinLogging
 import org.apache.commons.lang.StringUtils
+import org.apache.http.client.methods.HttpPost
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory
+import org.apache.http.entity.StringEntity
+import org.apache.http.impl.client.HttpClients
+import org.apache.http.ssl.SSLContexts
+import org.apache.http.util.EntityUtils
 import org.springframework.http.converter.StringHttpMessageConverter
 import org.springframework.stereotype.Service
 import org.springframework.web.client.RestTemplate
+import java.io.File
+import java.io.FileInputStream
 import java.nio.charset.StandardCharsets
+import java.security.KeyStore
+import kotlin.math.abs
 
 
 @Service
@@ -225,38 +236,68 @@
     override fun doQuery(transaction: TTransactionMain): AgentResponse<QrcodePayTrans> {
         val agentResponse = AgentResponse<QrcodePayTrans>()
         val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false)
+        val refundFlag = TradeDict.REVERSE_FLAG_REFUND == transaction.reverseType
         if (checkCfg(config, agentResponse)) {
             //H5 支付
             val bean = WechatReqResp().apply {
                 this.appid = config[PaytypeUtil.CFG_WECHAT_APPID]
                 this.mch_id = config[PaytypeUtil.CFG_WECHAT_MECHID]
                 this.key = config[PaytypeUtil.CFG_WECHAT_MECHKEY]
-                this.out_trade_no = transaction.refno
+                if (!refundFlag) {
+                    this.out_trade_no = transaction.refno
+                } else {
+                    this.out_refund_no = transaction.refno
+                }
             }
             bean.generalQuerySign()
             val xml = bean.generalQueryXML()
             restTemplate.messageConverters[1] = StringHttpMessageConverter(StandardCharsets.UTF_8)
-            val res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_QUERY, xml, String::class.java)
+            val url = if (!refundFlag) PaytypeUtil.CFG_WECHAT_QUERY else PaytypeUtil.CFG_WECHAT_REFUND_QUERY
+            val res = restTemplate.postForEntity(url, xml, String::class.java)
             val eleMap = XmlUtils.parseXml(res.body)
             val retcode = eleMap["return_code"]
             val resultCode = eleMap["result_code"]
-            val tradeState = eleMap["trade_state"]
-            if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
-                    && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
-                agentResponse.code = AgentCode.REQUIRE_QUERY
-                agentResponse.agentCode = resultCode
-                agentResponse.agentMsg = eleMap["return_msg"]
-                when (tradeState) {
-                    "SUCCESS" -> agentResponse.dtlStatus = DtlStatus.SUCCESS
-                    "REFUND" -> agentResponse.dtlStatus = DtlStatus.REFUND
-                    "NOTPAY", "CLOSED", "REVOKED", "PAYERROR" -> agentResponse.dtlStatus = DtlStatus.FAIL
-                    "USERPAYING" -> agentResponse.dtlStatus = DtlStatus.WAIT
+            if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode) {
+                if (!resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
+                    agentResponse.code = AgentCode.SUCCESS
+                    agentResponse.agentCode = resultCode
+                    if (!refundFlag) {
+                        when (eleMap["trade_state"]) {
+                            "SUCCESS" -> {
+                                agentResponse.dtlStatus = DtlStatus.SUCCESS
+                                agentResponse.agentRefno = eleMap["transaction_id"]
+                            }
+                            "REFUND" -> agentResponse.dtlStatus = DtlStatus.REFUND
+                            "NOTPAY", "CLOSED", "REVOKED", "PAYERROR" -> agentResponse.dtlStatus = DtlStatus.FAIL
+                            "USERPAYING" -> {
+                                agentResponse.code = AgentCode.REQUIRE_QUERY
+                                agentResponse.dtlStatus = DtlStatus.WAIT
+                            }
+                        }
+                    } else {
+                        when (eleMap["refund_status_0"]) {
+                            "SUCCESS" -> {
+                                agentResponse.dtlStatus = DtlStatus.SUCCESS
+                                agentResponse.agentRefno = eleMap["refund_id_0"]
+                            }
+                            "REFUNDCLOSE", "CHANGE" -> agentResponse.dtlStatus = DtlStatus.FAIL
+                            "PROCESSING" -> {
+                                agentResponse.code = AgentCode.REQUIRE_QUERY
+                                agentResponse.dtlStatus = DtlStatus.WAIT
+                            }
+                        }
+                    }
+                } else {
+                    logger.error { "code=${eleMap["err_code"]}},des=${eleMap["err_code_des"]}" }
+                    agentResponse.code = AgentCode.FAIL
+                    agentResponse.agentCode = eleMap["err_code"]
+                    agentResponse.agentMsg = eleMap["err_code_des"]
                 }
             } else {
-                logger.error { "code=${eleMap["err_code"]}},des=${eleMap["err_code_des"]}" }
+                logger.error { "code=${retcode}},des=${eleMap["return_msg"]}" }
                 agentResponse.code = AgentCode.FAIL
-                agentResponse.agentCode = eleMap["err_code"]
-                agentResponse.agentMsg = eleMap["err_code_des"]
+                agentResponse.agentCode = retcode
+                agentResponse.agentMsg = eleMap["return_msg"]
             }
         }
         return agentResponse
@@ -264,36 +305,73 @@
 
     override fun doRefund(transaction: TTransactionMain): AgentResponse<QrcodePayTrans> {
         val agentResponse = AgentResponse<QrcodePayTrans>()
+        val originTrans = transactionService.findTransactionByRefno(transaction.reverseRefno)
+                ?: throw InternalServerError("被退款流水未找到")
         val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false)
         if (checkCfg(config, agentResponse)) {
+            //  生成请求参数
             val bean = WechatReqResp().apply {
                 this.appid = config[PaytypeUtil.CFG_WECHAT_APPID]
                 this.mch_id = config[PaytypeUtil.CFG_WECHAT_MECHID]
                 this.key = config[PaytypeUtil.CFG_WECHAT_MECHKEY]
-                this.out_trade_no = transaction.refno
-                this.total_fee = MoneyUtil.YuanToFen(transaction.shopDtl.amount)
-                this.refund_fee = MoneyUtil.YuanToFen(transaction.refundAmount)
-                this.out_refund_no = transaction.reverseRefno
+                this.out_trade_no = transaction.reverseRefno
+                this.total_fee = abs(MoneyUtil.YuanToFen(originTrans.personDtl.amount))
+                this.refund_fee = abs(MoneyUtil.YuanToFen(transaction.personDtl.amount))
+                this.out_refund_no = transaction.refno
                 this.notify_url = StringUtil.urlAppend(config[PaytypeUtil.CFG_WECHAT_NOTIFY], transaction.tenantid)
             }
             bean.generaReverseSign()
             val xml = bean.generaReverseXML()
-            val res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_REFUND, xml, String::class.java)
-            val eleMap = XmlUtils.parseXml(res.body)
-            val retcode = eleMap["return_code"]
-            val resultCode = eleMap["result_code"]
-            if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
-                    && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
-                agentResponse.code = AgentCode.REQUIRE_QUERY
-                agentResponse.agentCode = resultCode
-                agentResponse.agentRefno = eleMap["refund_id"]
-                agentResponse.agentMsg = eleMap["return_msg"]
-            } else {
-                logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
-                agentResponse.code = AgentCode.FAIL
-                agentResponse.agentCode = eleMap["err_code"]
-                agentResponse.agentMsg = eleMap["err_code_des"]
+            //  设置证书
+            val password = config[PaytypeUtil.CFG_WECHAT_MECHID]!!.toCharArray()
+            val certStream = FileInputStream(File(config[PaytypeUtil.CFG_WECHAT_REFUNDCERT]!!))
+            val keyStore = KeyStore.getInstance("PKCS12")
+            certStream.use {
+                keyStore.load(it, password)
             }
+            val sslContext = SSLContexts.custom()
+                    //这里也是写密码的
+                    .loadKeyMaterial(keyStore, password)
+                    .build()
+            val socketFactory = SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.getDefaultHostnameVerifier())
+            val httpClient = HttpClients.custom()
+                    .setSSLSocketFactory(socketFactory)
+                    .build()
+
+            httpClient.use {
+                // 发送请求
+                val httpPost = HttpPost(PaytypeUtil.CFG_WECHAT_REFUND)
+                httpPost.entity = StringEntity(xml, "UTF-8")
+                val response = httpClient.execute(httpPost)
+                // 解析响应
+                response.use {
+                    val entity = EntityUtils.toString(response.entity, "UTF-8")
+                    val eleMap = XmlUtils.parseXml(entity)
+
+                    val retcode = eleMap["return_code"]
+                    val resultCode = eleMap["result_code"]
+                    if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode) {
+                        if (!resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
+                            agentResponse.code = AgentCode.REQUIRE_QUERY
+                            agentResponse.agentCode = resultCode
+                            agentResponse.agentRefno = eleMap["refund_id"]
+                            agentResponse.agentMsg = eleMap["return_msg"]
+                        } else {
+                            logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
+                            agentResponse.code = AgentCode.FAIL
+                            agentResponse.agentCode = eleMap["err_code"]
+                            agentResponse.agentMsg = eleMap["err_code_des"]
+                        }
+                    } else {
+                        logger.error { "微信退款请求通信失败:<${eleMap["return_msg"]}>" }
+                        agentResponse.code = AgentCode.FAIL
+                        agentResponse.agentCode = eleMap["err_code"]
+                        agentResponse.agentMsg = eleMap["return_msg"]
+                    }
+
+                }
+            }
+
         }
         return agentResponse
     }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt
index 6905ad9..2c70a2e 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt
@@ -43,8 +43,8 @@
             }
         }
         val transation = transactionServiceProxy.findTransactionByRefno(refno)
-        val resp = alipayService.doPayNotify(transation,map)
-         if (resp.code == AgentCode.SUCCESS) {
+        val resp = alipayService.doPayNotify(transation, map)
+        if (resp.code == AgentCode.SUCCESS) {
             alipayInAppResponse.payload = transactionServiceProxy.success(refno)
             alipayInAppResponse.agentBody = "success"
         } else {
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
index db1aaf3..f287282 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/async_tasks.kt
@@ -113,10 +113,10 @@
     private val transactionContainer = TransactionContainer("qrcode.pay", redisConnectionFactory)
 
     @Recover
-    fun quertRecover(ex: TaskRetryException, details: TenantDetails,
+    fun quertRecover(ex: Exception, details: TenantDetails,
                      transaction: TTransactionMain) {
         TenantContextHolder.getContext().tenant = details
-        logger.error("查询refno=[${transaction.refno}]流水结果超最大查询次数[${YnrccUtil.QUERY_MAX_COUNT}]")
+        logger.error("查询refno=[${transaction.refno}]流水结果超最大查询次数[${YnrccUtil.PAY_QUERY_MAX_COUNT}]")
         dtlQueryResultService.saveOrUpdateDtlQuery(TDtlQuery().apply {
             this.accdate = transaction.accdate
             this.refno = transaction.refno
@@ -128,7 +128,7 @@
     }
 
     @Async("queryAgentPayResult")
-    @Retryable(value = [TaskRetryException::class], maxAttempts = YnrccUtil.QUERY_MAX_COUNT, backoff = Backoff(value = 3000))
+    @Retryable(include = [TaskRetryException::class], maxAttempts = YnrccUtil.PAY_QUERY_MAX_COUNT, backoff = Backoff(value = 5000))
     fun queryResult(details: TenantDetails, transaction: TTransactionMain) {
         TenantContextHolder.getContext().tenant = details
 
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
index f500327..d8c8375 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
@@ -24,7 +24,10 @@
 import org.springframework.data.redis.core.RedisTemplate
 import org.springframework.http.ResponseEntity
 import org.springframework.validation.annotation.Validated
-import org.springframework.web.bind.annotation.*
+import org.springframework.web.bind.annotation.PostMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
 import javax.servlet.http.HttpServletRequest
 import javax.validation.Valid
 
@@ -334,7 +337,7 @@
                 setOutTransInfo(mainDtl.outId, param.requestbillno)
             }
             val refundTrans = builder.refundInit(mainDtl.refno,
-                    param.refundAmount / 100.0, transactionService)
+                    param.refundAmount / 100.0, transactionService, null, null)
             transactionService.wip(refundTrans.refno)
             val service = createAgentService<Any>(mainDtl.sourceType)
             val resp = service.refund(refundTrans)
@@ -449,7 +452,7 @@
                 .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败"))
     }
 
-//    @RequestMapping("/qrcode/init", method = [RequestMethod.POST, RequestMethod.GET])
+    //    @RequestMapping("/qrcode/init", method = [RequestMethod.POST, RequestMethod.GET])
     fun qrcodePayInit(@Validated(InitAction::class) @RequestBody param: QrcodePayParam)
             : ResponseEntity<QrcodePayResponse> {
         val apiResp = QrcodePayResponse()
@@ -528,7 +531,7 @@
 
     private fun qrcodeSummary(st: TSourceType): String = st.paydesc + "扫码付"
 
-//    @PostMapping("/qrcode/confirm")
+    //    @PostMapping("/qrcode/confirm")
     fun qrcodePayConfirm(@Validated(ConfirmAction::class) @RequestBody param: QrcodePayParam)
             : ResponseEntity<ApiResponse> {
         //1. 交易检查
@@ -622,7 +625,7 @@
         val response = service.pay(transaction)
         return when (response.code) {
             AgentCode.SUCCESS -> {
-                transactionService.success(transaction.refno, response.agentRefno)
+                transactionService.success(transaction.refno, response.agentRefno, null)
                 ResponseEntity.ok(ResponseBodyBuilder.create()
                         .success(apiResponse))
             }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/k12_consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/k12_consume_api_controller.kt
index 7bf36cd..14916b4 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/k12_consume_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/k12_consume_api_controller.kt
@@ -5,20 +5,26 @@
 import com.supwisdom.dlpay.agent.AgentPayServiceContext
 import com.supwisdom.dlpay.agent.domain.QrcodePayTrans
 import com.supwisdom.dlpay.agent.service.AgentServiceProxy
+import com.supwisdom.dlpay.api.AgentQueryResultTask
 import com.supwisdom.dlpay.api.ConsumeApi
+import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.service.ConsumePayService
 import com.supwisdom.dlpay.api.service.SourceTypeService
 import com.supwisdom.dlpay.api.service.TransactionServiceProxy
 import com.supwisdom.dlpay.api.service.UserService
 import com.supwisdom.dlpay.exception.BadRequestError
 import com.supwisdom.dlpay.exception.ConflictError
+import com.supwisdom.dlpay.exception.InternalServerError
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.MoneyUtil
 import com.supwisdom.dlpay.framework.util.StringUtil
 import com.supwisdom.dlpay.framework.util.TradeDict
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import com.supwisdom.dlpay.payapi.model.*
+import com.supwisdom.multitenant.TenantContextHolder
+import mu.KotlinLogging
 import org.apache.commons.lang3.StringUtils
 import org.springframework.dao.PessimisticLockingFailureException
 import org.springframework.http.ResponseEntity
@@ -27,6 +33,7 @@
 import org.springframework.web.context.request.NativeWebRequest
 import java.util.*
 import javax.validation.Valid
+import kotlin.math.abs
 
 @RestController
 @RequestMapping("\${openapi.aPITitle.base-path:/api}")
@@ -38,7 +45,10 @@
             private val agentPayServiceContext: AgentPayServiceContext,
             private val userService: UserService,
             private val consumePayService: ConsumePayService,
-            private val transactionService: TransactionServiceProxy) : ConsumeApi {
+            private val transactionService: TransactionServiceProxy,
+            private val agentQueryResultTask: AgentQueryResultTask) : ConsumeApi {
+
+    private val logger = KotlinLogging.logger { }
 
     override fun getRequest(): Optional<NativeWebRequest> {
         return Optional.ofNullable(request)
@@ -72,6 +82,7 @@
             // 3. 查询用户身份
             val service = createAgentService<QrcodePayTrans>(qrcode.sourceType)
             val agentResp = service.auth(param.shopaccno, param.billno)
+
             // 4. 重新读取 qrcode 交易明细表,以获取 service.auth 查询后的结果数据
             // 修改, 通过返回值来判断
 //        val qrcodeTransResp = agentServiceProxy.qrcodePayTransFindByMerchIdAndBillno(qrcodeTrans.agentMerchId,
@@ -93,13 +104,16 @@
                             if (person == null) {
                                 qrcodeTransResp.isAnonymous = true
                             } else {
+                                qrcodeTransResp.isAnonymous = false
                                 apiResp.apply {
-                                    qrcodeTransResp.isAnonymous = false
-                                    this.userid = qrcodeTransResp.agentUserId
+                                    this.userid = qrcodeTransResp.userid
                                     this.username = person.name
                                 }
                             }
                         }
+                        apiResp.apply {
+                            this.anonymous = qrcodeTransResp.isAnonymous
+                        }
                         agentServiceProxy.qrcodePayTransSaveOrUpdate(qrcodeTrans.also {
                             it.isAnonymous = qrcodeTransResp.isAnonymous
                         })
@@ -119,8 +133,8 @@
                 is PessimisticLockingFailureException -> throw ConflictError(e.message)
                 else -> {
                     e.printStackTrace()
-                    println("二维码消费初始化异常:<${e.message}>")
-                    throw InternalError(e.message)
+                    logger.error { "二维码消费初始化异常:<${e.message}>" }
+                    throw InternalServerError(e.message)
                 }
             }
         }
@@ -141,47 +155,39 @@
                 this.refno = transaction.refno
                 this.hostDate = systime.hostdate
                 this.hostTime = systime.hosttime
+                this.amount = abs(MoneyUtil.YuanToFen(transaction.personDtl.amount))
             }
             if (TradeDict.DTL_STATUS_INIT != transaction.status) {
-                return when (transaction.status) {
-                    TradeDict.DTL_STATUS_WIP -> {
-                        ResponseBodyBuilder.ok(apiResponse.apply {
-                            this.result = TransResult.REQUIRE_QUERY
-                        })
-                    }
-                    TradeDict.DTL_STATUS_FAIL -> {
-                        ResponseBodyBuilder.ok(apiResponse.apply {
-                            this.result = TransResult.FAILED
-                        })
-                    }
-                    TradeDict.DTL_STATUS_SUCCESS -> {
-                        ResponseBodyBuilder.ok(apiResponse.apply {
-                            this.result = TransResult.ALREADY_SUCCESS
-                        })
-                    }
-                    else -> {
-                        ResponseBodyBuilder.ok(apiResponse.apply {
-                            this.result = TransResult.FAILED
-                        })
-                    }
-                }
+                return ResponseBodyBuilder.ok(apiResponse.apply {
+                    this.result = checkAlreadyTransStatus(transaction.status)
+                })
             }
 
-            transactionService.qrcodeWip(param.billno, transaction)
+            transactionService.wip(transaction.refno)
 
             val service = createAgentService<QrcodePayTrans>(transaction.sourceType)
             val response = service.pay(transaction)
 
-            consumePayService.qrcodePayConfirmPostProcess(response, param.billno, transaction)
+            consumePayService.qrcodePayConfirmPostProcess(response, transaction.refno)
             return when (response.code) {
                 AgentCode.SUCCESS -> {
-                    ResponseBodyBuilder.ok(apiResponse.apply { this.result = TransResult.SUCCESS })
+                    ResponseBodyBuilder.ok(apiResponse.apply {
+                        this.description = response.agentMsg
+                        this.result = TransResult.SUCCESS
+                    })
                 }
                 AgentCode.REQUIRE_QUERY -> {
-                    ResponseBodyBuilder.ok(apiResponse.apply { this.result = TransResult.REQUIRE_QUERY })
+                    agentQueryResultTask.queryResult(TenantContextHolder.getContext().tenant, transaction)
+                    ResponseBodyBuilder.ok(apiResponse.apply {
+                        this.description = response.agentMsg
+                        this.result = TransResult.REQUIRE_QUERY
+                    })
                 }
                 else -> {
-                    ResponseBodyBuilder.ok(apiResponse.apply { this.result = TransResult.FAILED })
+                    ResponseBodyBuilder.ok(apiResponse.apply {
+                        this.description = response.agentMsg
+                        this.result = TransResult.FAILED
+                    })
                 }
             }
         } catch (e: Exception) {
@@ -190,8 +196,8 @@
                 is PessimisticLockingFailureException -> throw ConflictError(e.message)
                 else -> {
                     e.printStackTrace()
-                    println("二维码消费确认异常:<${e.message}>")
-                    throw InternalError(e.message)
+                    logger.error { "二维码消费确认异常:<${e.message}>" }
+                    throw InternalServerError(e.message)
                 }
             }
         }
@@ -200,15 +206,20 @@
     override fun qrcodePayQuery(xTenantId: String, refno: String): ResponseEntity<QrcodePayConfirmResponse> {
         try {
             val systime = systemUtilService.sysdatetime
+
             consumePayService.getTransactionMainDtl(refno, null, null)?.let {
                 return ResponseBodyBuilder.ok(QrcodePayConfirmResponse().apply {
                     this.refno = it.refno
                     this.hostDate = systime.hostdate
                     this.hostTime = systime.hosttime
+                    this.amount = abs(MoneyUtil.YuanToFen(it.personDtl.amount))
                     this.result = when (it.status) {
                         TradeDict.DTL_STATUS_SUCCESS -> TransResult.SUCCESS
                         TradeDict.DTL_STATUS_WIP -> TransResult.REQUIRE_QUERY
-                        TradeDict.DTL_STATUS_FAIL -> TransResult.FAILED
+                        TradeDict.DTL_STATUS_FAIL -> {
+                            this.description = it.personDtl.remark
+                            TransResult.FAILED
+                        }
                         else -> TransResult.FAILED
                     }
                 })
@@ -219,10 +230,125 @@
                 is PessimisticLockingFailureException -> throw ConflictError(e.message)
                 else -> {
                     e.printStackTrace()
-                    println("二维码消费查询异常:<${e.message}>")
-                    throw InternalError(e.message)
+                    logger.error { "二维码消费查询异常:<${e.message}>" }
+                    throw InternalServerError(e.message)
                 }
             }
         }
     }
+
+    override fun refund(xTenantId: String, param: RefundRequest): ResponseEntity<RefundResponse> {
+        try {
+            // 查询是否重试
+            val alreadyTrans = consumePayService.queryRefundRetry(param.billno, param.shopaccno)
+            val systime = systemUtilService.sysdatetime
+            val apiResponse = RefundResponse().apply {
+                this.billno = param.billno
+                this.hostDate = systime.hostdate
+                this.hostTime = systime.hosttime
+            }
+
+            val refundTrans: TTransactionMain
+            if (alreadyTrans != null) {
+                if (alreadyTrans.reverseType != TradeDict.REVERSE_FLAG_REFUND) {
+                    throw BadRequestError("退款请更换billno,该billno已使用")
+                }
+                val alreadyStatus = checkAlreadyTransStatus(alreadyTrans.status)
+                // 判断已有的流水是否是init状态
+                if (alreadyStatus != null) {
+                    return ResponseBodyBuilder.ok(apiResponse.apply {
+                        this.refno = alreadyTrans.refno
+                        this.result = alreadyStatus
+                    })
+                } else {
+                    // 直接发起第三方重试
+                    refundTrans = alreadyTrans
+                }
+            } else {
+                // 先进行流水初始化
+                refundTrans = consumePayService.initRefundTransactionMain(param)
+            }
+
+            val service = createAgentService<Any>(refundTrans.sourceType)
+            val resp = service.refund(refundTrans)
+
+            apiResponse.apply {
+                this.refno = refundTrans.refno
+            }
+            when (resp.code) {
+                AgentCode.SUCCESS -> {
+                    transactionService.success(refundTrans.refno, resp.agentRefno, false)
+                    return ResponseEntity.ok(apiResponse.apply { this.result = TransResult.SUCCESS })
+                }
+                AgentCode.REQUIRE_QUERY -> {
+                    //待查询
+                    transactionService.wip(refundTrans.refno)
+                    agentQueryResultTask.queryResult(TenantContextHolder.getContext().tenant, refundTrans)
+                    return ResponseEntity.ok(apiResponse.apply { this.result = TransResult.REQUIRE_QUERY })
+                }
+                else -> transactionService.fail(refundTrans.refno,
+                        "${resp.agentCode}-${resp.agentMsg}").let {
+                    logger.error { "退款业务失败:<${resp.agentMsg}>" }
+                    return ResponseEntity.ok(apiResponse.apply { this.result = TransResult.FAILED })
+                }
+            }
+        } catch (e: Exception) {
+            when (e) {
+                is BadRequestError -> throw BadRequestError(e.message)
+                is PessimisticLockingFailureException -> throw ConflictError(e.message)
+                else -> {
+                    e.printStackTrace()
+                    logger.error { "退款交易业务异常:<${e.message}>" }
+                    throw InternalServerError(e.message)
+                }
+            }
+        }
+    }
+
+    override fun refundQuery(xTenantId: String, refno: String): ResponseEntity<RefundResponse> {
+        val systime = systemUtilService.sysdatetime
+        consumePayService.getTransactionMainDtl(refno, null, null)?.let {
+            if (it.reverseType != TradeDict.REVERSE_FLAG_REFUND) {
+                throw BadRequestError("该笔交易不是退款交易")
+            }
+            val refundDtl = consumePayService.queryRefundDtl(refno)
+                    ?: throw InternalServerError("未找到refno:<${refno}")
+            return ResponseBodyBuilder.ok(RefundResponse().apply {
+                this.billno = it.outTradeNo
+                this.refno = it.refno
+                this.hostDate = systime.hostdate
+                this.hostTime = systime.hosttime
+                this.leftAmount= abs(MoneyUtil.YuanToFen(refundDtl.afteramount))
+                this.refundAmount = abs(MoneyUtil.YuanToFen(it.personDtl.amount))
+                this.result = when (it.status) {
+                    TradeDict.DTL_STATUS_SUCCESS -> TransResult.SUCCESS
+                    TradeDict.DTL_STATUS_WIP -> TransResult.REQUIRE_QUERY
+                    TradeDict.DTL_STATUS_INIT -> TransResult.REQUIRE_QUERY
+                    TradeDict.DTL_STATUS_FAIL -> TransResult.FAILED
+                    else -> TransResult.FAILED
+                }
+            })
+        } ?: throw BadRequestError("未找到refno:<${refno}")
+
+    }
+
+    fun checkAlreadyTransStatus(status: String): TransResult? {
+        return when (status) {
+            TradeDict.DTL_STATUS_WIP -> {
+                TransResult.REQUIRE_QUERY
+            }
+            TradeDict.DTL_STATUS_FAIL -> {
+                TransResult.FAILED
+            }
+            TradeDict.DTL_STATUS_SUCCESS -> {
+                TransResult.ALREADY_SUCCESS
+            }
+            TradeDict.DTL_STATUS_INIT -> {
+                null
+            }
+            else -> {
+                TransResult.FAILED
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt
index 09697b5..ac08430 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt
@@ -93,9 +93,9 @@
     @PostMapping("/inapp/payinit")
     fun inAppPayInit(@Valid @RequestBody param: InAppPayParam): ResponseEntity<*> {
         val response = InAppPayResponse()
-       /* if (transactionContainer.count() > 100) {
-            return ResponseBodyBuilder.internalServerError("第三方请求异常")
-        }*/
+        /* if (transactionContainer.count() > 100) {
+             return ResponseBodyBuilder.internalServerError("第三方请求异常")
+         }*/
         val sourceType = sourceTypeService.getBySourceType(param.sourceType)
                 ?: return ResponseBodyBuilder.badRequest("source type <${param.sourceType}> 不存在")
 
@@ -109,7 +109,7 @@
             "native" -> TradeCode.TRANSCODE_APPPAY
             else -> return ResponseBodyBuilder.badRequest("app typ <${param.inAppType}> 不支持")
         }
-        if(param.description==null){
+        if (param.description == null) {
             param.description = "描述为空"
         }
         val builder = TransactionBuilder()
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
index ae4c7a7..8475a22 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/user_api_controller.kt
@@ -323,7 +323,7 @@
             this.setOutTransInfo(request.operid, request.operSeqno)
         }
         val transaction = builder.refundInit(request.originRefno, request.totalAmount / 100.0,
-                transactionService)
+                transactionService,null,null)
 
         result.apply {
             refno = transaction.refno
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt
index 832cf5c..2dc45e3 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt
@@ -2,9 +2,11 @@
 
 import com.supwisdom.dlpay.agent.AgentResponse
 import com.supwisdom.dlpay.agent.domain.QrcodePayTrans
+import com.supwisdom.dlpay.api.domain.TRefundDtl
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.framework.domain.TDictionary
 import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmRequest
+import com.supwisdom.dlpay.payapi.model.RefundRequest
 import org.springframework.transaction.annotation.Propagation
 import org.springframework.transaction.annotation.Transactional
 
@@ -28,8 +30,17 @@
     fun checkCanReverse(sourcetype: String, shopaccno: String? = null): Boolean
 
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
-    fun qrcodePayConfirmPostProcess(response: AgentResponse<QrcodePayTrans>, billno: String,transaction:TTransactionMain)
+    fun qrcodePayConfirmPostProcess(response: AgentResponse<QrcodePayTrans>, refno: String)
 
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
     fun getTransactionMainByParam(param: QrcodePayConfirmRequest): TTransactionMain
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
+    fun initRefundTransactionMain(param: RefundRequest): TTransactionMain
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
+    fun queryRefundRetry(billno: String,shopaccno:String):TTransactionMain?
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
+    fun queryRefundDtl(refno:String):TRefundDtl?
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt
index 9d8b5c4..38a1bee 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/consume_pay_service_impl.kt
@@ -9,7 +9,9 @@
 import com.supwisdom.dlpay.agent.service.AgentServiceProxy
 import com.supwisdom.dlpay.api.AccountProxy
 import com.supwisdom.dlpay.api.TransactionBuilder
+import com.supwisdom.dlpay.api.dao.RefundDtlDao
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
+import com.supwisdom.dlpay.api.domain.TRefundDtl
 import com.supwisdom.dlpay.api.domain.TSourceType
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
@@ -18,12 +20,14 @@
 import com.supwisdom.dlpay.api.service.SourceTypeService
 import com.supwisdom.dlpay.api.service.TransactionServiceProxy
 import com.supwisdom.dlpay.exception.BadRequestError
+import com.supwisdom.dlpay.exception.InternalServerError
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.framework.dao.DictionaryDao
 import com.supwisdom.dlpay.framework.domain.TDictionary
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 import com.supwisdom.dlpay.framework.util.*
 import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmRequest
+import com.supwisdom.dlpay.payapi.model.RefundRequest
 import com.supwisdom.multitenant.TenantContextHolder
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
@@ -39,15 +43,17 @@
     @Autowired
     lateinit var agentServiceProxy: AgentServiceProxy
     @Autowired
-    lateinit var accountUtilServcie:AccountUtilServcie
+    lateinit var accountUtilServcie: AccountUtilServcie
     @Autowired
-    lateinit var transactionService:TransactionServiceProxy
+    lateinit var transactionService: TransactionServiceProxy
     @Autowired
     lateinit var agentPayServiceContext: AgentPayServiceContext
     @Autowired
     lateinit var systemUtilService: SystemUtilService
     @Autowired
     lateinit var qrcodePayTransDao: QrcodePayTransDao
+    @Autowired
+    lateinit var refundDtlDao: RefundDtlDao
 
     override fun checkShopPaytype(shopaccno: String, sourceType: String, anonymousflag: Boolean?): Boolean {
         return sourceTypeService.checkShopSourceType(shopaccno, sourceType, true == anonymousflag)
@@ -82,19 +88,16 @@
         }
     }
 
-    override fun qrcodePayConfirmPostProcess(response: AgentResponse<QrcodePayTrans>, billno: String,transaction:TTransactionMain) {
-        val qrcodeTrans = qrcodePayTransDao.findByQrcodePayTransForUpdate(transaction.outId, systemUtilService.sysdatetime.hostdate,
-                billno, TenantContextHolder.getContext().tenant.id)
-                ?: throw BadRequestError("未找到billno")
+    override fun qrcodePayConfirmPostProcess(response: AgentResponse<QrcodePayTrans>, refno: String) {
         when (response.code) {
             AgentCode.SUCCESS -> {
-                transactionService.qrcodeSuccess(transaction.refno, response.agentRefno,transaction)
+                transactionService.success(refno, response.agentRefno, null)
             }
             AgentCode.REQUIRE_QUERY -> {
                 return
             }
             else -> {
-                transactionService.qrcodeFail(transaction.refno, response.agentMsg,transaction)
+                transactionService.fail(refno, response.agentMsg)
             }
         }
     }
@@ -130,7 +133,7 @@
 
         if (!qrcodeTrans.refno.isNullOrEmpty()) {
             return getTransactionMainDtl(qrcodeTrans.refno, null, null)
-                    ?: throw InternalError("未找到refno")
+                    ?: throw InternalServerError("未找到refno")
         }
 
         //2. 初始化交易流水
@@ -181,4 +184,34 @@
 
         return transaction
     }
+
+    override fun initRefundTransactionMain(param: RefundRequest): TTransactionMain {
+        transactionMainDao.findByRefnoForUpdate(param.refno)?.let { mainDtl ->
+            if (mainDtl.sourceType.isNotEmpty()) {
+                //判断能否冲正
+                if (mainDtl.shop) {
+                    checkCanReverse(mainDtl.sourceType, mainDtl.shopDtl.shopaccno)
+                } else {
+                    checkCanReverse(mainDtl.sourceType)
+                }
+            } else {
+                throw BadRequestError("该笔交易未定义sourcetype, 不支持退款")
+            }
+
+            val builder = TransactionBuilder().apply {
+                setTransInfo(param.transDate, param.transTime, mainDtl.transCode, mainDtl.sourceType)
+                setOutTransInfo(mainDtl.outId, param.billno)
+            }
+            return builder.refundInit(mainDtl.refno,
+                    MoneyUtil.FenToYuan(param.amount), transactionService, param.billno, param.shopaccno)
+        } ?: throw BadRequestError("未找到refno")
+}
+
+    override fun queryRefundRetry(billno: String, shopaccno: String): TTransactionMain? {
+        return transactionMainDao.findByBillno(billno, shopaccno)
+    }
+
+    override fun queryRefundDtl(refno: String): TRefundDtl? {
+        return refundDtlDao.findByRefno(refno)
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
index 82ae2cc..22fa55a 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/transaction_service_impl.kt
@@ -2,20 +2,28 @@
 
 import com.supwisdom.dlpay.agent.dao.QrcodePayTransDao
 import com.supwisdom.dlpay.api.TransactionBuilder
+import com.supwisdom.dlpay.api.dao.RefundDtlDao
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
 import com.supwisdom.dlpay.api.domain.*
 import com.supwisdom.dlpay.api.repositories.AccountService
 import com.supwisdom.dlpay.api.service.AccountUtilServcie
 import com.supwisdom.dlpay.api.service.SourceTypeService
 import com.supwisdom.dlpay.api.service.TransactionService
+import com.supwisdom.dlpay.exception.BadRequestError
+import com.supwisdom.dlpay.exception.InternalServerError
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.exception.TransactionProcessException
 import com.supwisdom.dlpay.framework.service.SystemUtilService
-import com.supwisdom.dlpay.framework.util.*
+import com.supwisdom.dlpay.framework.util.DateUtil
+import com.supwisdom.dlpay.framework.util.Subject
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import com.supwisdom.multitenant.TenantContextHolder
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
+import java.math.BigDecimal
 import java.sql.SQLException
+import kotlin.math.abs
 import kotlin.math.absoluteValue
 
 
@@ -39,6 +47,9 @@
     @Autowired
     private lateinit var qrcodePayTransDao: QrcodePayTransDao
 
+    @Autowired
+    private lateinit var refundDtlDao: RefundDtlDao
+
 
     /// 公共函数部分
     private fun preCheck(builder: TransactionBuilder) {
@@ -286,25 +297,11 @@
 
     override fun wip(refno: String): TTransactionMain {
         val transaction = transactionMainDao.findByRefnoForUpdate(refno)
-                ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>参考号错误")
-
-        if (transaction.status != TradeDict.DTL_STATUS_INIT
-                && transaction.status != TradeDict.DTL_STATUS_WIP) {
-            throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误")
-        }
-
-        updateRecordStatus(transaction, TradeDict.DTL_STATUS_WIP)
-        transactionMainDao.save(transaction)
-        return transaction
-    }
-
-    override fun qrcodeWip(billno: String,transaction:TTransactionMain): TTransactionMain {
-        val qrcodeTrans = qrcodePayTransDao.findByQrcodePayTransForUpdate(transaction.outId, systemUtilService.sysdatetime.hostdate,
-                billno, TenantContextHolder.getContext().tenant.id)
-                ?: throw InternalError("未找到billno")
+                    ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>参考号错误")
         if (transaction.status != TradeDict.DTL_STATUS_INIT) {
-            throw InternalError("流水<${transaction.refno}>状态错误")
+            throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<${transaction.refno}>状态错误")
         }
+
         updateRecordStatus(transaction, TradeDict.DTL_STATUS_WIP)
         transactionMainDao.save(transaction)
         return transaction
@@ -317,33 +314,6 @@
     override fun fail(refno: String, remark: String): TTransactionMain {
         val transaction = transactionMainDao.findByRefnoForUpdate(refno)
                 ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>参考号错误")
-
-        val errorStatus = setOf(TradeDict.DTL_STATUS_SUCCESS, TradeDict.DTL_STATUS_CANCEL)
-        if (transaction.status in errorStatus) {
-            throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误")
-        }
-
-        updateRecordStatus(transaction, TradeDict.DTL_STATUS_FAIL)
-        if (transaction.person) {
-            transaction.personDtl.remark = remark
-        }
-        if (transaction.shop) {
-            transaction.shopDtl.remark = remark
-        }
-        if (transaction.reverseType != TradeDict.REVERSE_FLAG_NONE) {
-            val originTrans = transactionMainDao.findByRefnoNoLock(transaction.reverseRefno ?: "")
-                    ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
-                            "系统异常,无法处理退款流水")
-            originTrans.reverseFlag = TradeDict.REVERSE_FLAG_NONE
-            transactionMainDao.save(originTrans)
-        }
-        transaction.endTime = systemUtilService.sysdatetime.sysdate
-        transactionMainDao.save(transaction)
-        return transaction
-    }
-
-    override fun qrcodeFail(refno: String, remark: String, transaction: TTransactionMain): TTransactionMain {
-
         val errorStatus = setOf(TradeDict.DTL_STATUS_SUCCESS, TradeDict.DTL_STATUS_CANCEL)
         if (transaction.status in errorStatus) {
             throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误")
@@ -400,7 +370,6 @@
     override fun success(refno: String, sourcetypeRefno: String, accdateUpdate: Boolean?): TTransactionMain {
         val transaction = transactionMainDao.findByRefnoForUpdate(refno)
                 ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "参考号<$refno>错误,流水不存在")
-
         val errorStatus = setOf(TradeDict.DTL_STATUS_SUCCESS, TradeDict.DTL_STATUS_CANCEL)
         if (transaction.status in errorStatus) {
             throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误,流水已结束")
@@ -412,40 +381,9 @@
         transactionOnSuccess(transaction, sourcetypeRefno, false)
 
         if (transaction.reverseType != TradeDict.REVERSE_FLAG_NONE) {
-            val originTrans = transactionMainDao.findByRefnoNoLock(transaction.reverseRefno ?: "")
+            val originTrans = transactionMainDao.findByRefnoForUpdate(transaction.reverseRefno ?: "")
                     ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
-                            "系统异常,无法处理退款流水")
-            originTrans.reverseFlag = transaction.reverseType
-            if (originTrans.person) {
-                originTrans.personDtl.reverseFlag = originTrans.reverseFlag
-                originTrans.personDtl.reverseAmount = originTrans.refundAmount
-            }
-            if (originTrans.shop) {
-                originTrans.shopDtl.reverseFlag = originTrans.reverseFlag
-            }
-            transactionMainDao.save(originTrans)
-        }
-
-        transaction.endTime = systemUtilService.sysdatetime.sysdate
-        transactionMainDao.save(transaction)
-        return transaction
-    }
-
-    override fun qrcodeSuccess(refno: String, sourcetypeRefno: String, transaction: TTransactionMain, accdateUpdate: Boolean?): TTransactionMain {
-        val errorStatus = setOf(TradeDict.DTL_STATUS_SUCCESS, TradeDict.DTL_STATUS_CANCEL)
-        if (transaction.status in errorStatus) {
-            throw TransactionProcessException(TradeErrorCode.TRANSACTION_IS_FINISHED, "流水<$refno>状态错误,流水已结束")
-        }
-        transaction.status = TradeDict.DTL_STATUS_SUCCESS
-        if (true == accdateUpdate) {
-            transaction.accdate = systemUtilService.accdate
-        }
-        transactionOnSuccess(transaction, sourcetypeRefno, false)
-
-        if (transaction.reverseType != TradeDict.REVERSE_FLAG_NONE) {
-            val originTrans = transactionMainDao.findByRefnoNoLock(transaction.reverseRefno ?: "")
-                    ?: throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR,
-                            "系统异常,无法处理退款流水")
+                            "系统异常,被退款流水未找到")
             originTrans.reverseFlag = transaction.reverseType
             if (originTrans.person) {
                 originTrans.personDtl.reverseFlag = originTrans.reverseFlag
@@ -472,10 +410,13 @@
 
     //////////////////////////////////////////////////////////////////
 // 回退业务接口,包括撤销和退款
-    override fun refundInit(originRefno: String, refundAmount: Double, builder: TransactionBuilder): TTransactionMain {
+    override fun refundInit(originRefno: String, refundAmount: Double, builder: TransactionBuilder, billno: String?, shopaccno: String?): TTransactionMain {
         val originTrans = transactionMainDao.findByRefnoForUpdate(originRefno)
                 ?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS
                         , "被退款流水不存在")
+        if (!originTrans.person) {
+            throw BadRequestError("无法退款非个人流水")
+        }
         if (TradeDict.REVERSE_FLAG_NONE != originTrans.reverseType) {
             throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
                     "原始流水为撤销或退款流水,不能再被退款")
@@ -485,24 +426,81 @@
             throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
                     "原流水不是成功状态")
         }
-        if (originTrans.reverseFlag != TradeDict.REVERSE_FLAG_NONE) {
-            throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
-                    "原流水已被退款或正在处理退款中")
+
+        val tenantid = TenantContextHolder.getContext().tenant.id
+        val availableAmount: Double
+        val seqno: Int
+        // 校验原流水是否已被退款或撤销
+        when (originTrans.reverseFlag) {
+            TradeDict.REVERSE_FLAG_CANCEL -> {
+                throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
+                        "原流水已被撤销")
+            }
+            TradeDict.REVERSE_FLAG_REFUND -> {
+                //  查询原流水最后一笔退款流水
+                val lastRefundDtl = refundDtlDao.findFirstByOriginrefnoAndTenantidOrderBySeqnoDesc(originRefno, tenantid)
+                        ?: throw InternalServerError("原流水refno:<${originRefno}>的最后一笔退款流水未找到")
+                val lastTransMain = transactionMainDao.findByRefno(lastRefundDtl.refno)
+                        ?: throw InternalServerError("原流水refno:<${originRefno}>的最后一笔退款主流水未找到")
+
+                when (lastTransMain.status) {
+                    TradeDict.DTL_STATUS_WIP -> {
+                        throw BadRequestError("原流水refno:<${originRefno}>有一笔正在处理中的退款请求")
+                    }
+                    // TODO: init状态去查询一次?
+                    TradeDict.DTL_STATUS_INIT -> {
+                        lastTransMain.status = TradeDict.DTL_STATUS_CANCEL
+                        transactionMainDao.save(lastTransMain)
+                        throw InternalServerError("原流水refno:<${originRefno}>最后一笔退款流水已取消")
+                    }
+                    TradeDict.DTL_STATUS_SUCCESS -> {
+                        availableAmount = lastRefundDtl.afteramount
+                    }
+                    TradeDict.DTL_STATUS_FAIL -> {
+                        availableAmount = (BigDecimal(lastRefundDtl.afteramount.toString())
+                                + BigDecimal(lastRefundDtl.amount.toString())).toDouble()
+                    }
+                    else -> {
+                        throw InternalServerError("原流水refno:<${originRefno}>最后一笔退款流水状态异常")
+                    }
+                }
+                seqno = lastRefundDtl.seqno + 1
+            }
+            TradeDict.REVERSE_FLAG_NONE -> {
+                availableAmount = abs(originTrans.personDtl.amount)
+                seqno = 1
+            }
+            else -> {
+                throw TransactionProcessException(TradeErrorCode.TRANSDTL_STATUS_ERROR,
+                        "原流水的退款或撤销状态异常")
+            }
+        }
+
+        if (refundAmount > availableAmount) {
+            throw BadRequestError("退款金额不能超过原流水剩余金额")
         }
 
         doReversePrepareAndCheck(originTrans, builder, refundAmount)
-        //fixme: 判断退款金额 check 不支持部分退款
-        if (originTrans.person) {
-            if (!MoneyUtil.moneyEqual(Math.abs(originTrans.personDtl.amount), refundAmount)) {
-                throw TransactionProcessException(TradeErrorCode.BUSINESS_DEAL_ERROR
-                        , "暂不支持部分退款")
-            }
-        }
-        val transaction = doReverseProcess(originTrans, builder)
 
-        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_WIP
-        originTrans.refundAmount = refundAmount
+        // 交易主表生成一笔退款流水
+        val transaction = doReverseProcess(originTrans, builder, refundAmount)
+        // 标记原流水为已有退款
+        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_REFUND
         transactionMainDao.save(originTrans)
+        // 记录退款流水表
+        val refundDtl = TRefundDtl().apply {
+            this.refno = transaction.refno
+            this.originrefno = originRefno
+            this.amount = refundAmount
+            this.afteramount = (BigDecimal(availableAmount.toString()) - BigDecimal(refundAmount.toString())).toDouble()
+            this.seqno = seqno
+            this.outid = shopaccno
+            this.outtradeno = billno
+            this.tenantid = tenantid
+            this.tradeflag = transaction.personDtl.tradeflag
+        }
+        refundDtlDao.save(refundDtl)
+
         return transaction
     }
 
@@ -525,9 +523,9 @@
         }
 
         doReversePrepareAndCheck(originTrans, builder, 0.0)
-        val transaction = doReverseProcess(originTrans, builder)
+        val transaction = doReverseProcess(originTrans, builder, 0.0)
 
-        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_WIP
+//        originTrans.reverseFlag = TradeDict.REVERSE_FLAG_WIP
         transactionMainDao.save(originTrans)
         return transaction
     }
@@ -549,11 +547,11 @@
         }
     }
 
-    private fun doReverseProcess(originTrans: TTransactionMain, builder: TransactionBuilder): TTransactionMain {
+    private fun doReverseProcess(originTrans: TTransactionMain, builder: TransactionBuilder, amount: Double): TTransactionMain {
         val summarySuffix = getReverseSuffix(builder.reverseType)
         if (originTrans.person) {
             builder.person().apply {
-                setAmount(-originTrans.personDtl.amount, getOppositeTradeFlag(originTrans.personDtl.tradeflag))
+                setAmount(-amount, getOppositeTradeFlag(originTrans.personDtl.tradeflag))
                 setOpposite(originTrans.personDtl.oppositeAccNo, originTrans.personDtl.oppositeAccName)
             }
             builder.description = "${originTrans.personDtl.transdesc}$summarySuffix"
@@ -561,7 +559,7 @@
         }
         if (originTrans.shop) {
             builder.shop().apply {
-                setAmount(-originTrans.shopDtl.amount, getOppositeTradeFlag(originTrans.shopDtl.tradeflag))
+                setAmount(-amount, getOppositeTradeFlag(originTrans.shopDtl.tradeflag))
                 setOpposite(originTrans.shopDtl.oppositeAccNo, originTrans.shopDtl.oppositeAccName)
             }
             builder.description = "${originTrans.shopDtl.transdesc}$summarySuffix"
@@ -570,7 +568,7 @@
 
         originTrans.details.forEach {
             builder.addDebitCreditRecord(it.draccno, it.drsubjno, it.craccno, it.crsubjno,
-                    -it.amount, "${it.summary}$summarySuffix")
+                    -amount, "${it.summary}$summarySuffix")
         }
         builder.dtltype = originTrans.dtltype
         if (builder.operId.isNullOrEmpty()) {
@@ -584,14 +582,14 @@
         if (originTrans.person) {
             val account = accountUtilService.readAccount(originTrans.personDtl.userid)
             builder.person(account).apply {
-                setAmount(-originTrans.personDtl.amount,
+                setAmount(-amount,
                         getOppositeTradeFlag(originTrans.personDtl.tradeflag))
             }
         }
         if (originTrans.shop) {
             val shopacc = accountUtilService.readShopbyShopaccno(originTrans.shopDtl.shopaccno)
             builder.shop(shopacc).apply {
-                setAmount(-originTrans.shopDtl.amount,
+                setAmount(-amount,
                         getOppositeTradeFlag(originTrans.shopDtl.tradeflag))
             }
         }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
index dd9dff4..c94fc40 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/service/transaction_service.kt
@@ -23,24 +23,15 @@
     fun wip(builder: TransactionBuilder): TTransactionMain
 
     @Transactional
-    fun qrcodeWip(billno: String, transaction: TTransactionMain): TTransactionMain
-
-    @Transactional
     fun fail(refno: String): TTransactionMain
 
     @Transactional
     fun fail(refno: String, remark: String): TTransactionMain
 
     @Transactional
-    fun qrcodeFail(refno: String, remark: String, transaction: TTransactionMain): TTransactionMain
-
-    @Transactional
     fun success(refno: String, sourcetypeRefno: String, accdateUpdate: Boolean? = true): TTransactionMain
 
     @Transactional
-    fun qrcodeSuccess(refno: String, sourcetypeRefno: String, transaction: TTransactionMain, accdateUpdate: Boolean? = true): TTransactionMain
-
-    @Transactional
     fun success(refno: String): TTransactionMain
 
     @Transactional
@@ -50,7 +41,7 @@
      * 退款类业务
      */
     @Transactional
-    fun refundInit(originRefno: String, refundAmount: Double, builder: TransactionBuilder): TTransactionMain
+    fun refundInit(originRefno: String, refundAmount: Double, builder: TransactionBuilder, billno: String?, shopaccno: String?): TTransactionMain
 
     /**
      * 撤销业务
@@ -102,10 +93,6 @@
         return transactionService.wip(refno)
     }
 
-    fun qrcodeWip(billno: String, transaction: TTransactionMain): TTransactionMain {
-        return transactionService.qrcodeWip(billno, transaction)
-    }
-
     fun fail(refno: String): TTransactionMain {
         return transactionService.fail(refno)
     }
@@ -114,10 +101,6 @@
         return transactionService.fail(refno, remark)
     }
 
-    fun qrcodeFail(refno: String, remark: String, transaction: TTransactionMain): TTransactionMain {
-        return transactionService.qrcodeFail(refno, remark, transaction)
-    }
-
     fun success(refno: String, sourcetypeRefno: String, accdateUpdate: Boolean? = true): TTransactionMain {
         return transactionService.success(refno, sourcetypeRefno, accdateUpdate).also {
             if (it.shop) {
@@ -133,24 +116,9 @@
         }
     }
 
-    fun qrcodeSuccess(refno: String, sourcetypeRefno: String, transaction: TTransactionMain, accdateUpdate: Boolean? = true): TTransactionMain {
-        return transactionService.qrcodeSuccess(refno, sourcetypeRefno, transaction, accdateUpdate).also {
-            if (it.shop) {
-                shopAccBalanceAsyncTask.updateShopBalance(TenantContextHolder.getContext().tenant, it.shopDtl)
-            }
-
-            if (it.person && !it.personDtl.userid.isNullOrEmpty()) {
-                kafkaSendMsgService.sendJpushMessage(it.personDtl.userid,
-                        "交易提醒",
-                        "你有一笔${it.personDtl.amount}元的支出,点击查看详情",
-                        it.refno, mutableMapOf(), it.tenantid)
-            }
-        }
-    }
-
 
     fun success(refno: String): TTransactionMain {
-        return success(refno, "")
+        return success(refno, "", null)
     }
 
     fun cancel(originRefno: String, builder: TransactionBuilder, confirm: Boolean): TTransactionMain {
@@ -161,8 +129,8 @@
         return trans
     }
 
-    fun refund(originRefno: String, refundAmount: Double, builder: TransactionBuilder, confirm: Boolean): TTransactionMain {
-        val trans = transactionService.refundInit(originRefno, refundAmount, builder)
+    fun refund(originRefno: String, refundAmount: Double, billno: String?, shopaccno: String?, builder: TransactionBuilder, confirm: Boolean): TTransactionMain {
+        val trans = transactionService.refundInit(originRefno, refundAmount, builder, billno, shopaccno)
         if (confirm) {
             return success(trans.refno)
         }
@@ -185,10 +153,6 @@
         return transactionMainDao.findByRefno(refno)
     }
 
-    fun findTransactionByRefnoForUpdate(refno: String): TTransactionMain {
-        return transactionMainDao.findByRefnoForUpdate(refno)
-    }
-
     fun findByOutTradeNo(refno: String): TTransactionMain? {
         return transactionMainDao.findByOutTradeNo(refno)
     }
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt
index 80682b9..d607f1c 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/transaction_builder.kt
@@ -435,13 +435,13 @@
     fun refund(originRefno: String, amount: Double, transactionService: TransactionServiceProxy): TTransactionMain {
         this.reverseType = TradeDict.REVERSE_FLAG_REFUND
         this.reverseRefno = originRefno
-        return transactionService.refund(originRefno, amount, this, true)
+        return transactionService.refund(originRefno, amount, null, null, this, true)
     }
 
-    fun refundInit(originRefno: String, amount: Double, transactionService: TransactionServiceProxy): TTransactionMain {
+    fun refundInit(originRefno: String, amount: Double, transactionService: TransactionServiceProxy, billno: String?, shopaccno: String?): TTransactionMain {
         this.reverseType = TradeDict.REVERSE_FLAG_REFUND
         this.reverseRefno = originRefno
-        return transactionService.refund(originRefno, amount, this, false)
+        return transactionService.refund(originRefno, amount, billno, shopaccno, this, false)
     }
 
     fun cancel(originRefno: String, transactionService: TransactionServiceProxy): TTransactionMain {
diff --git a/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt b/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt
index 0d4f808..df2336d 100644
--- a/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt
+++ b/payapi/src/test/kotlin/com/supwisdom/dlpay/controller/security_controller_test.kt
@@ -125,7 +125,7 @@
 
     @Test
     fun testHMACSHA256() {
-        val token = "ddCUUHAF/OOBTAZq"
+        val token = "SIc4iIpjMphmZOLg"
         val secret = "dc1d26c0d43e442588092c8d45c21bce"
         val jwt = HmacUtil.HMACSHA256(token, secret)
         println(jwt)