JAVA实现微信支付V3

Posted dsn727455218

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA实现微信支付V3相关的知识,希望对你有一定的参考价值。

相信很多的码友在项目中都需要接入微信支付,虽说微信支付已成为一个普遍的现象,但是接入的过程中难免会遇到各种各样的坑,这一点支付宝的SDK就做的很好,已经完成的都知道了。

下面就开始我们的代码之旅,这里我将给大家提供两种支付一个是微信公众号支付,一个是APP微信支付。

一 微信公众号支付

流程:

1.获取用户openid

2.获取token,注意获取的token是有时效的而且接口是有获取上线,具体看微信API文档

3.拿商品信息(金额,名字等)去请求统一下单接口

4.统一下单接口获取预支付ID,后进行二次签名把参数返回给前端

5.前端JS中接收到参数调起支付

6.支付成功页面跳转以及回调处理

下面我们就来具体说说功能

GetOpenId:获取用户openid

public class GetOpenid extends HttpServlet {
 
	private static final Logger logger = Logger.getLogger(GetOpenid.class);
	
	@SuppressWarnings("unused")
	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");
		response.setContentType("text/html;charset=UTF-8");
		HttpSession session = request.getSession();
		PreparedStatement pst=null;
		String username="";
		//获取code
		String appid=WeiXinUitls.appid;
		
		String code = request.getParameter("code");
		String rturl = request.getParameter("rturl");
 
		String appsecret = WeiXinUitls.appsecret;
		String grant_type = "authorization_code";
		String returnJSON = HttpTool.getToken(appid, appsecret, grant_type,code);
		JSONObject obj = JSONObject.fromObject(returnJSON);
		if(!(obj==null)){
			String openid = obj.get("openid").toString();
			String token = obj.get("access_token").toString();
			String retoken = obj.get("refresh_token").toString();
			//获取微信用户
			String getuserinfo = HttpTool.getuserinfo(token, openid);
			JSONObject fromObject = JSONObject.fromObject(getuserinfo);
			String stropenid = fromObject.get("openid").toString();
			session.setAttribute("openid", stropenid);
			String strnickname = fromObject.get("nickname").toString();
			String strcity = fromObject.get("city").toString();
			String strcountry = fromObject.get("country").toString();
			String strprovince = fromObject.get("province").toString();
			String strsex = fromObject.get("sex").toString();
		
		}
		
	}
 
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}
	public static String RmFilter(String message){
 
		if ((message == null) || (message.equals(""))) {
	      message = "";
	    }
		message = message.replace("<",""); 
		message = message.replace(">",""); 
		message = message.replace("‘","");
		message = message.replace(""","");
		//message = message.replace("/","/");
		message = message.replace("%",""); 
		message = message.replace(";",""); 
		message = message.replace("(",""); 
		message = message.replace(")",""); 
		message = message.replace("&",""); 
		message = message.replace("+","_"); 
		return message;
	}
 
}

RefTicket:获取ticket

public class RefTicket extends TimerTask{
 
    private static ServletContext application = null;
    public RefTicket(ServletContext application){
        this.application = application;
    }
    
    public void run() {
        String jsapi_ticket = getTicket();
        if(!"".equalsIgnoreCase(jsapi_ticket)){
            this.application.setAttribute("jsapi_ticket", jsapi_ticket);
            System.out.println("jsapi_ticket:"+jsapi_ticket);
            System.out.println("jsapi_ticket--application:"+this.application.getAttribute("jsapi_ticket"));
        }
        
    }
    
    private static DefaultHttpClient httpclient;
    static {
        httpclient = new DefaultHttpClient();
        httpclient = (DefaultHttpClient) HttpClientConnectionManager
                .getSSLInstance(httpclient);
    }
    
    private String getTicket(){
        String token = (String) this.application.getAttribute("token");
        if("".equalsIgnoreCase(token) || null ==  token ){
            return "";
        }
        HttpGet get = HttpClientConnectionManager
                .getGetMethod("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+token+"&type=jsapi");
                        
        HttpResponse response;
        try {
            response = httpclient.execute(get);
            String jsonStr = EntityUtils
                    .toString(response.getEntity(), "utf-8");
            JSONObject demoJson = JSONObject.fromObject(jsonStr);
            return demoJson.getString("ticket");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "";
        
    }
 
}

RefToken:获取token

public class RefToken extends TimerTask{
 
    private  final static String appId = "wx842b838875cd9bd3";
    private final static String appSecret = "ce7948b66d04b5ae714c9d0e4bc6eba9";
    private static ServletContext application = null;
    public RefToken(ServletContext application){
        this.application = application;
    }
    
    public void run() {
        String token = getAccessToken(appId,appSecret);
        if(!"".equalsIgnoreCase(token)){
            this.application.setAttribute("token", token);
            System.out.println("token---init:"+token);
             String ticket = getTicket();
            this.application.setAttribute("jsapi_ticket", ticket);
            System.out.println("ticket--init:"+ticket);
        }
    }
    
    private static DefaultHttpClient httpclient;
    static {
        httpclient = new DefaultHttpClient();
        httpclient = (DefaultHttpClient) HttpClientConnectionManager
                .getSSLInstance(httpclient);
    }
    
    private static String getAccessToken(String appid, String secret) {
        HttpGet get = HttpClientConnectionManager
                .getGetMethod("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="
                        + appid + "&secret=" + secret);
        HttpResponse response;
        try {
            response = httpclient.execute(get);
            String jsonStr = EntityUtils
                    .toString(response.getEntity(), "utf-8");
            JSONObject demoJson = JSONObject.fromObject(jsonStr);
            return demoJson.getString("access_token");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "";
    }
    
    private String getTicket(){
        String token = (String) this.application.getAttribute("token");
        if("".equalsIgnoreCase(token) || null ==  token ){
            return "";
        }
        HttpGet get = HttpClientConnectionManager
                .getGetMethod("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+token+"&type=jsapi");
                        
        HttpResponse response;
        try {
            response = httpclient.execute(get);
            String jsonStr = EntityUtils
                    .toString(response.getEntity(), "utf-8");
            JSONObject demoJson = JSONObject.fromObject(jsonStr);
            return demoJson.getString("ticket");
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return "";
        
    }
 
}

GetSignature :

public class GetSignature extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = Logger.getLogger(GetSignature.class);
    public GetSignature() {
        super();
    }
 
 
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
    }
 
    
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try{
            response.setCharacterEncoding("UTF-8");
            request.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();
            //你的支付目录的Url,不需要转义,不包含#及其后面部分
            String url = request.getParameter("url");
            ServletContext application = this.getServletContext();
            String jsapi_ticket=String.valueOf(application.getAttribute("jsapi_ticket"));
            JSONObject obj = WeixinPay.getSignature(url, jsapi_ticket);
//            Map<String, String> sign = Sign.sign(jsapi_ticket,url);
            out.print(obj.toString());
            out.flush();
            out.close();
        }catch (Exception e) {
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
        
    }
 
}

JS中初始化:

//支付初始化
        function initPay(openId){
            //获取当前页面URL
            var geturl=window.location.href.split(‘#‘)[0];
            var getencodeurl=encodeURIComponent(geturl);
            $.ajax({
                type : ‘POST‘,
                url : "/GetSignature?url="+getencodeurl,
                contentType:"application/x-www-form-urlencoded", 
                success : function(response) {
                    var params = eval("(" + response + ")");
                    wx.config({
                         debug: false,
                        appId : params.appid, // 必填,公众号的唯一标识
                        timestamp : params.timestamp, // 必填,生成签名的时间戳
                        nonceStr : params.nonceStr,  // 必填,生成签名的随机串
                        signature : params.signature,// 必填,签名,见附录1
                        jsApiList : [ ‘chooseWXPay‘]
                    });
                    wx.ready(function() {
                        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
                        $("#weixinpay").on(‘click‘, function(t) {
//                             var c_sname =getQueryString("c_sname");
                            var paymoney=document.getElementById("money").value;//实际付款
                            var phone=document.getElementById("phone").value;//手机号
                            
                            if(phone==null||phone==""){
                                Dialog.alert("请填写手机号码!");
                            }else{
                                $("#weixinpay").unbind(‘click‘);
                                $("#mcover").css("display","block"); 
//                                 alert($("#payment").serialize());
                                $.ajax({
                                    type : ‘POST‘,
//                                     url:"/topayServlet",
                                    url : "/topayServlet?openId="+openId+"&money="+paymoney+"&phone="+phone,
//                                     data:$("#payment").serialize(),// 提交formid
//                                     async: false,
                                    success : function(response) {
                                            var params = eval("(" + response + ")");
                                            $("#mcover").css("display","none");
                                            wx.chooseWXPay({
                                                appId : params.appId,
                                                timestamp :params.timeStamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
                                                nonceStr  : params.nonceStr, // 支付签名随机串,不长于 32 位
                                                package : params.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
                                                signType :params.signType, 
                                                paySign : params.paySign, 
                                                success : function(res) {
                                                     if(res.errMsg == "chooseWXPay:ok" ) {
                                                         window.location.href="/3g/shareBusiness.jsp?sid="+sp+"&c_sname="+skf+"&phone="+phone;
                                                        //支付成功
                                                        $("#weixinpay").bind(‘click‘);
                                                    }
                                                },
                                                 cancel: function (res) { 
                                                     window.location.href="/3g/shop_list.jsp";
                                                     $("#weixinpay").bind(‘click‘);
                                                },
                                                fail:function(res){
                                                       window.location.href="/3g/shop_list.jsp";
                                                       $("#weixinpay").bind(‘click‘);
                                                }
                                            });
                                    },
                                    error : function() {
//                                         window.location.reload();
//                                         alert("服务器异常,统一下单接口出错!");
                                    }
                                })
                            }
                            
                        });
                    });
                    // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
//                     wx.error(function(res){
//                         alert(‘wx.error: ‘+JSON.stringify(res));
//                     });
                },
                error : function() {
//                     window.location.reload();
//                     Dialog.alert("服务器异常,支付初始化失败!");
                }
            })
    }

TopayServlet:统一下单接口

/**
 * 支付请求处理
 * @author dsn
 *
 */
public class TopayServlet extends HttpServlet {
 
 
    /**
     * 
     */
    private static final long serialVersionUID = 1359159929707330023L;
    private static final Logger logger = Logger.getLogger(TopayServlet.class);
    private String finalmoney=null;
    private String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    //商户相关资料 
    private    String appid = WeiXinUitls.appid;
    private    String appsecret = WeiXinUitls.appsecret;
    private    String partner = WeiXinUitls.partner;
    private    String partnerkey = WeiXinUitls.partnerkey;
    @SuppressWarnings("static-access")
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setCharacterEncoding("UTF-8");
        request.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        //网页授权后获取传递的参数
        String openId = request.getParameter("openId");     
        String sid = request.getParameter("sssp"); //商户ID
        String money = request.getParameter("money");//实际付款
        String phone = request.getParameter("phone");//手机号
        
        String c_sname = new String(skf.getBytes("ISO-8859-1"), "utf-8");
        //拼接字符串
        String zong=sid+"*"+money+"*"+phone+"*"+jfdy;
        //金额转化为分为单位
        String money2 = TenpayUtil.getMoney(money);
        //获取openId后调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder
                String currTime = TenpayUtil.getCurrTime();
                //8位日期
                String strTime = currTime.substring(8, currTime.length());
                //四位随机数
                String strRandom = TenpayUtil.buildRandom(4) + "";
                //10位序列号,可以自行调整。
                String strReq = strTime + strRandom;
                //商户号
                String mch_id = partner;
                //子商户号  非必输
                //String sub_mch_id="";
                //设备号   非必输
                String device_info="WEB";
                //随机数 
                String nonce_str = strReq;
                //商品描述
                //String body = describe;
                //商品描述根据情况修改
                String body = c_sname;
                //附加数据
                String attach = zong;
                //商户订单号
                String out_trade_no = NonceString.generate();
                //int intMoney = Integer.parseInt(finalmoney);
                //总金额以分为单位,不带小数点
                //int total_fee = intMoney;
                //订单生成的机器 IP
                String spbill_create_ip = request.getRemoteAddr();
                //订 单 生 成 时 间   非必输
                String time_start =TenpayUtil.getStartTime();
                //订单失效时间      非必输
                String time_expire =TenpayUtil.getEndTime();;
                //商品标记   非必输
                String goods_tag = "WXG";
                //这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。
                String notify_url ="http://www.yiquanmian.com/notifyServlet";
                String trade_type = "JSAPI";
                String openid = openId;
                //非必输
//                String product_id = "";
                SortedMap<String, String> packageParams = new TreeMap<String, String>();
                packageParams.put("appid", appid);  
                packageParams.put("mch_id", mch_id);  
                packageParams.put("nonce_str", nonce_str);  
                packageParams.put("body", body);  
                packageParams.put("attach", attach);  
                packageParams.put("out_trade_no", out_trade_no);  
                packageParams.put("total_fee", money2);  
                packageParams.put("spbill_create_ip", spbill_create_ip);
                packageParams.put("time_start", time_start); 
                packageParams.put("time_expire", time_expire); 
                packageParams.put("notify_url", notify_url);  
                packageParams.put("trade_type", trade_type);  
                packageParams.put("openid", openid);  
                RequestHandler reqHandler = new RequestHandler(request, response);
                reqHandler.init(appid, appsecret, partnerkey);
                String sign = reqHandler.createSign(packageParams);
                String xml="<xml>"+
                        "<appid>"+appid+"</appid>"+
                        "<mch_id>"+mch_id+"</mch_id>"+
                        "<nonce_str>"+nonce_str+"</nonce_str>"+
                        "<sign>"+sign+"</sign>"+
                        "<body><![CDATA["+body+"]]></body>"+
                        "<attach>"+attach+"</attach>"+
                        "<out_trade_no>"+out_trade_no+"</out_trade_no>"+
                        "<total_fee>"+money2+"</total_fee>"+
                        "<spbill_create_ip>"+spbill_create_ip+"</spbill_create_ip>"+
                        "<time_start>"+time_start+"</time_start>"+
                        "<time_expire>"+time_expire+"</time_expire>"+
                        "<notify_url>"+notify_url+"</notify_url>"+
                        "<trade_type>"+trade_type+"</trade_type>"+
                        "<openid>"+openid+"</openid>"+
                        "</xml>";
                String allParameters = "";
                try {
                    allParameters =  reqHandler.genPackage(packageParams);
                } catch (Exception e) {
                    logger.error(e.getMessage(), e);
                    e.printStackTrace();
                }
                String prepay_id="";
                try {
                    prepay_id= new GetWxOrderno().getPayNo(createOrderURL, xml);
//                    JSONObject xmls = p.getJSONObject("xml");
                    if(prepay_id.equals("")){
                        request.setAttribute("ErrorMsg", "统一支付接口获取预支付订单出错");
                        response.sendRedirect("error.jsp");
                    }
                } catch (Exception e1) {
                    logger.error(e1.getMessage(), e1);
                    e1.printStackTrace();
                }
                SortedMap<String, String> finalpackage = new TreeMap<String, String>();
                String appid2 = appid;
                String timestamp = Sha1Util.getTimeStamp();
                String nonceStr2 = nonce_str;
                String prepay_id2 = "prepay_id="+prepay_id;
                String packages = prepay_id2;
                finalpackage.put("appId", appid2);  
                finalpackage.put("timeStamp", timestamp);  
                finalpackage.put("nonceStr", nonceStr2);  
                finalpackage.put("package", packages);  
                finalpackage.put("signType", "MD5");
                String finalsign = reqHandler.createSign(finalpackage);
                finalpackage.put("paySign",finalsign);
                JSONObject jsonObject1 = JSONObject.fromObject(finalpackage);   
                out.print(jsonObject1);
                out.flush();
                out.close();
                 
    }
 
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
 
}

NotifyServlet:回调处理类

public class NotifyServlet extends HttpServlet {
 
    /**
     * 
     */
    private static final long serialVersionUID = 6743167121907086323L;
    private static final Logger logger = Logger.getLogger(NotifyServlet.class);
    private String resultXML;
 
 
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
//        response.setContentType("text/html;charset=utf-8");
        HttpSession session = request.getSession();
        int i = 0;
        //
        String inputLine;
        String notityXml = "";
        String resXml = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            Map m = GetWxOrderno.parseXmlToList2(notityXml);
            WxPayResult wpr = new WxPayResult();
            String appid = m.get("appid").toString();
            String bank_type = m.get("bank_type").toString();
            String attach = m.get("attach").toString();
            String cash_fee = m.get("cash_fee").toString();
            String fee_type = m.get("fee_type").toString();
            String is_subscribe = m.get("is_subscribe").toString();
            String mch_id = m.get("mch_id").toString();
            String nonce_str = m.get("nonce_str").toString();
            String openid = m.get("openid").toString();
            String out_trade_no = m.get("out_trade_no").toString();
            String result_code = m.get("result_code").toString();
            String return_code = m.get("return_code").toString();
            String sign = m.get("sign").toString();
            String time_end = m.get("time_end").toString();
            String times = time_end.substring(0, 4) + "-"
                    + time_end.substring(4, 6) + "-" + time_end.substring(6, 8)
                    + " " + time_end.substring(8, 10) + ":"
                    + time_end.substring(10, 12) + ":"
                    + time_end.substring(12, 14);
            Timestamp tstamp = Timestamp.valueOf(times);
            String total_fee = m.get("total_fee").toString();
            int totalint = Integer.parseInt(total_fee);
            double pasint = totalint * 0.01;
            String trade_type = m.get("trade_type").toString();
            String transaction_id = m.get("transaction_id").toString();
            
            if ("SUCCESS".equals(result_code)) {
                // 支付成功
                // 处理附加数据
                
                // 判断订单是否已经存在
                
                if (rs.next()) {
                    if(transaction_id.equals(rs.getString("ddh"))){
                        System.out.println("订单已经存在");
                    }
                } else {
                    
                    
                    
                    // ----------------------------------------------------发送短信-------------------------------------------
                    // 给用户发短信
                    
 
                    // 给商家发短信
                    
                    
 
                }
                resXml = "<xml>"
                        + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                resXml = "<xml>"
                        + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[false]]></return_msg>"
                        + "</xml> ";
            }
 
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            e.printStackTrace();
        }
 
    }
 
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

上面就是微信公众号的核心代码,需要源码的可以去我的地址下

https://download.csdn.net/download/dsn727455218/9325425

重点提示一下一定要在js的页面中引入微信的js文件不然会调不起支付的

<script type="text/javascript" charset="UTF-8"
src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

 

二 APP支付

流程:

1.android引入微信支付的SDK

2.拿商品信息请求统一下单接口

 

3.统一下单接口获取预支付ID,后进行二次签名把参数返回给前端

4.前端JS中接收到参数调起支付

5.支付成功页面跳转以及回调处理

具体骚操作:

首先在Constants.java中设置相关参数,具体请查看该文件注释,同时根据注释修改androidmanifest.xml文件

要保证: 包名和开放平台一致,签名和开放平台一致,并且再公众平台做设置,详情请阅读: http://pay.weixin.qq.com/wiki/doc/api/app.php?chapter=8_5,注意:此条仅仅适用于android,ios不受签名文件限制

要保证回调类WXPayEntryActivity.java文件必须位于包名的wxapi目录下,否则会导致无法回调的情况,注意:此条仅仅适用于android,ios有固定格式,请参考ios demo

上面是Android的注意事项

androidmanifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="你的项目包名"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk android:minSdkVersion="4" />
 
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        
        <activity
            android:name=".PayActivity"
            android:label="@string/app_name"
            android:exported="true"
            android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <data android:scheme="你的开发者ID"/>
            </intent-filter>
        </activity>
        
        <activity
            android:name=".wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop"/>
        
 
        <receiver
            android:name="net.sourceforge.simcpux.AppRegister">
            <intent-filter>
                <action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" />
            </intent-filter>
        </receiver>
        
    </application>
 
</manifest>

PayActivity:调起支付类

public class PayActivity extends Activity {
 
    private static final String TAG = "MicroMsg.SDKSample.PayActivity";
 
    PayReq req;
    final IWXAPI msgApi = WXAPIFactory.createWXAPI(this, null);
    TextView show;
    Map<String,String> resultunifiedorder;
    StringBuffer sb;
    
    private IWXAPI api; // IWXAPI 是第三方app和微信通信的openapi接口
 
    private Context context;
 
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay);
 
        //微信appId
        api = WXAPIFactory.createWXAPI( this, Constants.APP_ID);
        api.registerApp(Constants.APP_ID);
        final Button appayBtn = (Button) findViewById(R.id.appay_btn);
        appayBtn.setOnClickListener(new View.OnClickListener() {
            
            @Override
            public void onClick(View v) {
                String url = "http://192.168.0.104:8080/wx_pay/servlet/TopayServlet";
 
                Toast.makeText(PayActivity.this, "获取订单中...", Toast.LENGTH_SHORT).show();
                try{
                    byte[] buf = Util.httpGet(url);
                    if (buf != null && buf.length > 0) {
                        String content = new String(buf);
                        Log.e("get server pay params:",content);
                        JSONObject json = new JSONObject(content); 
                       
                        if(null != json && json.getString("returnstatus").equals("success") ){
                             String retmsg = json.getString("retmsg");
                             JSONObject json2 = new JSONObject(retmsg); 
                            PayReq req = new PayReq();
                            //req.appId = "wxf8b4f85f3a794e77";  // 测试用appId
                            Log.e("get appid  :",json2.getString("appid"));
                            Log.e("get partnerid  :",json2.getString("partnerid"));
                            Log.e("get prepayid  :",json2.getString("prepayid"));
                            Log.e("get noncestr  :",json2.getString("noncestr"));
                            Log.e("get timestamp  :",json2.getString("timestamp"));
                            Log.e("get package  :",json2.getString("package"));
                            Log.e("get sign  :",json2.getString("sign"));
                            //从服务器获取
                            req.appId           = json2.getString("appid");
                            req.partnerId       = json2.getString("partnerid");
                            req.prepayId        = json2.getString("prepayid");
                            req.nonceStr        = json2.getString("noncestr");
                            req.timeStamp       = json2.getString("timestamp");
                            req.packageValue    = json2.getString("package");
                            req.sign            = json2.getString("sign");
                            req.extData         = "app data"; // optional
                            Toast.makeText(PayActivity.this, "正常调起支付", Toast.LENGTH_SHORT).show();
                            // 在支付之前,如果应用没有注册到微信,应该先调用IWXMsg.registerApp将应用注册到微信
                            
                            api.sendReq(req);
                            Log.e("get api.sendReq(req)  :",api.sendReq(req)+"");
                        }else{
                            Log.d("PAY_GET", "返回错误"+json.getString("retmsg"));
                            Toast.makeText(PayActivity.this, "返回错误"+json.getString("retmsg"), Toast.LENGTH_SHORT).show();
                        }
                    }else{
                        Log.d("PAY_GET", "服务器请求错误");
                        Toast.makeText(PayActivity.this, "服务器请求错误", Toast.LENGTH_SHORT).show();
                    }
                }catch(Exception e){
                    Log.e("PAY_GET", "异常:"+e.getMessage());
                    Toast.makeText(PayActivity.this, "异常:"+e.getMessage(), Toast.LENGTH_SHORT).show();
                }
//                appayBtn.setEnabled(true);
            }
        });     
    }

WXPayEntryActivity:支付成功页面跳转类

public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler{
    
    private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
    
    private IWXAPI api;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.pay_result);
        //微信APP_ID
        api = WXAPIFactory.createWXAPI(this, Constants.APP_ID);
        api.handleIntent(getIntent(), this);
    }
 
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        api.handleIntent(intent, this);
    }
 
    @Override
    public void onReq(BaseReq req) {
    }
 
    @Override
    public void onResp(BaseResp resp) {
        Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
        String msg = "";
        if (resp.errCode == 0) {
            msg = "支付成功";
        } else if (resp.errCode == -1) {
            msg = "已取消支付";
        } else if (resp.errCode == -2) {
            msg = "支付失败";
        }
        Toast.makeText(WXPayEntryActivity.this, resp.errCode+"------"+msg, Toast.LENGTH_SHORT).show();
        finish();
    }
}

PrepayId:统一下单接口

/**
 * Servlet implementation class prepayid
 */
public class PrepayId extends HttpServlet {
    private static final long serialVersionUID = 1L;
    // key设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
 
    //TODO
    private static String KEY = "你的商户平台key";
 
    /**
     * Default constructor.
     */
    public PrepayId() {}
 
    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    @SuppressWarnings("rawtypes")
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
 
        SortedMap<String, String> map = new TreeMap<String, String>();
        //TODO 你的appid
        map.put("appid", "");
        //TODO 你的商户id
        map.put("mch_id", "");
        map.put("nonce_str", String.valueOf(System.currentTimeMillis()));
        map.put("body", "lidongliang");
        map.put("out_trade_no", String.valueOf(System.currentTimeMillis()));
        map.put("total_fee", "1");
        map.put("spbill_create_ip", "192.168.0.105");
        map.put("notify_url", "你的回调地址");
        map.put("trade_type", "APP");
        String sign = createSign(map);
        map.put("sign", sign);
 
        // 生成XMl
        Set set = map.entrySet();
        Iterator it = set.iterator();
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        while (it.hasNext()) {
            Map.Entry entry = (Map.Entry) it.next();
            String key = (String) entry.getKey();
            String value = (String) entry.getValue();
            sb.append("<" + key + "><![CDATA[");
            sb.append(value);
            sb.append("]]></" + key + ">");
        }
        sb.append("</xml>");
 
        try {
            System.out.println("111111111" + sb.toString());
            String postData = NetUtil.doPost(url, sb.toString());
            System.out.println("222222222" + postData.toString());
            SortedMap<String, String> test = new TreeMap<String, String>();
            JSONObject json = XML.toJSONObject(postData).getJSONObject("xml");
 
            test.put("appid", json.getString("appid"));
            test.put("partnerid", json.getString("mch_id"));
            test.put("prepayid", json.getString("prepay_id"));
            test.put("package", "Sign=WXPay");
            test.put("noncestr", String.valueOf(System.currentTimeMillis()));
            test.put("timestamp", String.valueOf(System.currentTimeMillis() / 1000));
            test.put("sign", createSign(test));
 
            response.getWriter().append(new JSONObject(test).toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
 
    }
 
    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     *      response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {}
 
    /**
     * 微信支付签名算法sign
     * 
     * @param characterEncoding
     * @param parameters
     * @return
     */
    @SuppressWarnings("rawtypes")
    public static String createSign(SortedMap<String, String> parameters) {
        StringBuffer sb = new StringBuffer();
        // 所有参与传参的参数按照accsii排序(升序)
        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=" + KEY);
        System.out.println("字符串拼接后是:" + sb.toString());
        String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8").toUpperCase();
        System.out.println("sign:" + sign);
        return sign;
    }
}

NotifyHandle:支付回调类

@Controller
@RequestMapping("notifyhandle")
public class NotifyHandle extends BaseAction{
    @Resource
    private ServiceSinggleService ssService;
    @Resource
    private ElutionRecordService edService;
    @Resource
    private AppUserService appuserService;
    @Resource
    private MsgJpushService mjService;
    private static final Logger logger = Logger.getLogger(NotifyHandle.class);
    @ResponseBody
    @RequestMapping(value="/notify")
    public String notify(ServiceSinggle ssinggle,ElutionRecord record,MsgJpush msgjpush,AppUser appuser,HttpServletRequest request,HttpSession session,HttpServletResponse response){
        String inputLine;
        String notityXml = "";
        String resXml = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
            Map m = GetWxOrderno.parseXmlToList2(notityXml);
            String result_code = m.get("result_code").toString();
            if("SUCCESS".equals(result_code)){
                //查询是否存在订单
                String attach = m.get("attach").toString();
                String out_trade_no = m.get("out_trade_no").toString();
                String time_end = m.get("time_end").toString();
                String total_fee = m.get("total_fee").toString();
                int totalint = Integer.parseInt(total_fee);
                //订单更新 继续你的逻辑操作
            } else {
                resXml = "<xml>"
                        + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[false]]></return_msg>"
                        + "</xml> ";
            }
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        
        return "";
    }
}

APP的微信支付就是这么的简单:上面我贴的核心代码,一些工具类没有贴出来需要demo可以去下面地址下载

https://download.csdn.net/download/dsn727455218/10304062

如果遇到签名错误,缺少参数,返回-1,等错误请参考我的另一篇文章:微信支付遇到的几个问题

https://blog.csdn.net/dsn727455218/article/details/70139320

看着是不是很简单,完美的解决。

到这里已经完成了微信支付功能,如有需要可以加我Q群【308742428】大家一起讨论技术。

后面会不定时为大家更新文章,敬请期待。

以上是关于JAVA实现微信支付V3的主要内容,如果未能解决你的问题,请参考以下文章

java微信支付v3系列——5.微信支付成功回调

java 微信支付v3 —8.微信支付之退款成功回调

Java中的微信支付:API V3 微信平台证书的获取与刷新

golang实现微信支付v3版本

微信支付v3的demo怎么转换成thinkphp代码

微信支付v3开发 收货地址共享接口