【小西】同步咪咕订单给咪咕方(写接口给第三方)

同步咪咕订单给咪咕方

    • 前言
    • 思路
    • 实现
      • 1、定义请求体和响应信息
        • MiGuOrderSyncReq
        • MiGuOrderSyncResp
      • 2、nacos定义好咪咕相关配置信息
      • 3、同步咪咕参数配置
      • 4、MiGuOrderSyncControl
      • 5、MiGuOrderSyncService
      • 6、MiGuOrderSyncServiceImpl
        • CreateAscIISignUtil 生成参数 字典排序 签名
        • Hmacsha256Util 加密
    • 测试

前言

需求:把小西中与咪咕相关的订单同步给咪咕方。

思路

思路如下:

  1. 定义好请求体和响应信息
  2. 在nacos定义好咪咕相关配置信息(用于之后验证请求体是否正确)
  3. 写接口

实现

1、定义请求体和响应信息

MiGuOrderSyncReq

@Data
@ApiModel(description = "咪咕订单同步请求参数")
public class MiGuOrderSyncReq implements Serializable {private static final long serialVersionUID = 1L;@JsonProperty("header")@Validprivate ReqHeader header;@JsonProperty("body")@Validprivate ReqBody body;@Datapublic static class ReqHeader implements Serializable {private static final long serialVersionUID = 8807000967257080242L;/*** 企业id*/@ApiModelProperty(value = "企业id", required = true)@NotEmpty(message = "企业id不能为空")private String corpId;/*** 合作伙伴(合众游戏平台)提供(类似appKey)*/@ApiModelProperty(value = "合作伙伴ID", required = true)@NotEmpty(message = "合作伙伴ID不能为空")private String partnerId;/*** 32位字母数字字符串,请求ID。用于请求去重。*/@ApiModelProperty(value = "请求流水号", required = true)@NotEmpty(message = "请求流水号不能为空")private String nonce;/*** HMAC('SHA256')请求的签名*/@ApiModelProperty(value = "签名", required = true)@NotEmpty(message = "签名不能为空")private String signature;}@Datapublic static class ReqBody implements Serializable {/*** 开始时间*/@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@NotNull(message = "开始时间不能为空")private Date startTime;/*** 结束时间*/@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")@NotNull(message = "结束时间不能为空")private Date endTime;}}

MiGuOrderSyncResp

@Data
public class MiGuOrderSyncResp implements Serializable {private static final long serialVersionUID = -1383580636250379564L;private String resultCode;private String resultDesc;public MiGuOrderSyncResp() {this.setResultCode(ErrorCode.SUCCESS.getCode());this.setResultDesc(ErrorCode.SUCCESS.getMsg());}public  MiGuOrderSyncResp(ErrorCode errorCode) {this.setResultCode(errorCode.getCode());this.setResultDesc(errorCode.getMsg());}public MiGuOrderSyncResp(List<QueryMiGuOrderSyncRespBody> result) {this.setResultCode(ErrorCode.SUCCESS.getCode());this.setResultDesc(ErrorCode.SUCCESS.getMsg());this.setResult(result);}@JsonProperty("result")private List<QueryMiGuOrderSyncRespBody> result;@Datapublic static class QueryMiGuOrderSyncRespBody implements Serializable {private static final long serialVersionUID = 1L;// 订单idprivate String orderId;// 商品Idprivate String spuId;// 商品名private String spuName;// 规格信息private String specInfo;// 图片private String picUrl;// 商品数量private Integer quantity;// 咪咕奖励编码private String prizeCode;//咪咕订单号private String miguOrderNo;//昵称private String nickName;// 用户idprivate String userId;// 支付金额(销售金额+运费金额-积分抵扣金额-电子券抵扣金额)private BigDecimal paymentPrice;//付款时间private LocalDateTime paymentTime;// 订单状态1、待发货 2、待收货 3、确认收货/已完成 5、已关闭 10、拼团中private String orderStatus;}
}

2、nacos定义好咪咕相关配置信息

joolun-thirdparty-api-dev.yml:

#migu
migu: partnerId: secretkey: corpId: 

3、同步咪咕参数配置

/*** @Description:  同步咪咕参数*/
@Data
@RefreshScope
@Configuration
@ConfigurationProperties(prefix = "migu")
public class MiGuConfigProperties {/*** 合作伙伴ID-tsp平台提供(类似appKey)*/private String partnerId;/*** 企业id*/private String corpId;/*** secretkey*/private String secretkey;
}

4、MiGuOrderSyncControl

@RestController
@AllArgsConstructor
@RequestMapping("sv")
@Slf4j
@Api(value = "MiGu_Order_Sync", tags = "咪咕订单同步模块API")
public class MiGuOrderSyncControl {@Autowiredprivate MiGuOrderSyncService miGuOrderSyncService;/*** @Description: 咪咕同步订单对接*/@ApiOperation(value = "咪咕订单同步任务")@PostMapping(value = "/app/miGuOrderSync")public MiGuOrderSyncResp miGuOrderSync(@Valid @RequestBody MiGuOrderSyncReq req) {log.info("MiGuOrderSyncDTO param:[{}]", JSON.toJSONString(req));MiGuOrderSyncResp resp = miGuOrderSyncService.miGuOrderSync(req);log.info("MiGuOrderSyncDTO resp:[{}]", JSON.toJSONString(resp));return resp;}
}

5、MiGuOrderSyncService

/**1. @Description: 咪咕同步订单对接*/
public interface MiGuOrderSyncService {MiGuOrderSyncResp miGuOrderSync(MiGuOrderSyncReq miGuOrderSyncReq);
}

6、MiGuOrderSyncServiceImpl

方法需进行以下判断:
1.判断请求体的参数是否和nacos配置参数相等
2. 判断接口幂等性(因为这接口是给咪咕方调用,因此要防止接口调用超时重试)
3. 进行验签

代码如下:

@Service
@Slf4j
@AllArgsConstructor
public class MiGuOrderSyncServiceImpl implements MiGuOrderSyncService {private final MiGuConfigProperties miGuConfigProperties;private final RedisTemplate<String, String> redisTemplate;@Autowiredprivate MiGuOrderSyncMapper miGuOrderSyncMapper;@Overridepublic MiGuOrderSyncResp miGuOrderSync(MiGuOrderSyncReq req) {log.info("miGuOrderSync param:{}", JSON.toJSONString(req));MiGuOrderSyncReq.ReqHeader header = req.getHeader();MiGuOrderSyncReq.ReqBody body = req.getBody();if (!StrUtil.equals(miGuConfigProperties.getCorpId(), header.getCorpId())) {log.error("miGuOrderSync fail! corpId is error!");return new MiGuOrderSyncResp(ErrorCode.MIGU_ORDER_SYNC_ERROR1);}if (!StrUtil.equals(miGuConfigProperties.getPartnerId(), header.getPartnerId())) {log.error("miGuOrderSync fail! partnerId is error!");return new MiGuOrderSyncResp(ErrorCode.MIGU_ORDER_SYNC_ERROR2);}if (!validateApi(body, header)) {log.error("miGuOrderSync fail! request repeat!");return new MiGuOrderSyncResp(ErrorCode.IO_POINTS_ISSUE_ERROR5);}boolean signFlag = validateSign(header, body);if (!signFlag) {log.error("miGuOrderSync fail! sign is error!");return new MiGuOrderSyncResp(ErrorCode.MIGU_ORDER_SYNC_ERROR3);}List<MiGuOrderSyncDTO> miGuOrderSyncList = miGuOrderSyncMapper.queryMiGuOrderSync(body.getStartTime(),body.getEndTime());if (CollUtil.isEmpty(miGuOrderSyncList)) {log.info("miGuOrderSyncList is Empty!");return new MiGuOrderSyncResp(new ArrayList<>());}List<MiGuOrderSyncResp.QueryMiGuOrderSyncRespBody> result = BeanConvertUtils.convert(miGuOrderSyncList, MiGuOrderSyncResp.QueryMiGuOrderSyncRespBody.class);return new MiGuOrderSyncResp(result);}/*** @Description: 接口幂等性*/private boolean validateApi(MiGuOrderSyncReq.ReqBody body, MiGuOrderSyncReq.ReqHeader header) {String key = body.getStartTime() + "_" + header.getNonce() + "_" + header.getSignature();if (incr(key, 2L) > 1) {return false;}return true;}/*** @Description: Redis原子性自增*/private long incr(String key, long expireTime) {long next = new RedisAtomicLong(key, redisTemplate.getConnectionFactory()).incrementAndGet();redisTemplate.expire(key, expireTime, TimeUnit.SECONDS);return next;}/*** @Description: 验签*/private boolean validateSign(MiGuOrderSyncReq.ReqHeader header, MiGuOrderSyncReq.ReqBody body) {Map<String, Object> params = BeanUtil.beanToMap(header);params.put("startTime", body.getStartTime());params.put("endTime", body.getEndTime());Map<String, Object> validateParams = new HashMap<>();validateParams.putAll(params);String signVal = MapUtil.getStr(validateParams, SyncDeptAndEmpConst.SIGNATURE);validateParams.remove(SyncDeptAndEmpConst.SIGNATURE);String val = CreateAscIISignUtil.getSignToken(validateParams);String sign = Hmacsha256Util.hmacMD5(val, miGuConfigProperties.getSecretkey());log.info("miGuOrderSync validateSign param:{}, sign:{},signVal:{}", val, sign, signVal);if (StrUtil.isNotBlank(signVal) && signVal.equals(sign)) {log.info("验签成功 param:{}, sign:{},signVal:{}", val, sign, signVal);return true;}log.error("验签失败 param:{}, sign:{},signVal:{}", val, sign, signVal);return false;}}

CreateAscIISignUtil 生成参数 字典排序 签名

@Slf4j
public class CreateAscIISignUtil {/*** @MethodName: getSignToken* @Description: 生成签名*/public static String getSignToken(Map<String, Object> map) {String result = "";try {List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(map.entrySet());// 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序)Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() {@Overridepublic int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) {return (o1.getKey()).toString().compareTo(o2.getKey());}});// 构造签名键值对的格式StringBuilder sb = new StringBuilder();for (Map.Entry<String, Object> item : infoIds) {if (StrUtil.isNotEmpty(item.getKey())) {String key = item.getKey();String val = StrUtil.toString(item.getValue());if (StrUtil.isNotEmpty(val)) {sb.append(key + "=" + val + "&");}}}result = StrUtil.sub(sb, 0, sb.length()-1);} catch (Exception e) {log.error("CreateAscIISignUtil error = [{}]", e.getMessage(), e);return null;}return result;}
}

Hmacsha256Util 加密

	 /*** @MethodName: hmacMD5* @Description: HmacMD5加密* @Param: [message加密原文, secret秘钥]* @Return: java.lang.String加密后字符串*/public static String hmacMD5(String message, String secret) {String hash = "";try {Mac sha256_HMAC = Mac.getInstance("HmacMD5");SecretKeySpec secret_key = new SecretKeySpec(secret.getBytes(Charset.forName("UTF-8")), "HmacMD5");sha256_HMAC.init(secret_key);byte[] bytes = sha256_HMAC.doFinal(message.getBytes(Charset.forName("UTF-8")));hash = byteArrayToHexString(bytes);} catch (Exception e) {log.error("Hmacsha256Util hmacMD5 error = [{}]", e);}return hash;}

测试

请求如下:
在这里插入图片描述
返回结果:
在这里插入图片描述
成功拉兄弟姐妹们!!!!!
我师父看了我的代码表扬我了!!!!
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/43479.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【小西】优化若依导出功能,若依继承导出

前言 现需求是在原有的导出功能基础上&#xff0c;新增两列。 实现 因为新增两列不是数据库表中字段。因此&#xff0c;需要需要建立一个VO类。 原本想用若依继承导出&#xff0c;如下所示&#xff1a; Data public class ThemeActivityUserVO extends ThemeActivityUser…

极光尔沃A6-3d打印机体验

第一次使用3d打印机来打印模件&#xff0c;打印的是机械臂夹爪部位的小零件&#xff0c;设计的效果图如下图1所示。 图1&#xff1a;设计的夹爪部位原图 1、模件的设计 本模件使用的是solidworks软件进行的设计&#xff0c;当然可以使用其他的软件设计。最终保存的时候要以.st…

微信小游戏开发新手教程1-人人都能做游戏

如果你正在阅读这篇文章&#xff0c;那么你就是我所说的“人人”了。在此我默认你符合如下的几个条件&#xff1a; 有一定的阅读理解能力对做游戏有一定的兴趣&#xff08;否则你为什么要看这篇文章呢&#xff09;有一台电脑&#xff08;做游戏至少需要一台电脑&#xff09; …

一起用Go做一个小游戏(下)

打包资源 使用file2byteslice包我们可以将图片和config.json文件打包进二进制程序中&#xff0c;之后编译生成一个二进制程序。然后拷贝这一个文件即可&#xff0c;不用再拷贝图片和其他配置文件了。 golang有很多第三方包可以将打包资源&#xff0c;原理其实很简单——读取资源…

chatgpt赋能python:Python简单小游戏制作教程——让你学会编写游戏代码

Python简单小游戏制作教程——让你学会编写游戏代码 Python是一种高级编程语言&#xff0c;越来越受欢迎&#xff0c;因为它易于学习和使用&#xff0c;而且灵活性非常高。在这篇文章中&#xff0c;我们将教你如何用Python编写一个简单的小游戏。让我们开始吧&#xff01; 需…

ChatGPT-4终究会取代人类嘛?

随着人工智能技术的迅速发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;已经成为了一个热门领域。其中&#xff0c;ChatGPT-4是一个备受瞩目的自然语言处理工具。在2022年高考语文中&#xff0c;ChatGPT-4表现出色&#xff0c;说明它在自然语言处理领域有很强的实力。…

宋宝华: 僵尸进程的成因以及僵尸可以被“杀死”吗?

僵尸不可能被杀死&#xff0c;因为它已经死了&#xff0c;不存在再死一次的问题。死的对立面是活&#xff0c;死者已死。只有活的进程才可能被杀死。 什么是僵尸 首先要明确一点&#xff0c;僵尸进程的含义是&#xff1a;子进程已经死了&#xff0c;但是父进程还没有wait它的一…

僵尸进程zombie与孤儿进程orphan

代码已上传至https://github.com/gatieme/AderXCoding/tree/master/system/unix/zombie 问题提出 以前在学习《unix环境高级编程》进程时候&#xff0c;提到孤儿进程和僵尸进程&#xff0c;但是一直对这两个概念比较模糊。于是今天做了一些测试程序,并把这些记录下来. 僵尸进程…

僵尸进程以及如何处理僵尸进程

僵尸进程&#xff1a;就是已经结束了的进程&#xff0c;但是没有从进程表中删除。太多了会导致进程表里面条目满了&#xff0c;进而导致系统崩溃&#xff0c;倒是不占用其他系统资源。最后有defunct的标记&#xff0c;就表明是僵尸进程。 今天配置Redis的时候结束停止Redis服务…

僵尸进程的一点玩法

僵尸进程的一点玩法 前言被忽略的RundownProtectionExAcquireRundownProtection 应用总结 前言 这几天在看WRK的时候&#xff0c;偶然间发现的一个东西&#xff0c;逆向之后&#xff0c;发现了个僵尸进程的玩法。目前菜鸡一枚&#xff0c;有说的不准确的地方&#xff0c;请大家…

PAT——1094 谷歌的招聘

2004 年 7 月&#xff0c;谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌&#xff08;如下图&#xff09;用于招聘。内容超级简单&#xff0c;就是一个以 .com 结尾的网址&#xff0c;而前面的网址是一个 10 位素数&#xff0c;这个素数是自然常数 e 中最早出现的 10 位连续…

PTA—7-5 谷歌的招聘

实际上这题是不难的&#xff0c;甚至说有点简单&#xff0c;连我这样的小菜比都可以顺利的AC。 废话不多说来看题目。 2004 年 7 月&#xff0c;谷歌在硅谷的 101 号公路边竖立了一块巨大的广告牌&#xff08;如下图&#xff09;用于招聘。内容超级简单&#xff0c;就是一个以…

AI对话AI才是正解?KAUST研究团队提出基于角色扮演的大模型交互代理框架CAMEL

电影《盗梦空间》中有这样一句非常经典的台词&#xff1a; “世上最具有可塑性的寄生虫是什么&#xff1f;是人类的想法。人类大脑中一个简单的想法&#xff0c;就可以建立一座庞大的城市。有时一个想法也可以改变世界&#xff0c;并改写一切规则&#xff0c;这就是我为什么要…

chatGpt的快捷使用

首页的界面&#xff0c;非常好看&#xff0c;有我经常使用的入口 第一步&#xff1a;打开edge浏览器 第二步&#xff1a;右上角的扩展程序 第三步&#xff1a;点击 扩展 第四步&#xff1a; 第五步&#xff1a; 第六步&#xff1a; 第七步&#xff1a; 新打开Tab页&#xf…

windows下通过远程桌面访问linux图形界面

一、安装epel库 epel库安装之前无法使用yum install xrdp命令安装xrdp 命令&#xff1a;yum install epel-release之后会自动匹配对应版本的rpm包&#xff0c;并解决依赖关系进行安装。 二、安装xrdp xrdp作为linux的图形化界面 1.命令&#xff1a;yum install xrdp2.开启…

如何在Mac上快速显示桌面以便快速访问

macOS 环境中充满了可用于执行有用任务的快捷方式和手势。其中之一被简单地命名为“显示桌面”。当您打开一大堆应用程序窗口时&#xff0c;这个方便的功能可以为您节省宝贵的时间。一起来看看如何在Mac上快速显示桌面的方法吧。 1.使用触控板手势 触控板手势可能很难描述&…

大牛证券解析恒指大跌800点+全球股市大跌

今日两市差异化或许是像上一年白马抱团强化相同&#xff0c;而本年白马被丢掉&#xff0c;接力的科技与锂电&#xff0c;而这两个板块特别是&#xff08;成果爆发工作高成长为特性&#xff09;&#xff0c;锂电有宁德时代&#xff0c;比亚迪、容百科技等&#xff0c;芯片&#…

股票大跌期权对冲

股票期权的出世标示着股票能够及时止损&#xff0c; 股票期权能够很好的与股票做对冲&#xff0c;可以把股票亏损的风险降低&#xff0c;减少投资者面对股票行情下跌产生的亏损。 股票期权的上市让股票多了一种对冲方式&#xff0c;投资者买入股票的时候同时买入一手认沽期权&…

美股历史行情数据之日频率数据

美股历史行情日频率数据 全交易所eod数据&#xff0c;阿里云盘分享全历史行情数据&#xff0c;最早数据记录于1970年。数据字段包含OHLC&#xff0c;除权&#xff0c;股息等全部字段阿里云盘订阅数据&#xff0c;数据每天更新。 全交易所eod数据&#xff0c;阿里云盘分享 交易…

洋姜和生姜的区别

1、科属不同 洋姜和生姜的本质区别就是科属不一类&#xff0c;洋姜是菊科的&#xff0c;而生姜属姜科的&#xff0c;虽然都是多年生草本植物&#xff0c;但是科属不同就代表着这两种食材之间是不一样的了。 洋姜生姜属科不同 2、味道不同 可以通过闻的方式和尝的方式来感受…