第三方支付接口调试
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}');