支付宝接口、微信接口
diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java
index 6ffef6f..c7f18f4 100644
--- a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java
+++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java
@@ -48,6 +48,17 @@
@NotNull(message = "必须指定是否匿名支付", groups = ConfirmAction.class)
private Boolean anonymous;
+ /**请求IP*/
+ private String spip;
+
+ public String getSpip() {
+ return spip;
+ }
+
+ public void setSpip(String spip) {
+ this.spip = spip;
+ }
+
public String getBillno() {
return billno;
}
diff --git a/payapi/build.gradle b/payapi/build.gradle
index e2cdedd..0381f48 100644
--- a/payapi/build.gradle
+++ b/payapi/build.gradle
@@ -83,6 +83,8 @@
implementation 'commons-dbcp:commons-dbcp:1.4'
implementation project(':payapi-common')
+ /*支付宝SDK*/
+ implementation group: 'com.alipay.sdk', name: 'alipay-sdk-java', version: '3.7.110.ALL'
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
annotationProcessor 'org.projectlombok:lombok:1.18.8'
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java
index 950f338..0d56cc1 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentCode.java
@@ -10,8 +10,8 @@
WAIT_NOTIFY("wait_notify", "交易已发起,等待通知"),
SHORT_OF_BALANCE("short_of_balance", "余额不足"),
NOT_SUPPORT("not_support", "不支持功能"),
- COMMON_ERROR("common_error", "其它错误");
-
+ COMMON_ERROR("common_error", "其它错误"),
+ CONFIG_ERROR("config_error", "参数配置错误");
AgentCode(String code, String msg) {
this.code = code;
this.msg = msg;
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 e776671..80f65a3 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java
@@ -1,50 +1,54 @@
package com.supwisdom.dlpay.agent;
public class AgentResponse {
- private AgentCode code;
- private String agentCode;
- private String agentMsg;
+ public static final String AGENTCODE_SUCCESS = "0";
- private String agentRefno;
- private DtlStatus dtlStatus;
+ public static final String AGENTCODE_FAIL = "1";
- public AgentCode getCode() {
- return code;
- }
+ private AgentCode code;
+ private String agentCode;
+ private String agentMsg;
- public void setCode(AgentCode code) {
- this.code = code;
- }
+ private String agentRefno;
+ private DtlStatus dtlStatus;
- public String getAgentCode() {
- return agentCode;
- }
+ public AgentCode getCode() {
+ return code;
+ }
- public void setAgentCode(String agentCode) {
- this.agentCode = agentCode;
- }
+ public void setCode(AgentCode code) {
+ this.code = code;
+ }
- public String getAgentMsg() {
- return agentMsg;
- }
+ public String getAgentCode() {
+ return agentCode;
+ }
- public void setAgentMsg(String agentMsg) {
- this.agentMsg = agentMsg;
- }
+ public void setAgentCode(String agentCode) {
+ this.agentCode = agentCode;
+ }
- public String getAgentRefno() {
- return agentRefno;
- }
+ public String getAgentMsg() {
+ return agentMsg;
+ }
- public void setAgentRefno(String agentRefno) {
- this.agentRefno = agentRefno;
- }
+ public void setAgentMsg(String agentMsg) {
+ this.agentMsg = agentMsg;
+ }
- public DtlStatus getDtlStatus() {
- return dtlStatus;
- }
+ public String getAgentRefno() {
+ return agentRefno;
+ }
- public void setDtlStatus(DtlStatus dtlStatus) {
- this.dtlStatus = dtlStatus;
- }
+ public void setAgentRefno(String agentRefno) {
+ this.agentRefno = agentRefno;
+ }
+
+ public DtlStatus getDtlStatus() {
+ return dtlStatus;
+ }
+
+ public void setDtlStatus(DtlStatus dtlStatus) {
+ this.dtlStatus = dtlStatus;
+ }
}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/DtlStatus.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/DtlStatus.java
index d80d503..a13f1d5 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/agent/DtlStatus.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/DtlStatus.java
@@ -4,5 +4,6 @@
SUCCESS, //成功
FAIL, //失败
REFUND, //已退款
- PARTIAL_REFUND //部分退款
+ PARTIAL_REFUND, //部分退款
+ WAIT //等待付款
}
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 96f8b06..fb42041 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
@@ -65,6 +65,9 @@
@Column(name = "tenantid", length = 20)
private String tenantid;
+ @Column(name = "spid", length = 20)
+ private String spip;
+
public QrcodePayTrans() {
}
@@ -179,4 +182,12 @@
public void setUpdateTime(Timestamp updateTime) {
this.updateTime = updateTime;
}
+
+ public String getSpip() {
+ return spip;
+ }
+
+ public void setSpip(String spip) {
+ this.spip = spip;
+ }
}
diff --git a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java
index f69eb68..40b62e5 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/api/bean/WechatReqResp.java
@@ -237,6 +237,41 @@
this.sign = MD5.encodeByMD5(str.toString());
return sign;
}
+ public String generalQuerySign(){
+ this.nonce_str = RandomUtils.getRandomString(30);
+ StringBuffer str = new StringBuffer()
+ .append("appid=").append(this.appid)
+ .append("&mch_id=").append(this.mch_id)
+ .append("&nonce_str=").append(nonce_str)
+ .append("&out_trade_no=").append(this.out_trade_no);
+ str.append("&key=").append(this.key);
+ this.sign = MD5.encodeByMD5(str.toString());
+ return sign;
+ }
+ public String generalQueryXML(){
+ StringBuffer requestStr = new StringBuffer();
+ requestStr
+ .append("<xml>")
+ .append("<appid>")
+ .append(this.appid)
+ .append("</appid>")
+ .append("<mch_id>")
+ .append(this.mch_id)
+ .append("</mch_id>")
+ .append("<nonce_str>")
+ .append(this.nonce_str)
+ .append("</nonce_str>")
+ .append("<out_trade_no>")
+ .append(this.out_trade_no)
+ .append("</out_trade_no>")
+ ;
+ requestStr.append("<sign>")
+ .append(this.sign)
+ .append("</sign>")
+ .append("</xml>");
+ return requestStr.toString();
+ }
+
public String generalCheckSign(){
this.nonce_str = RandomUtils.getRandomString(30);
StringBuffer str = new StringBuffer()
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 8222e90..55108af 100644
--- a/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
+++ b/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java
@@ -7,4 +7,40 @@
public static final String YKTPAY = "yktpay";
public static final String WECHAT = "wechat";
+
+
+ /**
+ * 支付宝支付,配置的KEY值
+ */
+ public static final String CFG_ALIPAY_APPID = "alipay.appid";
+
+ public static final String CFG_ALIPAY_PRIVATEKEY = "alipay.privatekey";
+
+ public static final String CFG_ALIPAY_PUBLICKEY = "alipay.publickey";
+
+ public static final String CFG_ALIPAY_PAYURL = "alipay.payurl";
+
+ public static final String CFG_ALIPAY_NOTIFY = "alipay.notify";
+
+ public static final String CFG_ALIPAY_RETURNURL = "alipay.returnurl";
+
+ /**
+ * 微信支付,配置的KEY值
+ */
+ public static final String CFG_WECHAT_APPID = "wechat.appid";
+
+ public static final String CFG_WECHAT_MECHID = "wechat.mechid";
+
+ public static final String CFG_WECHAT_MECHKEY = "wechat.mechkey";
+
+ public static final String CFG_WECHAT_NOTIFY = "wechat.notify";
+
+ 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";
+
+ public static final String CFG_WECHAT_UNIONPAY = "https://api.mch.weixin.qq.com/pay/unifiedorder";
+
+ public static final String CFG_WECHAT_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery";
+
}
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 a89e2e1..3f8cde2 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
@@ -4,29 +4,52 @@
import com.supwisdom.dlpay.agent.AgentPayService
import com.supwisdom.dlpay.agent.AgentResponse
import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.api.service.ConsumePayService
+import com.supwisdom.dlpay.framework.util.TradeCode
+import com.supwisdom.dlpay.framework.util.TradeDict
import org.springframework.stereotype.Component
+interface AlipayService {
+ fun doQrcodepay(transaction: TTransactionMain): AgentResponse
+
+ fun doPrepay(transaction: TTransactionMain): AgentResponse
+
+ fun doRefund(transaction: TTransactionMain): AgentResponse
+
+ fun doQuery(transaction: TTransactionMain): AgentResponse
+
+ fun doNotify(param: Map<String, String>): AgentResponse
+}
+
@Component("alipayAgent")
-class AlipayAgentService : AgentPayService {
+class AlipayAgentService(val consumePayService: ConsumePayService,
+ val aipayService: AlipayService) : AgentPayService {
+
override fun auth(shopaccno: String?, billno: String?): AgentResponse {
+ if (consumePayService.checkShopPaytype(shopaccno!!, TradeDict.PAYTYPE_ALIPAY, true)) {
+ //TODO 支付宝实名认证逻辑
+ }
return AgentResponse().apply {
this.code = AgentCode.NOT_SUPPORT
}
}
override fun pay(transaction: TTransactionMain): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ return when (transaction.transCode) {
+ TradeCode.TRANSCODE_QRCODE -> aipayService.doQrcodepay(transaction)
+ else -> aipayService.doPrepay(transaction)
+ }
}
override fun cancel(transaction: TTransactionMain): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ return refund(transaction)
}
override fun refund(transaction: TTransactionMain): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ return aipayService.doRefund(transaction)
}
override fun query(transaction: TTransactionMain): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ return aipayService.doQuery(transaction)
}
}
\ No newline at end of file
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
new file mode 100644
index 0000000..53afcd7
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt
@@ -0,0 +1,260 @@
+package com.supwisdom.dlpay.agent.service.impl
+
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.agent.service.AlipayService
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.util.PaytypeUtil
+import mu.KotlinLogging
+import org.springframework.stereotype.Service
+import com.alipay.api.request.AlipayTradePayRequest
+import com.alipay.api.DefaultAlipayClient
+import com.alipay.api.domain.AlipayTradePayModel
+import com.supwisdom.dlpay.agent.service.AgentServiceProxy
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.alipay.api.AlipayApiException
+import com.alipay.api.internal.util.AlipaySignature
+import com.alipay.api.request.AlipayTradeAppPayRequest
+import com.supwisdom.dlpay.api.service.ConsumePayService
+import com.supwisdom.dlpay.api.service.TransactionServiceProxy
+import com.alipay.api.request.AlipayTradeQueryRequest
+import com.supwisdom.dlpay.agent.DtlStatus
+import com.alipay.api.domain.AlipayTradeQueryModel
+import com.alipay.api.domain.AlipayTradeRefundModel
+
+
+@Service
+class AlipayServiceImpl(val sourceTypeService: SourceTypeService,
+ val agentServiceProxy: AgentServiceProxy,
+ val consumePayService: ConsumePayService,
+ val transactionService: TransactionServiceProxy) : AlipayService {
+ val logger = KotlinLogging.logger { }
+
+ fun checkCfg(config: Map<String, String?>, resp: AgentResponse): Boolean {
+ if (config[PaytypeUtil.CFG_ALIPAY_APPID].isNullOrEmpty()
+ || config[PaytypeUtil.CFG_ALIPAY_PRIVATEKEY].isNullOrEmpty()
+ || config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY].isNullOrEmpty()) {
+ resp.code = AgentCode.CONFIG_ERROR
+ resp.agentCode = AgentResponse.AGENTCODE_FAIL
+ resp.agentMsg = "支付宝相关配置为空"
+ logger.error { "请检查:${PaytypeUtil.CFG_ALIPAY_APPID},${PaytypeUtil.CFG_ALIPAY_PRIVATEKEY},${PaytypeUtil.CFG_ALIPAY_PUBLICKEY}" }
+ return false
+ }
+ return true
+ }
+
+ override fun doQrcodepay(transaction: TTransactionMain): AgentResponse {
+ var qrcodePayTrans = agentServiceProxy.qrcodePayTransFindByRefno(transaction.refno)
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_ALIPAY, transaction.shopDtl.shopaccno, qrcodePayTrans.isAnonymous, false)
+ var agentResponse = AgentResponse()
+ if (checkCfg(config, agentResponse)) {
+ var payurl = config[PaytypeUtil.CFG_ALIPAY_PAYURL]
+ if (payurl.isNullOrEmpty()) {
+ payurl = "https://openapi.alipay.com/gateway.do"
+ }
+ val alipayClient = DefaultAlipayClient(payurl, config[PaytypeUtil.CFG_ALIPAY_APPID], config[PaytypeUtil.CFG_ALIPAY_PRIVATEKEY], "json", "UTF-8", config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY], "RSA2")
+ val request = AlipayTradePayRequest()
+ request.bizModel = AlipayTradePayModel().apply {
+ this.authCode = qrcodePayTrans.qrcode
+ this.outTradeNo = transaction.refno
+ this.subject = "POS扫支付宝二维码消费"
+ this.totalAmount = transaction.shopDtl.amount.toString()
+ }
+ try {
+ val response = alipayClient.execute(request)
+ if ("10000" == response.code) {
+ if (response.isSuccess) {
+ agentResponse.agentRefno = response.tradeNo
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ } else {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = response.subMsg
+ logger.error { "支付宝:${response.code},${response.msg},${response.subCode},${response.subMsg}" }
+ }
+ } else if ("10003" == response.code || "20000" == response.code) {
+ agentResponse.code = AgentCode.REQUIRE_QUERY
+ agentResponse.agentMsg = "支付请求已提交,等待用户支付"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ logger.error { "支付宝:${response.code},${response.msg},${response.subCode},${response.subMsg}" }
+ } else {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentMsg = response.msg
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ logger.error { "支付宝:${response.code},${response.msg},${response.subCode},${response.subMsg}" }
+ }
+ } catch (e: AlipayApiException) {
+ logger.error { "支付宝:${e.message}" }
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentMsg = "调用支付宝异常"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doPrepay(transaction: TTransactionMain): AgentResponse {
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_ALIPAY, transaction.shopDtl.shopaccno, false, false)
+ var agentResponse = AgentResponse()
+ if (checkCfg(config, agentResponse)) {
+ if (config[PaytypeUtil.CFG_ALIPAY_NOTIFY].isNullOrEmpty()) {
+ agentResponse.code = AgentCode.CONFIG_ERROR
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "支付宝相关配置为空"
+ logger.error { "支付宝异步通知地址未配置:${PaytypeUtil.CFG_ALIPAY_NOTIFY}" }
+ }
+ var payurl = config[PaytypeUtil.CFG_ALIPAY_PAYURL]
+ if (payurl.isNullOrEmpty()) {
+ payurl = "https://openapi.alipay.com/gateway.do"
+ }
+ val alipayClient = DefaultAlipayClient(payurl, config[PaytypeUtil.CFG_ALIPAY_APPID], config[PaytypeUtil.CFG_ALIPAY_PRIVATEKEY], "json", "UTF-8", config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY], "RSA2")
+ val request = AlipayTradeAppPayRequest()
+ var productCode = ""
+ //判断是否为H5
+ //productCode = "QUICK_WAP_WAY"
+ request.bizModel = AlipayTradePayModel().apply {
+ this.outTradeNo = transaction.refno
+ this.subject = "支付宝支付"
+ this.totalAmount = transaction.shopDtl.amount.toString()
+ this.productCode = productCode
+ }
+ request.notifyUrl = config[PaytypeUtil.CFG_ALIPAY_NOTIFY]
+ request.returnUrl = config[PaytypeUtil.CFG_ALIPAY_RETURNURL]
+ try {
+ /**
+ * h5 支付方式
+ * String form = alipayClient.pageExecute(request).getBody();
+ *
+ * */
+ val response = alipayClient.sdkExecute(request)
+ if (response.isSuccess) {
+ agentResponse.agentRefno = response.tradeNo
+ agentResponse.code = AgentCode.REQUIRE_QUERY
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ //body 为APP
+ agentResponse.agentMsg = response.body
+ } else {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = response.subMsg
+ logger.error { "支付宝:${response.code},${response.msg},${response.subCode},${response.subMsg}" }
+ }
+ } catch (e: AlipayApiException) {
+ logger.error { "支付宝:${e.message}" }
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentMsg = "调用支付宝异常"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doRefund(transaction: TTransactionMain): AgentResponse {
+ var agentResponse = AgentResponse()
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_ALIPAY, transaction.shopDtl.shopaccno, false, false)
+ if (checkCfg(config, agentResponse)) {
+ var payurl = config[PaytypeUtil.CFG_ALIPAY_PAYURL]
+ if (payurl.isNullOrEmpty()) {
+ payurl = "https://openapi.alipay.com/gateway.do"
+ }
+ val alipayClient = DefaultAlipayClient(payurl, config[PaytypeUtil.CFG_ALIPAY_APPID], config[PaytypeUtil.CFG_ALIPAY_PRIVATEKEY], "json", "UTF-8", config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY], "RSA2")
+ val request = AlipayTradeQueryRequest()
+ request.bizModel = AlipayTradeRefundModel().apply {
+ this.outTradeNo = transaction.refno
+ this.refundAmount = transaction.shopDtl.amount.toString()
+ }
+ val response = alipayClient.execute(request)
+ if (response.isSuccess) {
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ agentResponse.dtlStatus = DtlStatus.REFUND
+ } else {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "支付宝退款失败"
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doQuery(transaction: TTransactionMain): AgentResponse {
+ var agentResponse = AgentResponse()
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_ALIPAY, transaction.shopDtl.shopaccno, false, false)
+ if (checkCfg(config, agentResponse)) {
+ var payurl = config[PaytypeUtil.CFG_ALIPAY_PAYURL]
+ if (payurl.isNullOrEmpty()) {
+ payurl = "https://openapi.alipay.com/gateway.do"
+ }
+ val alipayClient = DefaultAlipayClient(payurl, config[PaytypeUtil.CFG_ALIPAY_APPID], config[PaytypeUtil.CFG_ALIPAY_PRIVATEKEY], "json", "UTF-8", config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY], "RSA2")
+ val request = AlipayTradeQueryRequest()
+ request.bizModel = AlipayTradeQueryModel().apply {
+ this.outTradeNo = transaction.refno
+ }
+ val response = alipayClient.execute(request)
+ if (response.isSuccess) {
+ //check response.totalAmount
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ when (response.tradeStatus) {
+ "TRADE_SUCCESS", "TRADE_FINISHED" -> agentResponse.dtlStatus = DtlStatus.SUCCESS
+ "TRADE_CLOSED" -> agentResponse.dtlStatus = DtlStatus.REFUND
+ "WAIT_BUYER_PAY" -> agentResponse.dtlStatus = DtlStatus.WAIT
+ }
+ } else {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "支付宝查询失败"
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doNotify(param: Map<String, String>): AgentResponse {
+ var refno = param["out_trade_no"]
+ var agentResponse = AgentResponse()
+ if (refno.isNullOrEmpty()) {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentMsg = "返回流水号为空"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ var transaction = consumePayService.getTransactionMainDtl(refno, null, null)
+ if (transaction == null) {
+ agentResponse.code = AgentCode.REFNO_NOT_EXISTS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ if (transaction.status == TradeDict.DTL_STATUS_SUCCESS) {
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentMsg = "流水已成功,不能重复入账"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_ALIPAY, transaction.shopDtl.shopaccno, false, false)
+ if (config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY].isNullOrEmpty()) {
+ agentResponse.code = AgentCode.CONFIG_ERROR
+ agentResponse.agentMsg = "商户公钥未配置"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ var flag = AlipaySignature.rsaCheckV1(param, config[PaytypeUtil.CFG_ALIPAY_PUBLICKEY], "UTF-8", "RSA2")
+ return when (flag) {
+ true -> {
+ //total amt 校验 map["total_amount"]
+ transactionService.success(refno)
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ agentResponse
+ }
+ false -> {
+ logger.error { "支付宝签名校验错误" }
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentMsg = "签名校验错误"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse
+ }
+ }
+ }
+}
\ 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
new file mode 100644
index 0000000..e3beb79
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt
@@ -0,0 +1,263 @@
+package com.supwisdom.dlpay.agent.service.impl
+
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentResponse
+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.WechatReqResp
+import com.supwisdom.dlpay.api.dao.PersonIdentityDao
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.api.service.ConsumePayService
+import com.supwisdom.dlpay.api.service.SourceTypeService
+import com.supwisdom.dlpay.api.service.TransactionServiceProxy
+import com.supwisdom.dlpay.framework.util.*
+import com.supwisdom.dlpay.util.PaytypeUtil
+import mu.KotlinLogging
+import org.apache.commons.lang.StringUtils
+import org.springframework.stereotype.Service
+import org.springframework.web.client.RestTemplate
+
+
+@Service
+class WechatServiceImpl(val sourceTypeService: SourceTypeService,
+ val agentServiceProxy: AgentServiceProxy,
+ val personIdentityDao: PersonIdentityDao,
+ val consumePayService: ConsumePayService,
+ val transactionService: TransactionServiceProxy,
+ val restTemplate: RestTemplate) : WechatService {
+
+ val logger = KotlinLogging.logger { }
+
+ fun checkCfg(config: Map<String, String?>, resp: AgentResponse): Boolean {
+ if (config[PaytypeUtil.CFG_WECHAT_APPID].isNullOrEmpty()
+ || config[PaytypeUtil.CFG_WECHAT_MECHKEY].isNullOrEmpty()
+ || config[PaytypeUtil.CFG_WECHAT_MECHID].isNullOrEmpty()) {
+ resp.code = AgentCode.CONFIG_ERROR
+ resp.agentCode = AgentResponse.AGENTCODE_FAIL
+ resp.agentMsg = "微信相关配置为空"
+ logger.error { "请检查:${PaytypeUtil.CFG_WECHAT_APPID},${PaytypeUtil.CFG_WECHAT_MECHID},${PaytypeUtil.CFG_WECHAT_MECHKEY}" }
+ return false
+ }
+ return true
+ }
+
+ override fun doAuth(shopaccno: String?, billno: String?): AgentResponse {
+ var qrcodeTrans = agentServiceProxy.qrcodePayTransFindByMerchIdAndBillno(shopaccno, billno)
+ var agentResponse = AgentResponse()
+ if (qrcodeTrans == null) {
+ agentResponse.code = AgentCode.REFNO_NOT_EXISTS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, shopaccno, qrcodeTrans.isAnonymous, false)
+ if (checkCfg(config, agentResponse)) {
+ val bean = WechatReqResp().apply {
+ this.appid = config[PaytypeUtil.CFG_WECHAT_APPID]
+ this.auth_code = qrcodeTrans.qrcode
+ this.mch_id = config[PaytypeUtil.CFG_WECHAT_MECHID]
+ this.key = config[PaytypeUtil.CFG_WECHAT_MECHKEY]
+ }
+ bean.generalCheckSign()
+ var xml = bean.generalCheckXML()
+ var res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_OAUTHCODE, xml, String::class.java)
+ var eleMap = XmlUtils.parseXml(res.body)
+ var retcode = eleMap["return_code"]
+ var resultCode = eleMap["result_code"]
+ var openid = eleMap["openid"]
+ if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
+ && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode && !openid.isNullOrEmpty()) {
+ qrcodeTrans.agentUserId = openid
+ var ip = personIdentityDao.getByThirdUid(openid)
+ if (ip != null) {
+ qrcodeTrans.agentUserId = ip.person.userid
+ }
+ agentServiceProxy.qrcodePayTransSaveOrUpdate(qrcodeTrans)
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ } else {
+ logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "二维码身份查询失败"
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doQrcodepay(transaction: TTransactionMain): AgentResponse {
+ var qrcodeTrans = agentServiceProxy.qrcodePayTransFindByRefno(transaction.refno)
+ var agentResponse = AgentResponse()
+ if (qrcodeTrans == null) {
+ agentResponse.code = AgentCode.REFNO_NOT_EXISTS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, qrcodeTrans.isAnonymous, false)
+ if (checkCfg(config, agentResponse)) {
+ val bean = WechatReqResp().apply {
+ this.appid = config[PaytypeUtil.CFG_WECHAT_APPID]
+ this.auth_code = qrcodeTrans.qrcode
+ 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.spbill_create_ip = qrcodeTrans.spip
+ }
+
+ bean.generalPaySign()
+ var xml = bean.generaPayXML()
+ var res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_QRCODEPAY, xml, String::class.java)
+ var eleMap = XmlUtils.parseXml(res.body)
+ var retcode = eleMap["return_code"]
+ var resultCode = eleMap["result_code"]
+ var openid = eleMap["openid"]
+ if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
+ && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode && !openid.isNullOrEmpty()) {
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ agentResponse.dtlStatus = DtlStatus.SUCCESS
+ } else {
+ logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
+ agentResponse.code = AgentCode.REQUIRE_QUERY
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "请查询支付结果"
+ }
+ }
+ return agentResponse
+ }
+
+ 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 支付
+ 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.spbill_create_ip = ""
+ this.body = "微信支付"
+ this.trade_type = "MWEB"
+ this.notify_url = config[PaytypeUtil.CFG_WECHAT_NOTIFY]
+ this.scene_info = "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"" + config[PaytypeUtil.CFG_WECHAT_NOTIFY] + "\",\"wap_name\": \"微信支付\"}}"
+ }
+ //TODO IP 问题
+ bean.generaSign()
+ val xml = bean.generaXML()
+ var res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_UNIONPAY, xml, String::class.java)
+ var eleMap = XmlUtils.parseXml(res.body)
+ var retcode = eleMap["return_code"]
+ var resultCode = eleMap["result_code"]
+ val mweb_url = eleMap["mweb_url"]
+ if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
+ && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode && !mweb_url.isNullOrEmpty()) {
+ agentResponse.code = AgentCode.REQUIRE_QUERY
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ agentResponse.agentMsg = mweb_url
+ agentResponse.agentRefno = eleMap["prepay_id"]
+ } else {
+ logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "预下单失败"
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doQuery(transaction: TTransactionMain): AgentResponse {
+ var agentResponse = AgentResponse()
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false)
+ if (checkCfg(config, agentResponse)) {
+ //H5 支付
+ val bean = WechatReqResp().apply {
+ this.appid = config[PaytypeUtil.CFG_WECHAT_APPID]
+ this.mch_id = config[PaytypeUtil.CFG_WECHAT_MECHID]
+ this.key = config[PaytypeUtil.CFG_WECHAT_MECHKEY]
+ this.out_trade_no = transaction.refno
+ }
+ bean.generalQuerySign()
+ val xml = bean.generalQueryXML()
+ var res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_QUERY, xml, String::class.java)
+ var eleMap = XmlUtils.parseXml(res.body)
+ var retcode = eleMap["return_code"]
+ var resultCode = eleMap["result_code"]
+ val trade_state = eleMap["trade_state"]
+ if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode
+ && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
+ agentResponse.code = AgentCode.REQUIRE_QUERY
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ when (trade_state) {
+ "SUCCESS" -> agentResponse.dtlStatus = DtlStatus.SUCCESS
+ "REFUND" -> agentResponse.dtlStatus = DtlStatus.REFUND
+ "NOTPAY", "CLOSED", "REVOKED", "PAYERROR" -> agentResponse.dtlStatus = DtlStatus.FAIL
+ "USERPAYING" -> agentResponse.dtlStatus = DtlStatus.WAIT
+ }
+ } else {
+ logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" }
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "查询失败"
+ }
+ }
+ return agentResponse
+ }
+
+ override fun doRefund(transaction: TTransactionMain): AgentResponse {
+ TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
+ }
+
+ override fun doNotify(param: Map<String, String>): AgentResponse {
+ var agentResponse = AgentResponse()
+ var transaction = consumePayService.getTransactionMainDtl(param["out_trade_no"], null, null)
+ if (transaction == null) {
+ agentResponse.code = AgentCode.REFNO_NOT_EXISTS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ if (transaction.status == TradeDict.DTL_STATUS_SUCCESS) {
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentMsg = "流水已成功,不能重复入账"
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ return agentResponse
+ }
+ val sign = param["sign"]
+ if (StringUtils.isEmpty(sign)) {
+ logger.error("签名错误")
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "签名错误"
+ }
+ var temp = StringUtil.paraFilter(param)
+ var signStr = StringUtil.createLinkString(temp)
+ val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false)
+ var key = config[PaytypeUtil.CFG_WECHAT_MECHKEY]
+ signStr += "&key=$key"
+ val signRet = MD5.encodeByMD5(signStr)
+ logger.error("*******signStr=$signStr")
+ if (!signRet.equals(sign, ignoreCase = true)) {
+ logger.error("签名错误:$signRet,$sign")
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "签名错误"
+ }
+ val returnCode = param["return_code"]
+ val resultCode = param["result_code"]
+ if (!returnCode.isNullOrEmpty() && "SUCCESS" == returnCode
+ && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) {
+ transactionService.success(transaction.refno)
+ agentResponse.code = AgentCode.SUCCESS
+ agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS
+ } else {
+ agentResponse.code = AgentCode.FAIL
+ agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL
+ agentResponse.agentMsg = "${param["err_code"]}:${param["err_code_des"]}"
+ logger.error { "code=${param["err_code"]},des=${param["err_code_des"]}" }
+ }
+ return agentResponse
+ }
+}
\ 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
new file mode 100644
index 0000000..380221c
--- /dev/null
+++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt
@@ -0,0 +1,56 @@
+package com.supwisdom.dlpay.agent.service
+
+import com.supwisdom.dlpay.agent.AgentCode
+import com.supwisdom.dlpay.agent.AgentPayService
+import com.supwisdom.dlpay.agent.AgentResponse
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.api.service.ConsumePayService
+import com.supwisdom.dlpay.framework.util.TradeCode
+import com.supwisdom.dlpay.framework.util.TradeDict
+import org.springframework.stereotype.Component
+
+interface WechatService {
+ fun doAuth(shopaccno: String?, billno: String?): AgentResponse
+
+ fun doQrcodepay(transaction: TTransactionMain): AgentResponse
+
+ fun doPrepay(transaction: TTransactionMain): AgentResponse
+
+ fun doQuery(transaction: TTransactionMain): AgentResponse
+
+ fun doRefund(transaction: TTransactionMain): AgentResponse
+
+ fun doNotify(param: Map<String, String>): AgentResponse
+}
+
+@Component("wechatpayAgent")
+class WeChatPayAgentService(val consumePayService: ConsumePayService,
+ val wechatService: WechatService) : AgentPayService {
+ override fun auth(shopaccno: String?, billno: String?): AgentResponse {
+ if (consumePayService.checkShopPaytype(shopaccno!!, TradeDict.PAYTYPE_WECHAT, true)) {
+ return wechatService.doAuth(shopaccno, billno)
+ }
+ return AgentResponse().apply {
+ this.code = AgentCode.NOT_SUPPORT
+ }
+ }
+
+ override fun pay(transaction: TTransactionMain?): AgentResponse {
+ return when (transaction!!.transCode) {
+ TradeCode.TRANSCODE_QRCODE -> wechatService.doQrcodepay(transaction!!)
+ else -> wechatService.doPrepay(transaction!!)
+ }
+ }
+
+ override fun cancel(transaction: TTransactionMain?): AgentResponse {
+ return refund(transaction)
+ }
+
+ override fun refund(transaction: TTransactionMain?): AgentResponse {
+ return wechatService.doRefund(transaction!!)
+ }
+
+ override fun query(transaction: TTransactionMain?): AgentResponse {
+ return wechatService.doQuery(transaction!!)
+ }
+}
\ No newline at end of file
diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/weichat_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/weichat_service.kt
deleted file mode 100644
index dc748d7..0000000
--- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/weichat_service.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.supwisdom.dlpay.agent.service
-
-import com.supwisdom.dlpay.agent.AgentCode
-import com.supwisdom.dlpay.agent.AgentPayService
-import com.supwisdom.dlpay.agent.AgentResponse
-import com.supwisdom.dlpay.api.domain.TTransactionMain
-import org.springframework.stereotype.Component
-
-@Component("wechatpayAgent")
-class WeChatPayAgentService : AgentPayService {
- override fun auth(shopaccno: String?, billno: String?): AgentResponse {
- return AgentResponse().apply {
- this.code = AgentCode.NOT_SUPPORT
- }
- }
-
- override fun pay(transaction: TTransactionMain?): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
-
- override fun cancel(transaction: TTransactionMain?): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
-
- override fun refund(transaction: TTransactionMain?): AgentResponse {
- TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
- }
-
- override fun query(transaction: TTransactionMain?): AgentResponse {
- 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/consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt
index 9d923d2..3751c40 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
@@ -20,6 +20,7 @@
import org.springframework.http.ResponseEntity
import org.springframework.validation.annotation.Validated
import org.springframework.web.bind.annotation.*
+import javax.servlet.http.HttpServletRequest
import javax.validation.Valid
@RestController
@@ -548,6 +549,7 @@
.fail(apiResponse, TradeErrorCode.BUSINESS_DEAL_ERROR,
"支付方式<${qrcodeTrans.sourceType}>不支持匿名支付"))
}
+ qrcodeTrans.spip = param.spip
//2. 初始化交易流水
// sourcetype 资产类科目