Java微信支付服务端接口

转自:http://blog.csdn.net/u010399316/article/details/53007758

框架使用的是spring boot

我们集成微信支付 也就需要提供两个接口出来.一个是给前端 作用是拿到请求参数加签请求统一下单接口,得到预支付id,然后再加签返回给前端

前端拿到我们返回的数据.进行调起支付就行了,第二个接口是提供给微信支付的服务器,支付成功或者失败的时候.微信服务器会回调我们的这个接口.异步通知我们支付结果

好了.废话不哆嗦,直接上代码:


  1. @RestController  
  2. @RequestMapping("/wxpayment")  
  3. public class WxPaymentController {  
  4.     public static final String WXUNIFIEDORDER_HTTPURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";// 微信统一下单接口  
  5.     public static final String APP_ID = "";// 微信appid  
  6.     public static final String MCH_ID = "";// 商户号  
  7.     public static final String API_KEY = "";// apikey  
  8.   
  9.     /** 
  10.      * 对微信支付信息进行签名 
  11.      *  
  12.      * @param info 
  13.      *            数据类 
  14.      * @return 
  15.      * @throws AlipayApiException 
  16.      * @throws UnsupportedEncodingException 
  17.      */  
  18.     @PostMapping("/sign")  
  19.     public Object sign(@RequestBody WXSignInfo wxSignInfo, HttpServletRequest httpServletRequest)  
  20.             throws AlipayApiException, UnsupportedEncodingException {  
  21.         String create_ip = NetStateUtils.getIpAddr(httpServletRequest);  
  22.         ResponseWxSign4App response = new ResponseWxSign4App();  
  23.         response.setResult(wxUnifiedorder(create_ip, wxSignInfo.Content));  
  24.         String result = GsonUtils.object2Json(response);  
  25.         System.out.println("微信支付 加签结果:" + result);  
  26.         return result;  
  27.     }  
  28.   
  29.     /** 
  30.      * 微信支付成功后.微信服务器会回调该接口 
  31.      *  
  32.      * @param request 
  33.      * @return 
  34.      * @throws UnsupportedEncodingException 
  35.      */  
  36.     @PostMapping("/notify")  
  37.     public String notify(HttpServletRequest request) throws UnsupportedEncodingException {  
  38.         System.out.println("notify come");  
  39.         Response2WxPayServer response2WxPayServer = new Response2WxPayServer();  
  40.         ;  
  41.         // 读取 入参  
  42.         StringBuilder sb = new StringBuilder();  
  43.         try {  
  44.             BufferedReader br = new BufferedReader(  
  45.                     new InputStreamReader((ServletInputStream) request.getInputStream()));  
  46.             String line = null;  
  47.             while ((line = br.readLine()) != null) {  
  48.                 sb.append(line);  
  49.             }  
  50.             System.out.println("request:" + sb);  
  51.         } catch (Exception e) {  
  52.             e.printStackTrace();  
  53.             System.out.println("微信支付回调读取入参发生异常.直接返回更新失败");  
  54.             response2WxPayServer.setReturn_code(Constants.FAIL);  
  55.             response2WxPayServer.setReturn_msg("unknown");  
  56.             return XmlUtils.toXml(response2WxPayServer);  
  57.         }  
  58.         XStream xStream = new XStream();  
  59.         xStream.alias("xml", WxNotifyBean.class);  
  60.         WxNotifyBean wxNotifyBean = (WxNotifyBean) xStream.fromXML(sb.toString());  
  61.         System.out.println("notify info:" + GsonUtils.object2Json(wxNotifyBean));  
  62.         if (null != wxNotifyBean && wxNotifyBean.getReturn_code().equals(Constants.SUCCESS)  
  63.                 && wxNotifyBean.getResult_code().equals(Constants.SUCCESS)) {// 支付成功  
  64.             String result = PaymentController.updateALiPayOrderStatus(wxNotifyBean.getOut_trade_no());  
  65.             System.out.println("验证成功,去更新状态 \t订单号:" + wxNotifyBean.getOut_trade_no() + "来自微信支付,更新结果:" + result);  
  66.             BaseResponse baseResponse = GsonUtils.getGson().fromJson(result, BaseResponse.class);  
  67.             if (null != baseResponse && baseResponse.isSucceeded) {  
  68.                 response2WxPayServer.setReturn_code(Constants.SUCCESS);  
  69.             } else {  
  70.                 response2WxPayServer.setReturn_code(Constants.FAIL);  
  71.                 response2WxPayServer.setReturn_msg("unknown");  
  72.             }  
  73.         } else {  
  74.             // 支付失败  
  75.             response2WxPayServer.setReturn_code(Constants.FAIL);  
  76.             response2WxPayServer.setReturn_msg("unknown");  
  77.         }  
  78.         return XmlUtils.toXml(response2WxPayServer);  
  79.     }  
  80.   
  81.     // https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3 文档地址  
  82.     /** 
  83.      * 微信统一下单接口 
  84.      *  
  85.      * @param orderNumber 
  86.      * @return 
  87.      */  
  88.     public Return4AppWxPayBean wxUnifiedorder(String create_ip, RequestUnifiedOrderBean requestUnifiedOrderBean) {  
  89.         requestUnifiedOrderBean.setNonce_str(NumUtils.getRandomStringByDate());  
  90.         requestUnifiedOrderBean.setSign("");  
  91.         requestUnifiedOrderBean.setSpbill_create_ip(create_ip);  
  92.         HashMap<String, String> hashMap = getHashMap2SignFromRequestUnifiedOrderBean(requestUnifiedOrderBean);  
  93.         String sign = addSign(hashMap);  
  94.         if (null == sign) {  
  95.             return null;  
  96.         }  
  97.         requestUnifiedOrderBean.setSign(sign);  
  98.         String requestContent = XmlUtils.getXstream().toXML(requestUnifiedOrderBean);  
  99.         requestContent = requestContent.replaceAll("__""_");// xstream  
  100.                                                                 // 转换的时候会把单个下划线弄成两个,所以这里替换下  
  101.         String result = HttpUtils.doPost(WXUNIFIEDORDER_HTTPURL, requestContent);  
  102.         System.out.println("微信统一下单接口 返回结果:" + result);  
  103.         if (TextUtils.isEmpty(result)) {// 统一下单都失败了.直接返回null  
  104.             return null;  
  105.         }  
  106.         XStream xstream = XmlUtils.getXstream();  
  107.         xstream.alias("xml", ResponseUnifiedOrderBean.class);// xml对应ResponseUnifiedOrderBean的根节点的名字  
  108.         ResponseUnifiedOrderBean responseUnifiedOrderBean = (ResponseUnifiedOrderBean) xstream.fromXML(result);  
  109.         if (responseUnifiedOrderBean.getReturn_code().equals("SUCCESS")  
  110.                 && responseUnifiedOrderBean.getResult_code().equals("SUCCESS")) {// 全为成功.则进行相应的处理  
  111.             // 分割线  
  112.             Return4AppWxPayBean return4AppWxPayBean = new Return4AppWxPayBean();  
  113.             return4AppWxPayBean.setNonceStr(responseUnifiedOrderBean.getNonce_str());  
  114.             return4AppWxPayBean.setPrepayId(responseUnifiedOrderBean.getPrepay_id());  
  115.             // return4AppWxPayBean.setSign(responseUnifiedOrderBean.getSign());  
  116.             return4AppWxPayBean.setTimeStamp("" + TimeUtils.getTime_Second());  
  117.             // 再次签名appid,partnerid等全部参数必须全小写  
  118.             HashMap<String, String> hashMap2Sign = getHashMap2SignFromReturn4AppWxPayBean(return4AppWxPayBean);  
  119.             String sign1 = addSign(hashMap2Sign);  
  120.             if (null == sign1) {  
  121.                 return null;  
  122.             }  
  123.             return4AppWxPayBean.setSign(sign1);  
  124.             return return4AppWxPayBean;  
  125.         } else {  
  126.             return null;  
  127.         }  
  128.     }  
  129.   
  130.     /** 
  131.      * 从requestUnifiedOrderBean 拿到一个待签名的hashmap 
  132.      *  
  133.      * @param requestUnifiedOrderBean 
  134.      * @return 
  135.      */  
  136.     private HashMap<String, String> getHashMap2SignFromRequestUnifiedOrderBean(  
  137.             RequestUnifiedOrderBean requestUnifiedOrderBean) {  
  138.         HashMap<String, String> hashMap = new HashMap<>();  
  139.         hashMap.put("appid", requestUnifiedOrderBean.getAppid());  
  140.         hashMap.put("device_info", requestUnifiedOrderBean.getDevice_info());  
  141.         hashMap.put("mch_id", requestUnifiedOrderBean.getMch_id());  
  142.         hashMap.put("nonce_str", requestUnifiedOrderBean.getNonce_str());  
  143.         hashMap.put("notify_url", requestUnifiedOrderBean.getNotify_url());  
  144.         hashMap.put("spbill_create_ip", requestUnifiedOrderBean.getSpbill_create_ip());  
  145.         hashMap.put("trade_type", requestUnifiedOrderBean.getTrade_type());  
  146.         hashMap.put("body", requestUnifiedOrderBean.getBody());  
  147.         hashMap.put("total_fee", requestUnifiedOrderBean.getTotal_fee() + "");  
  148.         hashMap.put("out_trade_no", requestUnifiedOrderBean.getOut_trade_no());  
  149.         return hashMap;  
  150.     }  
  151.   
  152.     /** 
  153.      * 把信息从return4AppWxPayBean弄到hashmap里面 
  154.      *  
  155.      * @param return4AppWxPayBean 
  156.      * @return 
  157.      */  
  158.     private HashMap<String, String> getHashMap2SignFromReturn4AppWxPayBean(Return4AppWxPayBean return4AppWxPayBean) {  
  159.         HashMap<String, String> hashMap2Sign = new HashMap<>();  
  160.         hashMap2Sign.put("appid", return4AppWxPayBean.getAppId());  
  161.         hashMap2Sign.put("partnerid", return4AppWxPayBean.getPartnerId());  
  162.         hashMap2Sign.put("prepayid", return4AppWxPayBean.getPrepayId());  
  163.         hashMap2Sign.put("noncestr", return4AppWxPayBean.getNonceStr());  
  164.         hashMap2Sign.put("timestamp", return4AppWxPayBean.getTimeStamp());  
  165.         hashMap2Sign.put("package""Sign=WXPay");  
  166.         return hashMap2Sign;  
  167.     }  
  168.   
  169.     /** 
  170.      * 对hashmap进行加签 
  171.      *  
  172.      * @param hashMap2Sign 
  173.      * @return 
  174.      */  
  175.     private String addSign(HashMap<String, String> hashMap2Sign) {  
  176.         String stringA2Sign = AlipayCore.createLinkString(hashMap2Sign);  
  177.         String stringSignTemp2Sign = stringA2Sign + "&key=" + API_KEY;  
  178.         String md5 = EncodeUtils.md5(stringSignTemp2Sign);  
  179.         if (null == md5) {// 签名失败 直接返回null  
  180.             return null;  
  181.         }  
  182.         String sign1 = md5.toUpperCase();  
  183.         return sign1;  
  184.     }  


createLinkString方法是把一个hashmap依据参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string,方法实现如下:

  1. /**  
  2.     * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串 
  3.     * @param params 需要排序并参与字符拼接的参数组 
  4.     * @return 拼接后字符串 
  5.     */  
  6.    public static String createLinkString(Map<String, String> params) {  
  7.   
  8.        List<String> keys = new ArrayList<String>(params.keySet());  
  9.        Collections.sort(keys);  
  10.   
  11.        String prestr = "";  
  12.   
  13.        for (int i = 0; i < keys.size(); i++) {  
  14.            String key = keys.get(i);  
  15.            String value = params.get(key);  
  16.   
  17.            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符  
  18.                prestr = prestr + key + "=" + value;  
  19.            } else {  
  20.                prestr = prestr + key + "=" + value + "&";  
  21.            }  
  22.        }  
  23.   
  24.        return prestr;  
  25.    }  

说一下遇到的坑:

1.加签的时候appid和别的参数都是小写,并不是appId这种形式

2.本地服务器支付没问题.部署到win server2012服务器上时,签名失败,这个是因为本地服务器win8 默认utf-8编码,而win server 2012 默认 gbk编码,我们加签,进行md5编码的时候,把格式指定为utf-8就好了






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值