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】大家一起讨论技术。

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

原文地址:https://www.cnblogs.com/dsn727455218/p/9264096.html

时间: 2024-08-30 03:42:53

JAVA实现微信支付V3的相关文章

JAVA版微信支付V3—JSAPI支付

本人做的是微信V3版本的微信支付,也是目前最新的微信支付接口.官方文档下载地址 https://mp.weixin.qq.com/paymch/readtemplate?t=mp/business/course3_tmpl&lang=zh_CN

微信支付V3集成过程(Native)

长话短说,微信支付V3版本相比V2版本,简化许多接口,大大降低了商户的接入代价,只不过由于相关的集成说明文档写的过于笼统,细节描述不够具体,demo版本不够完善等等原因,被大家诟病. 最近基于业务需要,完成了微信支付的接入,选择的是公众号扫码支付(Native模式).在此把集成的大致过程贴出来,希望能对正在困扰的各位有所帮助. 整个交互过程分为四步: 1.商户:生成微信支付二维码 2.微信:扫描二维码,获取商户订单信息 3.微信:确认支付,调起微信支付模块,完成支付,回调商户通知接口 4.商户:

微信支付v3发布到iis时的证书问题

找了问题半天,调试没有问题,但是放到网站上就报错.最后解决方法. 一开始报“出现了内部错误” 解决方法是 方法一 var cer = new X509Certificate(certpath, password,X509KeyStorageFlags.MachineKeySet); 方法二 iis 找到部署的站点应用连接池,右键高级设置,找到“加载用户配置文件”改为true.window service2008 默认为false的. 解决后报另一个错误 基础连接已关闭 连接被意外关闭 其实是没访

坑爹的微信支付v3,其实没有那么坑

研究微信开发一年多了,每个新接口,都会第一时间进行研究.微信支付开放很久,一直没机会接触到支付接口,等了好久终于从朋友那儿搞到了接口,从此开始了我两天多的支付接口的研究. 拿到这个接口文档的第一个想法就是这也没什么难的嘛, 和支付宝.财付通.网银在线等一些传统接口的思路逻辑都是一样的,觉得差不多最多一个下午就可以搞定,结果第一步调用统一支付接口就给来了个下马威,不管怎么改,就一直返回签名错误.第一次遇到签名错误,首先想到的是应该是没有正确理解签名的生成规则,又从头看了几次签名的生成规则,每次都是

到处都是坑的微信支付V3之 微信支付回调页面

据上次 到处都是坑的微信支付V3 后很多园友在被虐了千百遍后终于跳转到了亲切的微信支付界面,但输入密码支付后却不知道怎么处理了,接下来补上支付后的处理流程. 1. html中根据前台支付后反馈信息成功与否跳转到相关页面 if (res.err_msg == "get_brand_wcpay_request:ok") { // message: "微信支付成功!", window.location.replace("@Url.Content("~/

微信支付[v3]

原文:微信支付[v3] V2升级V3 顺便记录一下 ,文档: http://pay.weixin.qq.com/wiki/doc/api/index.html !!! 支付授权目录与测试人的微信帐号白名单(出现access_denied或access_not_allow错误,请检查是否设置正确) 微信签名(用于jssdk调用支付,查询订单,异步参数签名等) 数字证书,用于微信退款 参数签名 对所有传入参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL 键值对的格式(即key1=v

微信支付v3开发(5) 扫码并输入金额支付

关键字:微信支付 微信支付v3 动态native支付 统一支付 Native支付 prepay_id 作者:方倍工作室 本文介绍微信支付下的扫描二维码并输入自定义金额的支付的开发过程. 注意 微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版.V3版的微信支付没有paySignKey参数.v2的相关介绍请参考方倍工作室的其他文章.本文介绍的为微信支付v3. 一. OAuth2.0授权 JSAPI 支付前需要调用 登录授权接口获取到用户的 Openid .所

微信支付v3版-微信支付开发教程

微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版.V3版的微信支付没有paySignKey参数. 微信支付v3 提示:因微信支付商户平台升级,若您在资料审核通过后,收到支付小助手发送的邮件通知为以下信息,请按本页面接口文档进行支付开发.1. 信息包括:商户ID.申请编号.登录帐号.登录密码.商户API密码2..证书包括:商户API证书.证书密钥.CA证书 1. 使用网页授权接口 使用网页授权接口获取用户的基本信息. [微信公众号]OAuth2.0授权.p

到处都是坑的微信支付V3

业务需要一个在微信上能付款的功能,于是乎想到了最普遍的支付宝,坑爹的是T与A是水火不容啊,默默的还是接微信支付吧,没想到从此掉进了连环坑…… 网上写微信支付接口的还是很多,PHP官方有(鄙视源码作者,连参数对应都错了,能跑通才怪),NET版 微信支付--入门篇 这篇算是比较全的,java版. PHP的只能参考,终究还是先按NET版的还创建项目,不过文章里面也没具体写到如何前后台交互(偶用的MVC),对于初次接触的人来说只能问题来一个解决一个. 至于怎么从0开发就不用详细说明了,参考这位仁兄的 微