关于form-data和http请求body&网关处理

文章讲述了在使用SpringCloudGateway作为API网关时,如何处理form-data格式的HTTP请求,包括在请求体中添加自定义参数以及处理文件传输。作者遇到了在form-data中添加额外信息导致文件损坏的问题,并分享了相关代码片段,讨论了可能的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于form-data和http请求body&网关处理

场景

  • 【在http过网关时,修改内容】

  • 在网关过滤器中,监听所有http请求,截获请求,并且修改body中内容。添加一组用户凭证,然后通过网关走向后台服务

  • 使用applicaon/json的请求时,能很好的解决

  • 使用form-data时,body采用下面的 'boundary—'限定边界,加入参数的形式进行传递

  • 后台我都是通过手动编译http协议body转string

  • 以前都不太清楚http具体内容,现在写出来记一下

  • 使用form-data传递文件时,并且添加参数,展示还未解决


form-data 只传参数—httpbody 对应字符串形式

http–请求协议内容:form-data————表单提交,只携带参数的情况

–form-data : key就是namae=“”的内容 ,value内容就是换行下面的那个参数

----------------------------402066259756119690380117
Content-Disposition: form-data; name="userId"

wuhong
----------------------------402066259756119690380117
Content-Disposition: form-data; name="123"

123123
----------------------------402066259756119690380117--

form-data 传文件 —httpbody 对应字符串形式

http–请求协议内容:form-data----携带文件的情况

  • 传文件的boundary边界中,添加了filename的标识
  • 【Content-Type: image/png】能看出文件的类型
    中间的内容是文件的内容
----------------------------360975841684466334428049
Content-Disposition: form-data; name="file"; filename="image-20210224172302222.png"
Content-Type: image/png

�PNG

IHDR  G     OEV>    IDATx��W��H����88:���U�ʪ������Y�,�\.�h���1�4^�xA3��v�8�;Þ���V�EjZG- �y� '"23";�*�
�x�P����u�'~p�	�A����M#��ԍF�M3�X�@���yד!lD�c't�3�V�A��I$� �۱�~�)#*��to�|!B�A���% �
��p`Z���]���U:�{8&
�	��:�\}
�� �(�F#�@����f�v%N7�aHL�
�)���,�K�)R�H�"E�)R���L+_z^"�CDh�,�DDd���PU��M��a���{v���+x�OXI���H�"E�CD��{!�hQ�;m����9�G�D
�#�~��H�h��粯
----------------------------360975841684466334428049--

温馨提示:如果要手动编辑http - form-data的body。如上面的格式,需要自行研究body的换行符号,我之前就是看着图上的格式进行\n换行,结果真实格式有一点点不一样,有点地方还要加斜杠。具体下面的filter代码有

吐槽&结果

  1. gateway处理非常恶心,加了webflux,响应式流的内容。这块方向我还是个彩笔
  2. 最后的代码方案其实能解决form-data传文件时,加入一组自定义的key-value信息。只是我的加入自定义信息的时候,使用了String打开和编辑。估计是这个地方,对文件的编码出现了影响。大致应该可以通过解析编码格式保存文件。

gateway fileter代码

package com.wuhong.filter;



import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import com.wuhong.entity.Accounts;
import com.wuhong.utils.JWTUtil;
import io.netty.buffer.ByteBufAllocator;

import lombok.extern.slf4j.Slf4j;



import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
import org.springframework.cloud.gateway.support.BodyInserterContext;
import org.springframework.cloud.gateway.support.DefaultServerRequest;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

import org.springframework.core.io.buffer.*;

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.codec.HttpMessageReader;

import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;

import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.HandlerStrategies;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;


import java.io.*;

import java.util.List;

/**
 * @ClassName DiaryFilter
 * @Description TODO
 * @Author director吴
 * @Date 2022/1/16 21:14
 * @Version 1.0
 **/
@Slf4j
@Configuration
public class DiaryFilter implements GlobalFilter, Ordered {
    

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        //从请求头获取Token
        String token = exchange.getRequest().getHeaders().get("token").get(0);

        if (token != null) {
            boolean status = JWTUtil.checkToken(token);
            //验证解析token
            Accounts info = JWTUtil.checkToken(token) ? JWTUtil.getTokenInfo(token) : null;
            ServerHttpRequest request = exchange.getRequest();
            
            HttpHeaders headers = request.getHeaders();
            MediaType contentType = headers.getContentType();
            long contentLength = headers.getContentLength();

            //判断请求类型
            if (contentLength > 0) {
                if (MediaType.APPLICATION_JSON.equals(contentType) || MediaType.APPLICATION_JSON_UTF8.equals(contentType)) {
                    return readJSONBody(exchange, chain, info);
                }
//                if (MediaType.APPLICATION_FORM_URLENCODED.equals(contentType)) {
//                    return readFormData(exchange, chain,gatewayContext);
//                }
                if (MediaType.MULTIPART_FORM_DATA.getSubtype().equals(contentType.getSubtype())) {
                    return readFormData(exchange, chain,info);
                }
            }

            return chain.filter(exchange);

        } else {

            String value = exchange.getRequest().getPath().value();

            if (value.indexOf("login") != -1) {
                return chain.filter(exchange);
            }

        }
        return null;
    }




    /*
    返回一个ServerHttpRequestDecorator对象。
    这个对象是用来构建一个request请求的适配。因为gateway使用webflux,流节点中(Mono、Flux)当request的数据被读取后,
    就不会在原来的节点存在。通俗来讲"就是拿出来用了,就没了。需要继续往下传递,必须再写一个数据放进去"
     */
    public ServerHttpRequestDecorator buildingServerHttpRequestDecorator(ServerWebExchange exchange,byte[] bytes){
        return new ServerHttpRequestDecorator(exchange.getRequest()) {

            //请求头配置
            @Override
            public HttpHeaders getHeaders() {
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.putAll(super.getHeaders());
                httpHeaders.setContentLength(bytes.length);
                return httpHeaders;
            }

            //请求体,body数据配置
            @Override
            public Flux<DataBuffer> getBody() {
                Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
                    DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);
                    DataBufferUtils.retain(buffer);
                    return Mono.just(buffer);
                });

                return cachedFlux;
            }
        };
    }



    /**
     * 暂未解决的问题:使用form-data-上传文件时,通过修改http请求体,byte转string修改,再转回byte,除了txt文件意外,其他文件都会损坏
     */
    private Mono<Void> readFormData(ServerWebExchange exchange, GatewayFilterChain chain,Accounts tokenInfo) {

        return DataBufferUtils.join(exchange.getRequest().getBody()).flatMap(dataBuffer -> {
            StringBuilder builder = new StringBuilder();
            byte[] bytes = new byte[dataBuffer.readableByteCount()];
            log.info("dataBuffer数据长度==" + dataBuffer.readableByteCount());
            try {
                //读取-响应式流结构中,http-from-data的请求数据
                dataBuffer.read(bytes);
                String bodyInfo = new String(bytes);
                System.out.println(bodyInfo);

                //判断-from-data的请求内容,是否携带了文件。携带了文件的话 body请求体中,会有filename参数
                if (bodyInfo.contains("filename=")){
                    ServerHttpRequestDecorator decorator = buildingServerHttpRequestDecorator(exchange, bytes);
                    return chain.filter(exchange.mutate().request(decorator).build());
                }

                //插入
                String newBody = insertBodyForFromData(bodyInfo, tokenInfo);

                byte[] overByte = newBody.getBytes();

                ServerHttpRequestDecorator decorator = buildingServerHttpRequestDecorator(exchange, overByte);



                return chain.filter(exchange.mutate().request(decorator).build());

            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        });


    }

    private Mono<Void> readJSONBody(ServerWebExchange exchange, GatewayFilterChain chain, Accounts tokenInfo) {

        // httpserverRequest 转 ServerRequest
        ServerRequest serverRequest = new DefaultServerRequest(exchange);

        Mono<String> modifiedBody = serverRequest.bodyToMono(String.class)
                .flatMap(body -> {//请求中的body数据
                    log.info("'[请求中的body数据]':\n" + body);

                    return Mono.just(insertBodyForJSON(body, tokenInfo));
                });
        BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);
        HttpHeaders headers = new HttpHeaders();
        headers.putAll(exchange.getRequest().getHeaders());
        headers.remove(HttpHeaders.CONTENT_LENGTH);
        CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);

        return bodyInserter.insert(outputMessage, new BodyInserterContext())
                .then(Mono.defer(() -> {
                    ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(
                            exchange.getRequest()) {
                        @Override
                        public HttpHeaders getHeaders() {
                            long contentLength = headers.getContentLength();
                            HttpHeaders httpHeaders = new HttpHeaders();
                            httpHeaders.putAll(super.getHeaders());
                            if (contentLength > 0) {
                                httpHeaders.setContentLength(contentLength);
                            } else {
                                httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");
                            }
                            return httpHeaders;
                        }

                        @Override
                        public Flux<DataBuffer> getBody() {
                            return outputMessage.getBody();
                        }
                    };
                    return chain.filter(exchange.mutate().request(decorator).build());
                }));
    }


    private String insertBodyForJSON(String oldBody, Accounts insertUserData) {

        JSONObject jsonObject = JSON.parseObject(oldBody);
        jsonObject.put("userId", insertUserData.getId());
        log.info("[gatway添加用户Id信息] :[id=" + insertUserData.getId() + "]");
        jsonObject.put("userAccount", insertUserData.getAccount());
        log.info("[gatway添加用户账号信息] :[account=" + insertUserData.getAccount() + "]");
        return jsonObject.toJSONString();

    }

    private String insertBodyForFromData(String oldBody, Accounts insertUserData) {
        String boundary = oldBody.split("Content-Disposition: form-data;")[0];
        StringBuilder builder = new StringBuilder();
        log.info("请求格式为form-data");
        //http form-data报文格式,需要添加\r\n
        builder.append(boundary + "Content-Disposition: form-data; name=\"userId\"\r\n" +
                "\r\n" +
                "wuhong\r\n");
//                builder.append(boundary + "Content-Disposition: form-data; name=\"userId\"" +
//                        "\n" +
//                        "\n" +
//                        "wuhong\n");
        builder.append(oldBody);
        log.info("修改以后的数据");
        System.out.println(builder.toString());
        return builder.toString();

    }


    private byte[] insertBodyFromData(DataBuffer dataBuffer) {
        InputStream inputStream = dataBuffer.asInputStream();
        StringBuilder builder = new StringBuilder();
        byte[] bytes = new byte[dataBuffer.readableByteCount()];
        System.out.println("dataBuffer数据长度==" + dataBuffer.readableByteCount());
        try {
            dataBuffer.read(bytes);
            String bodyInfo = new String(bytes);
            System.out.println(bodyInfo);
            String formDataInfo = bodyInfo.split("Content-Disposition: form-data;")[0];
            builder.append(formDataInfo + "Content-Disposition: form-data; name=\"userId\"" +
                    "\n" +
                    "\n" +
                    "wuhong\n");
            builder.append(bodyInfo);
            System.out.println(builder.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        String newBody = builder.toString();
        byte[] overByte = newBody.getBytes();

        return overByte;
    }


    @Override
    public int getOrder() {
        return 1;
    }


}

# 订单管理 ## 提交订单 **接口地址**:`/api/order/orderInfo/auth/submitOrder` **请求方式**:`POST` **请求数据类型**:`application/x-www-form-urlencoded,application/json` **响应数据类型**:`*/*` **接口描述**: **请求示例**: ```javascript { "userAddressId": 0, "feightFee": 0, "remark": "", "orderItemList": [ { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "orderId": 0, "skuId": 0, "skuName": "", "thumbImg": "", "skuPrice": 0, "skuNum": 0 } ] } ``` **请求参数**: | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | | ---------------------------------- | -------------- | -------- | -------- | -------------- | ------------ | | orderInfoDto | 请求参数实体类 | body | true | OrderInfoDto | OrderInfoDto | |   userAddressId | 送货地址id | | true | integer(int64) | | |   feightFee | 运费 | | true | number | | |   remark | 备注 | | false | string | | |   orderItemList | 订单项实体类 | | true | array | OrderItem | |     id | 唯一标识 | | false | integer | | |     createTime | 创建时间 | | false | string | | |     updateTime | 修改时间 | | false | string | | |     isDeleted | 是否删除 | | false | integer | | |     orderId | 订单id | | false | integer | | |     skuId | 商品sku编号 | | true | integer | | |     skuName | 商品sku名字 | | true | string | | |     thumbImg | 商品sku图片 | | true | string | | |     skuPrice | 商品sku价格 | | true | number | | |     skuNum | 商品购买的数量 | | true | integer | | **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ---------- | | 200 | OK | ResultLong | **响应参数**: | 参数名称 | 参数说明 | 类型 | schema | | -------- | ---------- | -------------- | -------------- | | code | 业务状态码 | integer(int32) | integer(int32) | | message | 响应消息 | string | | | data | 订单id | integer(int64) | integer(int64) | **响应示例**: ```javascript { "code": 0, "message": "", "data": 0 } ``` ## 获取订单分页列表 **接口地址**:`/api/order/orderInfo/auth/{page}/{limit}` **请求方式**:`GET` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | | ----------- | ---------- | -------- | -------- | -------------- | ------ | | page | 当前页码 | path | true | integer(int32) | | | limit | 每页记录数 | path | true | integer(int32) | | | orderStatus | 订单状态 | query | false | integer(int32) | | **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ----------------------- | | 200 | OK | ResultPageInfoOrderInfo | **响应参数**: | 参数名称 | 参数说明 | 类型 | schema | | ---------------------------------------------- | ------------------------------------------------------------ | ----------------- | ----------------- | | code | 业务状态码 | integer(int32) | integer(int32) | | message | 响应消息 | string | | | data | | PageInfoOrderInfo | PageInfoOrderInfo | |   total | | integer(int64) | | |   list | OrderInfo | array | OrderInfo | |     id | 唯一标识 | integer | | |     createTime | 创建时间 | string | | |     updateTime | 修改时间 | string | | |     isDeleted | 是否删除 | integer | | |     userId | 会员_id | integer | | |     nickName | 昵称 | string | | |     orderNo | 订单号 | string | | |     couponId | 使用的优惠券 | integer | | |     totalAmount | 订单总额 | number | | |     couponAmount | 优惠券 | number | | |     originalTotalAmount | 原价金额 | number | | |     feightFee | 运费 | number | | |     payType | 支付方式【1->微信】 | integer | | |     orderStatus | 订单状态【0->待付款;1->待发货;2->已发货;3->待用户收货,已完成;-1->已取消】 | integer | | |     receiverName | 收货人姓名 | string | | |     receiverPhone | 收货人电话 | string | | |     receiverTagName | 收货人地址标签 | string | | |     receiverProvince | 省份/直辖市 | string | | |     receiverCity | 城市 | string | | |     receiverDistrict | 区 | string | | |     receiverAddress | 详细地址 | string | | |     paymentTime | 支付时间 | string | | |     deliveryTime | 发货时间 | string | | |     receiveTime | 确认收货时间 | string | | |     remark | 订单备注 | string | | |     cancelTime | 取消订单时间 | string | | |     cancelReason | 取消订单原因 | string | | |     orderItemList | 订单项实体类 | array | OrderItem | |       id | 唯一标识 | integer | | |       createTime | 创建时间 | string | | |       updateTime | 修改时间 | string | | |       isDeleted | 是否删除 | integer | | |       orderId | 订单id | integer | | |       skuId | 商品sku编号 | integer | | |       skuName | 商品sku名字 | string | | |       thumbImg | 商品sku图片 | string | | |       skuPrice | 商品sku价格 | number | | |       skuNum | 商品购买的数量 | integer | | |   pageNum | | integer(int32) | | |   pageSize | | integer(int32) | | |   size | | integer(int32) | | |   startRow | | integer(int64) | | |   endRow | | integer(int64) | | |   pages | | integer(int32) | | |   prePage | | integer(int32) | | |   nextPage | | integer(int32) | | |   isFirstPage | | boolean | | |   isLastPage | | boolean | | |   hasPreviousPage | | boolean | | |   hasNextPage | | boolean | | |   navigatePages | | integer(int32) | | |   navigatepageNums | | array | integer(int32) | |   navigateFirstPage | | integer(int32) | | |   navigateLastPage | | integer(int32) | | **响应示例**: ```javascript { "code": 0, "message": "", "data": { "total": 0, "list": [ { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "userId": 0, "nickName": "", "orderNo": "", "couponId": 0, "totalAmount": 0, "couponAmount": 0, "originalTotalAmount": 0, "feightFee": 0, "payType": 0, "orderStatus": 0, "receiverName": "", "receiverPhone": "", "receiverTagName": "", "receiverProvince": "", "receiverCity": "", "receiverDistrict": "", "receiverAddress": "", "paymentTime": "", "deliveryTime": "", "receiveTime": "", "remark": "", "cancelTime": "", "cancelReason": "", "orderItemList": [ { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "orderId": 0, "skuId": 0, "skuName": "", "thumbImg": "", "skuPrice": 0, "skuNum": 0 } ] } ], "pageNum": 0, "pageSize": 0, "size": 0, "startRow": 0, "endRow": 0, "pages": 0, "prePage": 0, "nextPage": 0, "isFirstPage": true, "isLastPage": true, "hasPreviousPage": true, "hasNextPage": true, "navigatePages": 0, "navigatepageNums": [], "navigateFirstPage": 0, "navigateLastPage": 0 } } ``` ## 获取订单信息 **接口地址**:`/api/order/orderInfo/auth/{orderId}` **请求方式**:`GET` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | | -------- | -------- | -------- | -------- | -------------- | ------ | | orderId | 订单id | path | true | integer(int64) | | **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | --------------- | | 200 | OK | ResultOrderInfo | **响应参数**: | 参数名称 | 参数说明 | 类型 | schema | | ---------------------------------- | ------------------------------------------------------------ | ----------------- | -------------- | | code | 业务状态码 | integer(int32) | integer(int32) | | message | 响应消息 | string | | | data | | OrderInfo | OrderInfo | |   id | 唯一标识 | integer(int64) | | |   createTime | 创建时间 | string(date-time) | | |   updateTime | 修改时间 | string(date-time) | | |   isDeleted | 是否删除 | integer(int32) | | |   userId | 会员_id | integer(int64) | | |   nickName | 昵称 | string | | |   orderNo | 订单号 | string | | |   couponId | 使用的优惠券 | integer(int64) | | |   totalAmount | 订单总额 | number | | |   couponAmount | 优惠券 | number | | |   originalTotalAmount | 原价金额 | number | | |   feightFee | 运费 | number | | |   payType | 支付方式【1->微信】 | integer(int32) | | |   orderStatus | 订单状态【0->待付款;1->待发货;2->已发货;3->待用户收货,已完成;-1->已取消】 | integer(int32) | | |   receiverName | 收货人姓名 | string | | |   receiverPhone | 收货人电话 | string | | |   receiverTagName | 收货人地址标签 | string | | |   receiverProvince | 省份/直辖市 | string | | |   receiverCity | 城市 | string | | |   receiverDistrict | 区 | string | | |   receiverAddress | 详细地址 | string | | |   paymentTime | 支付时间 | string(date-time) | | |   deliveryTime | 发货时间 | string(date-time) | | |   receiveTime | 确认收货时间 | string(date-time) | | |   remark | 订单备注 | string | | |   cancelTime | 取消订单时间 | string(date-time) | | |   cancelReason | 取消订单原因 | string | | |   orderItemList | 订单项实体类 | array | OrderItem | |     id | 唯一标识 | integer | | |     createTime | 创建时间 | string | | |     updateTime | 修改时间 | string | | |     isDeleted | 是否删除 | integer | | |     orderId | 订单id | integer | | |     skuId | 商品sku编号 | integer | | |     skuName | 商品sku名字 | string | | |     thumbImg | 商品sku图片 | string | | |     skuPrice | 商品sku价格 | number | | |     skuNum | 商品购买的数量 | integer | | **响应示例**: ```javascript { "code": 0, "message": "", "data": { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "userId": 0, "nickName": "", "orderNo": "", "couponId": 0, "totalAmount": 0, "couponAmount": 0, "originalTotalAmount": 0, "feightFee": 0, "payType": 0, "orderStatus": 0, "receiverName": "", "receiverPhone": "", "receiverTagName": "", "receiverProvince": "", "receiverCity": "", "receiverDistrict": "", "receiverAddress": "", "paymentTime": "", "deliveryTime": "", "receiveTime": "", "remark": "", "cancelTime": "", "cancelReason": "", "orderItemList": [ { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "orderId": 0, "skuId": 0, "skuName": "", "thumbImg": "", "skuPrice": 0, "skuNum": 0 } ] } } ``` ## 确认下单 **接口地址**:`/api/order/orderInfo/auth/trade` **请求方式**:`GET` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: 暂无 **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ------------- | | 200 | OK | ResultTradeVo | **响应参数**: | 参数名称 | 参数说明 | 类型 | schema | | ---------------------------------- | -------------- | -------------- | -------------- | | code | 业务状态码 | integer(int32) | integer(int32) | | message | 响应消息 | string | | | data | | TradeVo | TradeVo | |   totalAmount | 结算总金额 | number | | |   orderItemList | 订单项实体类 | array | OrderItem | |     id | 唯一标识 | integer | | |     createTime | 创建时间 | string | | |     updateTime | 修改时间 | string | | |     isDeleted | 是否删除 | integer | | |     orderId | 订单id | integer | | |     skuId | 商品sku编号 | integer | | |     skuName | 商品sku名字 | string | | |     thumbImg | 商品sku图片 | string | | |     skuPrice | 商品sku价格 | number | | |     skuNum | 商品购买的数量 | integer | | **响应示例**: ```javascript { "code": 0, "message": "", "data": { "totalAmount": 0, "orderItemList": [ { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "orderId": 0, "skuId": 0, "skuName": "", "thumbImg": "", "skuPrice": 0, "skuNum": 0 } ] } } ``` ## 立即购买 **接口地址**:`/api/order/orderInfo/auth/buy/{skuId}` **请求方式**:`GET` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | | -------- | --------- | -------- | -------- | -------------- | ------ | | skuId | 商品skuId | path | true | integer(int64) | | **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ------------- | | 200 | OK | ResultTradeVo | **响应参数**: | 参数名称 | 参数说明 | 类型 | schema | | ---------------------------------- | -------------- | -------------- | -------------- | | code | 业务状态码 | integer(int32) | integer(int32) | | message | 响应消息 | string | | | data | | TradeVo | TradeVo | |   totalAmount | 结算总金额 | number | | |   orderItemList | 订单项实体类 | array | OrderItem | |     id | 唯一标识 | integer | | |     createTime | 创建时间 | string | | |     updateTime | 修改时间 | string | | |     isDeleted | 是否删除 | integer | | |     orderId | 订单id | integer | | |     skuId | 商品sku编号 | integer | | |     skuName | 商品sku名字 | string | | |     thumbImg | 商品sku图片 | string | | |     skuPrice | 商品sku价格 | number | | |     skuNum | 商品购买的数量 | integer | | **响应示例**: ```javascript { "code": 0, "message": "", "data": { "totalAmount": 0, "orderItemList": [ { "id": 0, "createTime": "", "updateTime": "", "isDeleted": 0, "orderId": 0, "skuId": 0, "skuName": "", "thumbImg": "", "skuPrice": 0, "skuNum": 0 } ] } } ``` # 支付宝接口 ## 支付宝异步回调 **接口地址**:`/api/order/alipay/callback/notify` **请求方式**:`POST` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | | -------- | -------- | -------- | -------- | -------- | ------ | | paramMap | | query | true | object | | **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ------ | | 200 | OK | | **响应参数**: 暂无 **响应示例**: ```javascript ``` ## 支付宝下单 **接口地址**:`/api/order/alipay/submitAlipay/{orderNo}` **请求方式**:`GET` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: | 参数名称 | 参数说明 | 请求类型 | 是否必须 | 数据类型 | schema | | -------- | -------- | -------- | -------- | -------- | ------ | | orderNo | 订单号 | path | true | string | | **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ------ | | 200 | OK | Result | **响应参数**: | 参数名称 | 参数说明 | 类型 | schema | | -------- | ---------- | -------------- | -------------- | | code | 业务状态码 | integer(int32) | integer(int32) | | message | 响应消息 | string | | | data | 业务数据 | object | | **响应示例**: ```javascript { "code": 0, "message": "", "data": {} } ``` ## 支付宝同步回调 **接口地址**:`/api/order/alipay/callback/return` **请求方式**:`GET` **请求数据类型**:`application/x-www-form-urlencoded` **响应数据类型**:`*/*` **接口描述**: **请求参数**: 暂无 **响应状态**: | 状态码 | 说明 | schema | | ------ | ---- | ------ | | 200 | OK | | **响应参数**: 暂无 **响应示例**: 在购物车的基础上 帮我实现一下支付宝功能
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值