java 二维码_Java对接微信二维码支付

整体的实现思路:自定义一个接口,用于生成二维码展示到页面,此时需要用到微信提供的sdk,以及自己的一些业务数据,比如:金额等;再定义一个异步通知接口,用于微信回调访问,同时可以处理一些业务数据及流水记录等。

1.下载sdk

2.引入sdk相关代码

3.整体代码实现如下:

控制层:

DemoController:一个Demo的入口;两个重要的方法,一个是生成二维码的请求,另一个是异步获取业务的状态(该订单支付完成的状态),当然也可以采用socket的方式,此例子为了简单化只用了setInterval,该代码在index.html

package com.example.demo.controller;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.ResponseBody;import com.example.demo.pay.service.impl.WxCreatePaySerivceImpl;import com.example.demo.service.ProductorService;import com.example.demo.service.Productorder;import com.example.demo.service.ResultMap;@Controllerpublic class DemoController {@Autowiredprivate WxCreatePaySerivceImpl createPaySerivce;@Autowiredprivate ProductorService productorService;@GetMapping("/")public String hello() {System.out.println("hello world!");return "index";}@GetMapping("/cpsPay")public void cpsPay(HttpServletRequest request,HttpServletResponse response) {System.out.println("cpsPay!");try {String ac = request.getParameter("ac");if("wxpay".equals(ac)) {createPaySerivce.doCreate(request, response);}} catch (Exception e) {e.printStackTrace();}}@PostMapping("/payStatus")@ResponseBodypublic Map payStatus(HttpServletRequest request,HttpServletResponse response) {System.out.println("payStatus!");try {Productorder productorder = productorService.getById(request.getParameter("orderno"));if("1".equals(productorder.getOrderstatus())) {return ResultMap.successRes();}} catch (Exception e) {e.printStackTrace();}return ResultMap.errorRes("error");}}

WxCallbackController: 用户微信异步通知的接口,该url会配置到下面的ConfigUtil类中

package com.example.demo.controller;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.math.BigDecimal;import java.text.SimpleDateFormat;import java.util.HashMap;import java.util.Map;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import com.example.demo.pay.util.ConfigUtil;import com.example.demo.service.ProductorService;import com.example.demo.service.Productorder;import com.example.demo.service.wxpay.sdk.WXPayUtil;public class WxCallbackController {@Autowiredprivate ProductorService productorService;@RequestMapping(value="/notifyWxPay",produces="text/html;charset=utf-8")@ResponseBody    public String notifyWxPay(HttpServletRequest request, HttpServletResponse response) throws Exception {Map return_data = new HashMap();InputStream inputStream ;          StringBuffer sb = new StringBuffer();          inputStream = request.getInputStream();          String s ;          BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));          while ((s = in.readLine()) != null){              sb.append(s);          }          in.close();          inputStream.close();            //解析xml成map          Map map = WXPayUtil.xmlToMap(sb.toString());        //判断签名是否正确   //        if(true) {                if(WXPayUtil.isSignatureValid(map, ConfigUtil.API_KEY)) {        if(!map.get("return_code").toString().equals("SUCCESS")){        return_data.put("return_code", "FAIL");        return_data.put("return_msg", "return_code不正确");        }else{                if(!map.get("result_code").toString().equals("SUCCESS")){            return_data.put("return_code", "FAIL");            return_data.put("return_msg", "result_code不正确");            return WXPayUtil.mapToXml(return_data);            }                            String orderno = (String)map.get("out_trade_no");//商户订单号                String transaction_id = (String)map.get("transaction_id");//微信支付订单号                 String time_end = (String)map.get("time_end");//支付完成时间yyyyMMddHHmmss                BigDecimal total_fee = new BigDecimal(map.get("total_fee").toString());                //付款完成后,支付宝系统发送该交易状态通知                Productorder order = productorService.getById(orderno);                if(order==null) {                System.out.println("订单不存在");                    return_data.put("return_code", "FAIL");                    return_data.put("return_msg", "订单不存在");                    return WXPayUtil.mapToXml(return_data);                }                                BigDecimal num = new BigDecimal("100");                  BigDecimal ordermoney = new BigDecimal(order.getOrdermoney());                ordermoney  = ordermoney.multiply(num);                //订单已经支付                if(order.getOrderstatus().equals("1")){                    System.out.println("订单已经支付");                    return_data.put("return_code", "SUCCESS");                    return_data.put("return_msg", "OK");                    return WXPayUtil.mapToXml(return_data);                }                //如果支付金额不等于订单金额返回错误                if(ordermoney.compareTo(total_fee)!=0){                System.out.println("资金异常");                    return_data.put("return_code", "FAIL");                    return_data.put("return_msg", "金额异常");                    return WXPayUtil.mapToXml(return_data);                }                //更新订单信息                try {                System.out.println("更新订单信息");                SimpleDateFormat sdf1=new SimpleDateFormat("yyyyMMddHHmmss");            SimpleDateFormat sdf2=new SimpleDateFormat("YYYY-MM-dd hh:mm:ss");                order.setOrderstatus("1");                order.setPaytime(sdf2.format(sdf1.parse(time_end)));                order.setPaymentway("1");                productorService.update(order);                                System.out.println("插入已经支付的订单表");                //插入支付流水TODO                                return_data.put("return_code", "SUCCESS");                    return_data.put("return_msg", "OK");                    return WXPayUtil.mapToXml(return_data);} catch (Exception e) {e.printStackTrace();return_data.put("return_code", "FAIL");                    return_data.put("return_msg", "更新订单失败");                    return WXPayUtil.mapToXml(return_data);}        }        } else{              System.out.println("通知签名验证失败");            return_data.put("return_code", "FAIL");        return_data.put("return_msg", "签名错误");        }          return WXPayUtil.mapToXml(return_data);}}

工具类及服务:

CommonUtil:一个通用的工具类

package com.example.demo.pay.util;import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.Inet4Address;import java.net.InetAddress;import java.net.URL;import java.net.UnknownHostException;import java.text.ParseException;import java.text.SimpleDateFormat;import java.util.Date;import javax.net.ssl.HttpsURLConnection;import javax.servlet.http.HttpServletRequest;import org.springframework.util.StringUtils; public class CommonUtil {public static String httpsRequest(String requestUrl, String requestMethod, String outputStr) {try {URL url = new URL(requestUrl);HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();conn.setDoOutput(true);conn.setDoInput(true);conn.setUseCaches(false);// 设置请求方式(GET/POST)conn.setRequestMethod(requestMethod);conn.setRequestProperty("content-type", "application/x-www-form-urlencoded"); // 当outputStr不为null时向输出流写数据if (null != outputStr) {OutputStream outputStream = conn.getOutputStream();// 注意编码格式outputStream.write(outputStr.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 (Exception e) {e.printStackTrace();}return null;}/** * 获取ip * @param request * @return */public static String getIp(HttpServletRequest request) {if (request == null)return "";String ip = request.getHeader("X-Requested-For");if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("X-Forwarded-For");}if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");}if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");}if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");}if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");}if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();}return ip;}public static String getOrderExpireTime(String timeStart, long l) {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");try {Date date = sdf.parse(timeStart);Long lastTime = date.getTime() + l;return sdf.format(new Date(lastTime));} catch (ParseException e) {e.printStackTrace();}return null;}public static String getLocalIp(){InetAddress localHost = null;try {  localHost = Inet4Address.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}String ip = localHost.getHostAddress();return ip;}}

ConfigUtil:用于定义一些对接时必须的参数,涉及到多商户或者多微信时,以下可以做成动态的参数

package com.example.demo.pay.util;public class ConfigUtil {/** * 服务号相关信息 */public final static String APPID = "";// 服务号的应用号public final static String MCH_ID = "";// 商户号public final static String APP_SECRECT = "";// 服务号的应用密码public final static String API_KEY = "";// API密钥 自己定义的public final static String SIGN_TYPE = "MD5";// 签名加密方式public final static String CERT_PATH = "D:/project/cert/apiclient_cert.p12";// 微信支付证书存放路径地址public final static String TOKEN = "";// 服务号的配置token// 填写自己网站的接口public final static String NOTIFY_URL = "notifyWxPay";// 微信支付统一接口的回调actionpublic static final String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";}

服务层:

BaseService:在这里能够获取到需要的基础信息

package com.example.demo.pay.service;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.core.env.Environment;import org.springframework.stereotype.Service;import com.example.demo.pay.util.CommonUtil;@Servicepublic class BaseService {Logger logger = LoggerFactory.getLogger(this.getClass());@AutowiredEnvironment environment;public String getLocalPort(){  return environment.getProperty("local.server.port");}public String getContextPath(){  return environment.getProperty("server.servlet.context-path");}public String getLocalIp(){return CommonUtil.getLocalIp();}public String getLocalOutNetUrl(){return environment.getProperty("local.outnet.url");}public String getLocalContextPath(){String contextPath = this.getLocalOutNetUrl() + this.getContextPath() + "/";System.out.println("local context path:" + contextPath);return contextPath;}}

ICreatePayService:支付的对接接口,为以后会涉及到多方对接,故采用接口方式

package com.example.demo.pay.service;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public interface ICreatePayService {public void doCreate(HttpServletRequest request, HttpServletResponse response) throws Exception ;}

WxCreatePaySerivceImpl:上面接口的微信对接实现类

package com.example.demo.pay.service.impl;import java.text.DecimalFormat;import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date;import java.util.Hashtable;import java.util.Map;import java.util.SortedMap;import java.util.TreeMap;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.example.demo.pay.service.BaseService;import com.example.demo.pay.service.ICreatePayService;import com.example.demo.pay.util.CommonUtil;import com.example.demo.pay.util.ConfigUtil;import com.example.demo.service.Productorder;import com.example.demo.service.wxpay.sdk.WXPayConstants.SignType;import com.example.demo.service.wxpay.sdk.WXPayUtil;import com.google.zxing.BarcodeFormat;import com.google.zxing.EncodeHintType;import com.google.zxing.MultiFormatWriter;import com.google.zxing.client.j2se.MatrixToImageWriter;import com.google.zxing.common.BitMatrix;@Service("wxpayCreatePaySerivce")public class WxCreatePaySerivceImpl implements ICreatePayService{@Autowiredprivate BaseService baseService;@Overridepublic void doCreate(HttpServletRequest request, HttpServletResponse response) throws Exception {String orderno = request.getParameter("orderno") == null ? "" : request.getParameter("orderno");Productorder p = new Productorder();Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");String timeStart = sdf.format(date);Calendar cal = Calendar.getInstance();cal.add(Calendar.DAY_OF_MONTH, 1);Date date1 = cal.getTime();String timeExpire = sdf.format(date1);SortedMap parameters = new TreeMap();parameters.put("appid", ConfigUtil.APPID);parameters.put("body", p.getPname());parameters.put("mch_id", ConfigUtil.MCH_ID);parameters.put("out_trade_no", orderno);parameters.put("spbill_create_ip", CommonUtil.getIp(request));DecimalFormat df = new DecimalFormat("#");parameters.put("total_fee", df.format(Double.parseDouble(p.getOrdermoney()) * 100));parameters.put("trade_type", "NATIVE");parameters.put("time_expire", CommonUtil.getOrderExpireTime(timeStart,5 * 60 * 1000L));// 二维码过期时间5分钟parameters.put("nonce_str", WXPayUtil.generateNonceStr());parameters.put("notify_url", baseService.getLocalContextPath() + ConfigUtil.NOTIFY_URL);// 支付成功后回调的action,与JSAPI相同String generateSignature = WXPayUtil.generateSignature(parameters, ConfigUtil.API_KEY, SignType.MD5);parameters.put("sign", generateSignature);String generateSignedXml = WXPayUtil.generateSignedXml(parameters, ConfigUtil.API_KEY);System.out.println("微信支付预下单请求xml格式::" + generateSignedXml);String result = CommonUtil.httpsRequest(ConfigUtil.UNIFIED_ORDER_URL, "POST", generateSignedXml);System.out.println(result);Map map;try {map = WXPayUtil.xmlToMap(result);String returnCode = map.get("return_code");String resultCode = map.get("result_code");//returnCode = "SUCCESS";//resultCode = "SUCCESS";if (returnCode.equalsIgnoreCase("SUCCESS") && resultCode.equalsIgnoreCase("SUCCESS")) {String codeUrl = map.get("code_url");//codeUrl = "testurl";// TODO 拿到codeUrl,写代码生成二维码System.out.println("codeUrl=" + codeUrl);int width = 300;int height = 300;// 二维码的图片格式String format = "JPEG";Hashtable hints = new Hashtable();// 内容所使用编码hints.put(EncodeHintType.CHARACTER_SET, "utf-8");BitMatrix bitMatrix = new MultiFormatWriter().encode(codeUrl, BarcodeFormat.QR_CODE, width, height,hints);// response.setContentType("image/JPEG");MatrixToImageWriter.writeToStream(bitMatrix, format, response.getOutputStream());}} catch (Exception e) {e.printStackTrace();}}}

index.html 生成二维码页面

Insert title here首页

pom.xml

<?xml version="1.0" encoding="UTF-8"?>4.0.0org.springframework.bootspring-boot-starter-parent2.1.13.RELEASEcom.exampledemo0.0.1-SNAPSHOTdemoDemo project for Spring Boot1.8org.springframework.bootspring-boot-starter-weborg.springframework.bootspring-boot-devtoolsruntimetrueorg.apache.httpcomponents            httpclient            4.5.3org.slf4j            slf4j-api            1.7.5org.slf4j            slf4j-simple            1.7.21org.springframework.boot    spring-boot-starter-thymeleafcom.google.zxing    core    3.3.0com.google.zxing    javase    3.2.1The BSD 3-Clause Licensehttps://opensource.org/licenses/BSD-3-Clauserepowxpayhttps://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=11_1releaseosshttps://oss.sonatype.org/content/repositories/snapshots/osshttps://oss.sonatype.org/service/local/staging/deploy/maven2/org.apache.maven.plugins                        maven-source-plugin                        3.0.1packagejar-no-forkorg.apache.maven.plugins                        maven-javadoc-plugin                        2.10.4packagejarorg.apache.maven.plugins                        maven-gpg-plugin                        1.6sign-artifactsverifysignorg.springframework.bootspring-boot-maven-plugin

该例子只适用于对接微信二维码支付,给没有对接过支付接口的童鞋一些参考,老鸟可以忽略,大宝六

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值