完成二维码消费接口
diff --git a/config/application-devel-pg.properties b/config/application-devel-pg.properties
index 538f23a..973c02d 100644
--- a/config/application-devel-pg.properties
+++ b/config/application-devel-pg.properties
@@ -6,7 +6,7 @@
 # Postgresql settings
 spring.datasource.platform=postgresql
 #spring.datasource.url=jdbc:postgresql://ykt.supwisdom.com:15432/payapidev
-spring.datasource.url=jdbc:postgresql://172.28.201.70:15432/payapidev
+spring.datasource.url=jdbc:postgresql://172.28.201.70:15432/touchorder
 spring.datasource.username=payapi
 spring.datasource.password=123456
 spring.datasource.continue-on-error=true
@@ -55,4 +55,5 @@
 spring.kafka.consumer.auto-commit-interval=100
 # 指定消息key和消息体的编解码方式
 spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
-spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
\ No newline at end of file
+spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
+payapi.url=localhost:8080/payapi
\ No newline at end of file
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmRequest.java b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmRequest.java
index e9db9f1..e7064c7 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmRequest.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/payapi/model/QrcodePayConfirmRequest.java
@@ -28,8 +28,8 @@
   @JsonProperty("transTime")
   private String transTime;
 
-  @JsonProperty("dlttype")
-  private String dlttype;
+  @JsonProperty("dtltype")
+  private String dtltype;
 
   @JsonProperty("amount")
   private Integer amount;
@@ -126,24 +126,24 @@
     this.transTime = transTime;
   }
 
-  public QrcodePayConfirmRequest dlttype(String dlttype) {
-    this.dlttype = dlttype;
+  public QrcodePayConfirmRequest dtltype(String dtltype) {
+    this.dtltype = dtltype;
     return this;
   }
 
   /**
-   * Get dlttype
-   * @return dlttype
+   * Get dtltype
+   * @return dtltype
   */
   @ApiModelProperty(value = "")
 
 
-  public String getDlttype() {
-    return dlttype;
+  public String getDtltype() {
+    return dtltype;
   }
 
-  public void setDlttype(String dlttype) {
-    this.dlttype = dlttype;
+  public void setDtltype(String dtltype) {
+    this.dtltype = dtltype;
   }
 
   public QrcodePayConfirmRequest amount(Integer amount) {
@@ -261,7 +261,7 @@
         Objects.equals(this.shopaccno, qrcodePayConfirmRequest.shopaccno) &&
         Objects.equals(this.transDate, qrcodePayConfirmRequest.transDate) &&
         Objects.equals(this.transTime, qrcodePayConfirmRequest.transTime) &&
-        Objects.equals(this.dlttype, qrcodePayConfirmRequest.dlttype) &&
+        Objects.equals(this.dtltype, qrcodePayConfirmRequest.dtltype) &&
         Objects.equals(this.amount, qrcodePayConfirmRequest.amount) &&
         Objects.equals(this.userid, qrcodePayConfirmRequest.userid) &&
         Objects.equals(this.anonymous, qrcodePayConfirmRequest.anonymous) &&
@@ -271,7 +271,7 @@
 
   @Override
   public int hashCode() {
-    return Objects.hash(billno, shopaccno, transDate, transTime, dlttype, amount, userid, anonymous, qrcode, qrcodeFormat);
+    return Objects.hash(billno, shopaccno, transDate, transTime, dtltype, amount, userid, anonymous, qrcode, qrcodeFormat);
   }
 
   @Override
@@ -283,7 +283,7 @@
     sb.append("    shopaccno: ").append(toIndentedString(shopaccno)).append("\n");
     sb.append("    transDate: ").append(toIndentedString(transDate)).append("\n");
     sb.append("    transTime: ").append(toIndentedString(transTime)).append("\n");
-    sb.append("    dlttype: ").append(toIndentedString(dlttype)).append("\n");
+    sb.append("    dtltype: ").append(toIndentedString(dtltype)).append("\n");
     sb.append("    amount: ").append(toIndentedString(amount)).append("\n");
     sb.append("    userid: ").append(toIndentedString(userid)).append("\n");
     sb.append("    anonymous: ").append(toIndentedString(anonymous)).append("\n");
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPIRequestInterceptor.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPIRequestInterceptor.java
index 604d9ff..7b43372 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPIRequestInterceptor.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPIRequestInterceptor.java
@@ -7,11 +7,12 @@
 import feign.RequestInterceptor;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
 import org.springframework.stereotype.Component;
 
 import java.util.Optional;
 
-@Component
+@Configuration
 public class PayAPIRequestInterceptor {
 
   private final JwtTokenClientManager manager;
diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPISDKConfigure.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPISDKConfigure.java
index 065ba9c..fed5022 100644
--- a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPISDKConfigure.java
+++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/PayAPISDKConfigure.java
@@ -8,11 +8,13 @@
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.DependsOn;
+import org.springframework.context.annotation.Import;
 import org.springframework.stereotype.Component;
 
 @Configuration
 @EnableTenantJwtClient
 @EnableFeignClients(basePackages = "com.supwisdom.dlpay.paysdk")
+@Import({PayAPIRequestInterceptor.class})
 public class PayAPISDKConfigure {
   @Bean
   public JwtTokenClientCallback jwtTokenClientCallback(ApiLoginProxy loginProxy) {
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 dc287f3..fabcbbf 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,24 +1,20 @@
 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.mutlitenant.client.annotations.JwtMethod;
 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;
+import org.springframework.web.bind.annotation.*;
+
+import javax.validation.Valid;
 
 @FeignClient(name = "consumePropxy", url = "${payapi.url}")
 @RequestMapping("/api/consume")
 public interface ConsumePropxy {
 
-    @PostMapping("/qrcode/init")
-    @JwtMethod
-    QrcodePayResponse qrcodePayInit(@RequestBody QrcodePayParam param);
-
-    @PostMapping("/qrcode/confirm")
-    @JwtMethod
-    QrcodePayResponse  qrcodePayConfirm(@RequestBody QrcodePayParam param);
-
     @PostMapping("/thirdpay/init")
     @JwtMethod
     ThirdPayResponse thirdpayInit(@RequestBody ThirdPayinitParam param);
@@ -30,4 +26,20 @@
     @PostMapping("/qrcodequery")
     @JwtMethod
     DoorQrcodeResponse qrcodequery(@RequestBody DoorQRCodeParam param);
+
+
+    @RequestMapping(value = "/qrcode/init", method = RequestMethod.POST)
+    @JwtMethod
+    QrcodePayInitResponse qrcodePayInit(@RequestHeader(name = "X-TENANT-ID") String xTenantId,
+                                        @Valid @RequestBody QrcodePayInitRequest qrcodePayInitRequest);
+
+    @RequestMapping(value = "/qrcode/confirm", method = RequestMethod.POST)
+    @JwtMethod
+    QrcodePayConfirmResponse qrcodePayConfirm(@RequestHeader(name = "X-TENANT-ID") String xTenantId,
+                                              @Valid @RequestBody QrcodePayConfirmRequest qrcodePayConfirmRequest);
+
+    @RequestMapping(value = "/qrcode/query/{refno}", method = RequestMethod.GET)
+    @JwtMethod
+    QrcodePayConfirmResponse qrcodePayQuery(@RequestHeader(name = "X-TENANT-ID") String xTenantId,
+                                            @PathVariable("refno") String refno);
 }
diff --git a/payapi-spec/consumeapi.yaml b/payapi-spec/consumeapi.yaml
index 80df543..1df2d8c 100644
--- a/payapi-spec/consumeapi.yaml
+++ b/payapi-spec/consumeapi.yaml
@@ -52,7 +52,7 @@
           $ref: 'definitions.yaml#/components/schemas/TransDate'
         transTime:
           $ref: 'definitions.yaml#/components/schemas/TransTime'
-        dlttype:
+        dtltype:
           type: string
           title: 交易类型
         amount:
diff --git a/payapi-spec/definitions.yaml b/payapi-spec/definitions.yaml
index d45a0d7..4ca2848 100644
--- a/payapi-spec/definitions.yaml
+++ b/payapi-spec/definitions.yaml
@@ -1,7 +1,7 @@
 components:
   headers:
     TenantId:
-      name: X-Tenant-Id
+      name: X-TENANT-ID
       in: header
       description: 租户ID
       required: true
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 1a54012..191eb57 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
@@ -2,10 +2,14 @@
 
 import com.supwisdom.dlpay.agent.domain.QrcodePayTrans;
 import org.springframework.data.jpa.repository.Lock;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.jpa.repository.QueryHints;
 import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
 import org.springframework.stereotype.Repository;
 
 import javax.persistence.LockModeType;
+import javax.persistence.QueryHint;
 
 
 @Repository
@@ -16,5 +20,11 @@
   QrcodePayTrans findByAgentMerchIdAndHostdateAndBillnoAndTenantid(String agentMerchId, String hostdate,
                                                                    String billno, String tenantid);
 
+  @Lock(LockModeType.PESSIMISTIC_WRITE)
+  @Query("select t from QrcodePayTrans t where t.agentMerchId=:agentMerchId and t.hostdate=:hostdate and t.billno=:billno and t.tenantid=:tenantid")
+  @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "0")})
+  QrcodePayTrans findByQrcodePayTransForUpdate(@Param("agentMerchId") String agentMerchId,@Param("hostdate") String hostdate,
+                                               @Param("billno")String billno,@Param("tenantid") String tenantid);
+
   void deleteByRefnoAndTenantid(String refno, String tenantid);
 }
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 ec57610..4619435 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
@@ -68,7 +68,7 @@
   @Column(name = "tenantid", length = 20)
   private String tenantid;
 
-  @Column(name = "spid", length = 20)
+  @Column(name = "spip", length = 20)
   private String spip;
 
   public QrcodePayTrans() {
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 e33c0db..8eaf790 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
@@ -42,6 +42,11 @@
         systemUtilService.getSysdatetime().getHostdate(), billno, TenantContextHolder.getContext().getTenant().getId());
   }
 
+  public QrcodePayTrans findByQrcodePayTransForUpdate(String merchid, String billno) {
+    return qrcodeTransDao.findByQrcodePayTransForUpdate(merchid,
+        systemUtilService.getSysdatetime().getHostdate(), billno, TenantContextHolder.getContext().getTenant().getId());
+  }
+
   public QrcodePayTrans qrcodePayTransSaveOrUpdate(@NotNull QrcodePayTrans bean) {
     if (StringUtil.isEmpty(bean.getTenantid())) {
       bean.setTenantid(TenantContextHolder.getContext().getTenant().getId());
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 7c59309..4625ca9 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/ConsumeApi.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/ConsumeApi.java
@@ -74,7 +74,7 @@
         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 xTenantId,@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"))) {
@@ -96,7 +96,7 @@
     @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 xTenantId,@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"))) {
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 7d86677..7bf36cd 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
@@ -3,21 +3,24 @@
 import com.supwisdom.dlpay.agent.AgentCode
 import com.supwisdom.dlpay.agent.AgentPayService
 import com.supwisdom.dlpay.agent.AgentPayServiceContext
-import com.supwisdom.dlpay.agent.domain.QrcodePattern
 import com.supwisdom.dlpay.agent.domain.QrcodePayTrans
 import com.supwisdom.dlpay.agent.service.AgentServiceProxy
 import com.supwisdom.dlpay.api.ConsumeApi
-import com.supwisdom.dlpay.api.service.*
+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.TransactionCheckException
 import com.supwisdom.dlpay.framework.ResponseBodyBuilder
 import com.supwisdom.dlpay.framework.service.SystemUtilService
 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.QrcodePayInitRequest
-import com.supwisdom.dlpay.payapi.model.QrcodePayInitResponse
-import com.supwisdom.multitenant.TenantContextHolder
+import com.supwisdom.dlpay.payapi.model.*
 import org.apache.commons.lang3.StringUtils
+import org.springframework.dao.PessimisticLockingFailureException
 import org.springframework.http.ResponseEntity
 import org.springframework.web.bind.annotation.RequestMapping
 import org.springframework.web.bind.annotation.RestController
@@ -35,83 +38,90 @@
             private val agentPayServiceContext: AgentPayServiceContext,
             private val userService: UserService,
             private val consumePayService: ConsumePayService,
-            private val transactionService: TransactionServiceProxy,
-            private val accountUtilServcie: AccountUtilServcie) : ConsumeApi {
+            private val transactionService: TransactionServiceProxy) : ConsumeApi {
 
     override fun getRequest(): Optional<NativeWebRequest> {
         return Optional.ofNullable(request)
     }
 
     override fun qrcodePayInit(xTenantId: String, @Valid param: QrcodePayInitRequest): ResponseEntity<QrcodePayInitResponse> {
-        val apiResp = QrcodePayInitResponse()
-        // 1. 检查 qrcode
-        val qrcode: QrcodePattern
         try {
-            qrcode = agentServiceProxy.qrcodeMatch(param.qrcode)
+            val apiResp = QrcodePayInitResponse()
+            // 1. 检查 qrcode
+            val qrcode = agentServiceProxy.qrcodeMatch(param.qrcode)
                     ?: throw BadRequestError("未识别的支付码")
-        } catch (e: Exception) {
-            throw BadRequestError(e.message!!)
-        }
-        val sourceType = sourceTypeService.getBySourceType(qrcode.sourceType)
-                ?: throw BadRequestError("不支持的支付方式<${qrcode.sourceType}>")
-        if (sourceType.paySubjno.isEmpty()
-                || !StringUtils.isNumeric(sourceType.paySubjno)) {
-            throw BadRequestError("支付方式<${qrcode.sourceType}>未配置科目号")
-        }
-        val 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.updateTime = systime.sysdate
-                })
-        // 3. 查询用户身份
-        val service = createAgentService<QrcodePayTrans>(qrcode.sourceType)
-        val agentResp = service.auth(param.shopaccno, param.billno)
-        // 4. 重新读取 qrcode 交易明细表,以获取 service.auth 查询后的结果数据
-        // 修改, 通过返回值来判断
+            val sourceType = sourceTypeService.getBySourceType(qrcode.sourceType)
+                    ?: throw BadRequestError("不支持的支付方式<${qrcode.sourceType}>")
+            if (sourceType.paySubjno.isEmpty()
+                    || !StringUtils.isNumeric(sourceType.paySubjno)) {
+                throw BadRequestError("支付方式<${qrcode.sourceType}>未配置科目号")
+            }
+            val 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.updateTime = systime.sysdate
+                        this.isAnonymous = true
+                    })
+            // 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,
 //                qrcodeTrans.billno)
-        apiResp.also {
-            it.sourcetype = sourceType.sourceType
-        }
-        return when (agentResp.code) {
-            AgentCode.SUCCESS -> {
-                val qrcodeTransResp = agentResp.payload
-                if (!sourceType.anonymousEnable && qrcodeTransResp.isAnonymous) {
-                    throw BadRequestError("支付方式<${qrcode.sourceType}> 不支持匿名支付")
-                } else {
-                    // 更新qrcode交易明细表 是否匿名 字段
-                    if (StringUtil.isEmpty(qrcodeTransResp.userid)) {
-                        qrcodeTransResp.isAnonymous = true
+            apiResp.also {
+                it.sourcetype = sourceType.sourceType
+            }
+            return when (agentResp.code) {
+                AgentCode.SUCCESS -> {
+                    val qrcodeTransResp = agentResp.payload
+                    if (!sourceType.anonymousEnable && qrcodeTransResp.isAnonymous) {
+                        throw BadRequestError("支付方式<${qrcode.sourceType}> 不支持匿名支付")
                     } else {
-                        val person = userService.findByUseridOrThirdUniqueIdenty(qrcodeTransResp.userid, null)
-                        if (person == null) {
+                        // 更新qrcode交易明细表 是否匿名 字段
+                        if (StringUtil.isEmpty(qrcodeTransResp.userid)) {
                             qrcodeTransResp.isAnonymous = true
                         } else {
-                            apiResp.apply {
-                                qrcodeTransResp.isAnonymous = false
-                                this.userid = qrcodeTransResp.agentUserId
-                                this.username = person.name
+                            val person = userService.findByUseridOrThirdUniqueIdenty(qrcodeTransResp.userid, null)
+                            if (person == null) {
+                                qrcodeTransResp.isAnonymous = true
+                            } else {
+                                apiResp.apply {
+                                    qrcodeTransResp.isAnonymous = false
+                                    this.userid = qrcodeTransResp.agentUserId
+                                    this.username = person.name
+                                }
                             }
                         }
+                        agentServiceProxy.qrcodePayTransSaveOrUpdate(qrcodeTrans.also {
+                            it.isAnonymous = qrcodeTransResp.isAnonymous
+                        })
+                        ResponseBodyBuilder.ok(apiResp)
                     }
-                    agentServiceProxy.qrcodePayTransSaveOrUpdate(qrcodeTrans.also {
-                        it.isAnonymous = qrcodeTransResp.isAnonymous
-                    })
-                    ResponseBodyBuilder.ok(apiResp)
+                }
+                AgentCode.NOT_SUPPORT -> {
+                    throw BadRequestError("系统或商户暂不支持当前的支付类型}")
+                }
+                else -> {
+                    throw BadRequestError("第三方身份错误,<${agentResp.agentMsg}")
                 }
             }
-            AgentCode.NOT_SUPPORT -> {
-                throw BadRequestError("系统或商户暂不支持当前的支付类型}")
-            }
-            else -> {
-                throw BadRequestError("第三方身份错误,<${agentResp.agentMsg}")
+        } catch (e: Exception) {
+            when (e) {
+                is BadRequestError -> throw BadRequestError(e.message)
+                is PessimisticLockingFailureException -> throw ConflictError(e.message)
+                else -> {
+                    e.printStackTrace()
+                    println("二维码消费初始化异常:<${e.message}>")
+                    throw InternalError(e.message)
+                }
             }
         }
     }
@@ -122,118 +132,97 @@
                         "支付类型<$sourceType>未定义")
     }
 
-//    override fun qrcodePayConfirm(xTenantId: String, @Valid param: QrcodePayConfirmRequest): ResponseEntity<Void> {
-//        //1. 交易检查
-//        val apiResponse = QrcodePayResponse()
-//        val qrcodeTrans = agentServiceProxy.qrcodePayTransFindByMerchIdAndBillno(param.shopaccno,
-//                param.billno) ?: return ResponseBodyBuilder.notFound(
-//                "未找到billno") as ResponseEntity<Void>
-//        if (!qrcodeTrans.refno.isNullOrEmpty()) {
-//            return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                    .fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR, "该交易已确认,请查询结果"))
-//        }
-//
-//        if (qrcodeTrans.qrcode != param.qrcode && param.qrcode.isNotEmpty()) {
-//            val qrcode = agentServiceProxy.qrcodeMatch(param.qrcode)
-//                    ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                            .fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR, "未识别的支付码"))
-//            if (qrcodeTrans.sourceType != qrcode.sourceType) {
-//                return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                        .fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR, "支付码不符"))
-//            }
-//            qrcodeTrans.qrcode = param.qrcode
-//        }
-//
-//        val sourceType = sourceTypeService.getBySourceType(qrcodeTrans.sourceType)
-//                ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                        .fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR,
-//                                "不支持的支付方式<${qrcodeTrans.sourceType}>"))
-//        if (!sourceType.anonymousEnable && qrcodeTrans.isAnonymous) {
-//            return ResponseEntity.ok(ResponseBodyBuilder.create()
-//                    .fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR,
-//                            "支付方式<${qrcodeTrans.sourceType}>不支持匿名支付"))
-//        }
-//        qrcodeTrans.spip = param.spip
-//        val dtlType = consumePayService.getDtltypeDictionary(param.dtltype, Dictionary.DTLTYPES)
-//        //2. 初始化交易流水
-//        // sourcetype 资产类科目
-//        val stSubject = accountUtilServcie.readSubject(sourceType.paySubjno)
-//        // build 交易明细
-//        val builder = TransactionBuilder().apply {
-//            setTransInfo(param.transdate, param.transtime, TradeCode.TRANSCODE_QRCODE, qrcodeTrans.sourceType)
-//            setOutTransInfo(qrcodeTrans.agentMerchId, qrcodeTrans.billno)
-//            payinfo = qrcodeSummary(sourceType)
-//            description = dtlType.dictcaption
-//            dtltype = param.dtltype
-//        }
-//
-//        val shopacc = accountUtilServcie.readShopbyShopaccno(qrcodeTrans.agentMerchId)
-//        val amount = param.amount / 100.0
-//        builder.shop(shopacc).apply {
-//            setAmount(amount, TradeDict.TRADE_FLAG_IN)
-//        }
-//        if (qrcodeTrans.isAnonymous) {
-//            builder.anonymous().apply {
-//                setAmount(amount, TradeDict.TRADE_FLAG_OUT)
-//                setOpposite(shopacc.shopaccno, shopacc.shopname)
-//            }.and() // 匿名消费时,借 科目 , 贷 商户
-//                    .addDebitCreditRecord(AccountProxy(stSubject), AccountProxy(shopacc),
-//                            amount, qrcodeSummary(sourceType))
-//        } else {
-//            val account = accountUtilServcie.readAccount(param.userid)
-//            builder.person(account).apply {
-//                setAmount(amount, TradeDict.TRADE_FLAG_OUT)
-//                setOpposite(shopacc.shopaccno, shopacc.shopname)
-//            }.and().shop().apply {
-//                setOpposite(account.accno, account.accname)
-//            }.and() // 实名消费时, 1. 借 科目, 贷 个人账户 ;2. 借 个人账户 贷 商户
-//                    .addDebitCreditRecord(AccountProxy(stSubject), AccountProxy(account),
-//                            amount, qrcodeSummary(sourceType))
-//                    .addDebitCreditRecord(AccountProxy(account), AccountProxy(shopacc),
-//                            amount, qrcodeSummary(sourceType))
-//        }
-//
-//        // 同一个客户ID + billno 是唯一索引,如果重复请求不能保存
-//        val transaction = builder.init(transactionService)
-//
-//        // qrcode 交易明细表记录 refno
-//        qrcodeTrans.refno = transaction.refno
-//        // 保存失败,可能客户端重复请求,导致前序交易已完成
-//        agentServiceProxy.qrcodePayTransSaveOrUpdate(qrcodeTrans)
-//
-//        //3. 调用第三方支付
-//        transactionService.wip(transaction.refno)
-//        val service = createAgentService<QrcodePayTrans>(qrcodeTrans.sourceType)
-//        apiResponse.apply {
-//            refno = transaction.refno
-//            accdate = transaction.accdate
-//            isRequireQuery = false
-//            anonymous = qrcodeTrans.isAnonymous
-//        }
-//
-//        val response = service.pay(transaction)
-//        return when (response.code) {
-//            AgentCode.SUCCESS -> {
-//                transactionService.success(transaction.refno, response.agentRefno)
-//                ResponseEntity.ok(ResponseBodyBuilder.create()
-//                        .success(apiResponse))
-//            }
-//            AgentCode.REQUIRE_QUERY -> {
-//                ResponseEntity.ok(ResponseBodyBuilder.create()
-//                        .success(apiResponse.also {
-//                            it.isRequireQuery = true
-//                        }))
-//            }
-//            else -> {
-//                transactionService.fail(transaction.refno, response.agentMsg)
-//                ResponseEntity.ok(ResponseBodyBuilder.create()
-//                        .fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR,
-//                                "第三方身份错误,<${response.agentMsg}"))
-//            }
-//        }
-//    }
+    override fun qrcodePayConfirm(xTenantId: String, @Valid param: QrcodePayConfirmRequest): ResponseEntity<QrcodePayConfirmResponse> {
+        try {//1. 交易检查
 
-//    override fun qrcodePayQuery(xTenantId: String, refno: String): ResponseEntity<Void> {
-//        return null
-//    }
+            val transaction = consumePayService.getTransactionMainByParam(param)
+            val systime = systemUtilService.sysdatetime
+            val apiResponse = QrcodePayConfirmResponse().apply {
+                this.refno = transaction.refno
+                this.hostDate = systime.hostdate
+                this.hostTime = systime.hosttime
+            }
+            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
+                        })
+                    }
+                }
+            }
+
+            transactionService.qrcodeWip(param.billno, transaction)
+
+            val service = createAgentService<QrcodePayTrans>(transaction.sourceType)
+            val response = service.pay(transaction)
+
+            consumePayService.qrcodePayConfirmPostProcess(response, param.billno, transaction)
+            return when (response.code) {
+                AgentCode.SUCCESS -> {
+                    ResponseBodyBuilder.ok(apiResponse.apply { this.result = TransResult.SUCCESS })
+                }
+                AgentCode.REQUIRE_QUERY -> {
+                    ResponseBodyBuilder.ok(apiResponse.apply { this.result = TransResult.REQUIRE_QUERY })
+                }
+                else -> {
+                    ResponseBodyBuilder.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()
+                    println("二维码消费确认异常:<${e.message}>")
+                    throw InternalError(e.message)
+                }
+            }
+        }
+    }
+
+    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.result = when (it.status) {
+                        TradeDict.DTL_STATUS_SUCCESS -> TransResult.SUCCESS
+                        TradeDict.DTL_STATUS_WIP -> TransResult.REQUIRE_QUERY
+                        TradeDict.DTL_STATUS_FAIL -> TransResult.FAILED
+                        else -> TransResult.FAILED
+                    }
+                })
+            } ?: throw BadRequestError("未找到refno")
+        } catch (e: Exception) {
+            when (e) {
+                is BadRequestError -> throw BadRequestError(e.message)
+                is PessimisticLockingFailureException -> throw ConflictError(e.message)
+                else -> {
+                    e.printStackTrace()
+                    println("二维码消费查询异常:<${e.message}>")
+                    throw InternalError(e.message)
+                }
+            }
+        }
+    }
 }
\ No newline at end of file
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 29867ae..832cf5c 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
@@ -1,7 +1,10 @@
 package com.supwisdom.dlpay.api.service
 
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.domain.QrcodePayTrans
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.framework.domain.TDictionary
+import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmRequest
 import org.springframework.transaction.annotation.Propagation
 import org.springframework.transaction.annotation.Transactional
 
@@ -19,9 +22,14 @@
     fun getTransactionMainDtl(refno: String?, billno: String?, shopaccno: String?): TTransactionMain?
 
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class], readOnly = true)
-    fun getDtltypeDictionary(dictval:String, dicttype:String):TDictionary
+    fun getDtltypeDictionary(dictval: String, dicttype: String): TDictionary
 
     @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class], readOnly = true)
     fun checkCanReverse(sourcetype: String, shopaccno: String? = null): Boolean
 
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
+    fun qrcodePayConfirmPostProcess(response: AgentResponse<QrcodePayTrans>, billno: String,transaction:TTransactionMain)
+
+    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = [Exception::class])
+    fun getTransactionMainByParam(param: QrcodePayConfirmRequest): TTransactionMain
 }
\ 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 8830fcd..9d8b5c4 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
@@ -1,14 +1,30 @@
 package com.supwisdom.dlpay.api.service.impl
 
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentPayService
+import com.supwisdom.dlpay.agent.AgentPayServiceContext
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.dao.QrcodePayTransDao
+import com.supwisdom.dlpay.agent.domain.QrcodePayTrans
+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.TransactionMainDao
+import com.supwisdom.dlpay.api.domain.TSourceType
 import com.supwisdom.dlpay.api.domain.TTransactionMain
 import com.supwisdom.dlpay.api.exception.RequestParamCheckException
+import com.supwisdom.dlpay.api.service.AccountUtilServcie
 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.BadRequestError
+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.util.StringUtil
+import com.supwisdom.dlpay.framework.service.SystemUtilService
+import com.supwisdom.dlpay.framework.util.*
+import com.supwisdom.dlpay.payapi.model.QrcodePayConfirmRequest
+import com.supwisdom.multitenant.TenantContextHolder
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.stereotype.Service
 
@@ -20,6 +36,18 @@
     lateinit var transactionMainDao: TransactionMainDao
     @Autowired
     lateinit var dictionaryDao: DictionaryDao
+    @Autowired
+    lateinit var agentServiceProxy: AgentServiceProxy
+    @Autowired
+    lateinit var accountUtilServcie:AccountUtilServcie
+    @Autowired
+    lateinit var transactionService:TransactionServiceProxy
+    @Autowired
+    lateinit var agentPayServiceContext: AgentPayServiceContext
+    @Autowired
+    lateinit var systemUtilService: SystemUtilService
+    @Autowired
+    lateinit var qrcodePayTransDao: QrcodePayTransDao
 
     override fun checkShopPaytype(shopaccno: String, sourceType: String, anonymousflag: Boolean?): Boolean {
         return sourceTypeService.checkShopSourceType(shopaccno, sourceType, true == anonymousflag)
@@ -53,4 +81,104 @@
             sourceTypeService.checkShopCanReverse(sourcetype, shopaccno);
         }
     }
+
+    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")
+        when (response.code) {
+            AgentCode.SUCCESS -> {
+                transactionService.qrcodeSuccess(transaction.refno, response.agentRefno,transaction)
+            }
+            AgentCode.REQUIRE_QUERY -> {
+                return
+            }
+            else -> {
+                transactionService.qrcodeFail(transaction.refno, response.agentMsg,transaction)
+            }
+        }
+    }
+
+    private fun qrcodeSummary(st: TSourceType): String = st.paydesc + "扫码付"
+
+    fun <T> createAgentService(sourceType: String): AgentPayService<T> {
+        return agentPayServiceContext.findAgentPayService(sourceType)
+                ?: throw TransactionCheckException(TradeErrorCode.BUSINESS_DEAL_ERROR,
+                        "支付类型<$sourceType>未定义")
+    }
+
+    override fun getTransactionMainByParam(param: QrcodePayConfirmRequest): TTransactionMain {
+        // 1.交易检查
+        val qrcodeTrans = qrcodePayTransDao.findByQrcodePayTransForUpdate(param.shopaccno, systemUtilService.sysdatetime.hostdate,
+                param.billno, TenantContextHolder.getContext().tenant.id)
+                ?: throw BadRequestError("未找到billno")
+
+        if (qrcodeTrans.qrcode != param.qrcode && param.qrcode.isNotEmpty()) {
+            val qrcode = agentServiceProxy.qrcodeMatch(param.qrcode)
+                    ?: throw BadRequestError("未识别的支付码")
+            if (qrcodeTrans.sourceType != qrcode.sourceType) {
+                throw BadRequestError("支付码不符")
+            }
+            qrcodeTrans.qrcode = param.qrcode
+        }
+
+        val sourceType = sourceTypeService.getBySourceType(qrcodeTrans.sourceType)
+                ?: throw BadRequestError("不支持的支付方式<${qrcodeTrans.sourceType}>")
+        if (!sourceType.anonymousEnable && qrcodeTrans.isAnonymous) {
+            throw BadRequestError("支付方式<${qrcodeTrans.sourceType}>不支持匿名支付")
+        }
+
+        if (!qrcodeTrans.refno.isNullOrEmpty()) {
+            return getTransactionMainDtl(qrcodeTrans.refno, null, null)
+                    ?: throw InternalError("未找到refno")
+        }
+
+        //2. 初始化交易流水
+        qrcodeTrans.spip = "192.168.43.90"
+        val dtlType = getDtltypeDictionary(param.dtltype, Dictionary.DTLTYPES)
+        // sourcetype 资产类科目
+        val stSubject = accountUtilServcie.readSubject(sourceType.paySubjno)
+        val builder = TransactionBuilder().apply {
+            setTransInfo(param.transDate, param.transTime, TradeCode.TRANSCODE_QRCODE, qrcodeTrans.sourceType)
+            setOutTransInfo(qrcodeTrans.agentMerchId, qrcodeTrans.billno)
+            payinfo = qrcodeSummary(sourceType)
+            description = dtlType.dictcaption
+            dtltype = param.dtltype
+        }
+
+        val shopacc = accountUtilServcie.readShopbyShopaccno(qrcodeTrans.agentMerchId)
+        val amount = param.amount / 100.0
+        builder.shop(shopacc).apply {
+            setAmount(amount, TradeDict.TRADE_FLAG_IN)
+        }
+        if (qrcodeTrans.isAnonymous) {
+            builder.anonymous().apply {
+                setAmount(amount, TradeDict.TRADE_FLAG_OUT)
+                setOpposite(shopacc.shopaccno, shopacc.shopname)
+            }.and() // 匿名消费时,借 科目 , 贷 商户
+                    .addDebitCreditRecord(AccountProxy(stSubject), AccountProxy(shopacc),
+                            amount, qrcodeSummary(sourceType))
+        } else {
+            val account = accountUtilServcie.readAccount(param.userid)
+            builder.person(account).apply {
+                setAmount(amount, TradeDict.TRADE_FLAG_OUT)
+                setOpposite(shopacc.shopaccno, shopacc.shopname)
+            }.and().shop().apply {
+                setOpposite(account.accno, account.accname)
+            }.and() // 实名消费时, 1. 借 科目, 贷 个人账户 ;2. 借 个人账户 贷 商户
+                    .addDebitCreditRecord(AccountProxy(stSubject), AccountProxy(account),
+                            amount, qrcodeSummary(sourceType))
+                    .addDebitCreditRecord(AccountProxy(account), AccountProxy(shopacc),
+                            amount, qrcodeSummary(sourceType))
+        }
+
+        // 同一个客户ID + billno 是唯一索引,如果重复请求不能保存
+        val transaction = builder.init(transactionService)
+        // qrcode 交易明细表记录 refno
+        qrcodeTrans.refno = transaction.refno
+        // 保存失败,可能客户端重复请求,导致前序交易已完成
+        agentServiceProxy.qrcodePayTransSaveOrUpdate(qrcodeTrans)
+
+        return transaction
+    }
 }
\ 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 6165d49..2061144 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
@@ -1,5 +1,6 @@
 package com.supwisdom.dlpay.api.service.impl
 
+import com.supwisdom.dlpay.agent.dao.QrcodePayTransDao
 import com.supwisdom.dlpay.api.TransactionBuilder
 import com.supwisdom.dlpay.api.dao.TransactionMainDao
 import com.supwisdom.dlpay.api.domain.*
@@ -35,6 +36,9 @@
     @Autowired
     private lateinit var sourceTypeService: SourceTypeService
 
+    @Autowired
+    private lateinit var qrcodePayTransDao: QrcodePayTransDao
+
 
     /// 公共函数部分
     private fun preCheck(builder: TransactionBuilder) {
@@ -293,6 +297,18 @@
         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")
+        if (transaction.status != TradeDict.DTL_STATUS_INIT) {
+            throw InternalError("流水<${transaction.refno}>状态错误")
+        }
+        updateRecordStatus(transaction, TradeDict.DTL_STATUS_WIP)
+        transactionMainDao.save(transaction)
+        return transaction
+    }
+
     override fun fail(refno: String): TTransactionMain {
         return fail(refno, "")
     }
@@ -325,6 +341,32 @@
         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>状态错误")
+        }
+
+        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
+    }
+
     //////////////////////////////////////////////////////////////////
 // 成功
     private fun transactionOnSuccess(transaction: TTransactionMain, sorcetypeRefno: String, overdraft: Boolean) {
@@ -388,6 +430,37 @@
         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
+                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 success(refno: String): TTransactionMain {
         return success(refno, "", true)
     }
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 cb4a931..dd9dff4 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,15 +23,24 @@
     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
@@ -93,6 +102,10 @@
         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)
     }
@@ -101,6 +114,10 @@
         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) {
@@ -116,6 +133,22 @@
         }
     }
 
+    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, "")
     }
diff --git a/payapi/src/main/resources/application.properties b/payapi/src/main/resources/application.properties
index 3223e1c..6df1eef 100644
--- a/payapi/src/main/resources/application.properties
+++ b/payapi/src/main/resources/application.properties
@@ -57,5 +57,5 @@
 multi-tenant.session.enableSessionScopedBean=false
 multi-tenant.datasource.base-package=com.supwisdom.dlpay
 multi-tenant.task.datacenter=default
-multi-tenant.environment=default
+multi-tenant.environment=touchorder
 multi-tenant.task.worker.name=payapi
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 96d2460..0d4f808 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,8 +125,8 @@
 
     @Test
     fun testHMACSHA256() {
-        val token = "TJ3UlX9/tyunSZ2b"
-        val secret = "5f788ce433ec44f299351cdf7f137e81"
+        val token = "ddCUUHAF/OOBTAZq"
+        val secret = "dc1d26c0d43e442588092c8d45c21bce"
         val jwt = HmacUtil.HMACSHA256(token, secret)
         println(jwt)
     }