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】大家一起讨论技术。
后面会不定时为大家更新文章,敬请期待。
喜欢的朋友可以关注下,粉丝也缺。
如果对你有帮助,请打赏一下!!!