From: qiaowei Date: Tue, 23 Jul 2019 09:58:01 +0000 (+0800) Subject: 第三方支付接口调试 X-Git-Tag: 1.0.0^2~6 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=139c58fa1c4510495fc67bec7f58664f52ee0476;p=epayment%2Ffood_payapi.git 第三方支付接口调试 --- 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 c7f18f41..d8e4f13b 100644 --- a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java +++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/QrcodePayParam.java @@ -49,6 +49,7 @@ public class QrcodePayParam extends APIRequestParam { private Boolean anonymous; /**请求IP*/ + @Sign private String spip; public String getSpip() { diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayResponse.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayResponse.java new file mode 100644 index 00000000..226ed292 --- /dev/null +++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayResponse.java @@ -0,0 +1,17 @@ +package com.supwisdom.dlpay.api.bean; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@AllArgsConstructor +@NoArgsConstructor +public class ThirdPayResponse extends ApiResponse { + private String refno; + private String billno; + private Double amount; + private String body; +} diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayfinishParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayfinishParam.java new file mode 100644 index 00000000..b7c19286 --- /dev/null +++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayfinishParam.java @@ -0,0 +1,23 @@ +package com.supwisdom.dlpay.api.bean; + + +import com.supwisdom.dlpay.api.APIRequestParam; +import com.supwisdom.dlpay.api.annotation.Sign; +import com.supwisdom.dlpay.api.exception.RequestParamCheckException; +import lombok.Getter; +import lombok.Setter; + +import javax.validation.constraints.NotNull; + +@Getter +@Setter +public class ThirdPayfinishParam extends APIRequestParam { + @Sign + @NotNull(message = "交易参考号不能为空") + private String refno; + + @Override + public boolean checkParam() throws RequestParamCheckException { + return true; + } +} diff --git a/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayinitParam.java b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayinitParam.java new file mode 100644 index 00000000..fae16dc1 --- /dev/null +++ b/payapi-common/src/main/java/com/supwisdom/dlpay/api/bean/ThirdPayinitParam.java @@ -0,0 +1,58 @@ +package com.supwisdom.dlpay.api.bean; + +import com.supwisdom.dlpay.api.APIRequestParam; +import com.supwisdom.dlpay.api.annotation.Sign; +import com.supwisdom.dlpay.api.exception.RequestParamCheckException; +import com.supwisdom.dlpay.api.util.DateUtil; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@Getter +@Setter +public class ThirdPayinitParam extends APIRequestParam { + @Sign + private String uid; + @Sign + @NotEmpty(message = "请指定交易商户") + private String shopaccno; + @Sign + @NotNull(message = "支付金额不能为空") + @Min(value = 0, message = "支付金额不能小于 0") + private Integer amount; + private List feelist; + @Sign + @NotNull(message = "订单号不能为空") + private String billno; + @Sign + @NotNull(message = "交易日期不能为空") + private String transdate; + @Sign + @NotNull(message = "交易时间不能为空") + private String transtime; + @Sign + @NotNull(message = "流水类型不能为空") + private String dtltype; + @Sign + @NotNull(message = "支付方式不能为空") + private String sourceType; + + + @Override + public boolean checkParam() throws RequestParamCheckException { + if (!DateUtil.checkDatetimeValid(transdate, DateUtil.DATE_FMT)) { + throw new RequestParamCheckException("交易日期错误[yyyyMMdd]"); + } + if (!DateUtil.checkDatetimeValid(transtime, DateUtil.TIME_FMT)) { + throw new RequestParamCheckException("交易时间错误[HHmmss]"); + } + + return true; + } +} + diff --git a/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java new file mode 100644 index 00000000..54975a55 --- /dev/null +++ b/payapi-sdk/src/main/java/com/supwisdom/dlpay/paysdk/proxy/ConsumePropxy.java @@ -0,0 +1,20 @@ +package com.supwisdom.dlpay.paysdk.proxy; + +import com.supwisdom.dlpay.api.bean.QrcodePayParam; +import com.supwisdom.dlpay.api.bean.QrcodePayResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; + +@FeignClient(name = "consumePropxy", url = "${payapi.url}") +@RequestMapping("/api/consume") +public interface ConsumePropxy { + + @PostMapping("/qrcode/init") + QrcodePayResponse qrcodePayInit(@RequestBody QrcodePayParam param); + + @PostMapping("/qrcode/confirm") + QrcodePayResponse qrcodePayConfirm(@RequestBody QrcodePayParam param); + +} diff --git a/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java b/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java index 0ae4a62f..2d09e9dc 100644 --- a/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java +++ b/payapi-sdk/src/test/java/com/supwisdom/dlpay/paysdktest/CitizenCardPayProxyTest.java @@ -2,6 +2,7 @@ package com.supwisdom.dlpay.paysdktest; import com.supwisdom.dlpay.api.bean.*; +import com.supwisdom.dlpay.api.util.DateUtil; import com.supwisdom.dlpay.paysdk.ApiLoginHelper; import com.supwisdom.dlpay.paysdk.proxy.*; import org.junit.Assert; @@ -16,6 +17,7 @@ import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.cloud.openfeign.FeignAutoConfiguration; import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration; import org.springframework.context.annotation.ComponentScan; +import org.springframework.http.ResponseEntity; import org.springframework.test.context.junit4.SpringRunner; import static org.hamcrest.MatcherAssert.assertThat; @@ -44,11 +46,13 @@ public class CitizenCardPayProxyTest { @Autowired private ApiCommonProxy apiCommonProxy; - @Autowired private ShopProxy shopProxy; @Autowired private UserProxy userProxy; + @Autowired + private ConsumePropxy consumePropxy; + @org.junit.Test public void citizencardPayinit() { @@ -75,21 +79,6 @@ public class CitizenCardPayProxyTest { } @Test public void openShopAccount(){ - /* - * - * shopUniqueId = "35315266" -shoptype = "normal" -fshopid = null -shopname = "test1" -contactman = null -idtype = null -idno = null -mobile = null -email = null -address = null -zipcode = null -sign = "23AE31C973EA8CC79A82B03C6DF48F9C" - * */ ApiLoginHelper helper = new ApiLoginHelper(apiLoginProxy); helper.login(appid, secret); @@ -130,6 +119,58 @@ sign = "23AE31C973EA8CC79A82B03C6DF48F9C" response.getRetcode(), equalTo(0)); } + @Test + public void qrcodeInit(){ + ApiLoginHelper helper = new ApiLoginHelper(apiLoginProxy); + helper.login(appid, secret); + ApiVersionResponse version = apiCommonProxy.apiVersion(); + + assertThat("get version error " + version.getException(), + version.getVersion(), notNullValue()); + + QrcodePayParam param = new QrcodePayParam(); + param.setAmount(1); + param.setAnonymous(true); + param.setBillno(DateUtil.getNow()); + param.setQrcodeFormat("origin"); + param.setTransdate(DateUtil.getNow("yyyyMMdd")); + param.setTranstime(DateUtil.getNow("HHmmss")); + param.setTenantid("default"); + param.setShopaccno("2000000012"); + param.setQrcode("286972142340737770"); + QrcodePayResponse response = consumePropxy.qrcodePayInit(param); + assertThat("qrcodeInit " + response.getRetmsg() + response.getException(), + response.getRetcode(), equalTo(0)); + } + + @Test + public void qrcodePay(){ + ApiLoginHelper helper = new ApiLoginHelper(apiLoginProxy); + helper.login(appid, secret); + ApiVersionResponse version = apiCommonProxy.apiVersion(); + + assertThat("get version error " + version.getException(), + version.getVersion(), notNullValue()); + + QrcodePayParam param = new QrcodePayParam(); + param.setAmount(1); + param.setAnonymous(true); + param.setBillno(DateUtil.getNow()); + param.setQrcodeFormat("origin"); + param.setTransdate(DateUtil.getNow("yyyyMMdd")); + param.setTranstime(DateUtil.getNow("HHmmss")); + param.setTenantid("default"); + param.setShopaccno("2000000012"); + param.setQrcode("286972142340737770"); + QrcodePayResponse response = consumePropxy.qrcodePayInit(param); + assertThat("qrcodeInit " + response.getRetmsg() + response.getException(), + response.getRetcode(), equalTo(0)); + + response = consumePropxy.qrcodePayConfirm(param); + assertThat("qrcodeConfirm " + response.getRetmsg() + response.getException(), + response.getRetcode(), equalTo(0)); + } + public static void main(String[] args) { } diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java index 80f65a36..d07cba56 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/AgentResponse.java @@ -8,10 +8,18 @@ public class AgentResponse { private AgentCode code; private String agentCode; private String agentMsg; - + private String agentBody; private String agentRefno; private DtlStatus dtlStatus; + public String getAgentBody() { + return agentBody; + } + + public void setAgentBody(String agentBody) { + this.agentBody = agentBody; + } + public AgentCode getCode() { return code; } diff --git a/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java b/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java index 2f75c01a..1a540124 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/agent/dao/QrcodePayTransDao.java @@ -13,7 +13,7 @@ public interface QrcodePayTransDao extends CrudRepository pattern = qrcodePatternService.getAllQrcodePattern(); List found = new ArrayList<>(); diff --git a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java index 6c554a8e..d55d3456 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/framework/util/TradeCode.java @@ -9,7 +9,9 @@ public class TradeCode { public static final int TRANSCODE_YKTCARD_PAY = 3020; //一卡通支付 - public static final int TRANSCODE_WECHAT = 1001; + public static final int TRANSCODE_WECHAT = 3030;//微信支付 + + public static final int TRANSCODE_ALIPAY = 3040;//支付宝支付 // QRcode 聚合支付 public static final int TRANSCODE_QRCODE = 1002; diff --git a/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java b/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java index 55108af4..045e54c9 100644 --- a/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java +++ b/payapi/src/main/java/com/supwisdom/dlpay/util/PaytypeUtil.java @@ -14,13 +14,13 @@ public class PaytypeUtil { */ public static final String CFG_ALIPAY_APPID = "alipay.appid"; - public static final String CFG_ALIPAY_PRIVATEKEY = "alipay.privatekey"; + public static final String CFG_ALIPAY_PRIVATEKEY = "alipay.rsa.private.key"; - public static final String CFG_ALIPAY_PUBLICKEY = "alipay.publickey"; + public static final String CFG_ALIPAY_PUBLICKEY = "alipay.public.key"; public static final String CFG_ALIPAY_PAYURL = "alipay.payurl"; - public static final String CFG_ALIPAY_NOTIFY = "alipay.notify"; + public static final String CFG_ALIPAY_NOTIFY = "notify.url"; public static final String CFG_ALIPAY_RETURNURL = "alipay.returnurl"; @@ -35,6 +35,11 @@ public class PaytypeUtil { public static final String CFG_WECHAT_NOTIFY = "wechat.notify"; + public static final String CFG_WECHAT_REFUNDCERT = "wechat.refund.certpath"; + + public static final String CFG_WECHAT_REFUNDCERT_PWD = "wechat.refund.certpwd"; + + public static final String CFG_WECHAT_OAUTHCODE = "https://api.mch.weixin.qq.com/tools/authcodetoopenid"; public static final String CFG_WECHAT_QRCODEPAY = "https://api.mch.weixin.qq.com/pay/micropay"; @@ -43,4 +48,6 @@ public class PaytypeUtil { public static final String CFG_WECHAT_QUERY = "https://api.mch.weixin.qq.com/pay/orderquery"; + public static final String CFG_WECHAT_REFUND = "https://api.mch.weixin.qq.com/secapi/pay/refund"; + } diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt index 3f8cde22..0174c653 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/alipay_service.kt @@ -3,6 +3,7 @@ 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.bean.BaseResp import com.supwisdom.dlpay.api.domain.TTransactionMain import com.supwisdom.dlpay.api.service.ConsumePayService import com.supwisdom.dlpay.framework.util.TradeCode @@ -19,6 +20,11 @@ interface AlipayService { fun doQuery(transaction: TTransactionMain): AgentResponse fun doNotify(param: Map): AgentResponse + + /** + * 下载对账单 + * */ + fun downloadBill(shopacc:String,accdate:String): BaseResp } @Component("alipayAgent") diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt index 53afcd71..cc19440d 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/alipay_service_impl.kt @@ -22,6 +22,7 @@ import com.alipay.api.request.AlipayTradeQueryRequest import com.supwisdom.dlpay.agent.DtlStatus import com.alipay.api.domain.AlipayTradeQueryModel import com.alipay.api.domain.AlipayTradeRefundModel +import com.supwisdom.dlpay.api.bean.BaseResp @Service @@ -134,7 +135,7 @@ class AlipayServiceImpl(val sourceTypeService: SourceTypeService, agentResponse.code = AgentCode.REQUIRE_QUERY agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS //body 为APP - agentResponse.agentMsg = response.body + agentResponse.agentBody = response.body } else { agentResponse.code = AgentCode.FAIL agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL @@ -243,7 +244,12 @@ class AlipayServiceImpl(val sourceTypeService: SourceTypeService, return when (flag) { true -> { //total amt 校验 map["total_amount"] - transactionService.success(refno) + var tradeno = param["trade_no"] + if(tradeno.isNullOrEmpty()){ + transactionService.success(transaction.refno) + }else{ + transactionService.success(transaction.refno,tradeno, true) + } agentResponse.code = AgentCode.SUCCESS agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS agentResponse @@ -257,4 +263,8 @@ class AlipayServiceImpl(val sourceTypeService: SourceTypeService, } } } + + override fun downloadBill(shopacc: String, accdate: String): BaseResp { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } } \ No newline at end of file diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt index e3beb793..94cd0312 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/impl/wechat_service_impl.kt @@ -5,6 +5,7 @@ import com.supwisdom.dlpay.agent.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.BaseResp import com.supwisdom.dlpay.api.bean.WechatReqResp import com.supwisdom.dlpay.api.dao.PersonIdentityDao import com.supwisdom.dlpay.api.domain.TTransactionMain @@ -129,7 +130,6 @@ class WechatServiceImpl(val sourceTypeService: SourceTypeService, override fun doPrepay(transaction: TTransactionMain): AgentResponse { var agentResponse = AgentResponse() - val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false) if (checkCfg(config, agentResponse)) { //H5 支付 @@ -157,7 +157,7 @@ class WechatServiceImpl(val sourceTypeService: SourceTypeService, && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode && !mweb_url.isNullOrEmpty()) { agentResponse.code = AgentCode.REQUIRE_QUERY agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS - agentResponse.agentMsg = mweb_url + agentResponse.agentBody = mweb_url agentResponse.agentRefno = eleMap["prepay_id"] } else { logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" } @@ -208,7 +208,38 @@ class WechatServiceImpl(val sourceTypeService: SourceTypeService, } override fun doRefund(transaction: TTransactionMain): AgentResponse { - TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + var agentResponse = AgentResponse() + val config = sourceTypeService.getConsumePaytypeConfig(TradeDict.PAYTYPE_WECHAT, transaction.shopDtl.shopaccno, false, false) + if (checkCfg(config, agentResponse)) { + val bean = WechatReqResp().apply { + this.appid = config[PaytypeUtil.CFG_WECHAT_APPID] + this.mch_id = config[PaytypeUtil.CFG_WECHAT_MECHID] + this.key = config[PaytypeUtil.CFG_WECHAT_MECHKEY] + this.out_trade_no = transaction.refno + this.total_fee = MoneyUtil.YuanToFen(transaction.shopDtl.amount) + this.refund_fee = MoneyUtil.YuanToFen(transaction.refundAmount) + this.out_refund_no = transaction.reverseRefno + this.notify_url = config[PaytypeUtil.CFG_WECHAT_NOTIFY] + } + bean.generaReverseSign() + val xml = bean.generaReverseXML() + var res = restTemplate.postForEntity(PaytypeUtil.CFG_WECHAT_REFUND, xml, String::class.java) + var eleMap = XmlUtils.parseXml(res.body) + var retcode = eleMap["return_code"] + var resultCode = eleMap["result_code"] + if (!retcode.isNullOrEmpty() && "SUCCESS" == retcode + && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode ) { + agentResponse.code = AgentCode.REQUIRE_QUERY + agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS + agentResponse.agentRefno = eleMap["refund_id"] + } else { + logger.error { "code=${eleMap["err_code"]},des=${eleMap["err_code_des"]}" } + agentResponse.code = AgentCode.FAIL + agentResponse.agentCode = AgentResponse.AGENTCODE_FAIL + agentResponse.agentMsg = "退款申请失败失败:${eleMap["err_code_des"]}" + } + } + return agentResponse } override fun doNotify(param: Map): AgentResponse { @@ -249,7 +280,12 @@ class WechatServiceImpl(val sourceTypeService: SourceTypeService, val resultCode = param["result_code"] if (!returnCode.isNullOrEmpty() && "SUCCESS" == returnCode && !resultCode.isNullOrEmpty() && "SUCCESS" == resultCode) { - transactionService.success(transaction.refno) + val transid = param["transaction_id"] + if(transid.isNullOrEmpty()){ + transactionService.success(transaction.refno) + }else{ + transactionService.success(transaction.refno,transid, true) + } agentResponse.code = AgentCode.SUCCESS agentResponse.agentCode = AgentResponse.AGENTCODE_SUCCESS } else { @@ -260,4 +296,8 @@ class WechatServiceImpl(val sourceTypeService: SourceTypeService, } return agentResponse } + + override fun downloadBill(shopacc:String,accdate:String): BaseResp { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } } \ No newline at end of file diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt index 380221c4..8de5cfe0 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/agent/service/wechat_service.kt @@ -3,6 +3,7 @@ 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.bean.BaseResp import com.supwisdom.dlpay.api.domain.TTransactionMain import com.supwisdom.dlpay.api.service.ConsumePayService import com.supwisdom.dlpay.framework.util.TradeCode @@ -21,6 +22,11 @@ interface WechatService { fun doRefund(transaction: TTransactionMain): AgentResponse fun doNotify(param: Map): AgentResponse + + /** + * 下载对账单 + * */ + fun downloadBill(shopacc:String,accdate:String):BaseResp } @Component("wechatpayAgent") diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt index 874a5396..4e3c906b 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/advices.kt @@ -6,6 +6,7 @@ import com.supwisdom.dlpay.exception.TransactionCheckException import com.supwisdom.dlpay.exception.TransactionException import com.supwisdom.dlpay.framework.ResponseBodyBuilder import com.supwisdom.dlpay.framework.service.CommonService +import com.supwisdom.dlpay.framework.tenant.TenantContext import com.supwisdom.dlpay.framework.util.TradeErrorCode import mu.KotlinLogging import org.aspectj.lang.ProceedingJoinPoint @@ -117,6 +118,7 @@ class RestControllerAspect { fun logPostMethods(joinPoint: ProceedingJoinPoint, body: Any): Any { return try { if (body is APIRequestParam) { + TenantContext.setTenantSchema(body.tenantid) body.checkParam() if (requestSignCheck && diff --git a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt index 3751c401..e47701ba 100644 --- a/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt +++ b/payapi/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt @@ -13,6 +13,7 @@ import com.supwisdom.dlpay.api.service.* import com.supwisdom.dlpay.exception.TransactionCheckException import com.supwisdom.dlpay.framework.ResponseBodyBuilder import com.supwisdom.dlpay.framework.service.SystemUtilService +import com.supwisdom.dlpay.framework.tenant.TenantContext import com.supwisdom.dlpay.framework.util.* import org.apache.commons.lang3.StringUtils import org.springframework.beans.factory.annotation.Autowired @@ -56,6 +57,7 @@ class ConsumeAPIController { * */ @PostMapping("/queryresult") fun queryDtlResult(@Valid @RequestBody param: QueryDtlResultParam): ResponseEntity { + //TODO 第三方支付,根据支付结果主动触发一次查询 consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let { return ResponseEntity.ok(ResponseBodyBuilder.create() .success(QueryTransDtlResponse(it.refno, it.outTradeNo, it.shopDtl.amount, @@ -463,12 +465,18 @@ class ConsumeAPIController { .fail(apiResp, TradeErrorCode.BUSINESS_DEAL_ERROR, "支付方式<${qrcode.sourceType}>未配置科目号")) } + var systime = systemUtilService.sysdatetime // 2. 记录 qrcode 交易明细表 val qrcodeTrans = agentServiceProxy.qrcodePayTransSaveOrUpdate( QrcodePayTrans().apply { this.agentMerchId = param.shopaccno this.billno = param.billno this.qrcode = param.qrcode + this.createTime = systime.sysdate + this.hostdate = systime.hostdate + this.sourceType = sourceType.sourceType + this.isAnonymous = param.anonymous + this.updateTime = systime.sysdate }) // 3. 查询用户身份 @@ -517,7 +525,7 @@ class ConsumeAPIController { private fun qrcodeSummary(st: TSourceType): String = st.paydesc + "扫码付" - @PostMapping("/qrcodepay/confirm") + @PostMapping("/qrcode/confirm") fun qrcodePayConfirm(@Validated(ConfirmAction::class) @RequestBody param: QrcodePayParam): ResponseEntity { //1. 交易检查 val apiResponse = QrcodePayResponse() @@ -626,4 +634,100 @@ class ConsumeAPIController { } } } + + /** + * ============================================================================ + * 第三方(支付宝、微信)支付【交易初始化】 + * ============================================================================ + * */ + @PostMapping("/thirdpay/payinit") + fun thirdpayInit(@RequestBody param: ThirdPayinitParam): ResponseEntity { + val dtlType = consumePayService.getDtltypeDictionary(param.dtltype, Dictionary.DTLTYPES) + val sourceType = sourceTypeService.getBySourceType(param.sourceType) + ?: return ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(ApiResponse(), TradeErrorCode.BUSINESS_DEAL_ERROR, + "不支持的支付方式<${param.sourceType}>")) + + if (consumePayService.checkShopPaytype(param.shopaccno, sourceType.sourceType)) { + val account = accountUtilServcie.readAccount(param.uid) + val shopacc = accountUtilServcie.readShopbyShopaccno(param.shopaccno) + val subject = accountUtilServcie.readSubject(sourceType.paySubjno) + var transcode=0 + when(sourceType.sourceType){ + TradeDict.PAYTYPE_ALIPAY ->transcode = TradeCode.TRANSCODE_ALIPAY + TradeDict.PAYTYPE_WECHAT ->transcode = TradeCode.TRANSCODE_WECHAT + } + val transaction = TransactionBuilder().apply { + setTransInfo(param.transdate, param.transtime,transcode, + sourceType.sourceType) + setOutTransInfo(shopacc.shopaccno, param.billno) + operator(param.shopaccno, TradeDict.OPERTYPE_SHOP) + + }.person(account).apply { + setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_OUT) + setOpposite(AccountProxy(shopacc)) + }.and().shop(shopacc).apply { + setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_IN) + setOpposite(AccountProxy(account)) + }.and().addDebitCreditRecord(AccountProxy(subject), AccountProxy(account), + param.amount / 100.0, dtlType.dictcaption) + .addDebitCreditRecord(AccountProxy(account), AccountProxy(shopacc), + param.amount / 100.0, dtlType.dictcaption) + .also { + param.feelist?.also { + TODO("feelist 费用清单未实现!") + } + }.init(transactionService) + + return ResponseEntity.ok(ResponseBodyBuilder.create() + .success(ThirdPayResponse(transaction.refno, + transaction.outTradeNo, + transaction.shopDtl.amount,null), "交易初始化成功")) + } + + return ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<第三方支付>")) + } + + + /** + * ============================================================================ + * 第三方(支付宝、微信)支付【交易确认】 + * ============================================================================ + * */ + @PostMapping("/thirdpay/payfinish") + fun thirdpayFinish(@RequestBody param: ThirdPayfinishParam): ResponseEntity { + val dtl = transactionService.wip(param.refno) + var type="" + if(dtl.transCode== TradeCode.TRANSCODE_ALIPAY){ + type = TradeDict.PAYTYPE_ALIPAY + }else if(dtl.transCode== TradeCode.TRANSCODE_WECHAT){ + type = TradeDict.PAYTYPE_WECHAT + } + val service = createAgentService(type) + val resp = service.pay(dtl) + when (resp.code) { + AgentCode.SUCCESS -> + transactionService.success(dtl.refno, resp.agentRefno, false).let { + return ResponseEntity.ok(ResponseBodyBuilder.create() + .success(ThirdPayResponse(it.refno, + it.outTradeNo, + it.shopDtl.amount,resp.agentBody), "交易确认成功")) + + } + AgentCode.REQUIRE_QUERY -> { + //去查询 + return ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(ThirdPayResponse(dtl.refno, + dtl.outTradeNo, + dtl.shopDtl.amount,resp.agentBody), TradeErrorCode.WAIT_QUERY_RESULT, "请查询支付结果")) + } + else -> //失败 + transactionService.fail(param.refno, resp.agentMsg).let { + return ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(ThirdPayResponse(dtl.refno, dtl.outTradeNo, dtl.shopDtl.amount,resp.agentBody), + TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${resp.agentMsg}")) + } + } + } } \ No newline at end of file diff --git a/payapi/src/main/resources/data.sql b/payapi/src/main/resources/data.sql index ac1da71b..7c5abc82 100644 --- a/payapi/src/main/resources/data.sql +++ b/payapi/src/main/resources/data.sql @@ -481,7 +481,7 @@ VALUES ('10', 'alipay', 'alipay.rsa.private.key', '支付宝商户应用RSA私 INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") VALUES ('11', 'alipay', 'alipay.rsa.public.key', '支付宝商户应用RSA公钥', NULL, 'f', '{tenantid}'); INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") -VALUES ('12', 'alipay', 'appid', '支付宝应用APPID', NULL, 'f', '{tenantid}'); +VALUES ('12', 'alipay', 'alipay.appid', '支付宝应用APPID', NULL, 'f', '{tenantid}'); INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") VALUES ('13', 'citizenCard', 'ynrcc.agent.url', '农商行前置地址前缀', NULL, 't', '{tenantid}'); INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") @@ -490,6 +490,18 @@ INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VAL VALUES ('16', 'citizenCard', 'merchant.bankcardno', '商户银行卡号', NULL, 'f', '{tenantid}'); INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") VALUES ('17', 'citizenCard', 'merchant.bankaccname', '银行开户名', NULL, 'f', '{tenantid}'); +INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") +VALUES ('18', 'wechat', 'wechat.appid', '微信APPID', null, 'f', '{tenantid}'); +INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") +VALUES ('19', 'wechat', 'wechat.mechid', '微信商户号', NULL, 'f', '{tenantid}'); +INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") +VALUES ('20', 'wechat', 'wechat.mechkey', '微信商户支付秘钥', NULL, 'f', '{tenantid}'); +INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") +VALUES ('21', 'wechat', 'wechat.notify', '微信支付结果通知地址', NULL, 't', '{tenantid}'); +INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") +VALUES ('22', 'wechat', 'wechat.refund.certpath', '微信退款证书路径', NULL, 'f', '{tenantid}'); +INSERT INTO TB_SOURCETYPE_CONFIG (ID, SOURCETYPE,CONFIGID,CONFIG_NAME,CONFIG_VALUE,GLOBALFLAG, "tenantid") +VALUES ('23', 'wechat', 'wechat.refund.certpwd', '微信退款证书密码', NULL, 'f', '{tenantid}'); INSERT INTO "tb_syspara" ("paraid", "displayflag", "editflag", "lastsaved", "paraname", "paraunit", "paraval", "remark", "valuetype", "tenantid") VALUES (1, 'yes', 1, '20190514165658', '账户最大余额默认值', '元', '10001', '账户开户时的默认账户最大余额', 'amount', '{tenantid}');