小程序端微信支付,服务端接口实现代码

请求过程: 小程序端,先提交微信支付请求,服务端获取请求。然后再向微信发生支付请求,微信获取服务端提交的支付请求。根据api文档里的notify_url(设置接收反馈结果的路径)返回给服务端。服务器接收到微信端的结果之后,再把相应参数返回给小程序,小程序端再请调取微信支付接口,生成订单,最后客户完成支付。然后通知微信支付成功,整个过程就是这样,下面贴出详细的代码; 小程序微信支付api文档 :https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

//首先服务端得有个接口,来接收 小程序端来 提交支付请求 /** * 微信付款接口 * * @param params * @return */ @RequestMapping(value = "addWaybillTest", produces ="application/json;charset=UTF-8")
@ResponseBod public Map addWaybillTest(HttpServletRequest request,HttpServletResponse response,@RequestBody MlApiEntity mlApiEntity) { Map<String, Object> resultMap=new HashMap(); try { //得到一个时间戳 SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String str = sdf.format(new Date());

                    String  body="MLSystem"+"矿泉水2瓶测试";
                    String total_fee="1";
                String notify_url="获取微信支付通知接口URL,自定义" ;
                    String openId=WxCommon.getOpenId(mlApiEntity.getCode());
                    //先微信支付
                    resultMap    =WxCommon.wexinPlace( body, "220", total_fee, request, notify_url, openId);
                    
                    
                
    
    } catch (Exception e) {
        e.printStackTrace();
        loger.info("checkLogin=============error====" + e);
        resultMap.put("result", "系统服务器繁忙,请稍候!");
        e.printStackTrace();
    }
    return resultMap;    
}

//微信支付工具类 public class WxCommon {

    private static String appid="";
    private static String secret="";
    private static String mch_id="";
    private static String key="";

//获取oppenid
public  static String getOpenId(String code){
    Map<String, String>params=new HashMap();
    params.put("appid", appid);
    params.put("secret",secret );
    params.put("js_code", code);
    params.put("grant_type", "authorization_code");
    String result=HttpXmlClient.post("https://api.weixin.qq.com/sns/jscode2session", params);
    
    JSONObject jsonObj = JSONObject.fromObject(result);
    if(jsonObj.has("openid")){
            String openid=jsonObj.getString("openid");
            if("".equals(openid)){
                return "invalidCode";
            }else{
                return openid;
            }
    }else{
        return "invalidCode";
    }
    

}


 
    
    
    //统一下单

public static Map wexinPlace( String body,String waybillNo,String total_fee,HttpServletRequest request,String notify_url,String account){ Map<String, String> paramMap=new HashMap(); paramMap.put("appid", appid); paramMap.put("mch_id", mch_id); paramMap.put("device_info", "WEB"); paramMap.put("nonce_str", GeneratePwd.genRandomNum(32)); paramMap.put("sign_type","MD5"); paramMap.put("body",body); paramMap.put("out_trade_no",waybillNo); paramMap.put("total_fee",total_fee); paramMap.put("spbill_create_ip",getIpAddr(request)); paramMap.put("notify_url",notify_url); paramMap.put("trade_type","JSAPI"); paramMap.put("openid",account); paramMap.put("sign", createSign(paramMap)); // 把参数转换成XML数据格式 String xmlWeChat = assembParamToXml(paramMap); String resXml = HttpUtil.post("https://api.mch.weixin.qq.com/pay/unifiedorder", xmlWeChat); Map<String, String> resMap = null; if (!StrUtil.isBlank(resXml)) { try { resMap = parseXMLToMap(resXml); } catch (IOException e) { e.printStackTrace(); } catch (JDOMException e) { e.printStackTrace(); } } Map<String, String> map = new HashMap(); if (resMap == null) { map.put("status", "false"); return map; } String return_code = resMap.get("return_code"); if (return_code.equalsIgnoreCase("FAIL")) { map.put("message", resMap.get("return_msg")); map.put("status", "false"); return map; } else if (return_code.equalsIgnoreCase("SUCCESS")) { String err_code = resMap.get("err_code"); if (!StrUtil.isBlank(err_code)) { map.put("status", "false"); map.put("message", resMap.get("err_code_des")); } else if (resMap.get("result_code").equalsIgnoreCase("SUCCESS")) { map.put("appId",appid); // 时间戳 当前的时间 需要转换成秒 map.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); // 随机字符串 不长于32位 map.put("nonceStr", GeneratePwd.genRandomNum(32)); // 订单详情扩展字符串 统一下单接口返回的prepay_id参数值,提交格式如:prepay_id=*** map.put("package", "prepay_id=" + resMap.get("prepay_id")); // 签名方式 签名算法,暂支持MD5 map.put("signType", "MD5"); // 签名 map.put("paySign", createSign(map)); map.remove("appId"); map.put("status", "true"); }else { map.put("status", "false"); } } return map;

    }
    /**
     * 微信支付签名sign
     */
    public static String createSign(Map<String, String> param) {
        //签名步骤一:按字典排序参数
        List list = new ArrayList(param.keySet());
        Object[] ary = list.toArray();
        Arrays.sort(ary);
        list = Arrays.asList(ary);
        String str = "";
        for (int i = 0; i < list.size(); i++) {
            str += list.get(i) + "=" + param.get(list.get(i) + "") + "&";
        }
        //签名步骤二:加上key
        str += "key=" + key;
        System.err.println(str);
        //步骤三:加密并大写
        str = MD5Util.md5(str).toUpperCase();
        return str;
    }
    /**
     * 获取访问者IP
     * <p>
     * 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。
     * <p>
     * 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割),
     * 如果还不存在则调用Request .getRemoteAddr()。
     *
     * @param request
     * @return
     */
    public static String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("X-Real-IP");
        if (!StrUtil.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            if (ip.contains("../") || ip.contains("..\\")) {
                return "";
            }
            return ip;
        }
        ip = request.getHeader("X-Forwarded-For");
        if (!StrUtil.isBlank(ip) && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后会有多个IP值,第一个为真实IP。
            int index = ip.indexOf(',');
            if (index != -1) {
                ip = ip.substring(0, index);
            }
            if (ip.contains("../") || ip.contains("..\\")) {
                return "";
            }
            return ip;
        } else {
            ip = request.getRemoteAddr();
            if (ip.contains("../") || ip.contains("..\\")) {
                return "";
            }
            if (ip.equals("0:0:0:0:0:0:0:1")) {
                ip = "127.0.0.1";
            }
            return ip;
        }
    }
 // 通知微信正确接收
    public static void noticeWeChatSuccess(String weiXinPayUrl) {
        Map<String, String> parames = new HashMap<String, String>();
        parames.put("return_code", "SUCCESS");
        parames.put("return_msg", "OK");
        // 将参数转成xml格式
        String xmlWeChat = assembParamToXml(parames);
        try {
            if (!StrUtil.isBlank(weiXinPayUrl)) {
                String s = HttpUtil.post(weiXinPayUrl, xmlWeChat);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // 通知微信错误
    public static void noticeWeChatFAIL(String weiXinPayUrl) {
        Map<String, String> parames = new HashMap<String, String>();
        parames.put("return_code", "FAIL");
        parames.put("return_msg", "校验错误");
        // 将参数转成xml格式
        String xmlWeChat = assembParamToXml(parames);
        try {
            if (!StrUtil.isBlank(weiXinPayUrl)) {
                String s = HttpUtil.post(weiXinPayUrl, xmlWeChat);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
     */
    public static Map parseXMLToMap(String strxml) throws IOException, JDOMException {
        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;
    }
    /**
     * 获取子结点的xml
     *
     * @param children
     * @return String
     */
    private static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if (!children.isEmpty()) {
            Iterator it = children.iterator();
            while (it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if (!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }
        return sb.toString();
    }
    /**
     * 将需要传递给微信的参数转成xml格式
     *
     * @param parameters
     * @return
     */
    private static String assembParamToXml(Map<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        Set<String> es = parameters.keySet();
        List<Object> list = new ArrayList<Object>(es);
        Object[] ary = list.toArray();
        Arrays.sort(ary);
        list = Arrays.asList(ary);
        Iterator<Object> it = list.iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            String val = (String) parameters.get(key);

if ("attach".equalsIgnoreCase(key) || "body".equalsIgnoreCase(key) || "sign".equalsIgnoreCase(key)) { sb.append("<" + key + ">" + "<![CDATA[" + val + "]]></" + key + ">"); } else { sb.append("<" + key + ">" + val + "</" + key + ">"); } } sb.append("</xml>"); return sb.toString(); } /** * 处理xml请求信息 */ public static String getWeiXinResponse(HttpServletRequest request) { BufferedReader bis = null; String result = ""; try { bis = new BufferedReader(new InputStreamReader(request.getInputStream())); String line = null; while ((line = bis.readLine()) != null) { result += line; } } catch (Exception e) { e.printStackTrace(); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; }

}

/** *接收微信支付结果通知 成功付款 则新增订单 * * @param params * @return */ @RequestMapping(value = "wxPayResult", produces ="application/json;charset=UTF-8")
@ResponseBody public void wxPayResult(HttpServletRequest request,HttpServletResponse response)throws Exception { String resXml=WxCommon.getWeiXinResponse(request);//字节流 转换成 字符流 Map<String, String> resMap = null;

     if (!StrUtil.isBlank(resXml)) {
            try {
                resMap = WxCommon.parseXMLToMap(resXml);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JDOMException e) {
                e.printStackTrace();
            }
        }
      Map<String, String> map = new HashMap();
        if (resMap != null) {
              String return_code = resMap.get("return_code");
              if(return_code.equals("FAIL")){
                  String return_msg="";
                  return_msg=resMap.get("return_msg");
            
                  loger.info("===========================微信支付接口调用失败,返回结果=====================" +return_msg);
               }else if(return_code.equals("SUCCESS")){
                   String result_code=resMap.get("result_code");
                   if(result_code.equals("SUCCESS")){
                       String sign=resMap.get("sign");
                       resMap.remove("sign");
                       String result=WxCommon.createSign(resMap);
                       if(sign.equals(result)){
                          String out_trade_no=resMap.get("out_trade_no");
                              
                       
                           WxCommon.noticeWeChatSuccess("https://api.mch.weixin.qq.com/pay/unifiedorder");//支付成功后我们要通知微信

loger.info("===========================微信支付成====================="); } }else{

loger.info("===========================微信支付失=====================" ); }

                     }else if(result_code.equals("FAIL")){
                          String err_code=resMap.get("err_code");
                             if(!StrUtil.isBlank(err_code)){
                               
         loger.info("===========================微信支付失败:错误返回的信息描述:====================="+err_code );
                                 String err_code_des=resMap.get("err_code_des");
                                 if(!StrUtil.isBlank(err_code_des)){
                                   
                                    loger.info("===========================微信支付失败:错误返回的信息描述:====================="+err_code_des );
                                 }
                               
                             }else{
                                 
                                 
                             }
                     }
                 
                  
                  
              }
        }
 }

转载于:https://my.oschina.net/u/3363580/blog/1592435

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值