package com.supwisdom.dlpay.api.annotation;
+import com.supwisdom.dlpay.api.util.IDTypes;
import com.supwisdom.dlpay.api.validator.IDNoCheckValidator;
import javax.validation.Constraint;
*
* @return
*/
- String[] value();
+ IDTypes value();
}
\ No newline at end of file
-package com.supwisdom.dlpay.paysdk.bean;
+package com.supwisdom.dlpay.api.bean;
+import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
+@NoArgsConstructor
+@AllArgsConstructor
public class ApiLoginInitResponse extends ApiResponse {
private String timestamp;
private String token;
-package com.supwisdom.dlpay.paysdk.bean;
+package com.supwisdom.dlpay.api.bean;
+import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
+@AllArgsConstructor
+@NoArgsConstructor
public class ApiLoginResponse extends ApiResponse {
private String jwt;
private String appid;
-package com.supwisdom.dlpay.paysdk.bean;
+package com.supwisdom.dlpay.api.bean;
import lombok.Getter;
--- /dev/null
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+public class ApiVersionResponse extends ApiResponse {
+ private String version;
+}
--- /dev/null
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class CitizenPayResponse extends ApiResponse {
+ private String refno;
+ private String billno;
+ private Double amount;
+}
package com.supwisdom.dlpay.api.bean;
import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.IDNoCheck;
+import com.supwisdom.dlpay.api.annotation.MobileNumber;
import com.supwisdom.dlpay.api.annotation.Sign;
import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
import com.supwisdom.dlpay.api.annotation.ShopType;
+import com.supwisdom.dlpay.api.util.IDTypes;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
+@IDNoCheck(value = IDTypes.IDTYPE_LIST, idno = "idno", idtype = "idtype", message = "证件类型错误")
public class OpenShopParam extends APIRequestParam {
@Sign
@NotEmpty(message = "商户唯一号不能为空")
@Sign
private String idno;
@Sign
+ @MobileNumber
private String mobile;
@Sign
@Email(message = "Email 格式错误")
package com.supwisdom.dlpay.api.bean;
import com.supwisdom.dlpay.api.APIRequestParam;
+import com.supwisdom.dlpay.api.annotation.IDNoCheck;
import com.supwisdom.dlpay.api.annotation.MobileNumber;
import com.supwisdom.dlpay.api.annotation.Sex;
import com.supwisdom.dlpay.api.annotation.Sign;
import com.supwisdom.dlpay.api.exception.RequestParamCheckException;
import com.supwisdom.dlpay.api.util.Constants;
+import com.supwisdom.dlpay.api.util.IDTypes;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotEmpty;
+
@Setter
@Getter
+@IDNoCheck(value = IDTypes.IDTYPE_LIST, idno = "idno", idtype = "idtype", message = "证件类型错误")
public class OpenUserParam extends APIRequestParam {
@Sign
@NotEmpty(message = "用户唯一号不能为空")
--- /dev/null
+package com.supwisdom.dlpay.api.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@NoArgsConstructor
+@AllArgsConstructor
+@Getter
+@Setter
+public class PayReverseResponse extends ApiResponse {
+ private String refno;
+}
--- /dev/null
+package com.supwisdom.dlpay.api.bean;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Setter
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+public class QueryTransDtlResponse extends ApiResponse {
+ private String refno;
+ private String outTradeNo;
+ private Double amount;
+ private String status;
+ private String sourceType;
+ private String payinfo;
+ private String reverseFlag;
+ private String transdesc;
+}
-package com.supwisdom.dlpay.paysdk.bean;
+package com.supwisdom.dlpay.api.bean;
+import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
+@AllArgsConstructor
+@NoArgsConstructor
public class ShopResponse extends ApiResponse {
private Integer shopid;
private String shopaccno;
-package com.supwisdom.dlpay.paysdk.bean;
+package com.supwisdom.dlpay.api.bean;
+import lombok.AllArgsConstructor;
import lombok.Getter;
+import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
+@AllArgsConstructor
+@NoArgsConstructor
public class UserResponse extends ApiResponse {
private String userid;
private String uid;
public class Constants {
public static final String SEX_MALE = "male";
public static final String SEX_FEMALE = "female";
+
}
--- /dev/null
+package com.supwisdom.dlpay.api.util;
+
+public enum IDTypes {
+ IDTYPE_IDCARD("idcard"), // 身份证
+ IDTYPE_PASSPORT("passport"), // 护照
+ IDTYPE_DRIVING_LICENSE("driving_license"), // 驾照
+ IDTYPE_HK_MACAU_PASS("hk_macau_pass"), // 港澳通行证
+ IDTYPE_STUDENT_IDCARD("student_idcard"), // 学生证
+ IDTYPE_OTHER("unknown"),
+ IDTYPE_LIST(new IDTypes[]{IDTYPE_IDCARD, IDTYPE_PASSPORT,
+ IDTYPE_DRIVING_LICENSE, IDTYPE_HK_MACAU_PASS, IDTYPE_STUDENT_IDCARD, IDTYPE_OTHER}); // 其它
+
+ IDTypes(Object data) {
+ this.data = data;
+ }
+
+ public String value() {
+ return this.data.toString();
+ }
+
+ public Object getData() {
+ return this.data;
+ }
+
+ private Object data;
+}
package com.supwisdom.dlpay.api.validator;
import com.supwisdom.dlpay.api.annotation.IDNoCheck;
+import com.supwisdom.dlpay.api.util.IDTypes;
+import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang3.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
-public class IDNoCheckValidator implements ConstraintValidator<IDNoCheck, String> {
+public class IDNoCheckValidator implements ConstraintValidator<IDNoCheck, Object> {
private String idnoField;
private String idtypeField;
private String[] idtypeList;
@Override
- public boolean isValid(String value, ConstraintValidatorContext context) {
+ public boolean isValid(Object value, ConstraintValidatorContext context) {
+ try {
+ String idtype = BeanUtils.getProperty(value, idtypeField);
+ if (idtype == null) {
+ return true;
+ }
+ if (!Arrays.asList(idtypeList).contains(idtype)) {
+ return false;
+ }
+ String idno = BeanUtils.getProperty(value, idnoField);
+ if (StringUtils.isEmpty(idno)) {
+ return false;
+ }
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ }
return false;
}
if (StringUtils.isEmpty(idnoField) || StringUtils.isEmpty(idtypeField)) {
throw new IllegalArgumentException("IDNO 和 IDType 字段必须指定");
}
- idtypeList = constraintAnnotation.value();
+ Object value = constraintAnnotation.value().getData();
+ if (value instanceof IDTypes[]) {
+ idtypeList = new String[((IDTypes[]) value).length];
+ for (int i = 0; i < ((IDTypes[]) value).length; ++i) {
+ idtypeList[i] = ((IDTypes[]) value)[i].value();
+ }
+ } else if (value instanceof String) {
+ idtypeList = new String[]{(String) value};
+ } else {
+ throw new IllegalArgumentException("IDTypes 类型错误");
+ }
}
}
package com.supwisdom.dlpay.paysdk;
-import com.supwisdom.dlpay.paysdk.bean.ApiLoginInitResponse;
-import com.supwisdom.dlpay.paysdk.bean.ApiLoginResponse;
+import com.supwisdom.dlpay.api.bean.ApiLoginInitResponse;
+import com.supwisdom.dlpay.api.bean.ApiLoginResponse;
import com.supwisdom.dlpay.paysdk.proxy.ApiLoginProxy;
import com.supwisdom.dlpay.paysdk.utils.JwtContext;
import com.supwisdom.dlpay.paysdk.utils.Utils;
+++ /dev/null
-package com.supwisdom.dlpay.paysdk.bean;
-
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-public class CitizenPayInitResponse extends ApiResponse {
- private String refno;
- private String billno;
- private Double amount;
-}
--- /dev/null
+package com.supwisdom.dlpay.paysdk.proxy;
+
+import com.supwisdom.dlpay.api.bean.ApiVersionResponse;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+
+@FeignClient(name = "apiCommonProxy", url = "${payapi.url}")
+public interface ApiCommonProxy {
+ @GetMapping(value = "/api/common/version")
+ ApiVersionResponse apiVersion();
+}
package com.supwisdom.dlpay.paysdk.proxy;
-import com.supwisdom.dlpay.paysdk.bean.ApiLoginInitResponse;
-import com.supwisdom.dlpay.paysdk.bean.ApiLoginResponse;
+import com.supwisdom.dlpay.api.bean.ApiLoginInitResponse;
+import com.supwisdom.dlpay.api.bean.ApiLoginResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
-import javax.servlet.http.HttpServletRequest;
-
@FeignClient(value = "apiLoginProxy", url = "${payapi.url}")
public interface ApiLoginProxy {
@RequestMapping(value = "/api/auth/gettoken", method = RequestMethod.GET)
import com.supwisdom.dlpay.api.bean.CitizenCardPayfinishParam;
import com.supwisdom.dlpay.api.bean.CitizenCardPayinitParam;
-import com.supwisdom.dlpay.paysdk.bean.CitizenPayInitResponse;
+import com.supwisdom.dlpay.api.bean.CitizenPayResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient(value = "citizenCardPay", url = "${payapi.url}")
public interface CitizenCardPayProxy {
@RequestMapping(value = "/api/consume/citizencard/payinit", method = RequestMethod.GET)
- CitizenPayInitResponse citizencardPayinit(@RequestBody CitizenCardPayinitParam param);
+ CitizenPayResponse citizencardPayinit(@RequestBody CitizenCardPayinitParam param);
@RequestMapping(value = "/api/consume/citizencard/payfinish", method = RequestMethod.GET)
- CitizenPayInitResponse citizencardPayFinish(@RequestBody CitizenCardPayfinishParam param);
+ CitizenPayResponse citizencardPayFinish(@RequestBody CitizenCardPayfinishParam param);
}
+++ /dev/null
-package com.supwisdom.dlpay.paysdk.proxy;
-
-import com.supwisdom.dlpay.api.bean.ConsumePayCancelParam;
-import com.supwisdom.dlpay.api.bean.ConsumePayRefundParam;
-import org.springframework.cloud.openfeign.FeignClient;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-
-import java.util.Map;
-
-@FeignClient(name = "payReverseProxy", url = "${payapi.url}")
-public interface PayReverseProxy {
- @PostMapping("/api/consume/paycancel")
- ResponseEntity<Map<String, String>> payCancel(@RequestBody ConsumePayCancelParam param);
-
- @PostMapping("/api/consume/payrefund")
- ResponseEntity<Map<String, String>> payRefund(@RequestBody ConsumePayRefundParam param);
-}
import com.supwisdom.dlpay.api.bean.OpenShopParam;
import com.supwisdom.dlpay.api.bean.QueryShopParam;
-import com.supwisdom.dlpay.paysdk.bean.ShopResponse;
+import com.supwisdom.dlpay.api.bean.ShopResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
--- /dev/null
+package com.supwisdom.dlpay.paysdk.proxy;
+
+import com.supwisdom.dlpay.api.bean.*;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+@FeignClient(name = "payTransactionProxy", url = "${payapi.url}")
+public interface TransactionProxy {
+ @PostMapping("/api/consume/paycancel")
+ PayReverseResponse payCancel(@RequestBody ConsumePayCancelParam param);
+
+ @PostMapping("/api/consume/payrefund")
+ PayReverseResponse payRefund(@RequestBody ConsumePayRefundParam param);
+
+ @PostMapping("/api/consume/queryresult")
+ QueryTransDtlResponse queryDtlResult(@RequestBody QueryDtlResultParam param);
+}
import com.supwisdom.dlpay.api.bean.ModifyUserParam;
import com.supwisdom.dlpay.api.bean.OpenUserParam;
import com.supwisdom.dlpay.api.bean.QueryUserParam;
-import com.supwisdom.dlpay.paysdk.bean.UserResponse;
+import com.supwisdom.dlpay.api.bean.UserResponse;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import com.supwisdom.dlpay.api.bean.CitizenCardPayinitParam;
+import com.supwisdom.dlpay.api.bean.CitizenPayResponse;
import com.supwisdom.dlpay.paysdk.ApiLoginHelper;
import com.supwisdom.dlpay.paysdk.proxy.ApiLoginProxy;
import com.supwisdom.dlpay.paysdk.proxy.CitizenCardPayProxy;
-import com.supwisdom.dlpay.paysdk.bean.CitizenPayInitResponse;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.cloud.openfeign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.ribbon.FeignRibbonClientAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
-import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
import static org.hamcrest.MatcherAssert.assertThat;
initParam.setAmount(100);
initParam.setTransdate("20190708");
initParam.setTranstime("172713");
- CitizenPayInitResponse payInit = citizenCardPayProxy.citizencardPayinit(initParam);
+ CitizenPayResponse payInit = citizenCardPayProxy.citizencardPayinit(initParam);
assertThat("pay initialized " + payInit.getRetmsg() + payInit.getException(),
payInit.getRetcode(), equalTo(0));
}
fun queryDtlResult(@RequestBody param: QueryDtlResultParam): ResponseEntity<Any> {
consumePayService.getTransactionMainDtl(param.refno, param.billno, param.shopaccno)?.let {
return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("refno", it.refno)
- .data("billno", it.outTradeNo)
- .data("amount", it.shopDtl.amount)
- .data("status", it.status)
- .data("sourcetype", it.personDtl.sourceType)
- .data("payinfo", it.personDtl.payinfo)
- .data("reverseflag", it.reverseFlag)
- .data("transdesc", it.shopDtl.transdesc)
- .success("查询成功"))
+ .success(QueryTransDtlResponse(it.refno, it.outTradeNo, it.shopDtl.amount,
+ it.status, it.sourceType, it.personDtl.payinfo, it.reverseFlag,
+ it.shopDtl.transdesc), "查询成功"))
} ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
.fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
}
}.init(transactionService)
return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("refno", transaction.refno)
- .data("billno", transaction.outTradeNo)
- .data("amount", transaction.shopDtl.amount)
- .success("交易初始化成功"))
+ .success(CitizenPayResponse(transaction.refno,
+ transaction.outTradeNo,
+ transaction.shopDtl.amount), "交易初始化成功"))
}
return ResponseEntity.ok(ResponseBodyBuilder.create()
if (code.retcode == "0") {
transactionService.success(param.refno, "支付").let {
return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("refno", it.refno)
- .data("billno", it.outTradeNo)
- .data("amount", it.shopDtl.amount)
- .success("交易确认成功"))
+ .success(CitizenPayResponse(it.refno,
+ it.outTradeNo,
+ it.shopDtl.amount), "交易确认成功"))
}
} else {
}
transactionService.success(cancelTrans.refno)
return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("refno", cancelTrans.refno)
- .success("交易确认成功"))
+ .success(PayReverseResponse(cancelTrans.refno), "交易确认成功"))
} ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
.fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
}
}
transactionService.success(refundTrans.refno)
return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("refno", refundTrans.refno)
- .success("交易确认成功"))
+ .success(PayReverseResponse(refundTrans.refno), "交易确认成功"))
} ?: return ResponseEntity.ok(ResponseBodyBuilder.create()
.fail(TradeErrorCode.TRANSACTION_NOT_EXISTS, "流水不存在"))
}
package com.supwisdom.dlpay.framework.controller
import com.jcabi.manifests.Manifests
+import com.supwisdom.dlpay.api.bean.ApiVersionResponse
import com.supwisdom.dlpay.framework.ResponseBodyBuilder
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.GetMapping
return try {
Manifests.read("Payapi-Version").let {
ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("version", it)
- .success())
+ .success(ApiVersionResponse(it)))
}
} catch (e: IllegalArgumentException) {
ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("version", "unknown")
- .success())
+ .success(ApiVersionResponse("unknown")))
}
}
}
\ No newline at end of file
package com.supwisdom.dlpay.framework.controller
import com.google.code.kaptcha.Producer
+import com.supwisdom.dlpay.api.bean.ApiLoginInitResponse
+import com.supwisdom.dlpay.api.bean.ApiLoginResponse
import com.supwisdom.dlpay.exception.TransactionCheckException
import com.supwisdom.dlpay.framework.ResponseBodyBuilder
import com.supwisdom.dlpay.framework.core.JwtConfig
apiClientRepository.save(it)
}
return ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("token", token)
- .data("timestamp", now)
- .success())
+ .success(ApiLoginInitResponse(token, now)))
}
}
}
ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("jwt", token.jwtToken)
- .data("appid", appid)
- .data("expiredAt", DateUtil.getUTCTime(token.expiration.valueInMillis))
- .success())
+ .success(ApiLoginResponse(token.jwtToken,
+ appid, DateUtil.getUTCTime(token.expiration.valueInMillis))))
} else {
ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
}
ResponseEntity.ok(ResponseBodyBuilder.create()
- .data("jwt", token.jwtToken)
- .data("appid", appid)
- .data("expiredAt", DateUtil.getUTCTime(token.expiration.valueInMillis))
- .success())
+ .success(ApiLoginResponse(token.jwtToken,
+ appid, DateUtil.getUTCTime(token.expiration.valueInMillis))))
} else {
ResponseEntity.status(HttpStatus.UNAUTHORIZED).build()
}
package com.supwisdom.dlpay.framework
import com.google.gson.Gson
+import com.supwisdom.dlpay.api.APIRequestParam
+import com.supwisdom.dlpay.api.bean.ApiResponse
import com.supwisdom.dlpay.api.exception.RequestParamCheckException
import com.supwisdom.dlpay.exception.TransactionCheckException
import com.supwisdom.dlpay.exception.TransactionException
return build()
}
+ fun success(bean: ApiResponse, msg: String? = null): ApiResponse {
+ bean.retcode = 0
+ bean.retmsg = msg ?: "成功"
+ return bean
+ }
+
fun fail(code: Int, msg: String): Map<String, Any> {
if (code == 0) {
throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "错误码未正确定义")
return build()
}
+ fun fail(bean: ApiResponse, code: Int, msg: String): ApiResponse {
+ if (code == 0) {
+ throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "错误码未正确定义")
+ }
+ bean.retcode = code
+ bean.retmsg = msg
+ return bean
+ }
+
fun exception(code: Int, exception: Exception, msg: String? = null): Map<String, Any> {
data("exception", exception.message ?: "$exception")
result(code, msg)
return build()
}
+ fun exception(bean: ApiResponse, code: Int, cause: Throwable?, msg: String? = null): ApiResponse {
+ bean.retcode = code
+ bean.retmsg = msg ?: "失败"
+ bean.exception = cause?.message ?: "unknown exception"
+ return bean
+ }
+
fun transException(exception: TransactionException, msg: String): Map<String, Any> {
data("exception", exception.message!!)
result(exception.code(), "$msg - [${exception.message}]")
return build()
}
+ fun transException(bean: ApiResponse, exception: TransactionException, msg: String): ApiResponse {
+ bean.retcode = exception.code()
+ bean.retmsg = "$msg - [${exception.message}]"
+ bean.exception = "$exception"
+ return bean
+ }
+
fun requestException(exception: RequestParamCheckException, msg: String): Map<String, Any> {
data("exception", exception.message!!)
result(exception.errCode, "$msg - [${exception.message}]")
return build()
}
+ fun requestException(bean: ApiResponse, exception: RequestParamCheckException, msg: String): ApiResponse {
+ bean.retcode = exception.errCode
+ bean.retmsg = "$msg - [${exception.message}]"
+ bean.exception = "$exception"
+ return bean
+ }
+
fun data(name: String, value: Any): ResponseBodyBuilder {
if (name in RESERVED_KEY) {
throw TransactionCheckException(TradeErrorCode.INPUT_DATA_ERROR, "返回值 <$name> 为保留值,不能使用")