• JAVA实现微信支付功能


    ②准备好11个参数JSAPI支付方式

    1 配置微信平台

    ①配置微信公众平台

    登录微信公众平台=》公众号设置=》功能设置=》网页授权域名

     

     ②配置微信商家平台

    ①先去官方下载SDK,并导进项目中 

    2 后台代码的实现

    JSAPI官方文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

    ①先去官方下载SDK,并导进项目中

    地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

     ②准备好11个参数

    appid:商家平台ID。在微信的平台上有
    
    body:商品描述。
    
    mch_id:商户ID。在微信的平台上有
    
    nonce_str:随机字符串,UUID就好了。
    
    openid:用户标识。因为这边是用户已经登录成功了。所以在session中就能拿到。
    
    out_trade_no:商户订单号
    
    spbill_create_ip:终端IP。这个可以从请求头中拿到
    
    total_fee:支付金额。单位是分。
    
    trade_type:交易类型。这里我填JSAPI
    
    notify_url:通知地址。就是用户支付成功之后,微信访问你的哪个接口,跟你传递支付成功的相关信息。

    sign:签名。这个签名它是由上面的10个参数计算得出的。

    ③源码
    sendPay类:

    import java.io.IOException;
    import java.io.InputStream;
    import java.math.BigDecimal;
    import java.net.URLEncoder;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.http.auth.AUTH;
    import org.hamcrest.core.Is;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import com.jc.util.wxPay.WXPayUtil;
    import com.sun.xml.internal.fastinfoset.Encoder;
    
    import controller.AuthUtil;
    import net.sf.json.JSONObject;
    
    @Controller
    @RequestMapping("/pay")
    public class sendPay {
     
        /**
         * @Description 微信浏览器内微信支付/公众号支付(JSAPI)
         * @param request
         * @param code
         * @return Map
         */
        @RequestMapping(value = "orders")
        public @ResponseBody Map<String, String> orders(HttpServletRequest request, HttpServletResponse response) {
            try {
                 
                String openId = "用户的openid";
    
                // 拼接统一下单地址参数
                Map<String, String> paraMap = new HashMap<String, String>();
                // 获取请求ip地址
                String ip = request.getHeader("x-forwarded-for");
                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.getRemoteAddr();
                }
                if (ip.indexOf(",") != -1) {
                    String[] ips = ip.split(",");
                    ip = ips[0].trim();
                }
    
                paraMap.put("appid", AuthUtil.APPID); // 商家平台ID
                paraMap.put("body", "纯情小店铺-薯条"); // 商家名称-销售商品类目、String(128)
                paraMap.put("mch_id", AuthUtil.MCHID); // 商户ID
                paraMap.put("nonce_str", WXPayUtil.generateNonceStr()); // UUID
                paraMap.put("openid", openId);
                paraMap.put("out_trade_no", UUID.randomUUID().toString().replaceAll("-", ""));// 订单号,每次都不同
                paraMap.put("spbill_create_ip", ip);
                paraMap.put("total_fee", "1"); // 支付金额,单位分
                paraMap.put("trade_type", "JSAPI"); // 支付类型
                paraMap.put("notify_url", "用户支付完成后,你想微信调你的哪个接口");// 此路径是微信服务器调用支付结果通知路径随意写
                String sign = WXPayUtil.generateSignature(paraMap, AuthUtil.PATERNERKEY);
                paraMap.put("sign", sign);
                String xml = WXPayUtil.mapToXml(paraMap);// 将所有参数(map)转xml格式
    
                // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder
                String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    
                System.out.println("xml为:" + xml);
    
                // String xmlStr = HttpRequest.sendPost(unifiedorder_url,
                // xml);//发送post请求"统一下单接口"返回预支付id:prepay_id
    
                String xmlStr = HttpRequest.httpsRequest(unifiedorder_url, "POST", xml);
    
                System.out.println("xmlStr为:" + xmlStr);
    
                // 以下内容是返回前端页面的json数据
                String prepay_id = "";// 预支付id
                if (xmlStr.indexOf("SUCCESS") != -1) {
                    Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);
                    prepay_id = (String) map.get("prepay_id");
                }
    
                Map<String, String> payMap = new HashMap<String, String>();
                payMap.put("appId", AuthUtil.APPID);
                payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp() + "");
                payMap.put("nonceStr", WXPayUtil.generateNonceStr());
                payMap.put("signType", "MD5");
                payMap.put("package", "prepay_id=" + prepay_id);
                String paySign = WXPayUtil.generateSignature(payMap, AuthUtil.PATERNERKEY);
                payMap.put("paySign", paySign);
                //将这个6个参数传给前端
                return payMap;
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * @Title: callBack
         * @Description: 支付完成的回调函数
         * @param:
         * @return:
         */
        @RequestMapping("/notify")
        public String callBack(HttpServletRequest request, HttpServletResponse response) {
            // System.out.println("微信支付成功,微信发送的callback信息,请注意修改订单信息");
            InputStream is = null;
            try {
    
                is = request.getInputStream();// 获取请求的流信息(这里是微信发的xml格式所有只能使用流来读)
                String xml = WXPayUtil.InputStream2String(is);
                Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);// 将微信发的xml转map
                
                System.out.println("微信返回给回调函数的信息为:"+xml);
                
                if (notifyMap.get("result_code").equals("SUCCESS")) {
                    String ordersSn = notifyMap.get("out_trade_no");// 商户订单号
                    String amountpaid = notifyMap.get("total_fee");// 实际支付的订单金额:单位 分
                    BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);// 将分转换成元-实际支付金额:元
    
                    /*
                     * 以下是自己的业务处理------仅做参考 更新order对应字段/已支付金额/状态码
                     */
                    System.out.println("===notify===回调方法已经被调!!!");
                    
                }
                
                // 告诉微信服务器收到信息了,不要在调用回调action了========这里很重要回复微信服务器信息用流发送一个xml即可
                response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (is != null) {
                    try {
                        is.close();
                    } catch (IOException e) { 
                        e.printStackTrace();
                    }
                }
            }
            
            return null;
        }
    
    }

    HttpRequest类:

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.PrintWriter;
    import java.net.URL;
    import java.net.URLConnection;
    import java.util.List;
    import java.util.Map;
    
    import javax.net.ssl.HttpsURLConnection;
    
    public class HttpRequest {
        /**
         * 向指定URL发送GET方法的请求
         * 
         * @param url
         *            发送请求的URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return URL 所代表远程资源的响应结果
         */
        public static String sendGet(String url, String param) {
            String result = "";
            BufferedReader in = null;
            try {
                String urlNameString = url + "?" + param;
                System.out.println(urlNameString);
                URL realUrl = new URL(urlNameString);
                // 打开和URL之间的连接
                URLConnection connection = realUrl.openConnection();
                // 设置通用的请求属性
                connection.setRequestProperty("accept", "*/*");
                connection.setRequestProperty("connection", "Keep-Alive");
                connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 建立实际的连接
                connection.connect();
                // 获取所有响应头字段
                Map<String, List<String>> map = connection.getHeaderFields();
                // 遍历所有的响应头字段
                for (String key : map.keySet()) {
                    System.out.println(key + "--->" + map.get(key));
                }
                // 定义 BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送GET请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输入流
            finally {
                try {
                    if (in != null) {
                        in.close();
                    }
                } catch (Exception e2) {
                    e2.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * 向指定 URL 发送POST方法的请求
         * 
         * @param url
         *            发送请求的 URL
         * @param param
         *            请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
         * @return 所代表远程资源的响应结果
         */
        public static String sendPost(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                URL realUrl = new URL(url);
                // 打开和URL之间的连接
                URLConnection conn = realUrl.openConnection();
                // 设置通用的请求属性
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                // 发送POST请求必须设置如下两行
                conn.setDoOutput(true);
                conn.setDoInput(true);
                // 获取URLConnection对象对应的输出流
                out = new PrintWriter(conn.getOutputStream());
                // 发送请求参数
                out.print(param);
                // flush输出流的缓冲
                out.flush();
                // 定义BufferedReader输入流来读取URL的响应
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("发送 POST 请求出现异常!" + e);
                e.printStackTrace();
            }
            // 使用finally块来关闭输出流、输入流
            finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
            return result;
        }
    
        /**
         * post请求并得到返回结果
         * 
         * @param requestUrl
         * @param requestMethod
         * @param output
         * @return
         */
        public static String httpsRequest(String requestUrl, String requestMethod, String output) {
            try { 
                URL url = new URL(requestUrl);
                HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setUseCaches(false);
                connection.setRequestMethod(requestMethod);
                if (null != output) {
                    OutputStream outputStream = connection.getOutputStream();
                    outputStream.write(output.getBytes("UTF-8"));
                    outputStream.close();
                }
                // 从输入流读取返回内容
                InputStream inputStream = connection.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;
                connection.disconnect();
                return buffer.toString();
            } catch (Exception ex) {
                ex.printStackTrace();
            }
    
            return "";
        }
    }

    AuthUtil类

    import java.io.IOException;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.HttpResponse;
    import org.apache.http.client.ClientProtocolException;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.impl.client.DefaultHttpClient;
    import org.apache.http.util.EntityUtils;
    
    import net.sf.json.JSONObject;
    public class AuthUtil {
        public static final String APPID = "平台ID";
        public static final String APPSECRET = "平台密钥";
        public static final String MCHID = "商家ID";
        public static final String PATERNERKEY = "商家密钥";
        
        
        public static JSONObject doGetJson(String url) throws ClientProtocolException, IOException {
            JSONObject jsonObject = null;
            // 首先初始化HttpClient对象
            DefaultHttpClient client = new DefaultHttpClient();
            // 通过get方式进行提交
            HttpGet httpGet = new HttpGet(url);
            // 通过HTTPclient的execute方法进行发送请求
            HttpResponse response = client.execute(httpGet);
            // 从response里面拿自己想要的结果
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String result = EntityUtils.toString(entity, "UTF-8");
                jsonObject = jsonObject.fromObject(result);
            }
            // 把链接释放掉
            httpGet.releaseConnection();
            return jsonObject;
        }
    }

    2.3 前端的实现

    这是只用一个jsp页面来做测试

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <script type="text/javascript" src="./js/jquery-1.11.0.min.js"></script>
    <title>微信支付JSP</title>
    </head>
    <body> 
        <input type="button" value="进行微信支付" id="payId">
    
        <script type="text/javascript">
        
            $(function(){
                var appId,timeStamp,nonceStr,package,signType,paySign; 
                
                $("#payId").click(function(){
                    pay();
                });
                
                //去后台拿六个参数
                function pay(){   
                    var url = "http://localhost:8082/WeChat/pay/orders";
                      $.get(url,function(result) {    
                              appId = result.appId;
                            timeStamp = result.timeStamp;
                            nonceStr = result.nonceStr;
                            package = result.package;
                            signType = result.signType;
                            paySign = result.paySign;
                            
                            if (typeof WeixinJSBridge == "undefined") {
                                if (document.addEventListener) {
                                    document.addEventListener('WeixinJSBridgeReady',
                                            onBridgeReady, false);
                                } else if (document.attachEvent) {
                                    document.attachEvent('WeixinJSBridgeReady',
                                            onBridgeReady);
                                    document.attachEvent('onWeixinJSBridgeReady',
                                            onBridgeReady);
                                }
                                alert("请在微信上进行支付操作!");
                                onBridgeReady();
                            } else { 
                                onBridgeReady();
                            }
                        });
                    }
                //去微信那边发起支付请求
                function onBridgeReady(){
                    
                     alert("appId:"+appId+" "+"timeStamp:"+timeStamp+" "+"nonceStr:"+nonceStr+" "+"package:"+package+" "+"signType:"+signType+" "+"paySign:"+paySign+" ");
                    
                      WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
                          "appId":appId,     //公众号名称,由商户传入     
                          "timeStamp":timeStamp,         //时间戳,自1970年以来的秒数     
                          "nonceStr":nonceStr, //随机串     
                          "package":package,     
                          "signType":signType,         //微信签名方式:     
                          "paySign":paySign //微信签名 
                         }, 
                         function(res){      
                             if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                                 //alert('支付成功');
                                 console.log("支付成功");
                                 //支付成功后跳转的页面
                             }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
                                 alert('支付取消');
                             }else if(res.err_msg == "get_brand_wcpay_request:fail"){
                                 alert('支付失败');
                                 
                                 alert(JSON.stringify(res));
                                 
                                 WeixinJSBridge.call('closeWindow');
                             } //使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                   });    
                }
            })
    </script>
    
    </body>
    </html>

    三,总结

    虽然第一次看官方文档很乱,信息量很多,但仔细总结一下,其实就下面这点流程而已。

    再记录点,以防有用:

    url urlencode

    public static String inputStream2String(InputStream inStream, String encoding){
            String result = null;
            ByteArrayOutputStream outStream = null;
            try {
             if(inStream != null){
              outStream = new ByteArrayOutputStream();
              byte[] tempBytes = new byte[1024];
              int count = 0;
              while((count = inStream.read(tempBytes)) != -1){
               outStream.write(tempBytes, 0, count);
              }
              tempBytes = null;
              outStream.flush();
              result = new String(outStream.toByteArray(), encoding);
              outStream.close();
             }
            } catch (Exception e) {
             result = null;
            } 
            return result;
           }

    转载:

    https://blog.csdn.net/daotiao0199/article/details/85284038

    https://blog.csdn.net/javaYouCome/article/details/79473743

     

     

  • 相关阅读:
    Js获取当前浏览器的高和宽度
    js中使用键盘键,每个键的值
    网络搜索之实现网络蜘蛛
    进程和线程
    jquery.bgiframe.js在IE9下的错误
    [习题]GridView样版内部,改用CheckBox/Radio/DropDownList(单/复选)控件,取代TextBox
    [入门]C#语法里面,如何使用 VB的常用函数?(using Microsoft.VisualBasic)
    [全文下载/试读]补充,上集Ch. 3 Panel控件与常用属性,范例:问卷系统,动态产生「子问题」(使用障眼法)
    [ASP.NET] 上课 第一天的简介
    TextBox的 TextChanged事件#1 动态给予默认值,会触发TextChanged事件吗? / #2 EnableViewState属性是做什么用?
  • 原文地址:https://www.cnblogs.com/share-record/p/14325789.html
Copyright © 2020-2023  润新知