import com.supwisdom.dlpay.api.bean.CitizenCardPayfinishParam
import com.supwisdom.dlpay.api.bean.CitizenCardPayinitParam
import com.supwisdom.dlpay.api.bean.QueryDtlResultParam
+import com.supwisdom.dlpay.api.bean.YktCardPayinitParam
import com.supwisdom.dlpay.api.service.*
import com.supwisdom.dlpay.exception.RequestParamCheckException
import com.supwisdom.dlpay.exception.TransactionException
+import com.supwisdom.dlpay.exception.TransactionProcessException
import com.supwisdom.dlpay.framework.ResponseBodyBuilder
import com.supwisdom.dlpay.framework.service.CommonService
import com.supwisdom.dlpay.framework.service.SystemUtilService
}
/**
- * 市民卡交易初始化
+ * ============================================================================
+ * 账户【余额支付】
+ * ============================================================================
+ * */
+ @PostMapping("/balance/pay")
+ fun balancePay(@RequestBody param: CitizenCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
+ return try {
+ if (param.checkParam() && param.checkSign(commonService.getAppidSecretByRequest(request))) {
+ ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
+ }
+
+ val person = userService.findPersonByIdentityCheckStatus(param.cardNo)
+ if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_BALANCE)) {
+ val dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
+ .chooseTradetype(Tradetype.CONSUME) //消费
+ .setOwner(person) //记名
+ .setTransinfo(TradeCode.TRANSCODE_BALANCE_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 {
+ when(it.feetype){
+ TradeDict.FEETYPE_CONSUME_MEALER -> {
+ if (it.amount <= 0) {
+ throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "费用类别<${it.feetype}>的金额不能为负")
+ }
+ builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_BALANCE)
+ .with(AccountHolder.shop(param.shopaccno))
+ .with(AccountHolder.person(person.userid))
+ , it.amount / 100.0)
+ }
+ TradeDict.FEETYPE_CONSUME_DISCOUNT->{
+ TODO("折扣逻辑暂缺")
+ }
+ else -> throw TransactionProcessException(TradeErrorCode.FEETYPE_NOT_NOSUPPORT, "费用类别<${it.feetype}>不支持")
+ }
+
+ }
+ }
+ .done(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, "业务处理错误"))
+ }
+ }
+
+
+
+ /**
+ * ============================================================================
+ * 市民卡【交易初始化】
+ * ============================================================================
* */
@PostMapping("/citizencard/payinit")
fun citizencardPayinit(@RequestBody param: CitizenCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
val dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
.chooseTradetype(Tradetype.CONSUME) //消费
.setOwner(person) //记名
- .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易")
+ .setTransinfo(TradeCode.TRANSCODE_CITIZENCARD_PAY, "市民卡代扣消费")
.setTransDatetime(param.transdate, param.transtime) //交易时间
.selectPaytype(TradeDict.PAYTYPE_CITIZEN_CARD, param.cardNo)
.addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_CITIZEN_CARD),
param.amount / 100.0, "市民卡代扣消费")
.also { builder ->
param.feelist?.forEach {
+ //fixme: 科目 -> 商户 与个人无关
builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_CITIZEN_CARD)
.with(AccountHolder.shop(param.shopaccno))
.with(AccountHolder.subject(Subject.SUBJNO_PAY_CITIZEN_CARD))
}
/**
- * 市民卡交易确认
+ * ============================================================================
+ * 市民卡【交易确认】
+ * ============================================================================
* */
@PostMapping("/citizencard/payfinish")
fun citizencardPayinit(@RequestBody param: CitizenCardPayfinishParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
var dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
.setRefno(param.refno)
.wip(personBalancePayService)
- val code = CallService.CallCitizenCardPay(consumePayService.getPaytypeConfig(TradeDict.PAYTYPE_CITIZEN_CARD, "shopaccno"), dtl)
+ val code = CallService.CallCitizenCardPay(consumePayService.getPaytypeConfig(TradeDict.PAYTYPE_CITIZEN_CARD, dtl.shopaccno), dtl)
if (code.retcode == "0") {
dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
.setRefno(param.refno)
}
}
+
+
/**
- * 账户余额支付
+ * ============================================================================
+ * 一卡通支付【交易初始化】
+ * ============================================================================
* */
- @PostMapping("/balance/pay")
- fun balancePay(@RequestBody param: CitizenCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
+ @PostMapping("/ykt/payinit")
+ fun yktPayInit(@RequestBody param: YktCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
return try {
if (param.checkParam() && param.checkSign(commonService.getAppidSecretByRequest(request))) {
ResponseEntity.ok(ResponseBodyBuilder.create()
.fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
}
- val person = userService.findPersonByIdentityCheckStatus(param.cardNo)
- if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_BALANCE)) {
+ val person = param.uid?.let { userService.findByThirdUniqueIdenty(it) } ?: null //没注册,可能匿名?
+ if (consumePayService.checkShopPaytype(param.shopaccno, TradeDict.PAYTYPE_YKT_CARD, person==null)) {
val dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
.chooseTradetype(Tradetype.CONSUME) //消费
- .setOwner(person) //记名
- .setTransinfo(TradeCode.TRANSCODE_PAY, "支付交易")
+ .also {
+ if (null != person) it.setOwner(person)
+ }
+ .setTransinfo(TradeCode.TRANSCODE_YKTCARD_PAY, "一卡通支付")
.setTransDatetime(param.transdate, param.transtime) //交易时间
- .selectPaytype(TradeDict.PAYTYPE_BALANCE, param.cardNo)
- .addDetail(AccountHolder.person(person.userid),
+ .selectPaytype(TradeDict.PAYTYPE_YKT_CARD, param.stuempno)
+ .addDetail(AccountHolder.subject(Subject.SUBJNO_PAY_YKT),
AccountHolder.shop(param.shopaccno),
- param.amount / 100.0, "账户余额消费")
+ param.amount / 100.0, "一卡通支付")
.also { builder ->
param.feelist?.forEach {
- builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_BALANCE)
+ //fixme: 科目 -> 商户 与个人无关
+ builder.addDetail(AccountHolder.feetype(it.feetype, TradeDict.PAYTYPE_YKT_CARD)
.with(AccountHolder.shop(param.shopaccno))
- .with(AccountHolder.person(person.userid))
+ .with(AccountHolder.subject(Subject.SUBJNO_PAY_YKT))
, it.amount / 100.0)
}
}
- .done(personBalancePayService)
+ .addExtendParam("stuempno", param.stuempno)
+ .addExtendParam("yktshopid", param.yktshopid ?: "")
+ .addExtendParam("devphyid", param.devphyid ?: "")
+ //.addExtendParam(param.extendmap) //fixme: 保存调一卡通附加参数 (是否直接传附加参数map)
+ .init(personBalancePayService)
ResponseEntity.ok(ResponseBodyBuilder.create()
.data("refno", dtl.refno)
.data("amount", dtl.amount)
- .success("交易成功"))
+ .success("交易初始化成功"))
+
}
ResponseEntity.ok(ResponseBodyBuilder.create()
- .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<账户余额>"))
-
+ .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<一卡通支付>"))
} catch (ex: RequestParamCheckException) {
ResponseEntity.ok(ResponseBodyBuilder.create()
.requestException(ex, "请求参数错误"))
}
}
+
/**
- * 一卡通支付
+ * ============================================================================
+ * 一卡通支付【交易确认】
+ * ============================================================================
* */
- @PostMapping("/ykt/payinit")
- fun yktPayInit(@RequestBody param: CitizenCardPayinitParam, request: HttpServletRequest, response: HttpServletResponse): ResponseEntity<Any> {
+ @PostMapping("/ykt/payfinish")
+ fun yktPayFinish(@RequestBody param:CitizenCardPayfinishParam,request: HttpServletRequest,response: HttpServletResponse): ResponseEntity<Any> {
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)
+ var dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
+ .setRefno(param.refno)
+ .wip(personBalancePayService)
+ val extendMap = consumePayService.getUserdtlExtendParamMap(dtl.refno)
+ val code = CallService.callYktPay(consumePayService.getPaytypeConfig(TradeDict.PAYTYPE_YKT_CARD, dtl.shopaccno, dtl.userid==null),
+ dtl, DateUtil.getNow(), extendMap["stuempno"]!!, extendMap["yktshopid"]!!, extendMap["devphyid"])
+ if (code.retcode == "0") {
+ dtl = PersonTransBuilder.newBuilder(accountUtilServcie)
+ .setRefno(param.refno)
+ .addResult(code.data)
+ .success(personBalancePayService) //流水置成功
ResponseEntity.ok(ResponseBodyBuilder.create()
.data("refno", dtl.refno)
- .data("amount", dtl.amount)
- .success("交易初始化成功"))
-
+ .data("billno", dtl.outtradeno)
+ .success())
+ } else {
+ PersonTransBuilder.newBuilder(accountUtilServcie)
+ .setRefno(param.refno)
+ .addResult("errmsg", code.retmsg!!)
+ .finish(personBalancePayService, TradeDict.DTL_STATUS_FAIL) //流水置成功
+ ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.BUSINESS_DEAL_ERROR, "交易扣费失败-${code.retmsg}"))
}
- ResponseEntity.ok(ResponseBodyBuilder.create()
- .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "不支持支付方式<一卡通支付>"))
- } catch (ex: RequestParamCheckException) {
+ }catch (ex: RequestParamCheckException) {
ResponseEntity.ok(ResponseBodyBuilder.create()
.requestException(ex, "请求参数错误"))
} catch (et: TransactionException) {
// }
-//
-// @PostMapping("/ykt/payfinish")
-// fun yktPayFinish(refno: String, yktshopid: String, devphyid: String?): ResponseEntity<Any> {
-// return try {
-// val dtl = personBalancePayService.wip(refno)
-// val person = userService.findPersonByUserid(dtl.userid)
-// val code = CallService.callYktPay(paytypeService.getPaytypeConfigByPaytype(PaytypeUtil.YKTPAY),
-// dtl, DateUtil.getNow(), "", yktshopid, devphyid)
-// if (code.retcode == "0") {
-// PersonTransBuilder.newBuilder(accountUtilServcie)
-// .done(dtl.refno, TradeDict.DTL_STATUS_SUCCESS, personBalancePayService)
-// ResponseEntity.ok(ResponseBodyBuilder.create()
-// .data("refno", dtl.refno)
-// .success())
-// } else {
-// PersonTransBuilder.newBuilder(accountUtilServcie)
-// .done(dtl.refno, TradeDict.DTL_STATUS_FAIL, personBalancePayService)
-// ResponseEntity.ok(ResponseBodyBuilder.create()
-// .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "交易请求失败-${code.retcode}"))
-// }
-// } catch (e: TransactionException) {
-// ResponseEntity.ok(ResponseBodyBuilder.create()
-// .transException(e, "交易确认失败"))
-// }
-// }
+
//
// /**
// * 微信支付
import com.supwisdom.dlpay.api.PersonTransBuilder
import com.supwisdom.dlpay.api.dao.AccountDao
import com.supwisdom.dlpay.api.dao.DebitCreditDtlDao
+import com.supwisdom.dlpay.api.dao.UserdtlBusinessDao
import com.supwisdom.dlpay.api.dao.UserdtlDao
import com.supwisdom.dlpay.api.domain.TAccount
import com.supwisdom.dlpay.api.domain.TDebitCreditDtl
import com.supwisdom.dlpay.api.domain.TUserdtl
+import com.supwisdom.dlpay.api.domain.TUserdtlBusiness
import com.supwisdom.dlpay.api.service.AccountUtilServcie
import com.supwisdom.dlpay.api.service.PersonBalancePayService
import com.supwisdom.dlpay.exception.TransactionException
import com.supwisdom.dlpay.exception.TransactionProcessException
-import com.supwisdom.dlpay.framework.dao.FeetypeConfigDao
-import com.supwisdom.dlpay.framework.dao.ShopaccDao
-import com.supwisdom.dlpay.framework.dao.SubjectDao
-import com.supwisdom.dlpay.framework.dao.TranstypeDao
+import com.supwisdom.dlpay.framework.dao.*
import com.supwisdom.dlpay.framework.domain.TFeetypeConfig
import com.supwisdom.dlpay.framework.domain.TShopacc
import com.supwisdom.dlpay.framework.domain.TSubject
-import com.supwisdom.dlpay.framework.domain.TTranstype
import com.supwisdom.dlpay.framework.service.SystemUtilService
import com.supwisdom.dlpay.framework.util.*
import org.hibernate.exception.LockTimeoutException
@Autowired
lateinit var feetypeConfigDao: FeetypeConfigDao
-
override fun readAccountForUpdateNowait(userid: String): TAccount {
return try {
accountDao.getByUseridForUpdateNowait(userid)
@Autowired
lateinit var accountDao: AccountDao
+ @Autowired
+ lateinit var userdtlBusinessDao: UserdtlBusinessDao
+
@PersistenceContext
lateinit var em: EntityManager
?: throw TransactionProcessException(TradeErrorCode.TRANSACTION_NOT_EXISTS, "交易参考号<$refno>不存在")
}
- private fun checkOuttradenoExist(outtradeno: String): Boolean {
-// TODO("判断 outtradeno 重复发起")
- return false
- }
-
private fun doDealAccount(accno: String, amount: Double, overdraft: Boolean): TAccount {
val account = getlockAccount(accno)
if (account.tacCheck())
}
override fun init(builder: PersonTransBuilder): TUserdtl {
- val userdtl = TUserdtl()
+ //判断第三方流水号重复 标准:shopaccno + outtradeno 唯一?
+ var userdtl = userdtlDao.findByOuttradenoAndShopaccno(builder.outtradeno, builder.shopaccno) //加锁?
+ if (null != userdtl) {
+ if (TradeDict.DTL_STATUS_INIT != userdtl.status) {
+ throw TransactionProcessException(TradeErrorCode.OUTTRADENO_ALREADY_EXISTS, "外部流水号重复") //非初始化状态,直接报错
+ }
+ //fixme: 判断是同一笔交易重发(标准??) 是->已初始化直接返回;否 -> 报错:外部流水号重复
+ if(builder.amount == userdtl.amount && builder.paytype == userdtl.paytype && builder.transDate == userdtl.transdate && builder.transTime==userdtl.transtime){
+ return userdtl // 交易日期,时间重发时是否会变??
+ }else{
+ throw TransactionProcessException(TradeErrorCode.OUTTRADENO_ALREADY_EXISTS, "外部流水号重复")
+ }
+ }
+
+ userdtl = TUserdtl() // 新建流水
userdtl.refno = systemUtilService.refno
userdtl.accdate = systemUtilService.accdate
userdtl.userid = builder.person.userid
userdtl.payinfo = builder.payinfo
userdtl.transcode = builder.transcode
if (StringUtil.isEmpty(builder.description)) {
- userdtl.transdesc = systemUtilService.getTranscodeName(builder.transcode, null);
+ userdtl.transdesc = systemUtilService.getTranscodeName(builder.transcode, null)
} else {
userdtl.transdesc = builder.description
}
userdtl.outtradeno = builder.outtradeno
+ userdtl.shopaccno = builder.shopaccno
// userdtl.operid =
when (builder.tradetype) {
Tradetype.RECHARGE -> userdtl.tradeflag = 1
Tradetype.CONSUME -> userdtl.tradeflag = 2
}
userdtl.createtime = systemUtilService.sysdatetime.hostdatetime
- if (checkOuttradenoExist(userdtl.outtradeno)) {
- throw TransactionProcessException(TradeErrorCode.OUTTRADENO_ALREADY_EXISTS, "外部流水号重复")
- }
userdtl.amount = builder.amount
userdtl.status = TradeDict.DTL_STATUS_INIT
debitCreditDtlDao.save(this)
}
}
+
+ if(builder.extendMap.isNotEmpty()){
+ userdtlBusinessDao.save(TUserdtlBusiness(userdtl.refno, builder.extendMap)) //保存参数
+ }
+
return userdtl
}