1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 基于微信网页版二维码扫码支付

基于微信网页版二维码扫码支付

时间:2019-06-06 14:38:02

相关推荐

基于微信网页版二维码扫码支付

一、创建支付二维码

开发思路:使用Google的zxing来生成二维码,将图片生成base64,输出到前台显示!

1.1、用到的jar包

<!-- 生成微信二维码 --><dependency><groupId>jdom</groupId><artifactId>jdom</artifactId><version>1.1</version></dependency><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>2.2</version></dependency>

1.2、Action方法

/*** 创建微信二维码* -09-06* @param request* @param response*/@RequestMapping(value = "/createPayCode")public void createPayCode(HttpServletRequest request,HttpServletResponse response){HttpSession session=request.getSession();String userId = session.getAttribute("userId").toString();String money = request.getParameter("money");String orderId = request.getParameter("orderId");try {//预充值订单存redisboolean flag = createRechargeOrder(userId,money,Long.valueOf(orderId));if(flag){SortedMap<Object,Object> paras = new TreeMap<Object,Object>(); paras.put("appid", PayConfigUtil.APPID); paras.put("mch_id", PayConfigUtil.MCH_ID); paras.put("time_stamp", Long.toString(new Date().getTime())); paras.put("nonce_str", PayCommonUtil.CreateNoncestr()); paras.put("product_id", orderId);String sign = PayCommonUtil.createSign("UTF-8", paras); paras.put("sign", sign); String url = "weixin://wxpay/bizpayurl?sign=SIGN&appid=APPID&mch_id=MCHID&product_id=PRODUCTID&time_stamp=TIMESTAMP&nonce_str=NOCESTR";String result = url.replace("SIGN", sign).replace("APPID", PayConfigUtil.APPID).replace("MCHID", PayConfigUtil.MCH_ID).replace("PRODUCTID", String.valueOf(paras.get("product_id"))).replace("TIMESTAMP", String.valueOf(paras.get("time_stamp"))).replace("NOCESTR", String.valueOf(paras.get("nonce_str")));String res=PayCommonUtil.createCodeStream(result);response.setCharacterEncoding("utf-8");response.setContentType("text/plain");response.getWriter().println(res);}} catch (Exception e) {e.printStackTrace();}}/*** 创建预充值订单* -09-06* @param userId* @param money* @param orderId* @return*/private boolean createRechargeOrder(String userId, String money, Long orderId) {JSONObject json=new JSONObject();OrderRecharge recharge=new OrderRecharge();boolean flag = false;User user =null;Long num=0L;try {user = userService.getUserById(Integer.valueOf(userId));if(user !=null){recharge.setOrderId(orderId);recharge.setFriendpoolsId(user.getFriendpoolsId());recharge.setOrderCreateTime(new Date());recharge.setOrderMoney(Double.valueOf(money));recharge.setOrderStatus(1); //预缓存recharge.setOrderSystemPercentage(Const.SYSTEMPERCENTAGE);recharge.setUserId(Integer.valueOf(userId));json = (JSONObject) JSON.toJSON(recharge);num = PayConfigUtil.WXPAYHash.hSet(orderId.toString(), json.toJSONString());if(num == 0L){FileUtils.addDebugLog("订单入redis失败,请检查redis的状态");}else{flag =true;}}} catch (Exception e) {System.out.println("充值订单入Redis报错:"+e.getMessage());e.printStackTrace();}return flag;}

二、微信支付回调

2.1 个人思路:用户前台扫描支付二维码后,将扫描到的数据提交到微信系统,微信系统根据商户预设的后台回调地址,将订单productid回传,后台接收到以后,根据productid去redis中查询预存的订单。然后调用微信统一下单接口,下单完成后向商户系统数据库中插入一条充值订单!

微信下单接口:https://api.mch./pay/unifiedorder

/*** 微信支付回调* -09-06* @param request* @param response*/@SuppressWarnings("unchecked")@RequestMapping(value = "/wxPayCallBack",method=RequestMethod.POST)public void wxPayCallBack(HttpServletRequest request,HttpServletResponse response)throws Exception{InputStream stream = request.getInputStream();ByteArrayOutputStream outStream = new ByteArrayOutputStream();byte[] buff = new byte[1024];int len = 0;while((len = stream.read(buff)) !=-1){outStream.write(buff, 0, len); }outStream.close();stream.close();String result = new String(outStream.toByteArray(),"utf-8");Map<Object, Object> map=null;JSONObject object=new JSONObject();try {map = PayXmlUtil.doXMLParse(result);for(Object keyVal :map.entrySet()){System.out.println(keyVal+"="+map.get(keyVal)); }String orderId = map.get("product_id").toString();if(PayConfigUtil.WXPAYHash.hExists(orderId)){String value = PayConfigUtil.WXPAYHash.hGet(orderId);OrderRecharge recharge=new OrderRecharge();recharge = JSON.parseObject(value,OrderRecharge.class);recharge.setOrderStatus(0);// 调用微信统一下单接口boolean flag = getUnifiedorder(response,orderId,recharge.getOrderMoney(),request.getRemoteAddr());if(flag){orderService.addOrderRecharge(recharge);object = (JSONObject) JSON.toJSON(recharge);PayConfigUtil.WXPAYHash.hSet(orderId, object.toJSONString());}}} catch (Exception e) {e.printStackTrace();}}/*** 微信支付统一下单* -09-06* @param response* @param orderId* @param orderMoney* @param remoteAddr* @return*/@SuppressWarnings("unchecked")private boolean getUnifiedorder(HttpServletResponse response,String orderId, Double orderMoney, String remoteAddr) {boolean flag=true;SortedMap<Object, Object> sorte = new TreeMap<Object, Object>();sorte.put("appid", PayConfigUtil.APPID);//公众账号IDsorte.put("mch_id", PayConfigUtil.MCH_ID);//商户号IDsorte.put("nonce_str", PayCommonUtil.CreateNoncestr()); //随机字符串sorte.put("body", PayConfigUtil.BODY);//商品描述sorte.put("out_trade_no", orderId); //商户订单号sorte.put("total_fee", (int) (orderMoney*100)); //标价金额(分)sorte.put("spbill_create_ip", remoteAddr); //终端IPsorte.put("notify_url", PayConfigUtil.NOTIFY_URL); //支付成功通知地址sorte.put("trade_type", PayConfigUtil.TRADE_TYPE); //交易类型String sign = PayCommonUtil.createSign("UTF-8", sorte); sorte.put("sign", sign); //随机字符串String requestXML = PayCommonUtil.getRequestXml(sorte);String result2 = PayCommonUtil.httpsRequestSSL(PayConfigUtil.UNIFIED_ORDER_URL,"POST", requestXML);FileUtils.addDebugLog("-----------------------------微信统一下单结果---------------------------");FileUtils.addDebugLog("返回参数:"+result2);Map<String, String> resMap=null;try {resMap=PayXmlUtil.doXMLParse(result2);String result_code = resMap.get("result_code");String err_code_des = resMap.get("err_code_des");if("FAIL".equals(result_code)){flag = false;FileUtils.addDebugLog("-----------------------------微信统一下单结果---------------------------");FileUtils.addDebugLog("下单失败...");FileUtils.addDebugLog("失败原因:"+err_code_des);}//返回给微信SortedMap<Object, Object> rMap = new TreeMap<Object, Object>();rMap.put("return_code", resMap.get("return_code"));rMap.put("appid", resMap.get("appid"));rMap.put("mch_id", resMap.get("mch_id"));rMap.put("nonce_str", resMap.get("nonce_str"));rMap.put("prepay_id", resMap.get("prepay_id"));rMap.put("result_code", result_code);String rSign = PayCommonUtil.createSign("UTF-8", rMap); rMap.put("sign", rSign);String resXml = PayCommonUtil.getRequestXml(rMap);FileUtils.addDebugLog("-----------------------------返回微信参数---------------------------");FileUtils.addDebugLog("返回参数为:"+resXml);response.getWriter().println(resXml);} catch (Exception e) {e.printStackTrace();}return flag;}

三、微信支付结果通知

3.1 收到微信支付结果的通知后,根据订单id修改数据库中订单状态,进行相关入库操作,然后删除redis中的预存的订单(也可以不删除,只修改其支付状态保留,后面前台查询的时候。先查询redis中的支付状态,要是没有支付,则调用微信查询是否已经支付成功,进行页面相关提示!)

/*** 微信支付结果通知* @param request* @param response*/@SuppressWarnings("unchecked")@RequestMapping(value = "/wxPayResult",method = RequestMethod.POST)public void wxPayResult(HttpServletRequest request,HttpServletResponse response) throws Exception{SortedMap<Object, Object> sort = new TreeMap<Object, Object>();InputStream stream = request.getInputStream();ByteArrayOutputStream outStream = new ByteArrayOutputStream();byte[] buff = new byte[1024];int len = 0;try {while((len = stream.read(buff)) !=-1){outStream.write(buff, 0, len); }outStream.close();stream.close();} catch (IOException e) {FileUtils.addDebugLog("----------------------微信支付结果通知----------------------");FileUtils.addDebugLog("结果回调失败:"+e.getMessage());e.printStackTrace();}String result = new String(outStream.toByteArray(),"utf-8");Map<Object, Object> map=null;OrderRecharge recharge=new OrderRecharge();try {map = PayXmlUtil.doXMLParse(result);FileUtils.addDebugLog("----------------------微信支付结果通知----------------------");FileUtils.addDebugLog("结果参数:"+map);String return_code = map.get("return_code").toString();String orderId=null;String result_code=null;boolean flag =false;int num=0;if("SUCCESS".equals(return_code)){orderId = map.get("out_trade_no").toString();result_code =map.get("result_code").toString();if("SUCCESS".equals(result_code)){num = 2;}if(PayConfigUtil.WXPAYHash.hExists(orderId)){String value = PayConfigUtil.WXPAYHash.hGet(orderId);recharge = JSON.parseObject(value,OrderRecharge.class);//flag=orderService.updateRecharge(recharge.getUserId(),orderId,num,recharge.getOrderMoney());if(flag){PayConfigUtil.WXPAYHash.hDel(orderId);}}}else{String return_msg = map.get("return_msg").toString();FileUtils.addDebugLog("微信支付结果回调失败:"+return_msg);}// 通知微信已接收到结果sort.put("return_code","SUCCESS");String resMap = PayCommonUtil.getRequestXml(sort);response.getWriter().println(resMap);} catch (Exception e) {FileUtils.addDebugLog("----------------------微信支付结果解析异常----------------------");FileUtils.addDebugLog("异常原因:"+e.getMessage());e.printStackTrace();}}

四、查询订单

4.1、页面前台通过ajax轮询查询订单支付结果,进行相关页面跳转

微信查询接口:https://api.mch./pay/orderquery

/*** 查询订单* -09-06 17:16:16* @param request* @param response*/@SuppressWarnings("unchecked")@RequestMapping(value ="/getWxPayOrderStatus")public void getWxPayOrderStatus(HttpServletRequest request,HttpServletResponse response) throws Exception{HttpSession session=request.getSession();JSONObject json =new JSONObject();SortedMap<Object, Object> sortMap=new TreeMap<Object, Object>();String orderId = request.getParameter("orderId");String userId = session.getAttribute("userId").toString();boolean flag =false;double money = 0.00;if(StringUtils.isNotBlank(orderId)){sortMap.put("appid", PayConfigUtil.APPID);sortMap.put("mch_id", PayConfigUtil.MCH_ID);sortMap.put("out_trade_no", orderId);sortMap.put("nonce_str", PayCommonUtil.CreateNoncestr());String value = PayCommonUtil.createSign("UTF-8",sortMap);sortMap.put("sign", value);String resXml = PayCommonUtil.getRequestXml(sortMap);String result = PayCommonUtil.httpsRequestSSL(PayConfigUtil.CHECK_ORDER_URL, "POST", resXml);System.out.println("-------------------查询订单支付结果----------------------");System.out.println("结果参数:"+result);Map<String, String> map =null;try {map = PayXmlUtil.doXMLParse(result);String return_code = map.get("return_code");String trade_state = map.get("trade_state");int num = 0;if("SUCCESS".equals(return_code)){if("SUCCESS".equals(trade_state)){flag = true;num = 2;if(PayConfigUtil.WXPAYHash.hExists(orderId)){String val = PayConfigUtil.WXPAYHash.hGet(orderId);OrderRecharge recharge = JSON.parseObject(val,OrderRecharge.class);flag=orderService.updateRecharge(recharge.getUserId(),orderId,num,recharge.getOrderMoney());if(flag){PayConfigUtil.WXPAYHash.hDel(orderId);}}User user = userService.getUserById(Integer.valueOf(userId));if(user !=null){money =user.getRechargeRest();}json.put("money", money);}}} catch (Exception e) {FileUtils.addDebugLog("----------------------查询订单支付结果----------------------");FileUtils.addDebugLog("查询失败:"+e.getMessage());e.printStackTrace();}json.put("flag", flag);response.getWriter().println(json.toJSONString());}}

五、相关工具类

5.1、PayCommonUtil

import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import .ConnectException;import .URL;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Random;import java.util.Set;import java.util.SortedMap;import .ssl.HttpsURLConnection;import .ssl.SSLContext;import .ssl.SSLSocketFactory;import .ssl.TrustManager;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.google.zxing.BarcodeFormat;import com.google.zxing.EncodeHintType;import com.google.zxing.MultiFormatWriter;import com.mon.BitMatrix;/*** 微信支付工具* -09-06 16:16:16* @author dayun.wang**/public class PayCommonUtil {private static Logger log = LoggerFactory.getLogger(PayCommonUtil.class);/*** 随机数生成* @param length* @return*/public static String CreateNoncestr(int length) {String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";String res = "";for (int i = 0; i < length; i++) {Random rd = new Random();res += chars.indexOf(rd.nextInt(chars.length() - 1));}return res;}/*** 十六位随机数生成* @return*/public static String CreateNoncestr() {String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";String res = "";for (int i = 0; i < 16; i++) {Random rd = new Random();res += chars.charAt(rd.nextInt(chars.length() - 1));}return res;}/*** 创建sign值* -09-06 16:16:16* characterEncoding* parameters* @return*/@SuppressWarnings("rawtypes")public static String createSign(String characterEncoding,SortedMap<Object,Object> parameters){StringBuffer sb = new StringBuffer();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=" + PayConfigUtil.API_KEY);String sign = PayMd5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();return sign;}/*** 将请求参数转换为xml格式的string* -09-06 16:16:16* parameters* @return*/@SuppressWarnings("rawtypes")public static String getRequestXml(SortedMap<Object,Object> parameters){StringBuffer sb = new StringBuffer();sb.append("<xml>");Set es = parameters.entrySet();Iterator it = es.iterator();while(it.hasNext()) {Map.Entry entry = (Map.Entry)it.next();String k = (String)entry.getKey();String v = String.valueOf(entry.getValue());if ("attach".equalsIgnoreCase(k)||"body".equalsIgnoreCase(k)||"sign".equalsIgnoreCase(k)) {sb.append("<"+k+">"+"<![CDATA["+v+"]]></"+k+">");}else {sb.append("<"+k+">"+v+"</"+k+">");}}sb.append("</xml>");return sb.toString();}/*** 返回给微信的参数格式* -09-06 16:16:16* @param return_code* @param return_msg* @return*/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>";}/*** 创建SSL安全链接访问* -09-06* @param requestUrl* @param method* @param requestXML* @return*/public static String httpsRequestSSL(String requestUrl, String method, String requestXML) {try {// 创建SSLContext对象,并使用我们指定的信任管理器初始化TrustManager[] tm = { new MyX509TrustManager() };SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");sslContext.init(null, tm, new java.security.SecureRandom());SSLSocketFactory ssf = sslContext.getSocketFactory();URL url = new URL(requestUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setSSLSocketFactory(ssf);conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);conn.setRequestMethod(method);conn.setRequestProperty("content-type", "application/x-www-form-urlencoded");if (requestXML != null) {OutputStream outputStream = conn.getOutputStream();outputStream.write(requestXML.getBytes("UTF-8"));outputStream.close();}InputStream inputStream = conn.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");BufferedReader bufferedReader = new BufferedReader(inputStreamReader);String str = null;StringBuffer buffer = new StringBuffer();while ((str = bufferedReader.readLine()) != null) {buffer.append(str);}bufferedReader.close();inputStreamReader.close();inputStream.close();inputStream = null;conn.disconnect();return buffer.toString();} catch (ConnectException ce) {log.error("连接超时:{}", ce);} catch (Exception e) {log.error("https请求异常:{}", e);}return null;}/*** 生成二维码图片* -09-06* @param text* @param response* * @throws Exception*/@SuppressWarnings({ "unchecked", "rawtypes" })public static String createCodeStream(String text) throws Exception{ int width = 180; int height = 180; String format = "jpg"; MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); Map hints = new HashMap(); //内容所使用编码 hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); BitMatrix bitMatrix = multiFormatWriter.encode(text, BarcodeFormat.QR_CODE, width, height, hints); //生成二维码 String value=MatrixToImageWriter.writeToStream(bitMatrix, format);// sos.close();return value;}}

5.2、MatrixToImageWriter

import java.awt.image.BufferedImage;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;import com.mon.BitMatrix;import sun.misc.BASE64Encoder;/*** 生成二维码工具* -09-06* @author Administrator**/public class MatrixToImageWriter {private static final int BLACK = 0xFF000000;private static final int WHITE = 0xFFFFFFFF;public MatrixToImageWriter() {}public static BufferedImage toBufferedImage(BitMatrix matrix) {int width = matrix.getWidth();int height = matrix.getHeight();BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);for (int x = 0; x < width; x++) {for (int y = 0; y < height; y++) {image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);}}return image;}public static void writeToFile(BitMatrix matrix, String format, File file)throws IOException {BufferedImage image = toBufferedImage(matrix);if (!ImageIO.write(image, format, file)) {throw new IOException("Could not write an image of format " + format + " to " + file);}}public static String writeToStream(BitMatrix matrix, String format) throws IOException {BufferedImage image = toBufferedImage(matrix);ByteArrayOutputStream os=new ByteArrayOutputStream();ImageIO.write(image, format, os);byte[] b=os.toByteArray();String value=new BASE64Encoder().encode(b);return value;}}

5.3、PayMd5Util

import java.security.MessageDigest;public class PayMd5Util {private static String byteArrayToHexString(byte b[]) {StringBuffer resultSb = new StringBuffer();for (int i = 0; i < b.length; i++)resultSb.append(byteToHexString(b[i]));return resultSb.toString();}private static String byteToHexString(byte b) {int n = b;if (n < 0)n += 256;int d1 = n / 16;int d2 = n % 16;return hexDigits[d1] + hexDigits[d2];}public static String MD5Encode(String origin, String charsetname) {String resultString = null;try {resultString = new String(origin);MessageDigest md = MessageDigest.getInstance("MD5");if (charsetname == null || "".equals(charsetname))resultString = byteArrayToHexString(md.digest(resultString.getBytes()));elseresultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));} catch (Exception exception) {}return resultString;}/*** 生成 MD5** @param data 待处理数据* @return MD5结果*/public static String MD5(String data) throws Exception {java.security.MessageDigest md = MessageDigest.getInstance("MD5");byte[] array = md.digest(data.getBytes("UTF-8"));StringBuilder sb = new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));}return sb.toString().toUpperCase();}private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5","6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };}

5.4、PayXmlUtil

import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.jdom.Document;import org.jdom.Element;import org.jdom.JDOMException;import org.jdom.input.SAXBuilder;public class PayXmlUtil {/*** 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。* @param strxml* @return* @throws JDOMException* @throws IOException*/@SuppressWarnings({ "rawtypes", "unchecked" })public static Map doXMLParse(String strxml) throws JDOMException, IOException {strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");if(null == strxml || "".equals(strxml)) {return null;}Map m = new HashMap();InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));SAXBuilder builder = new SAXBuilder();Document doc = builder.build(in);Element root = doc.getRootElement();List list = root.getChildren();Iterator it = list.iterator();while(it.hasNext()) {Element e = (Element) it.next();String k = e.getName();String v = "";List children = e.getChildren();if(children.isEmpty()) {v = e.getTextNormalize();} else {v = PayXmlUtil.getChildrenText(children);}m.put(k, v);}//关闭流in.close();return m;}/*** 获取子结点的xml* @param children* @return String*/@SuppressWarnings("rawtypes")public static String getChildrenText(List children) {StringBuffer sb = new StringBuffer();if(!children.isEmpty()) {Iterator it = children.iterator();while(it.hasNext()) {Element e = (Element) it.next();String name = e.getName();String value = e.getTextNormalize();List list = e.getChildren();sb.append("<" + name + ">");if(!list.isEmpty()) {sb.append(PayXmlUtil.getChildrenText(list));}sb.append(value);sb.append("</" + name + ">");}}return sb.toString();}}

5.5、MyX509TrustManager

import java.security.cert.CertificateException;import java.security.cert.X509Certificate;import .ssl.X509TrustManager;public class MyX509TrustManager implements X509TrustManager {public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }

PS:结合微信文档以及网上相关资料来完成的,不足之处,望谅解....

开发不难,更多的是一颗学习的心!

新用户一年只要99.5元,/act/team1111/#/share?params=N.EN2hxhpNQG.d1ru6ogl

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。