java--spring boot微信支付服务端实现含代码(app支付、扫码支付等)
来源:互联网 发布:信广立诚贷之家数据 编辑:程序博客网 时间:2024/05/17 04:54
最近在弄支付宝、微信支付等的事,发现这两家的文档都写得很差,demo也让人看的云里雾里。所以写篇博客,来尽量减少后来的同学走的弯路。
首先,若是要做app支付的话,在微信第三方平台申请APP,若是安卓的话上传你的keystore和包名,ios上传bundle id,微信会生成相应的签名。
然后前往微信商户平台,拿到要做支付必要的各种id和密钥。
请看以下配置代码:
package com.kyd.callcenter.util.weixin;import com.github.wxpay.sdk.WXPayConfig;import java.io.ByteArrayInputStream;import java.io.File;import java.io.FileInputStream;import java.io.InputStream;public class WXMyConfigUtil implements WXPayConfig { private byte[] certData; public WXMyConfigUtil() throws Exception { String certPath = "证书地址";//从微信商户平台下载的安全证书存放的目录 File file = new File(certPath); InputStream certStream = new FileInputStream(file); this.certData = new byte[(int) file.length()]; certStream.read(this.certData); certStream.close(); } @Override public String getAppID() { return "填写你的appid"; } //parnerid @Override public String getMchID() { return "填写商户id"; } @Override public String getKey() { return "填写api密钥"; } @Override public InputStream getCertStream() { ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData); return certBis; } @Override public int getHttpConnectTimeoutMs() { return 8000; } @Override public int getHttpReadTimeoutMs() { return 10000; }}
要想调用微信sdk的话,请记得在你项目中的pom文件中加入以下:
<dependency> <groupId>com.github.wxpay</groupId> <artifactId>wxpay-sdk</artifactId> <version>0.0.3</version> </dependency>先说app支付,前端访问服务器端,服务器端返回生成签名后的订单信息。
如何生成订单信息呢?以下是代码:
controller:
@RequestMapping(value = "/pay", method = {RequestMethod.GET, RequestMethod.POST}) public String orderPay(/*@RequestParam(required = true,value = "user_id")String user_id, @RequestParam(required = true,value = "coupon_id")String coupon_id, @RequestParam(required = true,value = "out_trade_no")String out_trade_no, @RequestParam(required = true,value = "total_fee")String total_fee,*/ HttpServletRequest req, HttpServletResponse response) throws Exception { System.err.println("进入微信支付申请"); Date now = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");//可以方便地修改日期格式 String hehe = dateFormat.format(now); String out_trade_no=hehe+"wxpay"; //777777 需要前端给的参数 String total_fee="1"; //7777777 微信支付钱的单位为分 String user_id="1"; //77777 String coupon_id="7"; //777777 String attach=user_id+","+coupon_id; WXMyConfigUtil config = new WXMyConfigUtil();// String spbill_create_ip = GetIPAddrUtil.getIpAddr(req); String spbill_create_ip="10.4.21.78"; System.err.println(spbill_create_ip); Map<String,String> result = wxPayService.dounifiedOrder(attach,out_trade_no,total_fee,spbill_create_ip,1); String nonce_str = (String)result.get("nonce_str"); String prepay_id = (String)result.get("prepay_id"); Long time =System.currentTimeMillis()/1000; String timestamp=time.toString(); //签名生成算法 MD5Util md5Util = new MD5Util(); Map<String,String> map = new HashMap<>(); map.put("appid",config.getAppID()); map.put("partnerid",config.getMchID()); map.put("package","Sign=WXPay"); map.put("noncestr",nonce_str); map.put("timestamp",timestamp); map.put("prepayid",prepay_id); String sign = md5Util.getSign(map); String resultString="{\"appid\":\""+config.getAppID()+"\",\"partnerid\":\""+config.getMchID()+"\",\"package\":\"Sign=WXPay\"," + "\"noncestr\":\""+nonce_str+"\",\"timestamp\":"+timestamp+"," + "\"prepayid\":\""+prepay_id+"\",\"sign\":\""+sign+"\"}"; System.err.println(resultString); return resultString; //给前端app返回此字符串,再调用前端的微信sdk引起微信支付 }
其中调用了service中的方法,若是扫码支付的话只要把trade_type改成NATIVE即可,具体以微信官方文档为准:
@Override public Map<String, String> dounifiedOrder(String attach, String out_trade_no, String total_fee,String spbill_create_ip,int type) throws Exception { Map<String, String> fail = new HashMap<>(); WXMyConfigUtil config = new WXMyConfigUtil(); WXPay wxpay = new WXPay(config); Map<String, String> data = new HashMap<String, String>(); // data.put("appid", config.getAppID());// data.put("mch_id", config.getMchID());// data.put("nonce_str",WXPayUtil.generateNonceStr());// data.put("nonce_str","6128be982a7f40daa930025dedd1a90d"); String body="订单支付"; data.put("body", body); data.put("out_trade_no", out_trade_no); data.put("total_fee", total_fee); data.put("spbill_create_ip",spbill_create_ip); //异步通知地址(请注意必须是外网) data.put("notify_url", "http://1y8723.51mypc.cn:21813/api/wxpay/notify"); data.put("trade_type", "APP"); data.put("attach", attach);// data.put("sign", md5Util.getSign(data)); StringBuffer url= new StringBuffer(); try { Map<String, String> resp = wxpay.unifiedOrder(data); System.out.println(resp); String returnCode = resp.get("return_code"); //获取返回码 String returnMsg = resp.get("return_msg"); if("SUCCESS".equals(returnCode)){ //若返回码为SUCCESS,则会返回一个result_code,再对该result_code进行判断 String resultCode = (String)resp.get("result_code"); String errCodeDes = (String)resp.get("err_code_des"); System.out.print(errCodeDes); if("SUCCESS".equals(resultCode)){ //获取预支付交易回话标志 Map<String,String> map = new HashMap<>(); String prepay_id = resp.get("prepay_id"); String signType = "MD5"; map.put("prepay_id",prepay_id); map.put("signType",signType); String sign = md5Util.getSign(map); resp.put("realsign",sign); url.append("prepay_id="+prepay_id+"&signType="+signType+ "&sign="+sign); return resp; }else { logger.info("订单号:{},错误信息:{}",out_trade_no,errCodeDes); url.append(errCodeDes); } }else { logger.info("订单号:{},错误信息:{}",out_trade_no,returnMsg); url.append(returnMsg); } } catch (Exception e) { System.out.println("aaaaaaaaaaaaa"); System.out.println(e); logger.info(e.getMessage()); } return fail; }
若是支付成功,微信会给你的服务器发送异步通知。所以如何处理此通知也告诉大家:
controller:
/** * 订单支付异步通知 */ @ApiOperation(value = "手机订单支付完成后回调") @RequestMapping(value = "/notify",method = {RequestMethod.GET, RequestMethod.POST}) public String WXPayBack(HttpServletRequest request,HttpServletResponse response){ String resXml=""; System.err.println("进入异步通知"); try{ // InputStream is = request.getInputStream(); //将InputStream转换成String BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "\n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } resXml=sb.toString(); System.err.println(resXml); String result = wxPayService.payBack(resXml);// return "<xml><return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>"; return result; }catch (Exception e){ logger.error("手机支付回调通知失败",e); String result = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> "; return result; } }其中调用的service方法:
/** * 支付结果通知 * @param notifyData 异步通知后的XML数据 * @return */ @Override public String payBack(String notifyData) { WXMyConfigUtil config = null; try { config = new WXMyConfigUtil(); } catch (Exception e) { e.printStackTrace(); } WXPay wxpay = new WXPay(config); String xmlBack=""; Map<String, String> notifyMap = null; try { notifyMap = WXPayUtil.xmlToMap(notifyData); // 转换成map if (wxpay.isPayResultNotifySignatureValid(notifyMap)) { // 签名正确 // 进行处理。 // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功 String return_code = notifyMap.get("return_code");//状态 String out_trade_no = notifyMap.get("out_trade_no");//订单号 if(return_code.equals("SUCCESS")){ if(out_trade_no!=null){ //处理订单逻辑 /** * 更新数据库中支付状态。 * 特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功。 * 此处需要判断一下。后面写入库操作的时候再写 * */ System.err.println(">>>>>支付成功"); logger.info("微信手机支付回调成功订单号:{}",out_trade_no); xmlBack = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; }else { logger.info("微信手机支付回调失败订单号:{}",out_trade_no); xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> "; } } return xmlBack; } else { // 签名错误,如果数据里没有sign字段,也认为是签名错误 logger.error("手机支付回调通知签名错误"); xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> "; return xmlBack; } } catch (Exception e) { logger.error("手机支付回调通知失败",e); xmlBack = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> "; } return xmlBack; }要给微信服务器返回处理成功的xml格式的字符串,我在代码中已经写得很清楚了。
我相信以上代码不难看懂,如果有问题的同学评论问我我再做补充。
顺便把用到的工具类一起给大家:
MD5生成签名算法:
package com.kyd.callcenter.util.weixin;import com.github.wxpay.sdk.WXPayConstants;import java.io.UnsupportedEncodingException;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;import java.util.Map;import java.util.Set;public class MD5Util { public String getSign(Map<String, String> data) throws Exception { WXMyConfigUtil config = new WXMyConfigUtil(); Set<String> keySet = data.keySet(); String[] keyArray = keySet.toArray(new String[keySet.size()]); Arrays.sort(keyArray); StringBuilder sb = new StringBuilder(); for (String k : keyArray) { if (k.equals(WXPayConstants.FIELD_SIGN)) { continue; } if (data.get(k).trim().length() > 0) // 参数值为空,则不参与签名 sb.append(k).append("=").append(data.get(k).trim()).append("&"); } sb.append("key=").append(config.getKey()); MessageDigest md = null; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } byte[] array = new byte[0]; try { array = md.digest(sb.toString().getBytes("UTF-8")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } StringBuilder sb2 = new StringBuilder(); for (byte item : array) { sb2.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } return sb2.toString().toUpperCase(); }}
阅读全文
1 0
- java--spring boot微信支付服务端实现含代码(app支付、扫码支付等)
- 支付宝支付(网站支付,APP支付,扫码支付) Java服务端代码
- 微信支付(网站支付,APP支付,扫码支付)并充值钻石 Java服务端代码 xml解析 map排序
- Spring boot--支付宝APP支付安卓老版接口实现(含代码)
- 微信APP支付服务端(JAVA)
- 微信支付之扫码支付相关代码(Java)(转载)
- 微信支付之扫码支付相关代码(Java)
- java版app微信支付服务端代码【手机app微信支付】
- 微信支付之扫码支付(java版 native原生支付)
- 【手机app微信支付】app微信支付服务端(java)的实现
- 微信支付-扫码支付备忘
- 微信支付扫码支付
- 微信支付--扫码支付模式二实现
- java支付宝和微信app支付(服务端处理)
- Java 微信支付之APP支付服务端 (一)
- 微信APP支付Java服务端
- ThinkPHP之微信支付(扫码支付)
- 第三方支付之微信支付(扫码支付)
- VS2013 64位 32位|Microsoft Visual Studio Ultimate 2013(简体中文旗舰版)
- SQL优化
- 昂贵的聘礼 POJ
- Android——RecyclerView——Adapter完全图解,带你彻底掌握万能的适配器
- 【Scikit-Learn 中文文档】随机投影
- java--spring boot微信支付服务端实现含代码(app支付、扫码支付等)
- Android中插件开发篇总结和概述
- 部分和问题
- 【Scikit-Learn 中文文档】内核近似
- 解决linux中vi编辑出现乱码的问题
- 第04次上机作业所有源代码
- 160个破解练习之CrackMe 007
- Android滑动实现开关
- leetcode 371. Sum of Two Integers