需要の背景
静的 QR コード決済、BSanC、クエリ、返金機能など、WeChat Alipay 決済関連機能に接続するオープン API を作成します。これらのインターフェイスは、XML/JSON (Content-Type) の 2 つの形式をサポートする必要があります。署名を確認するには、以下のコードを直接投稿してください。この記事では、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>
ここでは例として order 関数を使用します
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;
}
インターフェースの定義
ここでは、個人の好みに応じて 2 つの形式を個別に定義するか、一緒に定義します。私は 2 つのインターフェイスを使用してそれぞれ 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 形式をサポートしているため、他の変換を行う必要はありません。