第三方支付接口调试
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java
index c7f18f4..d8e4f13 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java
@@ -49,6 +49,7 @@
   private Boolean anonymous;
 
   /**请求IP*/
+  @Sign
   private String spip;
 
   public String getSpip() {
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayResponse.java
new file mode 100644
index 0000000..226ed29
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayResponse.java
@@ -0,0 +1,17 @@
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class ThirdPayResponse extends ApiResponse {
+  private String refno;
+  private String billno;
+  private Double amount;
+  private String body;
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayfinishParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayfinishParam.java
new file mode 100644
index 0000000..b7c1928
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayfinishParam.java
@@ -0,0 +1,23 @@
+package com.supwisdom.dlpay.api.bean;
+
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+
+@Getter
+@Setter
+public class ThirdPayfinishParam extends APIRequestParam {
+  @Sign
+  @NotNull(message = "交易参考号不能为空")
+  private String refno;
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    return true;
+  }
+}
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayinitParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayinitParam.java
new file mode 100644
index 0000000..fae16dc
--- /dev/null
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayinitParam.java
@@ -0,0 +1,58 @@
+package com.supwisdom.dlpay.api.bean;
+
+import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.Sign;
+import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
+import com.supwisdom.dlpay.api.util.DateUtil;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Getter
+@Setter
+public class ThirdPayinitParam extends APIRequestParam {
+  @Sign
+  private String uid;
+  @Sign
+  @NotEmpty(message = "请指定交易商户")
+  private String shopaccno;
+  @Sign
+  @NotNull(message = "支付金额不能为空")
+  @Min(value = 0, message = "支付金额不能小于 0")
+  private Integer amount;
+  private List<ConsumeFeetype> feelist;
+  @Sign
+  @NotNull(message = "订单号不能为空")
+  private String billno;
+  @Sign
+  @NotNull(message = "交易日期不能为空")
+  private String transdate;
+  @Sign
+  @NotNull(message = "交易时间不能为空")
+  private String transtime;
+  @Sign
+  @NotNull(message = "流水类型不能为空")
+  private String dtltype;
+  @Sign
+  @NotNull(message = "支付方式不能为空")
+  private String sourceType;
+
+
+  @Override
+  public boolean checkParam() throws RequestParamCheckException {
+    if (!DateUtil.checkDatetimeValid(transdate, DateUtil.DATE_FMT)) {
+      throw new RequestParamCheckException("交易日期错误[yyyyMMdd]");
+    }
+    if (!DateUtil.checkDatetimeValid(transtime, DateUtil.TIME_FMT)) {
+      throw new RequestParamCheckException("交易时间错误[HHmmss]");
+    }
+
+    return true;
+  }
+}
+
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
new file mode 100644
index 0000000..54975a5
--- /dev/null
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java
@@ -0,0 +1,20 @@
+package com.supwisdom.dlpay.paysdk.proxy;
+
+import com.supwisdom.dlpay.api.bean.QrcodePayParam;
+import com.supwisdom.dlpay.api.bean.QrcodePayResponse;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@FeignClient(name = "consumePropxy", url = "${payapi.url}")
+@RequestMapping("/api/consume")
+public interface ConsumePropxy {
+
+    @PostMapping("/qrcode/init")
+    QrcodePayResponse qrcodePayInit(@RequestBody QrcodePayParam param);
+
+    @PostMapping("/qrcode/confirm")
+    QrcodePayResponse  qrcodePayConfirm(@RequestBody QrcodePayParam param);
+
+}
diff --git a/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java b/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java
index 0ae4a62..2d09e9d 100644
--- a/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java
+++ b/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java
@@ -2,6 +2,7 @@
 
 
 import com.supwisdom.dlpay.api.bean.*;
+import com.supwisdom.dlpay.api.util.DateUtil;
 import com.supwisdom.dlpay.paysdk.ApiLoginHelper;
 import com.supwisdom.dlpay.paysdk.proxy.*;
 import org.junit.Assert;
@@ -16,6 +17,7 @@
 import org.springframework.cloud.openfeign.FeignAutoConfiguration;
 import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
 import org.springframework.context.annotation.ComponentScan;
+import org.springframework.http.ResponseEntity;
 import org.springframework.test.context.junit4.SpringRunner;
 
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -44,11 +46,13 @@
 
   @Autowired
   private ApiCommonProxy apiCommonProxy;
-
   @Autowired
   private ShopProxy shopProxy;
   @Autowired
   private UserProxy userProxy;
+  @Autowired
+  private ConsumePropxy consumePropxy;
+
 
   @org.junit.Test
   public void citizencardPayinit() {
@@ -75,21 +79,6 @@
   }
   @Test
   public void openShopAccount(){
-    /*
-    *
-    * shopUniqueId = "35315266"
-shoptype = "normal"
-fshopid = null
-shopname = "test1"
-contactman = null
-idtype = null
-idno = null
-mobile = null
-email = null
-address = null
-zipcode = null
-sign = "23AE31C973EA8CC79A82B03C6DF48F9C"
-    * */
 
     ApiLoginHelper helper = new ApiLoginHelper(apiLoginProxy);
     helper.login(appid, secret);
@@ -130,6 +119,58 @@
             response.getRetcode(), equalTo(0));
   }
 
+  @Test
+  public void qrcodeInit(){
+    ApiLoginHelper helper = new ApiLoginHelper(apiLoginProxy);
+    helper.login(appid, secret);
+    ApiVersionResponse version = apiCommonProxy.apiVersion();
+
+    assertThat("get version error " + version.getException(),
+            version.getVersion(), notNullValue());
+
+    QrcodePayParam param = new QrcodePayParam();
+    param.setAmount(1);
+    param.setAnonymous(true);
+    param.setBillno(DateUtil.getNow());
+    param.setQrcodeFormat("origin");
+    param.setTransdate(DateUtil.getNow("yyyyMMdd"));
+    param.setTranstime(DateUtil.getNow("HHmmss"));
+    param.setTenantid("default");
+    param.setShopaccno("2000000012");
+    param.setQrcode("286972142340737770");
+    QrcodePayResponse response = consumePropxy.qrcodePayInit(param);
+    assertThat("qrcodeInit " + response.getRetmsg() + response.getException(),
+            response.getRetcode(), equalTo(0));
+  }
+
+  @Test
+  public void qrcodePay(){
+    ApiLoginHelper helper = new ApiLoginHelper(apiLoginProxy);
+    helper.login(appid, secret);
+    ApiVersionResponse version = apiCommonProxy.apiVersion();
+
+    assertThat("get version error " + version.getException(),
+            version.getVersion(), notNullValue());
+
+    QrcodePayParam param = new QrcodePayParam();
+    param.setAmount(1);
+    param.setAnonymous(true);
+    param.setBillno(DateUtil.getNow());
+    param.setQrcodeFormat("origin");
+    param.setTransdate(DateUtil.getNow("yyyyMMdd"));
+    param.setTranstime(DateUtil.getNow("HHmmss"));
+    param.setTenantid("default");
+    param.setShopaccno("2000000012");
+    param.setQrcode("286972142340737770");
+    QrcodePayResponse response = consumePropxy.qrcodePayInit(param);
+    assertThat("qrcodeInit " + response.getRetmsg() + response.getException(),
+            response.getRetcode(), equalTo(0));
+
+    response = consumePropxy.qrcodePayConfirm(param);
+    assertThat("qrcodeConfirm " + response.getRetmsg() + response.getException(),
+            response.getRetcode(), equalTo(0));
+  }
+
   public static void main(String[] args) {
 
   }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
index 80f65a3..d07cba5 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
@@ -8,10 +8,18 @@
     private AgentCode code;
     private String agentCode;
     private String agentMsg;
-
+    private String agentBody;
     private String agentRefno;
     private DtlStatus dtlStatus;
 
+    public String getAgentBody() {
+        return agentBody;
+    }
+
+    public void setAgentBody(String agentBody) {
+        this.agentBody = agentBody;
+    }
+
     public AgentCode getCode() {
         return code;
     }
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java
index 2f75c01..1a54012 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java
@@ -13,7 +13,7 @@
   QrcodePayTrans findByRefnoAndTenantid(String refno, String tenantid);
 
   @Lock(LockModeType.OPTIMISTIC)
-  QrcodePayTrans findByAgentMerchIdAndHostdateAndBillnoAndTenantid(String mechid, String host,
+  QrcodePayTrans findByAgentMerchIdAndHostdateAndBillnoAndTenantid(String agentMerchId, String hostdate,
                                                                    String billno, String tenantid);
 
   void deleteByRefnoAndTenantid(String refno, String tenantid);
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePattern.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePattern.java
index c74bbd3..f5e4e73 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePattern.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/QrcodePattern.java
@@ -2,10 +2,14 @@
 
 import javax.persistence.*;
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
 
 @Table(name = "tb_qrcode_pattern")
 @Entity
-public class QrcodePattern {
+public class QrcodePattern implements Serializable {
+
+  private static final long serialVersionUID = 1731574413627262946L;
+
   @SequenceGenerator(name = "qrcode_pattern_id", sequenceName = "SEQ_QRCODE_PATTERN", allocationSize = 1, initialValue = 10)
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "qrcode_pattern_id")
   @Id
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 fb42041..ec57610 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
@@ -2,6 +2,7 @@
 
 import javax.persistence.*;
 import javax.validation.constraints.NotNull;
+import java.io.Serializable;
 import java.sql.Timestamp;
 
 @Entity
@@ -9,7 +10,9 @@
     indexes = {@Index(name = "qrcode_pay_trans_idx", columnList = "qrcode, sourcetype"),
         @Index(name = "qrcode_pay_trans_idx2", columnList = "agent_merch_id, billno, tenantid", unique = true),
         @Index(name = "qrcode_pay_trans_idx3", columnList = "agent_merch_id, billno")})
-public class QrcodePayTrans {
+public class QrcodePayTrans implements Serializable {
+  private static final long serialVersionUID = 5203902461916249307L;
+
   @Id
   @SequenceGenerator(name = "qrcode_pay_trans_id", sequenceName = "SEQ_QRCODE_PAY_TRANS", allocationSize = 1, initialValue = 1)
   @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "qrcode_pay_trans_id")
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/service/AgentServiceProxy.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/service/AgentServiceProxy.java
index 7de65cd..80cb888 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/service/AgentServiceProxy.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/service/AgentServiceProxy.java
@@ -5,8 +5,11 @@
 import com.supwisdom.dlpay.agent.domain.QrcodePayTrans;
 import com.supwisdom.dlpay.framework.service.SystemUtilService;
 import com.supwisdom.dlpay.framework.tenant.TenantContext;
+import com.supwisdom.dlpay.framework.util.StringUtil;
 import org.jetbrains.annotations.NotNull;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.ArrayList;
 import java.util.HashSet;
@@ -28,17 +31,19 @@
     this.systemUtilService = systemUtilService;
   }
 
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
   public QrcodePayTrans qrcodePayTransFindByRefno(String refno) {
     return qrcodeTransDao.findByRefnoAndTenantid(refno, TenantContext.getTenantSchema());
   }
 
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
   public QrcodePayTrans qrcodePayTransFindByMerchIdAndBillno(String merchid, String billno) {
     return qrcodeTransDao.findByAgentMerchIdAndHostdateAndBillnoAndTenantid(merchid,
         systemUtilService.getSysdatetime().getHostdate(), billno, TenantContext.getTenantSchema());
   }
 
   public QrcodePayTrans qrcodePayTransSaveOrUpdate(@NotNull QrcodePayTrans bean) {
-    if (bean.getTenantid().isEmpty()) {
+    if (StringUtil.isEmpty(bean.getTenantid())) {
       bean.setTenantid(TenantContext.getTenantSchema());
     }
     return qrcodeTransDao.save(bean);
@@ -48,6 +53,7 @@
     return qrcodeMatch(code);
   }
 
+  @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, readOnly = true)
   public QrcodePattern qrcodeMatch(String code) {
     List<QrcodePattern> pattern = qrcodePatternService.getAllQrcodePattern();
     List<QrcodePattern> found = new ArrayList<>();
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
index 6c554a8..d55d345 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java
@@ -9,7 +9,9 @@
   public static final int TRANSCODE_YKTCARD_PAY = 3020; //一卡通支付
 
 
-  public static final int TRANSCODE_WECHAT = 1001;
+  public static final int TRANSCODE_WECHAT = 3030;//微信支付
+
+  public static final int TRANSCODE_ALIPAY = 3040;//支付宝支付
 
   // QRcode 聚合支付
   public static final int TRANSCODE_QRCODE = 1002;
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 55108af..045e54c 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
@@ -14,13 +14,13 @@
      */
     public static final String CFG_ALIPAY_APPID = "alipay.appid";
 
-    public static final String CFG_ALIPAY_PRIVATEKEY = "alipay.privatekey";
+    public static final String CFG_ALIPAY_PRIVATEKEY = "alipay.rsa.private.key";
 
-    public static final String CFG_ALIPAY_PUBLICKEY = "alipay.publickey";
+    public static final String CFG_ALIPAY_PUBLICKEY = "alipay.public.key";
 
     public static final String CFG_ALIPAY_PAYURL = "alipay.payurl";
 
-    public static final String CFG_ALIPAY_NOTIFY = "alipay.notify";
+    public static final String CFG_ALIPAY_NOTIFY = "notify.url";
 
     public static final String CFG_ALIPAY_RETURNURL = "alipay.returnurl";
 
@@ -35,6 +35,11 @@
 
     public static final String CFG_WECHAT_NOTIFY = "wechat.notify";
 
+    public static final String CFG_WECHAT_REFUNDCERT = "wechat.refund.certpath";
+
+    public static final String CFG_WECHAT_REFUNDCERT_PWD = "wechat.refund.certpwd";
+
+
     public static final String CFG_WECHAT_OAUTHCODE = "https://api.mch.weixin.qq.com/tools/authcodetoopenid";
 
     public static final String CFG_WECHAT_QRCODEPAY = "https://api.mch.weixin.qq.com/pay/micropay";
@@ -43,4 +48,6 @@
 
     public static final String CFG_WECHAT_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
 
+    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/alipay_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt
index 3f8cde2..0174c65 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt
@@ -3,6 +3,7 @@
 import com.supwisdom.dlpay.agent.AgentCode
 import com.supwisdom.dlpay.agent.AgentPayService
 import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.api.bean.BaseResp
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.service.ConsumePayService
 import com.supwisdom.dlpay.framework.util.TradeCode
@@ -19,6 +20,11 @@
     fun doQuery(transaction: TTransactionMain): AgentResponse
 
     fun doNotify(param: Map<String, String>): AgentResponse
+
+    /**
+     * 下载对账单
+     * */
+    fun downloadBill(shopacc:String,accdate:String): BaseResp
 }
 
 @Component("alipayAgent")
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt
index 53afcd7..cc19440 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt
@@ -22,6 +22,7 @@
 import com.supwisdom.dlpay.agent.DtlStatus
 import com.alipay.api.domain.AlipayTradeQueryModel
 import com.alipay.api.domain.AlipayTradeRefundModel
+import com.supwisdom.dlpay.api.bean.BaseResp
 
 
 @Service
@@ -134,7 +135,7 @@
                     agentResponse.code = AgentCode.REQUIRE_QUERY
                     agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
                     //body 为APP
-                    agentResponse.agentMsg = response.body
+                    agentResponse.agentBody = response.body
                 } else {
                     agentResponse.code = AgentCode.FAIL
                     agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
@@ -243,7 +244,12 @@
         return when (flag) {
             true -> {
                 //total amt 校验 map["total_amount"]
-                transactionService.success(refno)
+                var tradeno = param["trade_no"]
+                if(tradeno.isNullOrEmpty()){
+                    transactionService.success(transaction.refno)
+                }else{
+                    transactionService.success(transaction.refno,tradeno, true)
+                }
                 agentResponse.code = AgentCode.SUCCESS
                 agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
                 agentResponse
@@ -257,4 +263,8 @@
             }
         }
     }
+
+    override fun downloadBill(shopacc: String, accdate: String): BaseResp {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
 }
\ No newline at end of file
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 e3beb79..94cd031 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
@@ -5,6 +5,7 @@
 import com.supwisdom.dlpay.agent.DtlStatus
 import com.supwisdom.dlpay.agent.service.AgentServiceProxy
 import com.supwisdom.dlpay.agent.service.WechatService
+import com.supwisdom.dlpay.api.bean.BaseResp
 import com.supwisdom.dlpay.api.bean.WechatReqResp
 import com.supwisdom.dlpay.api.dao.PersonIdentityDao
 import com.supwisdom.dlpay.api.domain.TTransactionMain
@@ -129,7 +130,6 @@
 
     override fun doPrepay(transaction: TTransactionMain): AgentResponse {
         var agentResponse = AgentResponse()
-
         val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false)
         if (checkCfg(config, agentResponse)) {
             //H5 支付
@@ -157,7 +157,7 @@
                     && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode && !mweb_url.isNullOrEmpty()) {
                 agentResponse.code = AgentCode.REQUIRE_QUERY
                 agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
-                agentResponse.agentMsg = mweb_url
+                agentResponse.agentBody = mweb_url
                 agentResponse.agentRefno = eleMap["prepay_id"]
             } else {
                 logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
@@ -208,7 +208,38 @@
     }
 
     override fun doRefund(transaction: TTransactionMain): AgentResponse {
-        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+        var agentResponse = AgentResponse()
+        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.notify_url = config[PaytypeUtil.CFG_WECHAT_NOTIFY]
+            }
+            bean.generaReverseSign()
+            val xml = bean.generaReverseXML()
+            var res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_REFUND, xml, String::class.java)
+            var eleMap = XmlUtils.parseXml(res.body)
+            var retcode = eleMap["return_code"]
+            var resultCode = eleMap["result_code"]
+            if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
+                    && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode ) {
+                agentResponse.code = AgentCode.REQUIRE_QUERY
+                agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+                agentResponse.agentRefno = eleMap["refund_id"]
+            } else {
+                logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
+                agentResponse.code = AgentCode.FAIL
+                agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+                agentResponse.agentMsg = "退款申请失败失败:${eleMap["err_code_des"]}"
+            }
+        }
+        return agentResponse
     }
 
     override fun doNotify(param: Map<String, String>): AgentResponse {
@@ -249,7 +280,12 @@
         val resultCode = param["result_code"]
         if (!returnCode.isNullOrEmpty() && "SUCCESS" == returnCode
                 && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
-            transactionService.success(transaction.refno)
+            val transid = param["transaction_id"]
+            if(transid.isNullOrEmpty()){
+                transactionService.success(transaction.refno)
+            }else{
+                transactionService.success(transaction.refno,transid, true)
+            }
             agentResponse.code = AgentCode.SUCCESS
             agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
         } else {
@@ -260,4 +296,8 @@
         }
         return agentResponse
     }
+
+    override fun downloadBill(shopacc:String,accdate:String): BaseResp {
+        TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt
index 380221c..8de5cfe 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt
@@ -3,6 +3,7 @@
 import com.supwisdom.dlpay.agent.AgentCode
 import com.supwisdom.dlpay.agent.AgentPayService
 import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.api.bean.BaseResp
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.service.ConsumePayService
 import com.supwisdom.dlpay.framework.util.TradeCode
@@ -21,6 +22,11 @@
     fun doRefund(transaction: TTransactionMain): AgentResponse
 
     fun doNotify(param: Map<String, String>): AgentResponse
+
+    /**
+     * 下载对账单
+     * */
+    fun downloadBill(shopacc:String,accdate:String):BaseResp
 }
 
 @Component("wechatpayAgent")
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
index 874a539..4e3c906 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt
@@ -6,6 +6,7 @@
 import com.supwisdom.dlpay.exception.TransactionException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.CommonService
+import com.supwisdom.dlpay.framework.tenant.TenantContext
 import com.supwisdom.dlpay.framework.util.TradeErrorCode
 import mu.KotlinLogging
 import org.aspectj.lang.ProceedingJoinPoint
@@ -117,6 +118,7 @@
     fun logPostMethods(joinPoint: ProceedingJoinPoint, body: Any): Any {
         return try {
             if (body is APIRequestParam) {
+                TenantContext.setTenantSchema(body.tenantid)
                 body.checkParam()
 
                 if (requestSignCheck &&
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 3751c40..e47701b 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
@@ -13,6 +13,7 @@
 import com.supwisdom.dlpay.exception.TransactionCheckException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.tenant.TenantContext
 import com.supwisdom.dlpay.framework.util.*
 import org.apache.commons.lang3.StringUtils
 import org.springframework.beans.factory.annotation.Autowired
@@ -56,6 +57,7 @@
      * */
     @PostMapping("/queryresult")
     fun queryDtlResult(@Valid @RequestBody param: QueryDtlResultParam): ResponseEntity<Any> {
+        //TODO 第三方支付,根据支付结果主动触发一次查询
         consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let {
             return ResponseEntity.ok(ResponseBodyBuilder.create()
                     .success(QueryTransDtlResponse(it.refno, it.outTradeNo, it.shopDtl.amount,
@@ -463,12 +465,18 @@
                     .fail(apiResp, TradeErrorCode.BUSINESS_DEAL_ERROR,
                             "支付方式<${qrcode.sourceType}>未配置科目号"))
         }
+        var systime = systemUtilService.sysdatetime
         // 2. 记录 qrcode 交易明细表
         val qrcodeTrans = agentServiceProxy.qrcodePayTransSaveOrUpdate(
                 QrcodePayTrans().apply {
                     this.agentMerchId = param.shopaccno
                     this.billno = param.billno
                     this.qrcode = param.qrcode
+                    this.createTime = systime.sysdate
+                    this.hostdate = systime.hostdate
+                    this.sourceType = sourceType.sourceType
+                    this.isAnonymous = param.anonymous
+                    this.updateTime = systime.sysdate
                 })
 
         // 3. 查询用户身份
@@ -517,7 +525,7 @@
 
     private fun qrcodeSummary(st: TSourceType): String = st.paydesc + "扫码付"
 
-    @PostMapping("/qrcodepay/confirm")
+    @PostMapping("/qrcode/confirm")
     fun qrcodePayConfirm(@Validated(ConfirmAction::class) @RequestBody param: QrcodePayParam): ResponseEntity<ApiResponse> {
         //1. 交易检查
         val apiResponse = QrcodePayResponse()
@@ -626,4 +634,100 @@
             }
         }
     }
+
+    /**
+     * ============================================================================
+     *                           第三方(支付宝、微信)支付【交易初始化】
+     * ============================================================================
+     * */
+    @PostMapping("/thirdpay/payinit")
+    fun thirdpayInit(@RequestBody param: ThirdPayinitParam): ResponseEntity<Any> {
+        val dtlType = consumePayService.getDtltypeDictionary(param.dtltype, Dictionary.DTLTYPES)
+        val sourceType = sourceTypeService.getBySourceType(param.sourceType)
+                ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(ApiResponse(), TradeErrorCode.BUSINESS_DEAL_ERROR,
+                                "不支持的支付方式<${param.sourceType}>"))
+
+        if (consumePayService.checkShopPaytype(param.shopaccno, sourceType.sourceType)) {
+            val account = accountUtilServcie.readAccount(param.uid)
+            val shopacc = accountUtilServcie.readShopbyShopaccno(param.shopaccno)
+            val subject = accountUtilServcie.readSubject(sourceType.paySubjno)
+            var transcode=0
+            when(sourceType.sourceType){
+                TradeDict.PAYTYPE_ALIPAY ->transcode = TradeCode.TRANSCODE_ALIPAY
+                TradeDict.PAYTYPE_WECHAT ->transcode = TradeCode.TRANSCODE_WECHAT
+            }
+            val transaction = TransactionBuilder().apply {
+                setTransInfo(param.transdate, param.transtime,transcode,
+                        sourceType.sourceType)
+                setOutTransInfo(shopacc.shopaccno, param.billno)
+                operator(param.shopaccno, TradeDict.OPERTYPE_SHOP)
+
+            }.person(account).apply {
+                setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_OUT)
+                setOpposite(AccountProxy(shopacc))
+            }.and().shop(shopacc).apply {
+                setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_IN)
+                setOpposite(AccountProxy(account))
+            }.and().addDebitCreditRecord(AccountProxy(subject), AccountProxy(account),
+                    param.amount / 100.0, dtlType.dictcaption)
+                    .addDebitCreditRecord(AccountProxy(account), AccountProxy(shopacc),
+                            param.amount / 100.0, dtlType.dictcaption)
+                    .also {
+                        param.feelist?.also {
+                            TODO("feelist 费用清单未实现!")
+                        }
+                    }.init(transactionService)
+
+            return ResponseEntity.ok(ResponseBodyBuilder.create()
+                    .success(ThirdPayResponse(transaction.refno,
+                            transaction.outTradeNo,
+                            transaction.shopDtl.amount,null), "交易初始化成功"))
+        }
+
+        return ResponseEntity.ok(ResponseBodyBuilder.create()
+                .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<第三方支付>"))
+    }
+
+
+    /**
+     * ============================================================================
+     *                            第三方(支付宝、微信)支付【交易确认】
+     * ============================================================================
+     * */
+    @PostMapping("/thirdpay/payfinish")
+    fun thirdpayFinish(@RequestBody param: ThirdPayfinishParam): ResponseEntity<Any> {
+        val dtl = transactionService.wip(param.refno)
+        var type=""
+        if(dtl.transCode== TradeCode.TRANSCODE_ALIPAY){
+            type = TradeDict.PAYTYPE_ALIPAY
+        }else if(dtl.transCode== TradeCode.TRANSCODE_WECHAT){
+            type = TradeDict.PAYTYPE_WECHAT
+        }
+        val service = createAgentService(type)
+        val resp = service.pay(dtl)
+        when (resp.code) {
+            AgentCode.SUCCESS ->
+                transactionService.success(dtl.refno, resp.agentRefno, false).let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .success(ThirdPayResponse(it.refno,
+                                    it.outTradeNo,
+                                    it.shopDtl.amount,resp.agentBody), "交易确认成功"))
+
+                }
+            AgentCode.REQUIRE_QUERY -> {
+                //去查询
+                return ResponseEntity.ok(ResponseBodyBuilder.create()
+                        .fail(ThirdPayResponse(dtl.refno,
+                                dtl.outTradeNo,
+                                dtl.shopDtl.amount,resp.agentBody), TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果"))
+            }
+            else -> //失败
+                transactionService.fail(param.refno, resp.agentMsg).let {
+                    return ResponseEntity.ok(ResponseBodyBuilder.create()
+                            .fail(ThirdPayResponse(dtl.refno, dtl.outTradeNo, dtl.shopDtl.amount,resp.agentBody),
+                                    TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.agentMsg}"))
+                }
+        }
+    }
 }
\ No newline at end of file
diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql
index ac1da71..7c5abc8 100644
--- a/payapi/src/main/resources/data.sql
+++ b/payapi/src/main/resources/data.sql
@@ -481,7 +481,7 @@
 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
 VALUES ('11', 'alipay', 'alipay.rsa.public.key', '支付宝商户应用RSA公钥', NULL, 'f', '{tenantid}');
 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
-VALUES ('12', 'alipay', 'appid', '支付宝应用APPID', NULL, 'f', '{tenantid}');
+VALUES ('12', 'alipay', 'alipay.appid', '支付宝应用APPID', NULL, 'f', '{tenantid}');
 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
 VALUES ('13', 'citizenCard', 'ynrcc.agent.url', '农商行前置地址前缀', NULL, 't', '{tenantid}');
 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
@@ -490,6 +490,18 @@
 VALUES ('16', 'citizenCard', 'merchant.bankcardno', '商户银行卡号', NULL, 'f', '{tenantid}');
 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
 VALUES ('17', 'citizenCard', 'merchant.bankaccname', '银行开户名', NULL, 'f', '{tenantid}');
+INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
+VALUES ('18', 'wechat', 'wechat.appid', '微信APPID', null, 'f', '{tenantid}');
+INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
+VALUES ('19', 'wechat', 'wechat.mechid', '微信商户号', NULL, 'f', '{tenantid}');
+INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
+VALUES ('20', 'wechat', 'wechat.mechkey', '微信商户支付秘钥', NULL, 'f', '{tenantid}');
+INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
+VALUES ('21', 'wechat', 'wechat.notify', '微信支付结果通知地址', NULL, 't', '{tenantid}');
+INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
+VALUES ('22', 'wechat', 'wechat.refund.certpath', '微信退款证书路径', NULL, 'f', '{tenantid}');
+INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid")
+VALUES ('23', 'wechat', 'wechat.refund.certpwd', '微信退款证书密码', NULL, 'f', '{tenantid}');
 
 INSERT INTO "tb_syspara" ("paraid", "displayflag", "editflag", "lastsaved", "paraname", "paraunit", "paraval", "remark", "valuetype", "tenantid")
 VALUES (1, 'yes', 1, '20190514165658', '账户最大余额默认值', '元', '10001', '账户开户时的默认账户最大余额', 'amount', '{tenantid}');