java集成微信支付(完整流程)
java集成微信支付(完整流程)
1.申请微信支付能力
* 要想使用微信支付能力,不管是app支付、公众号支付、h5支付等支付方式都需要先在微信商户平台申请开通支付能力。 * 申请开通支付能力的资料有公司营业执照、负责人身份证正反面等图片,相关所需的所有资料在微信官方商户平台上有说明。 * 申请完开通支付能力后,我们会得到商户号以及appId,然后设置32位官方密钥。 123
2.准备工作
* 如果你是h5支付,还需要去微信商户平台设置支付URL的IP或者域名,一般最多可以设置5个IP或者域名,建议同时将正式环境和测试环境的IP或者域名设置好。 * 如果你是公众号支付,同上,你也需要设置你的支付IP或者域名,注意,异步通知的URL也要在你设置的IP或者域名下。 12
3.开始集成
*** APP支付** 支付集成流程如下: 步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。(app端向服务端发起请求) 步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。(服务端向微信请求) 步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式为Sign=WXPay(将微信回传的prepayid与其他参数组合返回给app端) 步骤4:商户APP调起微信支付。(app端利用服务端回传的参数调起微信支付) 步骤5:商户后台接收支付通知。(微信将支付结果异步通知服务端) 步骤6:商户后台查询支付结果。(微信将支付结果同步通知app端) 上代码: DecimalFormat df = new DecimalFormat("######0.00"); //根据订单id查询出该订单的金额money=df.format(Double.parseDouble(okamiOrder.getReallMoney()));//定义返回值ReturnValue rv=new ReturnValue();String token=request.getParameter("token");//当前用户的idString userId=TokenParmValue.getUserId(token);//开始组装调用统一下单接口所需的参数String currTime = TenpayUtil.getCurrTime();// 8位日期String strTime = currTime.substring(8, currTime.length());// 四位随机数String strRandom = TenpayUtil.buildRandom(4) + "";// 10位序列号,可以自行调整。String strReq =strTime+strRandom;SONObject retMsgJson = new JSONObject(); //应用配置String appId=""; //appidString appSecret=""; //微信支付appsecretString partner=""; //微信商户号String partnerkey=""; //api密钥//定义应用支付配置appId=WeixinPayUtil.appid; appSecret=WeixinPayUtil.appsecret; partner=WeixinPayUtil.partner; partnerkey=WeixinPayUtil.partnerkey; //********************************************当前微信支付业务处理开始// 时间戳加后四位随机数作为商户订单号String sjbh = RandomUtil.getRandomFileName();// 封装参数TreeMap<String, String> treeMap = new TreeMap<String, String>();// 微信支付所需要的appIdtreeMap.put("appid",appId);// 微信商户号treeMap.put("mch_id",partner);// 随机数treeMap.put("nonce_str", strReq);// 订单内容treeMap.put("body",subject);// 商户订单号treeMap.put("out_trade_no", sjbh);// 终端ip(下单生成机器的ip),可以获取支付接口的请求IPtreeMap.put("spbill_create_ip", Property.getProperty("weixinIp"));// 订单金额treeMap.put("total_fee",money);// 支付类型treeMap.put("trade_type",WeixinPayUtil.trade_type);// 微信异步通知地址treeMap.put("notify_url",Property.getProperty("okamiWeixinUrl").trim());//禁止充值的时候使用信用卡if("3".equals(payType)){treeMap.put("limit_pay","no_credit");}StringBuilder sb = new StringBuilder();for (String key : treeMap.keySet()) {sb.append(key).append("=").append(treeMap.get(key)).append("&");}sb.append("key="+partnerkey);// 获得微信支付验签RequestHandler reqHandler = new RequestHandler(request, response);reqHandler.init(appId,appSecret,partnerkey);// 参数加签名认证String sign = reqHandler.createSign(treeMap);// 获取签名treeMap.put("sign", sign);StringBuilder xml = new StringBuilder();xml.append("<xml>n");for (Map.Entry<String, String> entry : treeMap.entrySet()) {if ("body".equals(entry.getKey()) || "sign".equals(entry.getKey())) {xml.append("<" + entry.getKey() + "><![CDATA[").append(entry.getValue()).append("]]></" + entry.getKey() + ">n");} else {xml.append("<" + entry.getKey() + ">").append(entry.getValue()).append("</" + entry.getKey() + ">n");}}xml.append("</xml>"); //开始调用统一下单接口String createOrderURL = WeixinPayUtil.createOrderURL;String prepay_id = "";try {// 获得预下单的订单号prepay_id = GetWxOrderno.getPayNo(createOrderURL,xml.toString());} catch (Exception e1) { e1.printStackTrace(); rv.setResult("error"); rv.setMsg(ReturnUtil.PAYMENT_FAILURE); return new JsonMapper().toJson(rv);}log.info("微信支付prepay_id的值为:----------------"+prepay_id);// 获取到prepayid后对以下字段进行签名最终发送给appSortedMap<Object, Object> finalpackage = new TreeMap<Object, Object>();String timestamp = Sha1Util.getTimeStamp();finalpackage.put("appid",appId);finalpackage.put("noncestr", strReq);finalpackage.put("partnerid", partner);finalpackage.put("timestamp", timestamp);finalpackage.put("package", "Sign=WXPay");finalpackage.put("prepayid", prepay_id);String wenXinSign=WenXinPay.createSign("UTF-8",finalpackage,partnerkey);retMsgJson.put("appid",appId);retMsgJson.put("timestamp",timestamp);retMsgJson.put("noncestr", strReq);retMsgJson.put("partnerid",partner);retMsgJson.put("prepayid", prepay_id);retMsgJson.put("packageX", "Sign=WXPay");retMsgJson.put("sign", wenXinSign);// 最终给app的参数String json = retMsgJson.toString();以上是app端发起微信支付,服务端回传app端所需要的参数。 异步通知处理: 在做异步通知功能之前一定要设计好异步通知功能,防止重复通知,建议通知成功后将记录储存与缓存或者数据库中,以避免重复异步通知。 @RequestMapping(value = "payment/wechatAsynchronous",method=RequestMethod.POST,produces = "text/html;charset=UTF-8") @ResponseBodypublic void wechatAsynchronous(HttpServletRequest requestWechat,HttpServletResponse response) throws Exception{log.info("进入微信异步通知啦"+moduleName+"方法名为:wechatAsynchronous");DecimalFormat df = new DecimalFormat("######0.00");DecimalFormat dformat = new DecimalFormat("######0");requestWechat.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");response.setContentType("text/html;charset=UTF-8");response.setHeader("Access-Control-Allow-Origin", "*");InputStream in = requestWechat.getInputStream();ByteArrayOutputStream out = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = 0;while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);}out.close();in.close();String msgxml = new String(out.toByteArray(), "utf-8");// xml数据System.out.println(msgxml);log.info("msgxml的值为:-----------------"+msgxml);Map map = XmlToMap.xmlToMap(msgxml); //过滤空 设置 TreeMap SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>(); Iterator it = map.keySet().iterator(); while (it.hasNext()) { String parameter = (String) it.next(); String parameterValue = (String) map .get(parameter); String v = ""; if(null != parameterValue) { v = parameterValue.trim(); } packageParams.put(parameter, v); } log.info("进入微信异步通知啦"+moduleName+"异步通知参数:"+packageParams);// 获得支付结果String result_code = (String) map.get("result_code");// 获得商户订单号String out_trade_no = (String) map.get("out_trade_no");// 获得订单签名String sign = (String) map.get("sign");log.info("sign订单签名为:---------------------"+sign); //买家实际支付金额String total_fee=(String)map.get("total_fee");String realMoney=String.valueOf(Double.parseDouble(total_fee)/100);// 交易记录表的idString tranId = out_trade_no.replace(" ", "");log.info("参数 tranId:" + tranId);log.info("微信支付的result_code为-----------------------:" + result_code);// 根据交易id查询一条交易记录Transaction tran = tranService.findById(tranId);if(tran!=null){log.info("tran对象的值不为空:--------------------");// 订单表的idString orderId = tran.getOrderId();log.info("参数订单主键 orderId:" + orderId);// 微信支付成功if (result_code.equals("SUCCESS")){ //防止重复通知long size=requestRedisTemplate.boundValueOps("weixinpay:lock:"+out_trade_no).increment(1);requestRedisTemplate.expire("weixinpay:lock:"+out_trade_no,24,TimeUnit.HOURS);if(size==1){ log.info("进入微信异步通知啦"+moduleName+"异步通知请求进入!!!");//插入异步通知日志asyncService.insertResrcord("weixin",tran.getUserId(),(String)map.get("transaction_id"),realMoney,tranId); // 财付通订单号String transaction_id = (String) map.get("transaction_id");//获得微支付商户号String mch_id=(String) map.get("mch_id");//获得微信支付appid---->异步通知String appid=(String) map.get("appid");if(StringUtils.isNotBlank(mch_id)&&StringUtils.isNotBlank(appid)){log.info("商户号与appid不为空");//根据不同的appid校验应用配置//应用1String appId_local_one=WeixinPayUtil.appid;//应用2String appId_local_two=WeixinPayUtil.appid_two;//应用3String appId_local_three=WeixinPayUtil.appid_three;Stringpartner_local=WeixinPayUtil.partner;StringpartnerKey_local=WeixinPayUtil.partnerkey;StringappVersion="1";// 验证商户号是否正确if (mch_id.equals(partner_local)) {log.info("微信商户号与appid验证验证成功");//验证签名if(WenXinPay.isTenpaySign("UTF-8", packageParams,partnerKey_local)){log.info("微信验证签名成功了!!!!!!");// 业务处理}else{response.getWriter().write(setXml("FAIL", "ERROR"));log.info("微信支付异步通知失败了!!!!!!");}}else{response.getWriter().write(setXml("FAIL", "ERROR"));log.info("微信支付异步通知失败了!!!!!!");}} //微信异步通知返回xml格式数据public static String setXml(String return_code, String return_msg) {return "<xml><return_code><![CDATA[" + return_code+ "]]></return_code><return_msg><![CDATA[" + return_msg+ "]]></return_msg></xml>";} 以上就是app支付的所有代码,其中所用的工具类大部分为微信支付开发文档中demo提供,下载地址为:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3 ***h5支付** 记得在微信官方商户平台配置好支付域名 基本流程: 1、用户在商户侧完成下单,使用微信支付进行支付。2、由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB。3、统一下单接口返回支付相关参数给商户后台,如支付跳转url(参数名“mweb_url”),商户通过mweb_url调起微信支付中间页。4、中间页进行H5权限的校验,安全性检查。5、如支付成功,商户后台会接收到微信侧的异步通知。6、用户在微信支付收银台完成支付或取消支付,返回商户页面。7、商户在展示页面,引导用户主动发起支付结果的查询。8,9、商户后台判断是否接到收微信侧的支付结果通知,如没有,后台调用我们的订单查询接口确认订单状态。10、展示最终的订单支付结果给用户。**此处注意微信h5支付最终的结果是提供前端一个支付链接的字符串。** 支付接口代码: /** * 微信发送支付请求,微信官方h5支付 * @param paramMap * @return */@Overridepublic Result officialSend(Map paramMap){Result result=new Result();String pay_url="";// 封装参数TreeMap<String, String> treeMap = new TreeMap<String, String>();// 微信支付所需要的appIdtreeMap.put("appid",WeiXinConstant.official_app_id);// 微信商户号treeMap.put("mch_id",WeiXinConstant.official_mch_id);// 随机数treeMap.put("nonce_str",TenpayUtil.getNonceStr());// 订单内容treeMap.put("body",paramMap.get("productname")+"");// 商户订单号treeMap.put("out_trade_no",paramMap.get("orderId")+"");// 终端ip(下单生成机器的ip)treeMap.put("spbill_create_ip",paramMap.get("spbill_create_ip")+"");// 订单金额treeMap.put("total_fee",new Double(Double.valueOf(paramMap.get("money")+"")*100).intValue()+"");// 支付类型treeMap.put("trade_type","MWEB");//h5支付// 微信异步通知地址treeMap.put("notify_url", PropertiesUtil.getDom()+WeiXinConstant.official_notify_url);//业务参数treeMap.put("attach",paramMap.get("orderId")+"");JSONObject js=new JSONObject();JSONObject jb=new JSONObject();if("1".equals(paramMap.get("source"))){//安卓js.put("type", "Android");js.put("app_name", "");js.put("package_name", "");jb.put("h5_info", js);}else{//iosjs.put("type", "IOS");js.put("bundle_id", "");js.put("app_name", "");jb.put("h5_info", js);}//场景信息treeMap.put("scene_info",jb.toString());//禁止充值的时候使用信用卡,默认可以使用//treeMap.put("limit_pay","no_credit"); Map<String,String> params = SignUtils.paraFilter(treeMap); StringBuilder buf = new StringBuilder((params.size() +1) * 10); SignUtils.buildPayParams(buf,params,false); String preStr = buf.toString(); String sign = MD5.sign(preStr, "&key=" + WeiXinConstant.partnerkey, "utf-8"); treeMap.put("sign", sign); CloseableHttpResponse response = null; CloseableHttpClient client = null; try { HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder"); StringEntity entityParams = new StringEntity(WXPayUtil.mapToXml(treeMap),"utf-8"); httpPost.setEntity(entityParams); //httpPost.setHeader("Content-Type", "text/xml;charset=ISO-8859-1"); client = HttpClients.createDefault(); response = client.execute(httpPost); if(response != null && response.getEntity() != null){ Map<String,String> resultMap = WXPayUtil.xmlToMap(new String(EntityUtils.toByteArray(response.getEntity()))); if("SUCCESS".equalsIgnoreCase(resultMap.get("return_code"))){ if("SUCCESS".equalsIgnoreCase(resultMap.get("result_code"))){ String prepay_id=resultMap.get("prepay_id"); String mweb_url=resultMap.get("mweb_url"); logger.info("微信官方支付mweb_url:"+mweb_url); String packagevalue=""; if(mweb_url.indexOf("&package=")!=-1){ packagevalue=mweb_url.substring(mweb_url.indexOf("&package=")+9,mweb_url.length()); } String type=""; if(PropertiesUtil.getDom().indexOf("test")!=-1){type="1"; }else{type="2"; } pay_url=PropertiesUtil.getDom()+"pay/pay_h5_wx.html?prepay_id="+prepay_id+"&packagevalue="+packagevalue+"&type="+type; } }else{ logger.info("微信官方h5支付失败,失败原因为:"+resultMap.get("return_msg")); } logger.info("支付结果为:"+resultMap.toString()); }else{ logger.info("微信官方h5支付失败,请求未响应"); } } catch (Exception e) { logger.info("微信官方支付错误信息:"+e.getMessage()); } finally { if(response != null){ try {response.close();} catch (IOException e) { logger.info("微信官方支付,响应关闭错误信息:"+e.getMessage());} } if(client != null){ try {client.close();} catch (IOException e) { logger.info("微信官方支付,请求关闭错误信息:"+e.getMessage());} } } JSONObject job=new JSONObject(); if(StringUtils.isNotBlank(pay_url)){job.put("res",pay_url); }else{job.put("res",""); } result.setData(job);return result;} 注意,微信h5支付接口最终返回给前端是一个支付链接,此链接所在的页面的IP或者域名必须要在你之前在商户平台配置的IP或者域名之下,另外如果是app请求h5支付接口,也同样将此链接返回给app端,最后贴上支付连接中页面的代码: <html><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta content="width=device-width, initial-scale=1, minimum-scale=1.0, user-scalable=no" name="viewport"><title>微信官方h5支付</title> <script type="text/javascript"> function GetRequest() { var url = location.search; //获取url中"?"符后的字串 var theRequest = new Object(); if (url.indexOf("?") != -1) { var str = url.substr(1); strs = str.split("&"); for(var i = 0; i < strs.length; i ++) { theRequest[strs[i].split("=")[0]]=decodeURI(strs[i].split("=")[1]); } } return theRequest; } var Request = new Object(); Request = GetRequest(); var prepay_id,packagevalue,type,redirect_url; prepay_id = Request['prepay_id']; packagevalue = Request['packagevalue']; type=Request['type'];//环境类型 1测试环境 2正式环境 //回调地址 if(type==1){ redirect_url="http://测试域名/pay/wxreturn.html"; }else{ redirect_url="http://正式域名pay/wxreturn.html"; } window.location="https://wx.tenpay.com/cgi-bin/mmpayweb-bin/checkmweb?prepay_id="+prepay_id+"&package="+packagevalue+"&redirect_url="+redirect_url; </script></head><body></body> </html> 异步通知代码: /** * 微信支付回调,微信官方h5支付 * @return */ @Overridepublic Result callbackUrlOfficial(HttpServletRequest req) throws Exception{ String resString = XmlUtils.parseRequst(req); logger.info("微信官方h5支付回调参数:"+resString); Result result = new Result(); if(StringUtils.isNotBlank(resString)){ Map<String,String> map = WXPayUtil.xmlToMap(resString); logger.info("微信官方h5支付通知map内容:"+map); String return_code = map.get("return_code"); logger.info("微信官方h5支付异步通知业务结果为:"+return_code); if("SUCCESS".equals(return_code)){//通知状态 SUCCESS:成功 if(map.containsKey("sign")){ if(SignUtils.checkParam(map, WeiXinConstant.partnerkey)){//验证签名通过logger.info("微信官方h5支付异步通知签名通过!!!sign-success");if("SUCCESS".equals(map.get("result_code"))){//支付结果 SUCCESS:成功 //业务处理//判断微信支付返回值表中是否存在记录,如果不存在则插入返回信息 List<PayResponseBean> list =payServiceImpl.getPayResponse(map.get("out_trade_no"));if(list == null || list.size() == 0){payServiceImpl.addPayResponse(map.get("out_trade_no"), map.get("transaction_id"), "5", map.toString());//开始业务处理} return result;}else{logger.info("微信官方h5订单支付失败:平台订单编号orderid="+map.get("attach")); result.setCode(SystemStatus.WX_ORDER_PAY_ERROR.CODE); result.setMsg(SystemStatus.WX_ORDER_PAY_ERROR.MSG); return result;} }else{ logger.info("微信官方h5支付回调签名错误:平台订单编号orderid="+map.get("attach")); result.setCode(SystemStatus.WX_SIGN_ERR.CODE); result.setMsg(SystemStatus.WX_SIGN_ERR.MSG+"签名错误"); return result; } }else{ logger.info("微信官方h5支付回调签名不存在:平台订单编号orderid="+map.get("attach")); result.setCode(SystemStatus.WX_SIGN_ERR.CODE); result.setMsg(SystemStatus.WX_SIGN_ERR.MSG+"签名不存在"); return result; } }else{logger.info("微信官方h5支付异步通知失败,失败原因为"+map.get("return_msg"));result.setCode(SystemStatus.PARAM_ERROR.CODE);result.setMsg(SystemStatus.PARAM_ERROR.MSG);return result; } }else{ result.setCode(SystemStatus.PARAM_ERROR.CODE); result.setMsg(SystemStatus.PARAM_ERROR.MSG); return result; }} 以上就是微信h5支付的所有代码,其中所涉及到的工具类请大家自己在官方开发文档上下载:https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=15_4 *公众号支付* 公众号支付与h5支付类似,只需要将支付方式改成公众号支付方式就行,参考文档为:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_3 同样,公众号支付也是需要在你的公众号后台设置授权域名。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489相关知识
对接支付宝、微信、第三方支付,超详细讲解+demo演示
基于Java的网上花店网站的设计与开发资源
Java通用型支付+电商平台双系统实战
花瓣支付可以扫微信吗
【网站项目】鲜花销售微信小程序
无法错过的微信花呗开通全攻略,轻松享受信用支付新体验
基于springboot+vue的花艺烘焙商城系统微信小程序
微信 OAuth2 网页授权获取用户信息
2024微信花呗开通申请流程大揭秘...
微信小程序期末大作业解析:打造花店小程序
网址: java集成微信支付(完整流程) https://www.huajiangbk.com/newsview849416.html
上一篇: java后端实现集成支付宝APP |
下一篇: 支付宝、微信等常用第三方支付接口 |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039