微信下单流程

1、统一下单生成预支付订单,获取对应参数
2、使用对应参数进行二次签名,返回给小程序进行发起支付
3、等待微信后台回调我们自己的回调接口

微信后台 接口文档
https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

统一下单工具类

/*** @param appKey         商户平台设置的密钥key* @param appid            应用id* @param openid           微信openid* @param mch_id           商户号id* @param body             商品描述* @param out_trade_no     商户订单号* @param total_fee        金额,单位:分* @param spbill_create_ip 终端ip* @param notify_url       通知地址* @param trade_type       交易类型,小程序:JSAPI* @return* @throws Exception*/public static UnifiedOrderResponse unifiedorder(String appKey, String appid, String openid, String mch_id, String body, String out_trade_no, Integer total_fee, String spbill_create_ip, String notify_url, String trade_type) throws Exception {SortedMap<String, String> ps = new TreeMap();ps.put("appid", appid);ps.put("openid", openid);ps.put("mch_id", mch_id);ps.put("nonce_str", EncryptionUtils.getMD5String(System.currentTimeMillis() + out_trade_no)); //随机字符串 ps.put("body", body);ps.put("out_trade_no", out_trade_no);ps.put("total_fee", String.valueOf(total_fee));ps.put("spbill_create_ip", spbill_create_ip);ps.put("notify_url", notify_url);ps.put("trade_type", trade_type);String sign = sign(ps, wxApiKey);ps.put("sign", sign);String xml = XmlUtil.mapToXml(ps);log.debug("unifiedorder xml:" + xml);try {RequestBody requestBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"), xml);Response execute = OkHttpUtil.getInstance().post("https://api.mch.weixin.qq.com/pay/unifiedorder";, (Map)null, requestBody);int code = execute.code();if (code == 200) {String result = execute.body().string();log.debug("unifiedorder result:" + result);UnifiedOrderResponse response = (UnifiedOrderResponse)XmlUtil.xmlToBeanByJAXB(UnifiedOrderResponse.class, result);if (response == null) {throw new Exception("wx统一下单结果未知,返回数据解析错误,返回数据为:" + result);} else if (response.getReturn_code().equals("SUCCESS")) {return response;} else {throw new Exception("wx统一下单通信失败,原因如下:" + result);}} else {throw new Exception("wx统一下单失败,http 访问结果不是 200,返回结果为:" + execute.body().string());}} catch (IOException var18) {throw new Exception("wx统一下单失败,http 访问错误:" + var18.getMessage());}}try {RequestBody requestBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"), xml);Response execute = OkHttpUtil.getInstance().post("https://api.mch.weixin.qq.com/pay/unifiedorder";, (Map)null, requestBody);int code = execute.code();if (code == 200) {String result = execute.body().string();log.debug("unifiedorder result:" + result);UnifiedOrderResponse response = (UnifiedOrderResponse)XmlUtil.xmlToBeanByJAXB(UnifiedOrderResponse.class, result);if (response == null) {throw new Exception("wx统一下单结果未知,返回数据解析错误,返回数据为:" + result);} else if (response.getReturn_code().equals("SUCCESS")) {return response;} else {throw new Exception("wx统一下单通信失败,原因如下:" + result);}} else {throw new Exception("wx统一下单失败,http 访问结果不是 200,返回结果为:" + execute.body().string());}} catch (IOException var18) {throw new Exception("wx统一下单失败,http 访问错误:" + var18.getMessage());}
}

获取用户ip

获取ip
import javax.servlet.http.HttpServletRequest;
public class IpAddress {/*** 获取用户真实IP地址,不使用request.getRemoteAddr()的原因是有可能用户使用了代理软件方式避免真实IP地址,* 可是,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值** @return ip*/public static String getIpAddress(HttpServletRequest request) {String ip = request.getHeader("x-forwarded-for");if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {if (ip.indexOf(",") != -1) {ip = ip.split(",")[0];}}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("X-Real-IP");}if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}
}

UnifiedOrderResponse

// 具体参数对照微信 api
@Data
public class UnifiedOrderResponse {private String return_code;private String return_msg;private String result_code;private String err_code;private String err_code_des;private String appid;private String mch_id;private String device_info;private String nonce_str;private String sign;private String trade_type;private String prepay_id;private String code_url;}

请求成功后 需要进行二次签名

/*** 设置统一下单返回给前端的参数 二次签名** @param unifiedorder* @return*/public WxparamVO getWxparamVO(UnifiedOrderResponse unifiedorder, Orders order, Integer realPaymentPrice) {String body = order.getProductFullName().split(";")[0];WxparamVO wxparamVO = new WxparamVO();wxparamVO.setPrepayId(unifiedorder.getPrepay_id());// 获取预支付交易idwxparamVO.setBody(body); // 显示支付内容wxparamVO.setNonce_str(unifiedorder.getNonce_str()); // 随机字符串Long timeStamp = System.currentTimeMillis() / 1000;SortedMap<String, String> ps = new TreeMap();ps.put("appId", unifiedorder.getAppid());ps.put("nonceStr", unifiedorder.getNonce_str());ps.put("package", "prepay_id=" + unifiedorder.getPrepay_id());ps.put("signType", "MD5");ps.put("timeStamp", String.valueOf(timeStamp));wxparamVO.setSign(sign(ps, WX_API_KEY)); // 签名wxparamVO.setOut_trade_no(order.getOrderId());//订单idwxparamVO.setTotal_fee(realPaymentPrice);//支付价格wxparamVO.setTimeStamp(String.valueOf(timeStamp));log.info("正在请求支付,支付信息:order_id" + order.getOrderId() + " 支付金额:" + order.getRealPaymentPrice());return wxparamVO;}

WxparamVO


@Data
public class WxparamVO {@ApiModelProperty(value = "预支付交易会话id")private String prepayId;/*随机字符串,长度要求在32位以内*/@ApiModelProperty(value = "随机字符串")`在这里插入代码片`private String nonce_str;/*签名*/@ApiModelProperty(value = "签名")private String sign;/*商品描述*/@ApiModelProperty(value = "商品描述")private String body;/*商户订单号*/@ApiModelProperty(value = "商户订单号 也就是 订单id orderId")@JsonSerialize(using = ToStringSerializer.class)private Long out_trade_no;/*标价金额 默认分*/@ApiModelProperty(value = "标价金额 默认分")private Integer total_fee;/*标价金额 默认分*/@ApiModelProperty(value = "时间戳")private String timeStamp;}

微信回调通知

回调通知需要进行校验签名!!!

//controller 类
@ApiOperation(value = "微信支付成功回调", notes = "微信支付成功异步回调,修改订单信息")@PostMapping("/xxx-notify")public String orderNotify() throws Exception {return OrderService.orderNotify();}// 实现类// 实现类public String orderNotify() {HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();//校验 订单String xml = request2String(request);boolean flag = validateSign(xml, WxDataManager.WX_API_KEY);if(flag){// TODO 业务return  success();}return false();
}String fail() {return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml>";}String success() {return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";}

request 转换为字符串

/*** 微信回调参数 转化为String的 xml** @param request* @return*/public static String request2String(HttpServletRequest request) {String notifyData = "";try {InputStream is = request.getInputStream();try {BufferedReader reader = new BufferedReader(new InputStreamReader(is));StringBuilder sb = new StringBuilder();String line = null;while ((line = reader.readLine()) != null) {sb.append(line + "\n");}notifyData = sb.toString();} catch (IOException e) {e.printStackTrace();} finally {is.close();}} catch (Exception e) {log.error("获取回调数据异常:" + e.getMessage());}return notifyData;}

校验sign签名 工具类

/*** 验证 签名sign** @param xml* @param APPKEY 商户的app key* @return*/public static boolean validateSign(String xml, String APPKEY) {SortedMap<String, String> stringStringMap = xmlToMap(xml);// 微信返回来的xml 参数是 已经按照字典序排序了String sign = stringStringMap.get("sign");if (StringUtils.isEmpty(sign)) {//签名为空return false;}String validSign = sign(stringStringMap, APPKEY);if (sign.equals(validSign)) {return true;}log.error("微信支付 签名错误");return false;}

微信支付统一下单与支付成功回调相关推荐

  1. 微信小程序支付统一下单接口and异步回调

     统一下单接口: <?phpnamespace pay;class WxPay {protected $appid;protected $mch_id;protected $key;protec ...

  2. 微信支付-----统一下单接口对接

    本以为没有机会接触鼎鼎大名的支付宝和微信接口(公司本身是做第三方支付的),最近由于一个售货机项目需要对接银联,支付宝和微信接口,因为我自身已经对接了银联,之后根据安排,由我对接微信的相关接口.话不多说 ...

  3. APP 对接 java 微信支付统一下单接口

    首先插入微信支付的时序图 统一下单时候的请求对象,需要把这个转为xml 文件格式所以需要在pom.xml 文件中导入 .和微信支付的sdk <dependency> <groupId ...

  4. 微信V3 - 微信支付统一下单 --01

    准备工作: private static PrivateKey merchantPrivateKey; static { try { merchantPrivateKey = PemUtil.load ...

  5. 微信支付 统一下单 字段 body 为中文时 报【签名错误】解决方案(C# SDK)

    微信支付 统一下单 字段 body 为中文时 报[签名错误]解决方案(C# SDK) 参考文章: (1)微信支付 统一下单 字段 body 为中文时 报[签名错误]解决方案(C# SDK) (2)ht ...

  6. SpringBoot实现小程序微信支付统一下单

    SpringBoot实现微信支付统一下单 最近做小程序有需要用到微信支付,而在页面拉起微信支付前需要先进行统一下单,然后再返回参数给前端调用微信支付wx.requestPayment.网上参考了很多代 ...

  7. 【微信支付统一下单】JAVA与XML请求内容体的双向映射

    在微信支付统一下单接口文档中,请求体body和微信端返回值都是xml格式的内容. 例如: <!-- 请求微信端的内容 ---> <xml><appid>wx2421 ...

  8. java微信支付 [统一下单接口] 与 [订单查询接口] 调用成功完整代码与结果

    公司最近要搞微信支付, 之前也没有做过, 但是搞过阿里云, 想来也不是很难. 在网上找了很多贴子, 在eclipse里做了5个测试工程, 没有测试成功, 后来下了微信SDK, 也做了个测试样例, 期间 ...

  9. 微信app支付统一下单设置回调地址php,微信支付配置回调地址

    需要超级管理员帐号登录才可操作 1) 所有使用公众号支付方式发起支付请求的链接地址,都必须在支付授权目录之下: 2) 支付授权目录最多可以设置5个目录 3) 头部要包含http或https,须细化到二 ...

  10. 微信支付统一下单支付结果回调

    在用户支付完过后微信会调用我们给它的异步通知地址返回支付的结果,需要注意的是我们给的通知地址是可以进行外网访问的 我使用的一些工具类方法大多是从官方给的demo,下面是下载地址 https://pay ...

最新文章

  1. python生成验证码
  2. php写的squid验证辅助器
  3. json数据转换成表格_电子表格会让您失望吗? 将行数据转换为JSON树很容易。
  4. [Python]使用 lambda 函数
  5. JEECG_3.7开发环境搭建与代码生成器入门级教程-张代浩-专题视频课程
  6. C#LeetCode刷题之#83-删除排序链表中的重复元素(Remove Duplicates from Sorted List)
  7. ActionScript读取XML的路径问题
  8. 继承extends(Java)
  9. android BaseAdapter多布局缓存
  10. SylixOS中RTC设备驱动
  11. mappedBy reference an unknown target entity property解决方法
  12. 进击的速溶咖啡:当中国AI开始玩工业化
  13. 一名IT民工开通博客
  14. python爬虫爬取下厨房食谱,周末聚餐真的停不下来
  15. 计算机视觉中的双目立体视觉和体积度量
  16. 基于PHP+MySQL的大学生求职招聘网站
  17. 【C++面试必备】一个专栏带你搞定剑指offer第二版
  18. 如何组织一场安全、可靠、高效的网络实战攻防演习?
  19. 从顺丰到菜鸟,洋女婿“爆改”俄罗斯邮政
  20. 2019年机器学习:追踪人工智能发展之路

热门文章

  1. python access token_Python config.ACCESS_TOKEN属性代码示例
  2. Python3入门教程:基础数据类型(上)
  3. HGOI8.21集训题解
  4. css:头像处理之将长方形的图片放在圆形框里居中
  5. 【RocketMQ】【源码】负载均衡源码分析
  6. 转行数字IC验证的学习路线是什么样的?现在开始转是否来得及?985本硕,电子学院研二
  7. 求求了还有没有点击就送的小公司啊,有口饭吃就行
  8. excel中宏与VBA的关系
  9. 浙江大学电气考研答疑及经验分享
  10. 转:Android(安卓)权限中文描述大全