需求背景
做一个对接微信支付宝支付相关功能的Open-Api,包含静态二维码支付、BSanC、查询、退款功能,这些接口都需要支持两种格式:XML/JSON(Content-Type),还需要统一做签名验证,下面直接贴代码吧!本文只讲接口支持XML格式!
定义实体类
1.在定义的实体类里面使用XmlRootElement 定义根节点的名字
2.XmlElement 定义属性的名字
以下是要用到的依赖
// gradle
implementation 'javax.xml.bind:jaxb-api'
implementation "com.sun.xml.bind:jaxb-core:${jaxbVersion}"
implementation "com.sun.xml.bind:jaxb-impl:${jaxbImplVersion}"
// maven
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-core</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
这里用下单功能为例
import io.swagger.annotations.ApiModelProperty;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.FieldDefaults;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author cainiao
* 下单
* @version MchtAcquirerTransactionReq: MchtAcquirerTransactionReq.java, v 0.1 2022-02-24 16:01
*/
@ToString
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@XmlRootElement(name = "xml")
@XmlAccessorType(XmlAccessType.FIELD)
@FieldDefaults(level = AccessLevel.PRIVATE)
public class MchtAcquirerTransactionReq{
@NotBlank
@XmlElement(name = "service")
@ApiModelProperty(value = "接口类型", example = "pay.weixin.proxy.jspay.intl")
String service;
@XmlElement(name = "version")
@ApiModelProperty(value = "版本号", example = "2.0")
String version;
@XmlElement(name = "charset")
@ApiModelProperty(value = "字符集", example = "UTF-8")
String charset;
@XmlElement(name = "signType")
@ApiModelProperty(value = "签名方式(默认MD5)", example = "MD5")
String signType;
@NotBlank
@XmlElement(name = "sign")
@ApiModelProperty(value = "签名", example = "2444D06685977A585F4C98D7C796BD92")
String sign;
@NotBlank
@XmlElement(name = "mchId")
@ApiModelProperty(value = "商户号", example = "")
String mchId;
@NotBlank
@XmlElement(name = "outTradeNo")
@ApiModelProperty(value = "商户订单号", example = "")
String outTradeNo;
@XmlElement(name = "deviceInfo")
@ApiModelProperty(value = "终端设备号", example = "")
String deviceInfo;
@NotBlank
@XmlElement(name = "body")
@ApiModelProperty(value = "商品描述")
String body;
@XmlElement(name = "attach")
@ApiModelProperty(value = "附加消息", example = "")
String attach;
@NotNull
@XmlElement(name = "totalFee")
@ApiModelProperty(value = "支付金额", example = "")
Integer totalFee;
@NotBlank
@XmlElement(name = "mchCreateIp")
@ApiModelProperty(value = "请求方IP(订单生成机器的IP地址)")
String mchCreateIp;
@XmlElement(name = "authCode")
@ApiModelProperty(value = "用户授权数据", example = "")
String authCode;
@XmlElement(name = "notifyUrl")
@ApiModelProperty(value = "支付接口通知地址", example = "")
String notifyUrl;
@XmlElement(name = "timeStart")
@ApiModelProperty(value = "订单生成时间", example = "20091225091010")
String timeStart;
@XmlElement(name = "timeExpire")
@ApiModelProperty(value = "订单失效时间", example = "20091225091010")
String timeExpire;
@XmlElement(name = "opShopId")
@ApiModelProperty(value = "操作商户号", example = "")
String opShopId;
@XmlElement(name = "opUserId")
@ApiModelProperty(value = "操作员", example = "")
String opUserId;
@XmlElement(name = "opDeviceId")
@ApiModelProperty(value = "操作设备号", example = "")
String opDeviceId;
@XmlElement(name = "goodsTag")
@ApiModelProperty(value = "商品标记", example = "")
String goodsTag;
@NotBlank
@XmlElement(name = "nonceStr")
@ApiModelProperty(value = "随机字符串(≤32位)", example = "")
String nonceStr;
@XmlElement(name = "limitCreditPay")
@ApiModelProperty(value = "是否限制信用卡(默认不禁用)", example = "0/1")
String limitCreditPay;
}
接口定义
这里定义两种格式分开还是一起根据个人喜好来,我用了两个接口分别指定了Content-Type
/**
* ==================================XML_Content-type====================================
* 订单支付
* @param req
* @return
*/
@ApiOperation(value = "order pay", response = MchtAcquirerTransactionResp.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = MchtAcquirerTransactionResp.class)})
@PostMapping(value = "/mcht-acquirer/transaction/xml/pay", consumes = MediaType.TEXT_XML_VALUE, produces = {
MediaType.TEXT_XML_VALUE})
public ResponseEntity payByXml(@Valid @RequestBody MchtAcquirerTransactionReq req) {
if (!ApiSignatureUtils.verifySign(req, req.getSign(), req.getNonceStr())) {
return new ResponseEntity<>("Signature Error", HttpStatus.BAD_REQUEST);
}
log.info("start mcht acquirer transaction pay,req:{}", req);
AcquirerTransactionResp res = mchtAcquirerTransactionClient.pay(RequestBeanConverter.toAcquirerTransactionReq(req));
log.info("end mcht acquirer transaction pay,res:{}", res);
return new ResponseEntity<>(ResponseBeanConverter.toMchtAcquirerTransactionResp(res), HttpStatus.OK);
}
/**
* ===================================JSON_Content-type======================================
* @param req
* @return
*/
@ApiOperation(value = "order pay", response = MchtAcquirerTransactionResp.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK", response = MchtAcquirerTransactionResp.class)})
@PostMapping(value = "/mcht-acquirer/transaction/json/pay/", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
produces = {
MediaType.APPLICATION_JSON_UTF8_VALUE})
public ResponseEntity pay(@Valid @RequestBody MchtAcquirerTransactionReq req) {
log.info("start mcht acquirer transaction pay,req:{}", req);
AcquirerTransactionResp res = mchtAcquirerTransactionClient.pay(RequestBeanConverter.toAcquirerTransactionReq(req));
log.info("end mcht acquirer transaction pay,res:{}", res);
return new ResponseEntity(ResponseBeanConverter.toMchtAcquirerTransactionResp(res), HttpStatus.OK);
}
到这里就定义好了,可以直接测试!支持Xml格式 不用再做其他的转换!