对接微信支付接口-详细步骤教程-你不知道的那些坑@TOC

近期公司项目需要对接微信支付宝等支付接口,然后就看官网看文档查百度,我这里只说对接微信支付接口,下一篇说微信退款.

先登录微信官网查看文档

这里我先解释一下微信支付接口的步骤

第一步:统一下单 (此操作是我们对接微信接口,微信接口需要生成订单的操作所以这里是第一步)

第二步:调起支付接口 (此操作是第一步调用微信然后返回参数 针对这些参数返还给ios或者安卓等 他们调起对应app的支付接口 )

第三步:支付结果通知 (这一步是支付完成之后我们通常所说的要回调 这个表示这最终的调用支付的结果 我们可以在这一步的时候进行我们修改自己内部的表等操作例如 将未付款状态修改为已付款等)

下面是第一步和第二步的详细流程,附加代码

统一下单的详细步骤和调起支付的详细步骤


前期要有一个准备工作 登录自己的企业账户进去申请上自己企业的
(1)应用id
(2)商户号
(3)微信的key

这里的(3)微信的appkey 在这里申请
这里设置好后自己保存下后面调用接口时要用
这里我再后期调用不通一直显示签名错误就是因为这里的坑

1.将微信接口连接写在配置中或者自己声明好 在调用接口时读取
2.写调用的方法我这里只写微信接口调用部分
3.将微信接口文档中的参数必填的都一一放入map中
4.生成对应的签名 这里说明一下生成签名必须要做排序 我下面的代码已经做了可以直接拿来用
5.调用接口 调动接口前要将参数转换为xml 微信只支持这种方式的传递
6.返回参数,根据参数来 走步骤的第二步 调起支付接口

以下是第一步和第二步的接口我是一起写了

  @ResponseBody@Transactionalpublic AjaxResult payWeixin(String orderNo, String money, HttpServletRequest request) {log.info("-------------------微信支付---------------------");String userIP = getIp(request); //获取前台的ipSystem.out.println("用户IP为:" + userIP);SortedMap<String, Object> parameterMap = new TreeMap<String, Object>();parameterMap.put("appid" , PayConstant.WX_APP_ID); //你自己的appid 应用idparameterMap.put("mch_id" , PayConstant.WX_MCH_ID);//你自己的mch_id 商户号parameterMap.put("nonce_str" , getRandomString(16)); //这是随机的一个字符串parameterMap.put("body" , "某某网站付款");//parameterMap.put("out_trade_no" , orderNo);//orderNo 具体操作的订单号parameterMap.put("fee_type" , "CNY");//因为微信支付的单位是分   只能是证书 不能有小数点所以要将传过来的值转换为分的单位//传过来的是以元为单位的 moneyString strmoney = changeY2F(money);int intmoney=0;try {intmoney = Integer.valueOf(strmoney).intValue();} catch (NumberFormatException e) {e.printStackTrace();}parameterMap.put("total_fee" , intmoney);parameterMap.put("spbill_create_ip" , userIP);//用户的ipparameterMap.put("notify_url" , notifyUrlwx);//回调地址 第三步的步骤需要的地址必须是公网能访问的 如果在测试阶段可以申请一个花生壳 这里可以内网穿透访问parameterMap.put("trade_type" , "APP");//设置签名String key = PayConstant.API_KEY;  //这里的key就是我上面说过的微信的key String sign = createSign("UTF-8" , parameterMap, key);System.out.println("最上面的签名____________________" + sign);parameterMap.put("sign" , sign);//封装请求参数结束String requestXML = getRequestXml(parameterMap);//调用统一下单接口String result = httpsRequest(PayConstant.WX_GETEWAY, "POST" , requestXML);System.out.println("请求参数:" + requestXML);System.out.println("返回参数:" + result);//这里是第二步调起支付的接口步骤了  当同一下单完成之后会执行第二步调起支付接口try {/**统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appId,partnerId,prepayId,nonceStr,timeStamp,package。注意:package的值格式为Sign=WXPay**/Map<String, String> map = WXPayUtil.doXMLParse(result);if ("".equals(map.get("prepay_id")) || map.get("prepay_id") == null) {return AjaxResult.error("微信支付拉取失败,请稍后重试!");}SortedMap<String, Object> parameterMap2 = new TreeMap<String, Object>();parameterMap2.put("appid" , PayConstant.WX_APP_ID);parameterMap2.put("partnerid" , PayConstant.WX_MCH_ID);parameterMap2.put("prepayid" , map.get("prepay_id"));parameterMap2.put("package" , "Sign=WXPay");parameterMap2.put("noncestr" , getRandomString(16));//本来生成的时间戳是13位,但是ios必须是10位,所以截取了一下parameterMap2.put("timestamp" , Long.parseLong(String.valueOf(System.currentTimeMillis()).toString().substring(0, 10)));String sign2 = createSign("UTF-8" , parameterMap2, key);System.out.println("第二次签名++++++++++++++++++++++++++++++++++++++" + sign2);parameterMap2.put("sign" , sign2);parameterMap2.put("packageX" , "Sign=WXPay");return AjaxResult.success("微信支付拉取成功!" , parameterMap2);} catch (JDOMException | IOException e) {e.printStackTrace();return AjaxResult.error("微信支付拉取失败,请稍后重试!");}}//随机字符串生成public static String getRandomString(int length) { //length表示生成字符串的长度String base = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";Random random = new Random();StringBuffer sb = new StringBuffer();for (int i = 0; i < length; i++) {int number = random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}//生成签名  public static String createSign(String characterEncoding, SortedMap<String, Object> parameters, String key) {StringBuffer sb = new StringBuffer();Set es = parameters.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();Object v = entry.getValue();if (null != v && !"".equals(v)&& !"sign".equals(k) && !"key".equals(k)) {sb.append(k + "=" + v + "&");}}//sb.append("key=" + PayConstant.API_KEY);sb.append("key=" + key);System.out.println(sb.toString());String sign = Md5Utils.MD5Encode(sb.toString(), characterEncoding).toUpperCase();return sign;}//请求xml组装public static String getRequestXml(SortedMap<String, Object> parameters) {StringBuffer sb = new StringBuffer();sb.append("<xml>");Set es = parameters.entrySet();Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String key = (String) entry.getKey();String value = (String) entry.getValue().toString();if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) {sb.append("<" + key + ">" + "<![CDATA[" + value + "]]></" + key + ">");} else {sb.append("<" + key + ">" + value + "</" + key + ">");}}sb.append("</xml>");return sb.toString();}//将单位为元的金钱的转换为分public  String changeY2F(String amount){String currency =  amount.replaceAll("\\$|\\¥|\\,", "");  //处理包含, ¥ 或者$的金额int index = currency.indexOf(".");int length = currency.length();Long amLong = 0l;if(index == -1){amLong = Long.valueOf(currency+"00");}else if(length - index >= 3){amLong = Long.valueOf((currency.substring(0, index+3)).replace(".", ""));}else if(length - index == 2){amLong = Long.valueOf((currency.substring(0, index+2)).replace(".", "")+0);}else{amLong = Long.valueOf((currency.substring(0, index+1)).replace(".", "")+"00");}return amLong.toString();}//xml解析public static Map doXMLParse(String strxml) throws JDOMException, IOException {strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");if (null == strxml || "".equals(strxml)) {return null;}Map m = new HashMap();InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));SAXBuilder builder = new SAXBuilder();Document doc = builder.build(in);Element root = doc.getRootElement();List list = root.getChildren();Iterator it = list.iterator();while (it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if (children.isEmpty()) {v = e.getTextNormalize();} else {v = getChildrenText(children);}m.put(k, v);}//关闭流in.close();return m;}//获取真实IPpublic static String getIp(HttpServletRequest request) {String ip = request.getHeader("X-Forwarded-For");if (!StringUtils.isBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {//多次反向代理后会有多个ip值,第一个ip才是真实ipint index = ip.indexOf(",");if (index != -1) {return ip.substring(0, index);} else {return ip;}}ip = request.getHeader("X-Real-IP");if (!StringUtils.isBlank(ip) && !"unKnown".equalsIgnoreCase(ip)) {return ip;}return request.getRemoteAddr();}//请求方法public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {try {URL url = new URL(requestUrl);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);// 设置请求方式(GET/POST)conn.setRequestMethod(requestMethod);conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");// 当outputStr不为null时向输出流写数据if (null != outputStr) {OutputStream outputStream = conn.getOutputStream();// 注意编码格式outputStream.write(outputStr.getBytes("UTF-8"));outputStream.close();}// 从输入流读取返回内容InputStream inputStream = conn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}// 释放资源bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;conn.disconnect();return buffer.toString();} catch (ConnectException ce) {System.out.println("连接超时:{}" + ce);} catch (Exception e) {System.out.println("https请求异常:{}" + e);}return null;}

以上是第一步和第二步的详细流程

第一步和第二步的操作已经完成了,这是安卓和ios就可以根据我们返回的参数来调起微信支付了,
但是这里有一个坑,我在调用微信接口的时候,我自己生成的签名和在微信官网生成的签名一模一样,
但是他老是提示我签名失败,网上找了好久,终于瞎猫碰上耗子给解决了,我的问题是,
前面在微信官网生成的key竟然不能用,但是微信不告诉我们不能用,反正你一调用就是签名失败,于是我登录微信官网,修改了一下key就成功了,所以这里不得不说,这微信的官方文档是真的坑啊!!!!
在这里修改的  重新设置一下就好了

以上第一步第一步通了之后就说明我们的微信支付已经完成了,但是还有一个第三步回调

第三步的回调

这个回调是微信支付成功后回调给我们的,地址是我们统一下单时写的通知的url
所以我们可以再这里写我们自己的逻辑

这里回调的话没什么好说的就是微信自动调用,要进行一个验签,成功之后就大功告成了!

/*** 微信回调* @param request* @param response* @return*/@RequestMapping("/newNotify")@ResponseBodypublic String wxpaySucc(HttpServletRequest request, HttpServletResponse response) {log.info("-------------------互助微信支付回调---------------------");String returnStr = "" ;Map<String, String> params = null;InputStream inputStream = null;ByteArrayOutputStream outputSteam = null;try {inputStream = request.getInputStream();outputSteam = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = inputStream.read(buffer)) != -1) {outputSteam.write(buffer, 0, len);}log.info("------------------------1微信读取回调---------------------------");String resultxml = new String(outputSteam.toByteArray(), "utf-8");params = WXPayUtil.doXMLParse(resultxml);log.info("------------------------2微信读取回调参数为:"+params+"---------------------------");} catch (IOException | JDOMException e) {log.info("---------------------------------3微信调用出现异常-------------------------");e.printStackTrace();} finally {try {if (outputSteam != null) {outputSteam.close();}if (inputStream != null) {inputStream.close();}} catch (IOException e) {e.printStackTrace();}}log.info("-----------------------------4-----------------------------");String out_trade_no = params.get("out_trade_no");//订单号String total_fee = params.get("total_fee");String return_code = params.get("return_code");//微信返回的状态码if("SUCCESS".equals(return_code)){//验签  手动代码验签if (!isTenpaySign(params, PayConstant.WX_APP_ID)) {log.info("===============付款失败=验签失败!=============" + out_trade_no);// 支付失败returnStr = getXML("FAIL" , "验签失败");}else{ //验签成功log.info("===============付款成功=验签成功!=============" + out_trade_no)returnStr = getXML("SUCCESS" , "验签成功");}}else{returnStr = getXML("FAIL" , "验签失败");}try {PrintWriter pw = response.getWriter();pw.write(returnStr);pw.flush();} catch (IOException e) {e.printStackTrace();}return returnStr;}/*** 验证回调签名* @return*/public static boolean isTenpaySign(Map<String, String> map,String key) {String charset = "utf-8";String signFromAPIResponse = map.get("sign");if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");return false;}System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);System.out.println(map+"微信返回的数据");//过滤空 设置 TreeMapSortedMap<String, String> packageParams = new TreeMap<>();for (String parameter : map.keySet()) {String parameterValue = map.get(parameter);String v = "";if (null != parameterValue) {v = parameterValue.trim();}packageParams.put(parameter, v);}StringBuffer sb = new StringBuffer();Set es = packageParams.entrySet();System.out.println(packageParams+"获取微信返回的数据进行对比");Iterator it = es.iterator();while (it.hasNext()) {Map.Entry entry = (Map.Entry) it.next();String k = (String) entry.getKey();String v = (String) entry.getValue();if (!"sign".equals(k) && null != v && !"".equals(v)) {sb.append(k + "=" + v + "&");}}sb.append("key=" + key);//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较//算出签名String resultSign = "";String tobesign = sb.toString();System.out.println(tobesign.toString()+"????????????????????????????????");if (null == charset || "".equals(charset)) {resultSign = Md5Utils.MD5Encode(tobesign, PayConstant.CHARSET).toUpperCase();} else {resultSign = Md5Utils.MD5Encode(tobesign, PayConstant.CHARSET).toUpperCase();}System.out.println(resultSign+"再次生成的签名++++++++++++++++++++++++++++++++++++++++++++++++++++");String tenpaySign = ((String) packageParams.get("sign")).toUpperCase();System.out.println(tenpaySign+"微信返回的签名____________________________________________________");return tenpaySign.equals(resultSign);}

微信支付接口详细步骤相关推荐

  1. 后端---最全最简单细致的Java接入微信支付接口(Native接入)

    首先,我简单总结一下这几天搞微信支付和支付宝支付接口的体会,通过这几天的动手实操,加强了自己对SSM框架的认识,以及对业务逻辑的思路,明白了许多以前不懂的许多空白. 做支付宝接口的接入完全可以按照支付 ...

  2. Android_APP 微信支付接口开发

    1.首先说一下我们在开发微信支付接口的时候遇到最多和最疑惑的问题,那就是明明 appid.商户号.API密钥 都对照了好几遍确实是和自己的一样,并且也没有在Log日志中出现签名错误等信息,却始终调不起 ...

  3. 微信支付接口,提示:调用支付jsapi缺少参数: $key0$

    下面是 官方给的 帮助文档. 支付返回签名错误 注意签名参数的大小写,支付密钥key要到商户平台设置,设置的规则是32位数字与字母大小写的组合.以下链接为签名过程. (https://pay.weix ...

  4. Android APP微信支付开发的步骤

    1.我们看官方文档的步骤 APP端开发步骤: https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5 在微信开放平台(https: ...

  5. 微信支付接口配置教程(下)

    微信第三方平台微信支付接口配置教程(下) 上传微信支付证书 登录后台系统,在后台微信商城里,点击微信支付证书.这一步我们需要上传对应的微信支付证书,这个证书就是文章<微信第三方平台微信支付接口配 ...

  6. 如何开通接入微信支付接口?(教程)

    个人进去     alywlzf.com 微信支付的使用用户越来越多,现在在超市餐厅都能使用微信支付就能付款了,那么商户开通微信支付接口是怎么做到的呢?今天就来介绍下商家如何开通微信支付接口的,商户开 ...

  7. 关于个人如何接入微信支付接口,适用于h5,小程序等应用场景

    关于个人如何接入微信支付接口,适用于h5,小程序等应用场景, 众所周知,要想使用微信支付实现公众号.商城.小程序.h5网页等产品或者服务购买,需要申请微信小程序或者服务号,并且要企业认证,还要提交微信 ...

  8. Java接入微信支付超级详细教程——从入门到精通

    源码下载 源码获取邮箱:xiaoshu1024@qq.com 本文介绍了"二维码付款"的代码.其他微信支付方式的代码都在源码中. 一.准备开发所需的账号以及配置信息 解释:想要接入 ...

  9. h5接微信js-sdk的详细步骤

    h5接微信js-sdk的详细步骤 JS-SDK配置流程(前端需要做的) 1.配置JS安全域名 2.服务接入 3.引入Js文件 4.使用wx.config进行权限验证 5.代码 JS-SDK配置流程(后 ...

  10. 搞定支付接口(一) 支付宝即时到账支付接口详细流程和代码

    搞定支付接口(一) 支付宝即时到账支付接口详细流程和java代码 为避免你们和我一样被支付接口搞得焦头烂额,写一个从申请开始到能收到钱为止的详细教程,实际上各个语言都可以用来集成支付接口,我用java ...

最新文章

  1. Android实现双击事件的两种方式
  2. Freemarker静态化ActiveMQ实现
  3. 启动Tomcat的小细节--MyEclipse
  4. verilog实现伺服电机控制
  5. 总结 一下UML 类图的关系
  6. 【Objective-C】玩转OC:正式开始自学OC
  7. Node.js: 认识流stream
  8. C++之vs2017导出动态库失败
  9. 【Golang】go程序性能测试教程+总结
  10. 平行坐标图:高维数据可视化必备图形
  11. 开发Awesomes系列合集
  12. mysql 美元符号_坑爹的PostgreSQL的美元符号(有时需要替换成单引号)
  13. java最新2019面试题
  14. 【2D detection】Deformable DETR论文阅读记录
  15. tkinter + wxpy 实现微信发送信息 接收消息 并保存聊天记录的功能(GUI)
  16. STM32使能/屏蔽外部中断
  17. tv3描述文件代理服务器,超强悍技术贴!Apple TV3复活DNS的刷机全教程
  18. Cmn组合数c语言,计算并输出组合数Cmn……不会打……要求递归……谢谢
  19. ElementUI中的 Cascader 级联选择器 卡顿问题
  20. 贝恩2021技术报告:到2025年,30%的云服务供应商将专注于人工智能计算工作负载

热门文章

  1. 2020年最新世界地图_2020世界地图下载
  2. 日本专利如何检索 昭57-192247
  3. C语言自学笔记(20)
  4. iOS 无线打印功能(AirPrint)
  5. 使用layui中的laypage遇到的各种问题总结
  6. compose UI(七)引入视频播放器ExoPlayer
  7. 学习问题:图像内插-最近邻内插法
  8. python语音识别终极指南_Python语音识别终极指南
  9. 仿今日头条项目——登录注册
  10. JAVA 分布式 - 分布式介绍