+// ============================ RECHARGE ============================ //
+class CommonRechargeInitParam : APIRequestParam() {
+ @Sign
+ var userid: String = "" //用户ID
+ @Sign
+ var amount: Int = 0 //必传
+
+ var feelist: List<ConsumeFeetype>? = null //TODO: 怎么拼接签名字符串??
+ @Sign
+ var sourcetype: String = "" //必传,充值方式
+ @Sign
+ var billno: String = "" //必传
+ @Sign
+ var transdate: String = "" //必传
+ @Sign
+ var transtime: String = "" //必传
+
+ override fun checkParam(): Boolean {
+ if (StringUtil.isEmpty(userid)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "请指定充值用户")
+ if (amount <= 0) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "充值金额必须大于零")
+ if (StringUtil.isEmpty(sourcetype)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "请指定充值的支付方式")
+ if (StringUtil.isEmpty(billno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "对接系统唯一订单号不能为空")
+ 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]")
+
+ return true
+ }
+}
+
+class CommonRechargeConfirmParam : APIRequestParam() {
+ @Sign
+ var refno:String = "" //流水号
+
+ override fun checkParam(): Boolean {
+ if(StringUtil.isEmpty(refno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "流水号不能为空")
+
+ return true
+ }
+}
+
+class CommonQueryRechargeResultParam : APIRequestParam() {
+ @Sign
+ var refno: String? = null //流水号
+ @Sign
+ var billno: String? = null
+
+ override fun checkParam(): Boolean {
+ if (StringUtil.isEmpty(refno) || StringUtil.isEmpty(billno)) throw RequestParamCheckException(TradeErrorCode.REQUEST_PARAM_ERROR, "流水号不能为空")
+
+ return true
+ }
+}
+
--- /dev/null
+package com.supwisdom.dlpay.api.controller
+
+import com.supwisdom.dlpay.api.AccountProxy
+import com.supwisdom.dlpay.api.TransactionBuilder
+import com.supwisdom.dlpay.api.bean.*
+import com.supwisdom.dlpay.api.service.AccountUtilServcie
+import com.supwisdom.dlpay.api.service.ChargeApiService
+import com.supwisdom.dlpay.api.service.TransactionService
+import com.supwisdom.dlpay.api.service.UserService
+import com.supwisdom.dlpay.exception.TransactionCheckException
+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
+import com.supwisdom.dlpay.framework.util.Subject
+import com.supwisdom.dlpay.framework.util.TradeCode
+import com.supwisdom.dlpay.framework.util.TradeDict
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.http.ResponseEntity
+import org.springframework.security.core.Authentication
+import org.springframework.web.bind.annotation.PostMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/api/recharge")
+class ChargeAPIController {
+ @Autowired
+ lateinit var accountUtilServcie: AccountUtilServcie
+ @Autowired
+ lateinit var systemUtilService: SystemUtilService
+ @Autowired
+ lateinit var transactionService: TransactionService
+ @Autowired
+ lateinit var commonService: CommonService
+ @Autowired
+ lateinit var userService: UserService
+ @Autowired
+ lateinit var chargeApiService: ChargeApiService
+
+
+ /**
+ * ============================================================================
+ * 通用充值(只记流水)
+ * ============================================================================
+ * */
+ @PostMapping("/common/init")
+ fun rechargeInit(@RequestBody param: CommonRechargeInitParam, authentication: Authentication): ResponseEntity<Any> {
+ if (param.checkSign(commonService.getSecretByAppid(authentication.name))) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
+ }
+
+ if(chargeApiService.checkRechargeSourcetype(param.sourcetype)) {
+ val person = userService.findOnePersonByUserid(param.userid)
+ val account = accountUtilServcie.readAccount(person.userid)
+ val rechargeDrsubjno = when (param.sourcetype) {
+ //根据不同支付方式确定借方科目,fixme:可根据outid或clientId自定义
+
+ TradeDict.PAYTYPE_CASH -> accountUtilServcie.readSubject(Subject.SUBJNO_RECHARGE_CASH)
+ TradeDict.PAYTYPE_OTHER_THIRDPART -> accountUtilServcie.readSubject(Subject.SUBJNO_RECHARGE_OTHER)
+ else -> throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "充值支付方式<${param.sourcetype}>未确定所属科目")
+ }
+
+ val transaction = TransactionBuilder().apply {
+ setTransInfo(param.transdate, param.transtime,
+ TradeCode.TRANSCODE_ERCHARGE,
+ param.sourcetype)
+ setOutTransInfo(authentication.name, param.billno) //fixme: outid取clientId
+// operator("", TradeDict.OPERTYPE_OPER) //充值操作员
+ payinfo = ""
+ description = "账户充值"
+ }.person(account).apply {
+ setAmount(param.amount / 100.0, TradeDict.TRADE_FLAG_IN)
+ this.opposite = AccountProxy(rechargeDrsubjno)
+ }.and().addDebitCreditRecord(AccountProxy(rechargeDrsubjno), AccountProxy(account),
+ param.amount / 100.0, "账户充值")
+ .also { builder ->
+ param.feelist?.forEach {
+ val feeamt = it.amount / 100.0
+ when (it.feetype) {
+ TradeDict.PAYTYPE_RECHARGE_COUPON -> {
+ //优惠折扣 优惠科目 -> 个人账户
+ val feetypeConfig = accountUtilServcie.readFeetype(TradeDict.PAYTYPE_RECHARGE_COUPON, param.sourcetype)
+ val subject = accountUtilServcie.readSubject(feetypeConfig.drsubjno) //不同在借方折扣科目
+ builder.addDebitCreditRecord(AccountProxy(subject), AccountProxy(account), feeamt, feetypeConfig.summary)
+ }
+ //fixme: 服务费暂缺
+// TradeDict.PAYTYPE_RECHARGE_SERVICEFEE -> {
+// //收服务费 借方 -> 服务费科目
+// val feetypeConfig = accountUtilServcie.readFeetype(TradeDict.PAYTYPE_RECHARGE_SERVICEFEE, param.sourcetype)
+// val subject = accountUtilServcie.readSubject(feetypeConfig.crsubjno) //不同在服务费放在贷方科目
+// builder.addDebitCreditRecord(AccountProxy(rechargeDrsubjno), AccountProxy(subject), feeamt, feetypeConfig.summary)
+//
+// }
+ else -> throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "充值费用清单不支持feetype<${it.feetype}>")
+ }
+ }
+ }.init(transactionService)
+
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .data("refno", transaction.refno)
+ .data("amount", transaction.personDtl.amount)
+ .success("初始化成功"))
+
+ }
+
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.BUSINESS_PAYTYPE_NOSUPPORT, "充值不支持支付方式<${param.sourcetype}>"))
+ }
+
+ @PostMapping("/common/confirm")
+ fun rechargeConfirm(@RequestBody param: CommonRechargeConfirmParam, authentication: Authentication): ResponseEntity<Any> {
+ if (param.checkSign(commonService.getSecretByAppid(authentication.name))) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
+ }
+
+ transactionService.success(param.refno).let {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .data("refno", it.refno)
+ .data("billno", it.outTradeNo)
+ .success("交易确认成功"))
+ }
+
+ }
+
+ /**
+ * ============================================================================
+ * 查询充值流水状态
+ * ============================================================================
+ * */
+ @PostMapping("/queryresult")
+ fun rechargeConfirm(@RequestBody param: CommonQueryRechargeResultParam, authentication: Authentication): ResponseEntity<Any> {
+ if (param.checkSign(commonService.getSecretByAppid(authentication.name))) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.REQUEST_SIGN_ERROR, "参数签名错误"))
+ }
+
+ chargeApiService.getTransactionMainDtl(param.refno, param.billno, authentication.name).let {
+ if (null == it) {
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "充值流水不存在"))
+ }
+
+ return ResponseEntity.ok(ResponseBodyBuilder.create()
+ .data("refno", it.refno)
+ .data("billno", it.outTradeNo)
+ .data("status", it.status)
+ .success("查询成功"))
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package com.supwisdom.dlpay.api.service.impl
+
+import com.supwisdom.dlpay.api.dao.SourceTypeDao
+import com.supwisdom.dlpay.api.dao.TransactionMainDao
+import com.supwisdom.dlpay.api.domain.TTransactionMain
+import com.supwisdom.dlpay.api.service.ChargeApiService
+import com.supwisdom.dlpay.exception.TransactionProcessException
+import com.supwisdom.dlpay.framework.util.StringUtil
+import com.supwisdom.dlpay.framework.util.TradeErrorCode
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.stereotype.Service
+
+@Service
+class ChargeApiServiceImpl : ChargeApiService {
+ @Autowired
+ lateinit var sourceTypeDao: SourceTypeDao
+ @Autowired
+ lateinit var transactionMainDao: TransactionMainDao
+
+ override fun checkRechargeSourcetype(sourceType: String): Boolean {
+ sourceTypeDao.getBySourceType(sourceType).let {
+ if (null == it) {
+ throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统不支持支付方式[$sourceType]")
+ } else {
+ if (!it.enable || !it.isChargeEnable) {
+ throw TransactionProcessException(TradeErrorCode.INPUT_DATA_ERROR, "系统充值未启用支付方式[$sourceType]")
+ }
+ }
+ }
+
+ return true
+ }
+
+ override fun getTransactionMainDtl(refno: String?, billno: String?, outid: String?): TTransactionMain? {
+ return when (!StringUtil.isEmpty(refno)) {
+ true -> transactionMainDao.findByRefno(refno)
+ false -> transactionMainDao.findByBillno(billno, outid)
+ }
+ }
+}
\ No newline at end of file