zoukankan      html  css  js  c++  java
  • APP微信支付

    前置准备

    微信的东西比支付宝要复杂一点,要先去注册开发者账号,然后一系列巴拉巴拉……,然后得到下面列出的我们开发需要的参数,下面的参数中TOKEN和CERT_PATH是需要退款和设计到其他功能才需要的,如果只做APP支付功能的同学可以忽略。

    • APP_ID : 服务号的应用ID
    • APP_SECRET : 服务号的应用密钥
    • TOKEN : 服务号的配置token
    • MCH_ID : 商户号
    • API_KEY : API密钥
    • SIGN_TYPE : 签名加密方式
    • CERT_PATH : 微信支付证书名称、

    支付流程

    具体的流程大概就是后台拿到(或生成)自己的订单号后,拿着一堆参数按ASCII码(即abc…)排序后用MD5加密后调用微信的服务器地址拿到一个prepayId,再将prepayId和当前的参数再次排序和加密(二次加密)生成sign后返回前端进行支付,支付完成后,微信的后台会回调我们的后台接口。

    Java代码

    maven依赖

     1 `<!-- 微信支付依赖 -->
     2 <dependency>
     3     <groupId>org.xmlpull</groupId>
     4     <artifactId>xmlpull</artifactId>
     5     <version>1.1.3.1 </version>
     6 </dependency>
     7 <dependency>
     8     <groupId>net.sf.json-lib</groupId>
     9     <artifactId>json-lib</artifactId>
    10     <version>2.3</version>
    11     <classifier>jdk15</classifier>
    12 </dependency>
    13 <!-- https://mvnrepository.com/artifact/com.thoughtworks.xstream/xstream -->
    14 <dependency>
    15     <groupId>com.thoughtworks.xstream</groupId>
    16     <artifactId>xstream</artifactId>
    17     <version>1.4.5</version>
    18 </dependency>
    19 <!-- https://mvnrepository.com/artifact/com.ning/async-http-client -->
    20 <dependency>
    21     <groupId>com.ning</groupId>
    22     <artifactId>async-http-client</artifactId>
    23     <version>1.8.13</version>
    24 </dependency>`

    Java代码

     1 @ResponseBody
     2 @RequestMapping(value="/wxpaySign",method=RequestMethod.POST)
     3 public JsonResult getWXPaySign(double totalAmount,String userId,String out_trade_no,String ip) 
     4             throws JDOMException, IOException{
     5         //预备参数
     6         WXPayDTO wxPayDTO = new WXPayDTO();
     7         String subject = "******";
     8         String body = "******";
     9         String nonceStr = setNonceStr();
    10         long timeStamp = (long)CommonUtil.getSecondTimestamp(new Date());
    11         String packageStr = "Sign=WXPay";
    12         String total_fee = String.valueOf(CommonUtil.double100ToInt(totalAmount));
    13 
    14         SortedMap<String,String> payMap = genOrderData(PayConstants.WX_APP_ID,body,out_trade_no,
    15                 nonceStr,packageStr,PayConstants.WX_PARTNER_ID,total_fee,subject,ip);
    16 
    17         //设置WXPayDTO
    18         wxPayDTO.setAppId(PayConstants.WX_APP_ID);
    19         //商家id
    20         wxPayDTO.setPartnerId(PayConstants.WX_PARTNER_ID);  
    21         wxPayDTO.setPrepayId(out_trade_no);     //订单
    22         wxPayDTO.setNonceStr(nonceStr); //设置随机串
    23         wxPayDTO.setTimeStamp(timeStamp);   //设置时间戳
    24         wxPayDTO.setPackageStr(packageStr);
    25         wxPayDTO.setSign(payMap.get("sign"));
    26         wxPayDTO.setPrepayId(payMap.get("prepayid"));
    27         return new JsonResult(Message.M2000,wxPayDTO);
    28     }
    29 
    30 
    31 private SortedMap<String, String> genOrderData(String appId, String body, String out_trade_no,
    32             String nonceStr, String packageStr, String partnerId,String total_fee,String subject,String ip) 
    33                     throws JDOMException, IOException {
    34         SortedMap<String, String> paraMap = new TreeMap<String,String>();
    35     //按照官方文档的要求,这里参数名ASCII码从小到大排序(字典序);
    36         paraMap.put("appid", appId);
    37         paraMap.put("body",body);
    38         paraMap.put("mch_id",partnerId);        //微信商户账号
    39         paraMap.put("nonce_str",nonceStr);  //32位不重复的编号
    40         paraMap.put("notify_url", 
    41         PayConstants.WX_Notify_Url);    //设置一个回调的地址
    42         paraMap.put("out_trade_no", out_trade_no);  //订单号
    43         paraMap.put("spbill_create_ip", ip);//前端传回来的ip
    44         paraMap.put("total_fee",total_fee);     //设置金额
    45         paraMap.put("trade_type","APP");    //方式为APP支付
    46         //用上面封装的参数生成sign
    47         String sign = PayCommonUtil.createSign("UTF-8", paraMap,PayConstants.WX_API_KEY);
    48         //这里的sign用二次签名生成的sign
    49         paraMap.put("sign",sign);
    50         //统一下单地址
    51         //将上面集合内容转成xml
    52         String xml = getRequestXML(paraMap);
    53         String xmlStr = HttpUtil.postData(PayConstants.WX_Notify_Url,xml);
    54         //将返回的xml转换成map
    55         Map map = XMLUtil.doXMLParse(xmlStr);
    56         //预付商品id
    57         String prepay_id = (String) map.get("prepay_id");
    58 
    59         //这里要对参数进行二次签名
    60         SortedMap<String, String> secParaMap = new TreeMap<String,String>();
    61         secParaMap.put("appid", appId);
    62         secParaMap.put("partnerid",partnerId);
    63         secParaMap.put("prepayid", prepay_id);
    64         //这里不确定是不是要重新生成一个随机串,再改
    65         secParaMap.put("noncestr", nonceStr);
    66         secParaMap.put("timestamp", CommonUtil.getTimeStamp());
    67         secParaMap.put("package", "Sign=WXPay");
    68         String secSign = PayCommonUtil.createSign("UTF-8", secParaMap, PayConstants.WX_API_KEY);
    69         secParaMap.put("sign", secSign);
    70         secParaMap.put("prepayid", prepay_id);
    71 
    72         return secParaMap;
    73     }

    支付回调 
    微信的支付回调是用流形式传输的,所以要先对流形式的数据进行解析再得到我们需要的东西。

     1     @RequestMapping(value = "payNotifyUrl", produces = "application/json;charset=UTF-8")
     2     @ResponseBody
     3     public String payNotifyUrl(HttpServletRequest request, HttpServletResponse response) throws Exception {
     4         //读取参数 
     5 
     6         InputStream inputStream ;  
     7         StringBuffer sb = new StringBuffer();  
     8         inputStream = request.getInputStream();  
     9         String s ;  
    10         BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));  
    11         while ((s = in.readLine()) != null){  
    12             sb.append(s);  
    13         }  
    14         in.close();  
    15         inputStream.close();  
    16 
    17         //解析xml成map  
    18         Map<String, String> m = new HashMap<String, String>();  
    19         m = XMLUtil.doXMLParse(sb.toString());  
    20 
    21         //过滤空 设置 TreeMap  
    22         SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();        
    23         Iterator it = m.keySet().iterator();  
    24         while (it.hasNext()) {  
    25             String parameter = (String) it.next();  
    26             String parameterValue = m.get(parameter);  
    27 
    28             String v = "";  
    29             if(null != parameterValue) {  
    30                 v = parameterValue.trim();  
    31             }  
    32             packageParams.put(parameter, v);  
    33         }  
    34 
    35         //判断签名是否正确  
    36         if(PayCommonUtil.isTenpaySign("UTF-8", packageParams,PayConstants.WX_API_KEY)) {  
    37             //------------------------------  
    38             //处理业务开始  
    39             //------------------------------  
    40             String resXml = "";  
    41             if("SUCCESS".equals((String)packageParams.get("result_code"))){  
    42                 // 这里是支付成功  
    43                 //////////执行自己的业务逻辑////////////////  
    44                 String mch_id = (String)packageParams.get("mch_id");  
    45                 String openid = (String)packageParams.get("openid");  
    46                 String is_subscribe = (String)packageParams.get("is_subscribe");  
    47                 String out_trade_no = (String)packageParams.get("out_trade_no");  
    48 
    49                 String total_fee = (String)packageParams.get("total_fee");  
    50 
    51                 System.out.println("mch_id:"+mch_id);  
    52                 System.out.println("openid:"+openid);  
    53                 logger.info("is_subscribe:"+is_subscribe);  
    54                 logger.info("out_trade_no:"+out_trade_no);  
    55                 logger.info("total_fee:"+total_fee);  
    56 
    57                 //////////执行自己的业务逻辑////////////////  
    58 
    59                 logger.info("支付成功");  
    60                 //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.  
    61                 resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
    62                         + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
    63 
    64             } else {  
    65                 logger.info("支付失败,错误信息:" + packageParams.get("err_code"));  
    66                 resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
    67                         + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
    68             }  
    69             //------------------------------  
    70             //处理业务完毕  
    71             //------------------------------  
    72             BufferedOutputStream out = new BufferedOutputStream(  
    73                     response.getOutputStream());  
    74             out.write(resXml.getBytes());  
    75             out.flush();  
    76             out.close();  
    77         } else{  
    78             logger.info("通知签名验证失败");  
    79         }  
    80         return "SUCCESS";
    81     }
  • 相关阅读:
    通过微软的HTML Help Workshop 利用.html文件 生成简单的chm帮助类的文件
    CHM编写软件
    tinyxml使用笔记与总结
    UCOS源码剖析 (一)
    灵性领悟的四个阶段-肯·威尔伯
    ans menu list
    lxm --- ans lb config
    macvtap介绍
    影子系统密码忘记
    Linux环境安装.NET运行环境
  • 原文地址:https://www.cnblogs.com/wangpeihua/p/9543187.html
Copyright © 2011-2022 走看看