From: Xia Kaixiang Date: Thu, 9 May 2019 10:45:38 +0000 (+0800) Subject: API请求Sign计算优化 X-Git-Tag: 1.0.0^2~229 X-Git-Url: https://source.supwisdom.com/gerrit/gitweb?a=commitdiff_plain;h=f712f3f3a29949f4bd82222e773a9c4090e03f60;p=epayment%2Ffood_payapi.git API请求Sign计算优化 --- diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TPaytype.java b/src/main/java/com/supwisdom/dlpay/api/domain/TPaytype.java index 58725608..be801038 100644 --- a/src/main/java/com/supwisdom/dlpay/api/domain/TPaytype.java +++ b/src/main/java/com/supwisdom/dlpay/api/domain/TPaytype.java @@ -21,6 +21,9 @@ public class TPaytype { @Column(name = "CONSUME_ENABLE",nullable = false, length = 10) private String consumeEnable; + @Column(name = "ANONYMOUS_ENABLE", nullable = false, length = 10) + private String anonymousEnable; + @Column(name = "PAYDESC", length = 200) private String paydesc; @@ -56,6 +59,14 @@ public class TPaytype { this.consumeEnable = consumeEnable; } + public String getAnonymousEnable() { + return anonymousEnable; + } + + public void setAnonymousEnable(String anonymousEnable) { + this.anonymousEnable = anonymousEnable; + } + public String getPaydesc() { return paydesc; } diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TShopPaytype.java b/src/main/java/com/supwisdom/dlpay/api/domain/TShopPaytype.java index 81c893ca..cb4662e4 100644 --- a/src/main/java/com/supwisdom/dlpay/api/domain/TShopPaytype.java +++ b/src/main/java/com/supwisdom/dlpay/api/domain/TShopPaytype.java @@ -17,6 +17,9 @@ public class TShopPaytype { @Column(name = "CONSUME_ENABLE", nullable = false, length = 10) private String consumeEnable; + @Column(name = "ANONYMOUS_ENABLE", nullable = false, length = 10) + private String anonymousEnable; + @Column(name = "REVERSE_ENABLE", nullable = false, length = 10) private String reverseEnable; @@ -47,6 +50,14 @@ public class TShopPaytype { this.consumeEnable = consumeEnable; } + public String getAnonymousEnable() { + return anonymousEnable; + } + + public void setAnonymousEnable(String anonymousEnable) { + this.anonymousEnable = anonymousEnable; + } + public String getReverseEnable() { return reverseEnable; } diff --git a/src/main/java/com/supwisdom/dlpay/api/domain/TUserdtl.java b/src/main/java/com/supwisdom/dlpay/api/domain/TUserdtl.java index fc89e320..aa195a73 100644 --- a/src/main/java/com/supwisdom/dlpay/api/domain/TUserdtl.java +++ b/src/main/java/com/supwisdom/dlpay/api/domain/TUserdtl.java @@ -7,7 +7,8 @@ import javax.persistence.*; indexes = {@Index(name = "userdtl_transdate_idx", columnList = "transdate"), @Index(name = "userdtl_accdate_idx", columnList = "accdate"), @Index(name = "userdtl_status_idx", columnList = "status"), - @Index(name = "userdtl_reverse_idx", columnList = "REVERSE_FLAG")}) + @Index(name = "userdtl_reverse_idx", columnList = "REVERSE_FLAG"), + @Index(name = "userdtl_outtradeno_uk", unique = true, columnList = "outtradeno,shopaccno")}) public class TUserdtl { @Id @Column(name = "REFNO", nullable = false, length = 32) diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/APIRequest.java b/src/main/java/com/supwisdom/dlpay/framework/util/APIRequest.java deleted file mode 100644 index 66791812..00000000 --- a/src/main/java/com/supwisdom/dlpay/framework/util/APIRequest.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.supwisdom.dlpay.framework.util; - -public class APIRequest { - private String app_id; - private String sign; - private String sign_method; - private String timestamp; - - public String getApp_id() { - return app_id; - } - - public void setApp_id(String app_id) { - this.app_id = app_id; - } - - public String getSign() { - return sign; - } - - public void setSign(String sign) { - this.sign = sign; - } - - public String getSign_method() { - return sign_method; - } - - public void setSign_method(String sign_method) { - this.sign_method = sign_method; - } - - public String getTimestamp() { - return timestamp; - } - - public void setTimestamp(String timestamp) { - this.timestamp = timestamp; - } - -} diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java b/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java new file mode 100644 index 00000000..78ea9d40 --- /dev/null +++ b/src/main/java/com/supwisdom/dlpay/framework/util/APIRequestParam.java @@ -0,0 +1,99 @@ +package com.supwisdom.dlpay.framework.util; + +import org.apache.log4j.Logger; + +import java.beans.Introspector; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +public class APIRequestParam { + @Sign + private String sign; + @Sign + private String sign_type; + @Sign + private String version; + + private static final Logger logger = Logger.getLogger(APIRequestParam.class); + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getSign_type() { + return sign_type; + } + + public void setSign_type(String sign_type) { + this.sign_type = sign_type; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + private boolean calcSignAndCheck(Map map, String key) { + String sign = map.get("sign"); + String signType = map.get("sign_type") == null ? "MD5" : map.get("sign_type"); + if (StringUtil.isEmpty(sign)) return false; + + String signdata = StringUtil.createLinkString(StringUtil.paraFilter(map)); + logger.info("signdata=[" + signdata + "]"); + + String calcSign = null; + //fixme: 根据 signType 计算签名 + if ("MD5".equalsIgnoreCase(signType)) { + calcSign = MD5.encodeByMD5(signdata + key); //默认MD5 + } + + if (sign.equalsIgnoreCase(calcSign)) { + return true; + } + return false; + } + + public boolean checkSign(String key){ + Class clazz = this.getClass(); + Map paramMap = new HashMap<>(); + Method[] allGetter = clazz.getMethods(); + + for (Method meth : allGetter) { + if (meth.getName().startsWith("get") || meth.getName().startsWith("is")) { + String fieldName = Introspector.decapitalize(meth.getName().substring(meth.getName().startsWith("get") ? 3 : 2)); + Field field; + try { + field = clazz.getDeclaredField(fieldName); + } catch (NoSuchFieldException e) { + try { + field = clazz.getSuperclass().getDeclaredField(fieldName); + } catch (NoSuchFieldException e1) { +// e1.printStackTrace(); + continue; + } + } + + if (field.isAnnotationPresent(Sign.class)) { + Object value; + try { + value = meth.invoke(this); + } catch (Exception e) { + e.printStackTrace(); + continue; + } + paramMap.put(fieldName, value == null ? null : value.toString()); + } + } + } + return calcSignAndCheck(paramMap,key); + } +} diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/Sign.java b/src/main/java/com/supwisdom/dlpay/framework/util/Sign.java new file mode 100644 index 00000000..399da556 --- /dev/null +++ b/src/main/java/com/supwisdom/dlpay/framework/util/Sign.java @@ -0,0 +1,12 @@ +package com.supwisdom.dlpay.framework.util; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Sign { + int order() default 0; +} diff --git a/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java b/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java index 2b392b32..7bec4217 100644 --- a/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java +++ b/src/main/java/com/supwisdom/dlpay/framework/util/TradeDict.java @@ -47,6 +47,7 @@ public class TradeDict { public static final String PAYTYPE_ALIPAY = "alipay"; //市民卡 public static final String PAYTYPE_WECHAT = "wechat"; //市民卡 public static final String PAYTYPE_CITIZEN_CARD = "citizenCard"; //市民卡 + public static final String PAYTYPE_YKT_CARD = "yktpay"; //一卡通 /** diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt b/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt index 90871495..414da8e6 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/bean/api_request_param.kt @@ -1,45 +1,31 @@ package com.supwisdom.dlpay.api.bean import com.supwisdom.dlpay.exception.RequestParamCheckException -import com.supwisdom.dlpay.framework.util.DateUtil -import com.supwisdom.dlpay.framework.util.MD5 -import com.supwisdom.dlpay.framework.util.StringUtil -import com.supwisdom.dlpay.framework.util.TradeErrorCode +import com.supwisdom.dlpay.framework.util.* import com.supwisdom.dlpay.util.ConstantUtil -open class APIRequestParam { - open val param_map = mutableMapOf() - - open fun checkSign(key: String): Boolean { - val sign = param_map["sign"] - val signType = param_map["sign_type"] ?: "MD5" - if (StringUtil.isEmpty(sign)) return false //未签名 - - //判断签名 - val signdata = StringUtil.createLinkString(StringUtil.paraFilter(param_map)) - val md5Sign = MD5.encodeByMD5(signdata + key) //默认MD5 - if (sign.equals(md5Sign, true)) { - return true - } - return false - } -} - - // ============================ USER ============================ // class OpenUserParam : APIRequestParam() { + @Sign var uid: String = "" //第三方用户ID,必传 + @Sign var name: String = "" //必传 + @Sign var sex: String? = null + @Sign var idtype: String = "" //必传 + @Sign var idno: String = "" //必传 + @Sign var mobile: String? = null + @Sign var tel: String? = null + @Sign var email: String? = null + @Sign var address: String? = null + @Sign var zipcode: String? = null - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(uid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "用户唯一号不能为空") @@ -51,39 +37,46 @@ class OpenUserParam : APIRequestParam() { if (!StringUtil.isEmpty(mobile) && !StringUtil.isMobile(mobile)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "手机号格式错误") if (!StringUtil.isEmpty(email) && !StringUtil.isEmail(email)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "邮箱格式错误") - param_map.plus(mapOf("uid" to uid, "name" to name, "sex" to sex, "idtype" to idtype, "idno" to idno, "mobile" to mobile, "tel" to tel, "email" to email, "address" to address, "zipcode" to zipcode, "sign" to sign, "sign_type" to sign_type)) return true } } class QueryUserParam : APIRequestParam() { + @Sign var userid: String? = null // 用户ID二选一 (两者都传取userid) + @Sign var uid: String? = null // 用户ID二选一 - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(userid) && StringUtil.isEmpty(uid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "用户唯一号不能为空") - param_map.plus(mapOf("userid" to userid, "uid" to uid, "sign" to sign, "sign_type" to sign_type)) return true } } class ModifyUserParam : APIRequestParam() { + @Sign var userid: String? = null // 用户ID二选一 (两者都传取userid) + @Sign var uid: String? = null // 用户ID二选一 + @Sign var name: String? = null + @Sign var sex: String? = null + @Sign var idtype: String? = null + @Sign var idno: String? = null + @Sign var mobile: String? = null + @Sign var tel: String? = null + @Sign var email: String? = null + @Sign var address: String? = null + @Sign var zipcode: String? = null - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(userid) && StringUtil.isEmpty(uid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "用户唯一号不能为空") @@ -95,8 +88,6 @@ class ModifyUserParam : APIRequestParam() { if (!StringUtil.isEmpty(mobile) && !StringUtil.isMobile(mobile)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "手机号格式错误") if (!StringUtil.isEmpty(email) && !StringUtil.isEmail(email)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "邮箱格式错误") - - param_map.plus(mapOf("userid" to userid, "uid" to uid, "name" to name, "sex" to sex, "idtype" to idtype, "idno" to idno, "mobile" to mobile, "tel" to tel, "email" to email, "address" to address, "zipcode" to zipcode, "sign" to sign, "sign_type" to sign_type)) return true } } @@ -104,19 +95,28 @@ class ModifyUserParam : APIRequestParam() { // ============================ SHOP ============================ // class OpenShopParam : APIRequestParam() { + @Sign var shopUniqueId: String = "" //必传 + @Sign var shoptype: Int = 1 + @Sign var fshopid: Int? = null + @Sign var shopname: String = "" //必传 + @Sign var contactman: String? = null + @Sign var idtype: String? = null + @Sign var idno: String? = null + @Sign var mobile: String? = null + @Sign var email: String? = null + @Sign var address: String? = null + @Sign var zipcode: String? = null - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(shopUniqueId)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "商户唯一号不能为空") @@ -128,22 +128,21 @@ class OpenShopParam : APIRequestParam() { if (!StringUtil.isEmpty(mobile) && !StringUtil.isMobile(mobile)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "手机号格式错误") if (!StringUtil.isEmpty(email) && !StringUtil.isEmail(email)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "邮箱格式错误") - param_map.plus(mapOf("shopUniqueId" to shopUniqueId, "shoptype" to shoptype, "fshopid" to fshopid, "shopname" to shopname, "contactman" to contactman, "idtype" to idtype, "idno" to idno, "mobile" to mobile, "email" to email, "address" to address, "zipcode" to zipcode, "sign" to sign, "sign_type" to sign_type)) return true } } class QueryShopParam : APIRequestParam() { + @Sign var shopid: Int? = null //注册时返回的shopid + @Sign var shopaccno: String? = null //注册时返回的shopaccno + @Sign var shopUniqueId: String? = null //注册传的商户唯一号 - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(shopUniqueId) && null == shopid && StringUtil.isEmpty(shopaccno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "商户唯一标志不能为空") - param_map.plus(mapOf("shopUniqueId" to shopUniqueId, "shopid" to shopid, "shopaccno" to shopaccno, "sign" to sign, "sign_type" to sign_type)) return true } } @@ -153,34 +152,42 @@ class QueryShopParam : APIRequestParam() { class ConsumeFeetype { var feetype: String = "" var amount: Int = 0 + + override fun toString(): String { + return "{feetype='$feetype', amount=$amount}" + } } class QueryDtlResultParam : APIRequestParam() { + @Sign var refno:String?=null //二选一 + @Sign var billno:String?=null //二选一 (billno+shopaccno) ä¼ billno时,shopaccno必传 + @Sign var shopaccno: String?=null - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(refno) && (StringUtil.isEmpty(billno) || StringUtil.isEmpty(shopaccno))) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "流水唯一号不能为空") - param_map.plus(mapOf("refno" to refno, "billno" to billno, "shopaccno" to shopaccno, "sign" to sign, "sign_type" to sign_type)) return true } } class CitizenCardPayinitParam : APIRequestParam() { + @Sign var cardNo: String = "" //必传 + @Sign var shopaccno: String = "" //必传 + @Sign var amount: Int = 0 //必传 - var feelist: List? = null// 的json字符串 + + var feelist: List? = null //TODO: 怎么拼接签名字符串?? + @Sign var billno: String = "" //必传 + @Sign var transdate: String = "" //必传 + @Sign var transtime: String = "" //必传 - var extend_data: String? = null //扩展参数,原样返回 - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(cardNo)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "卡唯一号不能为空") @@ -190,20 +197,17 @@ class CitizenCardPayinitParam : APIRequestParam() { if (!DateUtil.checkDatetimeValid(transdate, DateUtil.DATE_FMT)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "交易日期错误[yyyyMMdd]") if (!DateUtil.checkDatetimeValid(transtime, DateUtil.TIME_FMT)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "交易时间错误[HHmmss]") - param_map.plus(mapOf("cardNo" to cardNo, "amount" to amount, "feelist" to feelist, "shopaccno" to shopaccno, "billno" to billno, "transdate" to transdate, "transtime" to transtime, "sign" to sign, "sign_type" to sign_type)) return true } } class CitizenCardPayfinishParam : APIRequestParam() { + @Sign var refno:String="" - var sign: String = "" //必传 - var sign_type: String? = null fun checkParam(): Boolean { if (StringUtil.isEmpty(refno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "交易参考号不能为空") - param_map.plus(mapOf("refno" to refno, "sign" to sign, "sign_type" to sign_type)) return true } } diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/comsume_builder.kt b/src/main/kotlin/com/supwisdom/dlpay/api/comsume_builder.kt index 94e5a08a..2c1555c2 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/comsume_builder.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/comsume_builder.kt @@ -85,6 +85,7 @@ class PersonTransBuilder private constructor(accUitl: AccountUtilServcie) { lateinit var tradetype: Tradetype lateinit var refno: String lateinit var status: String + lateinit var shopaccno: String val resultMap = mutableMapOf() //存调第三方结果数据 var transcode = 0 @@ -196,20 +197,11 @@ class PersonTransBuilder private constructor(accUitl: AccountUtilServcie) { } } - amount = 0.0 if (this.details.size < 1) { throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "未指定交易明细") } - val buyer = accountUtil.readAccount(person.userid) //判断是一个人的流水 amount = this.details.sumByDouble { detail -> - if (detail.debitSubjNo == buyer.subjno && detail.debitAccNo != buyer.accno) { - throw throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "交易明细用户错误") - } - - if (detail.creditSubjNo == buyer.subjno && detail.creditAccNo != buyer.accno) { - throw throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "交易明细用户错误") - } detail.amount } @@ -225,6 +217,8 @@ class PersonTransBuilder private constructor(accUitl: AccountUtilServcie) { if (StringUtil.isEmpty(this.outtradeno)) { throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "未传递外部流水号") } + + } private fun preCheckAccount() { @@ -244,6 +238,7 @@ class PersonTransBuilder private constructor(accUitl: AccountUtilServcie) { it.accno to it.subjno } AccountHolder.IDTYPE_SHOP -> holder.withLock().let { + if(null==this.shopaccno) this.shopaccno=it.shopaccno it.shopaccno to it.subjno } AccountHolder.IDTYPE_SUBJECT -> holder.withLock().let { @@ -257,6 +252,7 @@ class PersonTransBuilder private constructor(accUitl: AccountUtilServcie) { it.accno to it.subjno } AccountHolder.IDTYPE_SHOP -> holder.get().let { + if(null==this.shopaccno) this.shopaccno=it.shopaccno it.shopaccno to it.subjno } AccountHolder.IDTYPE_SUBJECT -> holder.get().let { diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt b/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt index debf0e59..a35b8cef 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/controller/consume_api_controller.kt @@ -89,29 +89,34 @@ class ConsumeController { } val person = userService.findPersonByIdentityCheckStatus(param.cardNo) - val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) - .chooseTradetype(Tradetype.CONSUME) //消费 - .setOwner(person) //记名 - .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易") - .setTransDatetime(param.transdate, param.transtime) //交易时间 - .selectPaytype(TradeDict.PAYTYPE_CITIZEN_CARD, param.cardNo) - .addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_CITIZEN_CARD), - AccountHolder.shop(param.shopaccno), - param.amount / 100.0, "市民卡代扣消费") - .also { builder -> - param.feelist?.forEach { - builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_CITIZEN_CARD) - .with(AccountHolder.shop(param.shopaccno)) - .with(AccountHolder.subject(Subject.SUBJNO_PAY_CITIZEN_CARD)) - , it.amount / 100.0) + if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_CITIZEN_CARD)) { + val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) + .chooseTradetype(Tradetype.CONSUME) //消费 + .setOwner(person) //记名 + .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易") + .setTransDatetime(param.transdate, param.transtime) //交易时间 + .selectPaytype(TradeDict.PAYTYPE_CITIZEN_CARD, param.cardNo) + .addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_CITIZEN_CARD), + AccountHolder.shop(param.shopaccno), + param.amount / 100.0, "市民卡代扣消费") + .also { builder -> + param.feelist?.forEach { + builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_CITIZEN_CARD) + .with(AccountHolder.shop(param.shopaccno)) + .with(AccountHolder.subject(Subject.SUBJNO_PAY_CITIZEN_CARD)) + , it.amount / 100.0) + } } - } - .init(personBalancePayService) + .init(personBalancePayService) + + ResponseEntity.ok(ResponseBodyBuilder.create() + .data("refno", dtl.refno) + .data("amount", dtl.amount) + .success("交易初始化成功")) + } ResponseEntity.ok(ResponseBodyBuilder.create() - .data("refno", dtl.refno) - .data("amount", dtl.amount) - .success("交易初始化成功")) + .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<市民卡代扣>")) } catch (ex: RequestParamCheckException) { ResponseEntity.ok(ResponseBodyBuilder.create() @@ -166,6 +171,9 @@ class ConsumeController { } } + /** + * 账户余额支付 + * */ @PostMapping("/balance/pay") fun balancePay(@RequestBody param: CitizenCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity { return try { @@ -175,29 +183,34 @@ class ConsumeController { } val person = userService.findPersonByIdentityCheckStatus(param.cardNo) - val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) - .chooseTradetype(Tradetype.CONSUME) //消费 - .setOwner(person) //记名 - .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易") - .setTransDatetime(param.transdate, param.transtime) //交易时间 - .selectPaytype(TradeDict.PAYTYPE_BALANCE, param.cardNo) - .addDetail(AccountHolder.person(person.userid), - AccountHolder.shop(param.shopaccno), - param.amount / 100.0, "账户余额消费") - .also { builder -> - param.feelist?.forEach { - builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_BALANCE) - .with(AccountHolder.shop(param.shopaccno)) - .with(AccountHolder.person(person.userid)) - , it.amount / 100.0) + if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_BALANCE)) { + val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) + .chooseTradetype(Tradetype.CONSUME) //消费 + .setOwner(person) //记名 + .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易") + .setTransDatetime(param.transdate, param.transtime) //交易时间 + .selectPaytype(TradeDict.PAYTYPE_BALANCE, param.cardNo) + .addDetail(AccountHolder.person(person.userid), + AccountHolder.shop(param.shopaccno), + param.amount / 100.0, "账户余额消费") + .also { builder -> + param.feelist?.forEach { + builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_BALANCE) + .with(AccountHolder.shop(param.shopaccno)) + .with(AccountHolder.person(person.userid)) + , it.amount / 100.0) + } } - } - .done(personBalancePayService) + .done(personBalancePayService) + + ResponseEntity.ok(ResponseBodyBuilder.create() + .data("refno", dtl.refno) + .data("amount", dtl.amount) + .success("交易成功")) + } ResponseEntity.ok(ResponseBodyBuilder.create() - .data("refno", dtl.refno) - .data("amount", dtl.amount) - .success("交易成功")) + .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<账户余额>")) } catch (ex: RequestParamCheckException) { ResponseEntity.ok(ResponseBodyBuilder.create() @@ -208,6 +221,59 @@ class ConsumeController { } } + /** + * 一卡通支付 + * */ + @PostMapping("/ykt/payinit") + fun yktPayInit(@RequestBody param: CitizenCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity { + return try { + if (param.checkParam() && param.checkSign(commonService.getAppidSecretByRequest(request))) { + ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误")) + } + + var person = userService.findByThirdUniqueIdenty(param.cardNo) //可能匿名? + if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_YKT_CARD, person==null)) { + val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) + .chooseTradetype(Tradetype.CONSUME) //消费 + .also { + if(null!=person) it.setOwner(person) + } + .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易") + .setTransDatetime(param.transdate, param.transtime) //交易时间 + .selectPaytype(TradeDict.PAYTYPE_YKT_CARD, param.cardNo) + .addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_YKT), + AccountHolder.shop(param.shopaccno), + param.amount / 100.0, "一卡通支付") + .also { builder -> + param.feelist?.forEach { + builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_YKT_CARD) + .with(AccountHolder.shop(param.shopaccno)) + .with(AccountHolder.subject(Subject.SUBJNO_PAY_YKT)) + , it.amount / 100.0) + } + } + .init(personBalancePayService) + + ResponseEntity.ok(ResponseBodyBuilder.create() + .data("refno", dtl.refno) + .data("amount", dtl.amount) + .success("交易初始化成功")) + + + } + + ResponseEntity.ok(ResponseBodyBuilder.create() + .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<一卡通支付>")) + } catch (ex: RequestParamCheckException) { + ResponseEntity.ok(ResponseBodyBuilder.create() + .requestException(ex, "请求参数错误")) + } catch (et: TransactionException) { + ResponseEntity.ok(ResponseBodyBuilder.create() + .transException(et, "业务处理错误")) + } + } + // ============================================== // // // @GetMapping("/account/payinit") @@ -231,62 +297,8 @@ class ConsumeController { // .done(refno, TradeDict.DTL_STATUS_SUCCESS, personBalancePayService) // return ResponseEntity.ok(dtl) // } -// -// @PostMapping("/ykt/payinit") -// fun yktPayInit(userid: String, amount: Int, manageFee: Int, -// stuempno: String, shopid: String, transdate: String, transtime: String, -// outtradeno: String, payinfo: String, feetype: String): ResponseEntity { -// //一卡通支付款 112240 -// return try { -// val paytype = paytypeService.getByPaytype(PaytypeUtil.YKTPAY) -// if (paytype == null || ConstantUtil.ENABLE_YES != paytype.enable) { -// ResponseEntity.ok(ResponseBodyBuilder.create() -// .fail(1, "支付方式未开启")) -// } -// val person = userService.findByThirdUniqueIdenty(stuempno) -// val dtl = PersonTransBuilder.newBuilder(accountUtilServcie) -// .setTransDatetime(transdate, transtime) -// .selectPaytype(PaytypeUtil.YKTPAY, payinfo) -// .setOuttradeno(outtradeno) -// .also { -// if (null != person) it.setOwner(person) -// } -// .tryLock(true) -// .setTransinfo(TradeCode.TRANSCODE_YKTPAY, "一卡通支付") -// .chooseTradetype(Tradetype.CONSUME) -// .also { -// when (feetype) { -// TradeDict.FEETYPE_CONSUME_MEALER -> { -// it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_YKT), -// AccountHolder.shop(shopid), -// amount / 100.0, "一卡通支付") -// .addDetail(AccountHolder.transType(TranstypeCode.TT_CONSUUME_MANAGE_FEE) -// .with(AccountHolder.shop(shopid)), -// manageFee / 100.0) -// } -// TradeDict.FEETYPE_CONSUME_DISCOUNT -> { -// it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_YKT), -// AccountHolder.shop(shopid), -// (amount - manageFee) / 100.0, "一卡通支付") -// .addDetail(AccountHolder.subject(Subject.SUBJNO_CONSUME_DISCOUNT), -// AccountHolder.shop(shopid), -// manageFee / 100.0, "优惠折扣") -// } -// else -> { -// it.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_YKT), -// AccountHolder.shop(shopid), -// amount / 100.0, "一卡通支付") -// } -// } -// }.done(personBalancePayService, false) -// ResponseEntity.ok(ResponseBodyBuilder.create() -// .data("refno", dtl.refno) -// .success()) -// } catch (e: TransactionException) { -// ResponseEntity.ok(ResponseBodyBuilder.create() -// .transException(e, "交易初始化异常")) -// } -// } + + // // @PostMapping("/ykt/payfinish") // fun yktPayFinish(refno: String, yktshopid: String, devphyid: String?): ResponseEntity { diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt index 5d85e0f6..a81b21a0 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/consume_pay_service.kt @@ -5,8 +5,8 @@ import org.springframework.transaction.annotation.Transactional interface ConsumePayService{ @Transactional(propagation = Propagation.REQUIRED, rollbackFor = arrayOf(Exception::class)) - fun checkShopPaytype(shopaccno: String, paytype: String): Boolean + fun checkShopPaytype(shopaccno: String, paytype: String, anonymousflag: Boolean? = false): Boolean @Transactional(propagation = Propagation.REQUIRED, rollbackFor = arrayOf(Exception::class)) - fun getPaytypeConfig(paytype: String, shopaccno: String, ignoreStatus: Boolean? = false): Map + fun getPaytypeConfig(paytype: String, shopaccno: String, anonymousflag: Boolean? = false, ignoreStatus: Boolean? = false): Map } \ No newline at end of file diff --git a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/Consume_pay_service_impl.kt b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/Consume_pay_service_impl.kt index cdb134b4..6f361556 100644 --- a/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/Consume_pay_service_impl.kt +++ b/src/main/kotlin/com/supwisdom/dlpay/api/service/impl/Consume_pay_service_impl.kt @@ -20,7 +20,7 @@ class ConsumePayServiceImpl: ConsumePayService{ @Autowired lateinit var shopPaytypeConfigDao: ShopPaytypeConfigDao - override fun checkShopPaytype(shopaccno: String, paytype: String): Boolean{ + override fun checkShopPaytype(shopaccno: String, paytype: String, anonymousflag: Boolean?): Boolean{ paytypeDao.getByPaytype(paytype).let { if (null == it) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[$paytype]") @@ -28,6 +28,9 @@ class ConsumePayServiceImpl: ConsumePayService{ if (ConstantUtil.ENABLE_YES != it.enable || ConstantUtil.ENABLE_YES != it.consumeEnable) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统未启用支付方式[$paytype]消费") } + if (true == anonymousflag && ConstantUtil.ENABLE_YES != it.anonymousEnable) { + throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统支付方式[$paytype]未启用匿名消费") + } } } shopPaytypeDao.getById(paytype, shopaccno).let { @@ -37,12 +40,15 @@ class ConsumePayServiceImpl: ConsumePayService{ if (ConstantUtil.ENABLE_YES != it.consumeEnable) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "该商户[$shopaccno]未启用支付方式[$paytype]") } + if (true == anonymousflag && ConstantUtil.ENABLE_YES != it.anonymousEnable) { + throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "该商户[$shopaccno]的支付方式[$paytype]未启用匿名消费") + } } } return true } - override fun getPaytypeConfig(paytype: String, shopaccno: String, ignoreStatus: Boolean?): Map { + override fun getPaytypeConfig(paytype: String, shopaccno: String, anonymousflag: Boolean?, ignoreStatus: Boolean?): Map { paytypeDao.getByPaytype(paytype).let { if (null == it) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[$paytype]") @@ -50,6 +56,9 @@ class ConsumePayServiceImpl: ConsumePayService{ if (true != ignoreStatus && (ConstantUtil.ENABLE_YES != it.enable || ConstantUtil.ENABLE_YES != it.consumeEnable)) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统未启用支付方式[$paytype]消费") } + if (true != ignoreStatus && true == anonymousflag && ConstantUtil.ENABLE_YES != it.anonymousEnable) { + throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统支付方式[$paytype]未启用匿名消费") + } } } @@ -60,6 +69,9 @@ class ConsumePayServiceImpl: ConsumePayService{ if (true != ignoreStatus && ConstantUtil.ENABLE_YES != it.consumeEnable) { throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "该商户[$shopaccno]未启用支付方式[$paytype]") } + if (true != ignoreStatus && true == anonymousflag && ConstantUtil.ENABLE_YES != it.anonymousEnable) { + throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "该商户[$shopaccno]的支付方式[$paytype]未启用匿名消费") + } } }