增加第三方in app 支付类接口
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayServiceContext.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayServiceContext.java
index a17a1fc..79e0470 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayServiceContext.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentPayServiceContext.java
@@ -28,4 +28,18 @@
return null;
}
}
+
+ public <T> InAppPayService<T> findInAppPayService(String service) {
+ try {
+ Object bean = applicationContext.getBean(service + "InAppAgent");
+ if (bean instanceof InAppPayService) {
+ return (InAppPayService<T>) bean;
+ } else {
+ return null;
+ }
+ } catch (BeansException ex) {
+ log.error("can't create bean <{}> , ex {}", service, ex.getMessage());
+ return null;
+ }
+ }
}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/InAppPayService.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/InAppPayService.java
new file mode 100644
index 0000000..47f51d9
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/InAppPayService.java
@@ -0,0 +1,37 @@
+package com.supwisdom.dlpay.agent;
+
+import com.supwisdom.dlpay.api.domain.TTransactionMain;
+import org.springframework.http.HttpRequest;
+
+/**
+ * 微信、支付宝、银联等第三方支付平台 H5 , JSAPI , Native , 小程序等手机端支付接口
+ *
+ * @param <T>
+ */
+public interface InAppPayService<T> {
+ /**
+ * 支付初始化,由客户端发起,服务端请求第三方支付平台进行交易初始化
+ * 第三方平台会返回支付相关参数,服务端根据需要保存参数,并返回给上层处理
+ *
+ * @param transation
+ * @return
+ */
+ AgentResponse<T> init(TTransactionMain transation);
+
+ /**
+ * 当用支付完成后,第三方支付平台会发起通知给服务端,由服务端处理后续业务
+ *
+ * @param transaction - 交易参数
+ * @param request - 第三方平台通知请求的 HttpRequest
+ * @return
+ */
+ AgentResponse<T> notify(TTransactionMain transaction, HttpRequest request);
+
+ /**
+ * 由服务端主动发起的查询第三方支付平交易情况
+ *
+ * @param transation - 交易参数
+ * @return
+ */
+ AgentResponse<T> query(TTransactionMain transation);
+}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/InAppPayTrans.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/InAppPayTrans.java
new file mode 100644
index 0000000..933557a
--- /dev/null
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/domain/InAppPayTrans.java
@@ -0,0 +1,45 @@
+package com.supwisdom.dlpay.agent.domain;
+
+import org.joda.time.DateTime;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.sql.Timestamp;
+import java.time.Instant;
+
+@Entity
+@Table(name = "tb_inapp_pay_trans")
+@SequenceGenerator(name = "inapp_pay_trans_seq")
+public class InAppPayTrans implements Serializable {
+ private static final long serialVersionUID = 4414357931991577103L;
+
+ @Id
+ @Column(name = "id")
+ @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "inapp_pay_trans_seq")
+ private Integer id;
+
+ @Column(name = "refno")
+ @NotNull
+ private String refno;
+
+ @Column(name = "sourcetype")
+ @NotNull
+ private String sourceType;
+
+ @Column(name = "agent_refno")
+ private String agentRefno;
+
+ @Column(name = "create_time")
+ private Timestamp createTime;
+
+ @Column(name = "update_time")
+ private Timestamp updateTime;
+
+ @PrePersist
+ public void prePersist() {
+ if (this.createTime == null) {
+ this.createTime = Timestamp.from(Instant.now());
+ }
+ }
+}
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt
new file mode 100644
index 0000000..b0bcc31
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_alipay.kt
@@ -0,0 +1,26 @@
+package com.supwisdom.dlpay.agent.service
+
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.InAppPayService
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import org.springframework.http.HttpRequest
+import org.springframework.stereotype.Component
+
+class AlipayInAppResponse {
+
+}
+
+@Component("alipayInAppAgent")
+class AlipayInAppServcie : InAppPayService<AlipayInAppResponse> {
+ override fun init(transation: TTransactionMain?): AgentResponse<AlipayInAppResponse> {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun notify(transaction: TTransactionMain?, request: HttpRequest?): AgentResponse<AlipayInAppResponse> {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun query(transation: TTransactionMain?): AgentResponse<AlipayInAppResponse> {
+ 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/inapp_wechatpay.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_wechatpay.kt
new file mode 100644
index 0000000..2022d9a
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/inapp_wechatpay.kt
@@ -0,0 +1,30 @@
+package com.supwisdom.dlpay.agent.service
+
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.InAppPayService
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import org.springframework.http.HttpRequest
+import org.springframework.stereotype.Component
+
+class WechatPayResponse {
+ var preId: String = "";
+}
+
+@Component("wechatInAppAgent")
+class WechatInAppService(private val sourceTypeService: SourceTypeService)
+ : InAppPayService<WechatPayResponse> {
+ val APIUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"
+
+ override fun init(transation: TTransactionMain?): AgentResponse<WechatPayResponse> {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun notify(transaction: TTransactionMain?, request: HttpRequest?): AgentResponse<WechatPayResponse> {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun query(transation: TTransactionMain?): AgentResponse<WechatPayResponse> {
+ 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/api/controller/transaction_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt
index 63312ad..44e0753 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/transaction_controller.kt
@@ -1,10 +1,14 @@
package com.supwisdom.dlpay.api.controller
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentPayServiceContext
+import com.supwisdom.dlpay.agent.InAppPayService
import com.supwisdom.dlpay.api.TransactionBuilder
import com.supwisdom.dlpay.api.bean.InAppPayParam
import com.supwisdom.dlpay.api.bean.InAppPayResponse
import com.supwisdom.dlpay.api.bean.TransactionQueryResponse
import com.supwisdom.dlpay.api.domain.TSourceType
+import com.supwisdom.dlpay.api.domain.TTransactionMain
import com.supwisdom.dlpay.api.service.AccountUtilServcie
import com.supwisdom.dlpay.api.service.SourceTypeService
import com.supwisdom.dlpay.api.service.TransactionServiceProxy
@@ -19,6 +23,7 @@
import org.springframework.context.annotation.Lazy
import org.springframework.data.redis.connection.RedisConnectionFactory
import org.springframework.data.redis.core.RedisTemplate
+import org.springframework.http.HttpRequest
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
@@ -33,27 +38,45 @@
private val systemUtilService: SystemUtilService,
private val accountUtilServcie: AccountUtilServcie,
private val sourceTypeService: SourceTypeService,
+ private val agentPayServiceContext: AgentPayServiceContext,
redisConnectionFactory: RedisConnectionFactory) {
private val transactionContainer = TransactionContainer("inapp.pay", redisConnectionFactory)
+ fun doQuery(transaction: TTransactionMain, agent: InAppPayService<Any>): TTransactionMain {
+ val agentResponse = agent.query(transaction)
+ return when (agentResponse.agentCode) {
+ AgentCode.REQUIRE_QUERY.value() -> {
+ transaction
+ }
+ AgentCode.SUCCESS.value() -> {
+ transactionServiceProxy.success(transaction.refno)
+
+ }
+ else -> {
+ transactionServiceProxy.fail(transaction.refno, agentResponse.agentMsg)
+ }
+ }
+ }
+
@GetMapping("/inapp/query")
fun queryTransaction(refno: String): ResponseEntity<*> {
- val tranaction = transactionServiceProxy.findTransactionByRefno(refno)
+ val transaction = transactionServiceProxy.findTransactionByRefno(refno)
?: return ResponseBodyBuilder.notFound("未找到流水")
- if (tranaction.tenantid != TenantContextHolder.getContext().tenant.id) {
+ if (transaction.tenantid != TenantContextHolder.getContext().tenant.id) {
return ResponseBodyBuilder.conflict("未找到流水")
}
- if (tranaction.status != TradeDict.DTL_STATUS_SUCCESS) {
- transactionContainer.add(refno)
- // 查询第三方
- transactionContainer.remove(refno)
+ val agent = agentPayServiceContext.findInAppPayService<Any>(transaction.sourceType)
+ ?: return ResponseBodyBuilder.notFound("支付类别不支持 <${transaction.sourceType}>")
+ val resultTrans = when (transaction.status) {
+ TradeDict.DTL_STATUS_WIP -> doQuery(transaction, agent)
+ else -> transaction
}
return ResponseBodyBuilder.successEntity(TransactionQueryResponse().apply {
- this.refno = tranaction.refno
- accdate = tranaction.accdate
- status = tranaction.status
+ this.refno = resultTrans.refno
+ accdate = resultTrans.accdate
+ status = resultTrans.status
hostdate = systemUtilService.sysdatetime.hostdate
hosttime = systemUtilService.sysdatetime.hosttime
}, "成功")
@@ -71,11 +94,14 @@
fun inAppPayInit(@Valid param: InAppPayParam): ResponseEntity<*> {
val response = InAppPayResponse()
if (transactionContainer.count() > 100) {
- return ResponseBodyBuilder.serviceUnavailable("第三方请求异常")
+ return ResponseBodyBuilder.internalServerError("第三方请求异常")
}
val sourceType = sourceTypeService.getBySourceType(param.sourceType)
?: return ResponseBodyBuilder.badRequest("source type <${param.sourceType}> 不存在")
+ val agent = agentPayServiceContext.findInAppPayService<Any>(sourceType.sourceType)
+ ?: return ResponseBodyBuilder.badRequest("不支持支付方式<${sourceType.sourceType}>")
+
val subject = accountUtilServcie.readSubject(sourceType.depositeSubjno)
val tradeCode = when (param.inAppType) {
@@ -133,9 +159,14 @@
}
val transaction = transactionServiceProxy.init(builder)
// 调用第三方完成交易初始化
-
transactionServiceProxy.wip(transaction.refno)
transactionContainer.add(transaction.refno)
+ val agentResponse = agent.init(transaction)
+ if (agentResponse.code != AgentCode.SUCCESS) {
+ return ResponseBodyBuilder
+ .internalServerError("请求第三方支付平台失败,${agentResponse.agentMsg}")
+ }
+
response.apply {
when (param.recipientType) {
"shop" -> actuallyAmount = (transaction.shopDtl.amount * 100).roundToInt()
@@ -181,16 +212,33 @@
@RestController("/api/notify")
class TransactionNotifyController(@Lazy private val tenantDetailsRegistrar: TenantDetailsRegistrar,
- private val transactionServiceProxy: TransactionServiceProxy) {
+ private val transactionServiceProxy: TransactionServiceProxy,
+ private val agentPayServiceContext: AgentPayServiceContext) {
- @PostMapping("/inapp/alipay/{tenant}")
- fun inAppPayCallback(@PathVariable("tenant") tenant: String,
- refno: String): ResponseEntity<*> {
+ @PostMapping("/inapp/{sourcetype}/{tenant}")
+ fun inAppPayCallback(@PathVariable("sourcetype") sourcetype: String,
+ @PathVariable("tenant") tenant: String,
+ refno: String,
+ request: HttpRequest): ResponseEntity<*> {
val tenantDetails = tenantDetailsRegistrar.getTenantDetailsById(tenant)
?: return ResponseBodyBuilder.notFound("请求租户 <$tenant> 不存在")
+ val agent = agentPayServiceContext.findInAppPayService<Any>(sourcetype)
+ ?: return ResponseBodyBuilder.badRequest("请求支付类型错误 <$sourcetype> 不存在")
TenantContextHolder.getContext().tenant = tenantDetails.get()
- val transaction = transactionServiceProxy.success(refno)
- return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("refno", transaction.refno))
+ val transaction = transactionServiceProxy.findTransactionByRefno(refno)
+ val agentResponse = agent.notify(transaction, request)
+ if (agentResponse.code == AgentCode.SUCCESS) {
+ transactionServiceProxy.success(refno)
+ } else if (agentResponse.code == AgentCode.REQUIRE_QUERY) {
+ transaction
+ } else {
+ transactionServiceProxy.fail(refno, agentResponse.agentMsg)
+ }?.let {
+ return ResponseBodyBuilder.successEntity(InAppPayResponse().apply {
+ this.refno = it.refno
+ this.status = it.status
+ })
+ }
+ return ResponseBodyBuilder.internalServerError("请求参数错误")
}
}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt
index 597dedf..54863ea 100644
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/framework/framework_util.kt
@@ -55,8 +55,8 @@
return fail(HttpStatus.UNAUTHORIZED, msg)
}
- fun serviceUnavailable(msg: String): ResponseEntity<*> {
- return fail(HttpStatus.SERVICE_UNAVAILABLE, msg)
+ fun internalServerError(msg: String): ResponseEntity<*> {
+ return fail(HttpStatus.INTERNAL_SERVER_ERROR, msg)
}
}