小米支付

小米支付不像微信/支付宝支付那样的流程,而是直接由客户端APP进行发起的支付回调。

小米支付官网地址 https://dev.mi.com/distribute/doc/details?pId=1150#_21

个人支付案例git地址[微信支付/支付宝支付/华为支付/苹果支付/小米支付]:https://gitee.com/wazk2008/demo-pay

支付回调

yml配置

xiaomi:appid: 自己的appidapp-secret: 自己的app对应的密钥

回调参数

@Data
public class PayMiCallbackRequest implements Serializable {// 游戏IDprivate String appId;// 开发商订单IDprivate String cpOrderId;// 开发商透传信息private String cpUserInfo;// 用户IDprivate String uid;// 游戏平台订单IDprivate String orderId;// 订单状态,TRADE_SUCCESS 代表成功private String orderStatus;// 支付金额,单位为分,即0.01米币private String payFee;// 商品代码private String productCode;// 商品名称private String productName;// 商品数量private String productCount;// 支付时间,格式 yyyy-MM-dd HH:mm:ssprivate String payTime;// 签名private String signature;}

回调Controller

@RestController
@RequestMapping(value = "/pay")
@Slf4j
public class PayController {@Autowiredprivate MiService miService;@PostMapping(value = "/miPayCallback")public Result<Object> payMiCallback (@RequestBody PayMiCallbackRequest payMiCallbackRequest) {try {log.info("小米支付回调接口开始执行,请求参数:{}", JSON.toJSON(payMiCallbackRequest));miService.payCallback(payMiCallbackRequest);log.info("小米支付回调接口执行成功,请求参数:{}", JSON.toJSON(payMiCallbackRequest));return Result.getSuccess();} catch (ResponseException e) {log.error("小米支付回调接口执行失败1,请求参数:{},异常原因:{}", JSON.toJSON(payMiCallbackRequest), e.getMessage());e.printStackTrace();return Result.getFail(e.getCode(), e.getMessage());} catch (Exception e) {log.error("小米支付回调接口执行失败2,请求参数:{},异常原因:{}", JSON.toJSON(payMiCallbackRequest), e.getMessage());e.printStackTrace();return Result.getFail(ResultCode.INTERNAL_SERVER_ERROR);}}}

回调Service

@Service
public class MiService {@Value("${xiaomi.appid}")private String appId;@Value("${xiaomi.app-secret}")private String appSecret;@Autowiredprivate RestTemplate restTemplate;private static final String MAC_NAME = "HmacSHA1";private static final String MI_QUERY_ORDER_URL = "https://mis.migc.xiaomi.com/api/biz/service/queryOrder.do";public void payCallback(PayMiCallbackRequest payMiCallbackRequest) {if (!"TRADE_SUCCESS".equals(payMiCallbackRequest.getOrderStatus())) {throw new ResponseException(ResultCode.MI_PAY_CALLBACK_ORDER_STATUS_ERROR);}if (!appId.equals(payMiCallbackRequest.getAppId())) {throw new ResponseException(ResultCode.MI_PAY_CALLBACK_APPID_ERROR);}// 校验签名String encryptText = generateEncryptText(convertOrderPayXiaomiCallbackRequestToMap(payMiCallbackRequest));String checkSignature = hmacSHA1Encrypt(encryptText, appSecret);if (!payMiCallbackRequest.getSignature().equals(checkSignature)) {// 签名校验失败throw new ResponseException(ResultCode.MI_PAY_CALLBACK_VALID_SIGN_ERROR);}// 请求小米支付服务端,获取小米支付状态boolean validMiRemoteService = validMiRemoteService(payMiCallbackRequest);if (!validMiRemoteService) {// 小米支付回调处理错误,请求小米校验订单状态错误throw new ResponseException(ResultCode.MI_PAY_CALLBACK_ORDER_STATUS_ERROR);}// todo 校验订单是否存在String outTradeNo = payMiCallbackRequest.getCpOrderId();// todo 校验订单是否已支付// todo 校验支付金额Double buyerAmount = Double.valueOf(payMiCallbackRequest.getPayFee());// todo 修改支付和订单的状态}// 生成验签字符串private String generateEncryptText (Map<String, String> map) {// 排序Set<String> keySet = map.keySet();String[] keyArray = keySet.toArray(new String[keySet.size()]);Arrays.sort(keyArray);StringBuilder sb = new StringBuilder();for (String k : keyArray) {sb.append("&").append(k).append("=").append(map.get(k).trim());}String sign = sb.toString();return sign.replaceFirst("&", "");}// 将 PayMiCallbackRequest 中的非空属性全部转为 map 格式private Map<String, String> convertOrderPayXiaomiCallbackRequestToMap (PayMiCallbackRequest payMiCallbackRequest){Class<? extends PayMiCallbackRequest> clazz = payMiCallbackRequest.getClass();Field[] fields = clazz.getDeclaredFields();Map<String, String> map = new HashMap<>();try {for (Field field : fields) {field.setAccessible(true);String fieldName = field.getName();Object fieldValue = field.get(payMiCallbackRequest);if (!Objects.isNull(fieldValue) && !StringUtils.isEmpty(fieldValue.toString()) && !"signature".equals(fieldName) && !"ivyTransactionId".equals(fieldName)) {map.put(fieldName, URLDecoder.decode(fieldValue.toString(), CharEncoding.UTF_8));}}} catch (Exception e) {throw new ResponseException(ResultCode.MI_PAY_CALLBACK_PARAMS_CONVERT_ERROR);}return map;}// 使用 HMAC-SHA1 签名方法对对encryptText进行签名private String hmacSHA1Encrypt( String encryptText, String encryptKey) {byte[] data = encryptKey.getBytes(StandardCharsets.UTF_8);// 根据给定的字节数组构造一个密钥,第二参数指定一个密钥算法的名称SecretKey secretKey = new SecretKeySpec( data, MAC_NAME );// 生成一个指定 Mac 算法 的 Mac 对象Mac mac = null;try {mac = Mac.getInstance( MAC_NAME );// 用给定密钥初始化 Mac 对象mac.init( secretKey );} catch (Exception e) {// 生成签名错误throw new ResponseException(ResultCode.MI_PAY_CALLBACK_GENERATE_SIGN_ERROR);}byte[] text = encryptText.getBytes(StandardCharsets.UTF_8);// 完成 Mac 操作byte[] digest = mac.doFinal( text );StringBuilder sBuilder = bytesToHexString( digest );return sBuilder.toString();}private StringBuilder bytesToHexString( byte[] bytesArray ){if ( bytesArray == null ){return null;}StringBuilder sBuilder = new StringBuilder();for ( byte b : bytesArray ){String hv = String.format("%02x", b);sBuilder.append( hv );}return sBuilder;}// 向小米服务端发起校验private boolean validMiRemoteService (PayMiCallbackRequest payMiCallbackRequest) {// 请求小米支付服务端,获取小米支付状态String cpOrderId = payMiCallbackRequest.getCpOrderId();String uid = payMiCallbackRequest.getUid();Map<String, String> paramMap = new HashMap<>();paramMap.put("appId", appId);paramMap.put("cpOrderId", payMiCallbackRequest.getCpOrderId());paramMap.put("uid", uid);String newSignature = hmacSHA1Encrypt(generateEncryptText(paramMap), appSecret);String url = MI_QUERY_ORDER_URL + "?appId=" + appId + "&cpOrderId=" + cpOrderId + "&uid=" + uid + "&signature=" + newSignature;JSONObject miResponse = sendHttpRequest(url);return "TRADE_SUCCESS".equals(miResponse.getString("orderStatus"));}public JSONObject sendHttpRequest(String url) {HttpHeaders headers = new HttpHeaders();HttpEntity<String> httpEntity = new HttpEntity(headers);ResponseEntity<String> exchange = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class, new Object[0]);String response = (String)exchange.getBody();return JSON.parseObject(response);}}

SpringBoot集成小米支付相关推荐

  1. springboot 集成支付宝支付

    最简单的springboot集成支付宝 1 注册沙箱 沙箱是一个模拟环境登录,百度蚂蚁金服开放平台,支付宝扫码登录如下 然后沙箱需要注册一下,非常之简单,注册好以后进入到如下页面,选沙箱工具,然后下载 ...

  2. springboot集成支付宝支付2.0

    springboot集成微信APP支付V3最新版 流程详解 创建应用 添加支付能力 接口加签 获取证书 集成支付到springboot项目 流程详解 相对于集成微信支付来说,支付宝相对简单些,支付宝对 ...

  3. SpringBoot集成微信支付V3

    河南循中网络科技有限公司 - 精心创作,详细分解,按照步骤,均可成功! 文章目录 吐槽! 此文章包含实现了哪些接口? 学习资料 集成微信支付V3 什么是"商户证书"?什么是&quo ...

  4. SpringBoot集成微信支付微信退款

    微信支付 备注:本次支付接入的是微信支付v2.0版本,其中所有的请求格式均为XML. 如有需求可直接参阅官方文档 https://pay.weixin.qq.com/wiki/doc/api/inde ...

  5. SpringBoot集成华为支付

    华为支付 华为支付不像微信/支付宝支付那样的流程,而是直接由客户端APP进行发起的支付回调. 华为支付官网地址 个人支付案例git地址[微信支付/支付宝支付/华为支付/苹果支付/小米支付]:https ...

  6. SpringBoot集成支付宝支付支付宝退款

    支付宝支付 阅官方文档 https://opendocs.alipay.com/open/02e7gq 个人支付案例git地址[微信支付/支付宝支付/华为支付/苹果支付/小米支付]:https://g ...

  7. springboot集成微信支付

    一.先去微信申请相应的appid等,然后在yml文件增加相应配置 pay:   wxpay:     appID: ******     mchID: *****     key: *****     ...

  8. springboot集成微信支付V3 SDK

    微信支付开通支付方法在这里可以参考一下:申请开通微信支付教程_个人怎么申请微信支付_郑鹏川的博客-CSDN博客 因为微信支付回调需要一个外网可访问的地址,我本地调试是采用的内网穿透的方式进行调试的. ...

  9. SpringBoot 支付宝沙箱支付 natapp内网穿透

    沙箱应用支付宝开放平台 (alipay.com) 1.生成商户私钥.公钥(记得保存) 2.利用商户公钥生成支付宝公钥 Natapp内网穿透 NATAPP-内网穿透 基于ngrok的国内高速内网映射工具 ...

最新文章

  1. 2017杭州·云栖大会全纪实
  2. 九度OJ—题目1032:ZOJ
  3. python3.8安装pygame_Python3.8安装Pygame教程步骤详解
  4. 高并发 python socket send 异步_对于Python中socket.listen()与多线程结合的困惑?
  5. 关联规则算法c语言样例及分析_推荐系统总结系列-关联规则算法(四)
  6. 机器学习中的数学(六)--信息论与激活函数
  7. 木兰编程语言重现——儿歌查询实例,引用模块、字符串列表操作
  8. 案例-三角形(CSS3)
  9. windows获取cmd回显以及获取路径
  10. markDown零碎整理
  11. 上下文路径request.getContextPath();与${pageContext.request.contextPath}
  12. Tampermonkey油猴教程及Greasyfork脚本使用
  13. EBT 道客巴巴的加密与破解 - 实用组合工具箱
  14. 解决Vue中使用echart组件刷新问题
  15. 深入理解 JVM 垃圾回收机制及其实现原理
  16. 共享编辑文档系统dzzoffice安装
  17. stm32f7网口_【STM32F7】开发篇 - 详解STM32F7 TCPServer工程【申精】
  18. Android UI
  19. 硬纪元干货|爱奇艺吴霜:看好互动视频、AI陪伴以及VR直播
  20. adnroid 系统OTA升级

热门文章

  1. springboot整合spring Validated
  2. 想像人类一样聪明?AI先得突破算力极限
  3. *#OpenFOAM安装后的第一个案例的理解与运行(pitzDaily)
  4. 用 Python 轻松实现批量多层级嵌套 Excel 转 Word - 十分钟干完一个月的活
  5. Java基础——利用DMO4J编写一个商品管理系统
  6. 搜狗玩花样能否迎合年轻人?
  7. 网络编程——TCP网络编程UDP编程
  8. 新路由3 D2版本解锁刷入brend
  9. 怎样能显示计算机的配置高低,电脑配置怎么看高低,电脑配置知识大全
  10. H5新特性(一)——音视频标签