微信二维码支付

一、创建微服务

1、导入依赖



    com.github.wxpay
    wxpay-sdk
    0.0.3


    
    org.apache.httpcomponents
    httpclient

2、需要的工具类

HttpClient:http/https相关操作

public class HttpClient {
     
    private String url;
    private Map<String, String> param;
    private int statusCode;
    private String content;
    private String xmlParam;
    private boolean isHttps;

    public boolean isHttps() {
     
        return isHttps;
    }

    public void setHttps(boolean isHttps) {
     
        this.isHttps = isHttps;
    }

    public String getXmlParam() {
     
        return xmlParam;
    }

    public void setXmlParam(String xmlParam) {
     
        this.xmlParam = xmlParam;
    }

    public HttpClient(String url, Map<String, String> param) {
     
        this.url = url;
        this.param = param;
    }

    public HttpClient(String url) {
     
        this.url = url;
    }

    public void setParameter(Map<String, String> map) {
     
        param = map;
    }

    public void addParameter(String key, String value) {
     
        if (param == null)
            param = new HashMap<String, String>();
        param.put(key, value);
    }

    public void post() throws ClientProtocolException, IOException {
     
        HttpPost http = new HttpPost(url);
        setEntity(http);
        execute(http);
    }

    public void put() throws ClientProtocolException, IOException {
     
        HttpPut http = new HttpPut(url);
        setEntity(http);
        execute(http);
    }

    public void get() throws ClientProtocolException, IOException {
     
        if (param != null) {
     
            StringBuilder url = new StringBuilder(this.url);
            boolean isFirst = true;
            for (String key : param.keySet()) {
     
                if (isFirst) {
     
                    url.append("?");
                }else {
     
                    url.append("&");
                }
                url.append(key).append("=").append(param.get(key));
            }
            this.url = url.toString();
        }
        HttpGet http = new HttpGet(url);
        execute(http);
    }

    /**
     * set http post,put param
     */
    private void setEntity(HttpEntityEnclosingRequestBase http) {
     
        if (param != null) {
     
            List<NameValuePair> nvps = new LinkedList<NameValuePair>();
            for (String key : param.keySet()) {
     
                nvps.add(new BasicNameValuePair(key, param.get(key))); // 参数
            }
            http.setEntity(new UrlEncodedFormEntity(nvps, Consts.UTF_8)); // 设置参数
        }
        if (xmlParam != null) {
     
            http.setEntity(new StringEntity(xmlParam, Consts.UTF_8));
        }
    }

    private void execute(HttpUriRequest http) throws ClientProtocolException,
            IOException {
     
        CloseableHttpClient httpClient = null;
        try {
     
            if (isHttps) {
     
                SSLContext sslContext = new SSLContextBuilder()
                        .loadTrustMaterial(null, new TrustStrategy() {
     
                            // 信任所有
                            @Override
                            public boolean isTrusted(X509Certificate[] chain,
                                                     String authType)
                                    throws CertificateException {
     
                                return true;
                            }
                        }).build();
                SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                        sslContext);
                httpClient = HttpClients.custom().setSSLSocketFactory(sslsf)
                        .build();
            } else {
     
                httpClient = HttpClients.createDefault();
            }
            CloseableHttpResponse response = httpClient.execute(http);
            try {
     
                if (response != null) {
     
                    if (response.getStatusLine() != null) {
     
                        statusCode = response.getStatusLine().getStatusCode();
                    }
                    HttpEntity entity = response.getEntity();
                    // 响应内容
                    content = EntityUtils.toString(entity, Consts.UTF_8);
                }
            } finally {
     
                response.close();
            }
        } catch (Exception e) {
     
            e.printStackTrace();
        } finally {
     
            httpClient.close();
        }
    }

    public int getStatusCode() {
     
        return statusCode;
    }

    public String getContent() throws ParseException, IOException {
     
        return content;
    }
}

3、配置文件:application.yml

server:
  port: 18090
spring:
  application:
    name: pay
  main:
    allow-bean-definition-overriding: true
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
#hystrix 配置
hystrix:
  command:
    default:
      execution:
        timeout:
          #如果enabled设置为false,则请求超时交给ribbon控制
          enabled: true
        isolation:
          strategy: SEMAPHORE

#微信支付信息配置
weixin:
  #应用ID
  appid: wx8397f8696b538317
  #商户号
  partner: 1473426802
  #密钥
  partnerkey: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
  #支付回调地址 通知地址
  notifyurl: https://www.cnblogs.com/chawaner/

4、SpringBoot启动类

/**
 * @Author TeaBowl
 * @Date 2021/2/1 10:47
 * @Version 1.0
 */
@SpringBootApplication(exclude = {
     DataSourceAutoConfiguration.class})
@EnableEurekaClient
public class WeiXinPayApplication {
     
    public static void main(String[] args) {
     
        SpringApplication.run(WeiXinPayApplication.class,args);
    }
}

5、控制层

/**
 * @Author TeaBowl
 * @Date 2021/2/1 12:01
 * @Version 1.0
 */
@RestController
@RequestMapping(value = "/weixin/pay")
public class WeiXinPayController {
     

    @Autowired
    private WeixinPayService weixinPayService;

    /**
     * 创建二维码
     * @param parameterMap:用户订单信息
     * @return
     */
    @RequestMapping(value = "/create/native")
    public Result createNative(@RequestParam Map<String,String> parameterMap){
     
        Map<String,String> resultMap = weixinPayService.createnative(parameterMap);
        return new Result(true, StatusCode.OK,"创建二维码预付订单成功!",resultMap);
    }
}

6、应用层

/**
 * @Author TeaBowl
 * @Date 2021/2/1 11:01
 * @Version 1.0
 */
public interface WeixinPayService {
     
    /**
     * 创建二维码
     * @param parameterMap:用户订单信息
     * @return
     */
    Map createnative(Map<String,String> parameterMap);
}
/**
 * @Author TeaBowl
 * @Date 2021/2/1 11:00
 * @Version 1.0
 */
@Service
public class WeixinPayServiceImpl implements WeixinPayService {
     

    //应用ID
    @Value("${weixin.appid}")
    private String appid;
    //商户号
    @Value("${weixin.partner}")
    private String partner;
    //密钥
    @Value("${weixin.partnerkey}")
    private String partnerkey;
    //通知地址
    @Value("${weixin.notifyurl}")
    private String notifyurl;

    /**
     * 创建二维码
     *
     * @param parameterMap:用户订单信息
     * @return
     */
    @Override
    public Map createnative(Map<String, String> parameterMap) {
     
        try {
     
            //远程调用
            //创建一个Map集合存放请求参数
            Map<String, String> paramMap = new HashMap<>();
            //添加数据
            //应用ID
            paramMap.put("appid", appid);
            //商户号
            paramMap.put("mch_id", partner);
            //随机字符串
            paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
            //商品描述
            paramMap.put("body", "茶碗儿购物是真的好");
            //订单号
            paramMap.put("out_trade_no", parameterMap.get("outtradeno"));
            //交易总金额,单位为:分
            paramMap.put("total_fee", parameterMap.get("totalfee"));
            //终端IP
            paramMap.put("spbill_create_ip", "127.0.0.1");
            //通知地址,添URL地址
            paramMap.put("notify_url", notifyurl);
            //交易类型,NATIVE
            paramMap.put("trade_type", "NATIVE");

            //签名
            //paramMap.put("sign","");
            //Map转为XML数据,可以自带签名
            //将请求参数集合,转为带有签名的XML数据格式
            String xmlStr = WXPayUtil.generateSignedXml(paramMap, partnerkey);

            //URL地址,微信支付接口链接
            String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";

            //提交方式:HTTPS
            //创建HttpClient对象,对url请求地址进行操作
            HttpClient httpClient = new HttpClient(url);
            //设置提交方式为HTTPS
            httpClient.setHttps(true);

            //提交参数,参数以XML数据格式提交
            httpClient.setXmlParam(xmlStr);

            //执行请求
            //发送XML数据,使用post请求
            httpClient.post();

            //获取返回的数据,此时返回的数据为XML数据格式
            String content = httpClient.getContent();
            System.out.println("content:" + content);

            //返回数据转成Map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            return resultMap;

        } catch (Exception e) {
     
            e.printStackTrace();
        }
        return null;
    }
}

二、测试

1、浏览器输入请求地址:http://localhost:18090/weixin/pay/create/native?outtradeno=198999&totalfee=101

2、参数解释:

​ outtradeno:订单号

​ totalfee:总金额

3、浏览器请求结果

{
     
    "flag": true,
    "code": 20000,
    "message": "创建二维码预付订单成功!",
    "data": {
     
        "nonce_str": "pUPI4MeBq1ikJbOJ",
        "code_url": "weixin://wxpay/bizpayurl?pr=qJVBnYYzz",
        "appid": "wx8397f8696b538317",
        "sign": "7BCED5501AD892D5490A109DADE3383F",
        "trade_type": "NATIVE",
        "return_msg": "OK",
        "result_code": "SUCCESS",
        "mch_id": "1473426802",
        "return_code": "SUCCESS",
        "prepay_id": "wx011403161517455f3f2880f7e02e920000"
    }
}

三、生成二维码

1、使用qrious.js写一个页面pay.html,用于生成二维码

<html>
<head>
<title>二维码入门小demotitle>

<script src="qrious.js"> script>
head>
<body>
<img id="myqrious" >
body>
<script>
   var qrious = new QRious({
      
   		 element:document.getElementById("myqrious"),// 指定的是图片所在的DOM对象
   		 size:250,//指定图片的像素大小
		 level:'H',//指定二维码的容错级别(H:可以恢复30%的数据)
		 value:'weixin://wxpay/bizpayurl?pr=qJVBnYYzz'//指定二维码图片代表的真正的值
   })
script>
html>

2、打开pay.html,显示一个二维码,微信扫码支付
微信二维码支付_第1张图片

四、查询支付状态

1、控制层添加方法(controller)

/**
 * 微信支付状态查询
 * @param outtradeno:商户订单号,由微信服务器生成
 * @return
 */
@GetMapping(value = "/status/query")
public Result queryStatus(String outtradeno){
     
    //查询微信支付状态
    Map map = weixinPayService.queryStatus(outtradeno);
    return new Result(true, StatusCode.OK,"微信支付状态查询成功!",map);
}

2、应用层添加方法(service、serviceImpl)

/**
 * 查询微信支付状态
 * @param outtradeno:商户订单号,由微信服务器生成
 * @return
 */
 Map queryStatus(String outtradeno);
/**
     * 查询微信支付状态
     * @param outtradeno:商户订单号,由微信服务器生成
     * @return
     */
    @Override
    public Map queryStatus(String outtradeno) {
     
        try {
     
            //远程调用
            //创建一个Map集合存放请求参数
            Map<String, String> paramMap = new HashMap<>();
            //添加数据
            //应用ID
            paramMap.put("appid", appid);
            //商户号
            paramMap.put("mch_id", partner);
            //随机字符串
            paramMap.put("nonce_str", WXPayUtil.generateNonceStr());
            //订单号
            paramMap.put("out_trade_no", outtradeno);

            //签名
            //paramMap.put("sign","");
            //Map转为XML数据,可以自带签名
            //将请求参数集合,转为带有签名的XML数据格式
            String xmlStr = WXPayUtil.generateSignedXml(paramMap, partnerkey);

            //URL地址,微信查询订单接口链接
            String url = "https://api.mch.weixin.qq.com/pay/orderquery";

            //提交方式:HTTPS
            //创建HttpClient对象,对url请求地址进行操作
            HttpClient httpClient = new HttpClient(url);
            //设置提交方式为HTTPS
            httpClient.setHttps(true);

            //提交参数,参数以XML数据格式提交
            httpClient.setXmlParam(xmlStr);

            //执行请求
            //发送XML数据,使用post请求
            httpClient.post();

            //获取返回的数据,此时返回的数据为XML数据格式
            String content = httpClient.getContent();
            //System.out.println("content:" + content);

            //返回数据转成Map
            Map<String, String> resultMap = WXPayUtil.xmlToMap(content);
            return resultMap;

        } catch (Exception e) {
     
            e.printStackTrace();
        }
        return null;
    }

3、浏览器输入请求地址:http://localhost:18090/weixin/pay/status/query?outtradeno=198999

参数解释:outtradeno:订单号

{
     
    "flag": true,
    "code": 20000,
    "message": "微信支付状态查询成功!",
    "data": {
     
        "nonce_str": "9FMEOJb0nhdJzGOQ",
        "device_info": "",
        "out_trade_no": "198999",
        "trade_state": "NOTPAY",
        "appid": "wx8397f8696b538317",
        "total_fee": "101",
        "sign": "1C86209F252D64254542EFC5481FD0D0",
        "trade_state_desc": "订单未支付",
        "return_msg": "OK",
        "result_code": "SUCCESS",
        "mch_id": "1473426802",
        "return_code": "SUCCESS"
    }
}

因为上面测试支付二维码时候,我没支付,所以查询订单支付状态显示“订单未支付”。

五、支付结果回调

1、控制层添加方法

/**
     * 支付结果通知回调方法
     * @param request
     * @return
     */
    @RequestMapping(value = "/notify/url")
    public String notifyurl(HttpServletRequest request) throws Exception {
     
        //获取网络输入流,也就是网络输入流格式的通知结果
        ServletInputStream inputStream = request.getInputStream();

        //创建一个OutputStream输出流->输入文件
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        //定义缓冲区
        byte[] buffer = new byte[1024];

        //初始化一个数据长度
        int len = 0;

        //往缓冲区里读文件,数据长度 不等于-1说明有数据
        while ((len = inputStream.read(buffer))!=-1){
     
            //缓冲区中的数据  写入到   输出流对象中
            //从0开始读到长度最后一位
            byteArrayOutputStream.write(buffer,0,len);
        }

        //将byteArrayOutputStream字节流转为字节数组
        //这就是微信支付结果的字节数组
        byte[] byteArray = byteArrayOutputStream.toByteArray();

        //字节数组  转为  xml字符串
        String xmlResult = new String(byteArray, "Utf-8");
        System.out.println("xmlResult:\n"+xmlResult);

        //xml字符串  转为  Map
        Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlResult);
        System.out.println("resultMap:\n"+resultMap);

        //返回结果
        String result = "";
        return result;
    }

2、配置文件中修改回调地址为动态调用

#微信支付信息配置
weixin:
  #应用ID
  appid: wx8397f8696b538317
  #商户号
  partner: 1473426802
  #密钥
  partnerkey: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
  #支付回调地址 通知地址
  #外网域名:http://19453k43d4.51vip.biz:32375
  notifyurl: http://19453k43d4.51vip.biz:32375/weixin/pay/notify/url

3、创建二维码

浏览器输入请求:http://19453k43d4.51vip.biz:32375/weixin/pay//create/native?outtradeno=1999&totalfee=1

{
     
    "flag": true,
    "code": 20000,
    "message": "创建二维码预付订单成功!",
    "data": {
     
        "nonce_str": "pUPI4MeBq1ikJbOJ",
        "code_url": "weixin://wxpay/bizpayurl?pr=qJVBnYYzd",
        "appid": "wx8397f8696b538317",
        "sign": "7BCED5501AD892D5490A109DADE3383F",
        "trade_type": "NATIVE",
        "return_msg": "OK",
        "result_code": "SUCCESS",
        "mch_id": "1473426802",
        "return_code": "SUCCESS",
        "prepay_id": "wx011403161517455f3f2880f7e02e920000"
    }
}

4、修改pay.html中的value为上步的code_url

<html>
<head>
<title>二维码入门小demotitle>

<script src="qrious.js"> script>
head>
<body>
<img id="myqrious" >
body>
<script>
   var qrious = new QRious({
      
   		 element:document.getElementById("myqrious"),// 指定的是图片所在的DOM对象
   		 size:250,//指定图片的像素大小
		 level:'H',//指定二维码的容错级别(H:可以恢复30%的数据)
		 value:'weixin://wxpay/bizpayurl?pr=qJVBnYYzd'//指定二维码图片代表的真正的值
   })
script>
html>

5、双击打开pay.html,生成一个二维码,扫码支付后;

浏览器输入请求地址:http://19453k43d4.51vip.biz:32375/weixin/pay/status/query?outtradeno=1999

{
     
"flag": true,
"code": 20000,
"message": "微信支付状态查询成功!",
    "data": {
     
        "transaction_id": "4200000517202002187004756359",
        "nonce_str": "ZxVmHMCc1mVr8rxR",
        "trade_state": "SUCCESS",
        "bank_type": "OTHERS",
        "openid": "oNpSGwaqHv74waDX0BLPNrFiYIUo",
        "sign": "3DC6A5346C914DE745DBBB7796039BC1",
        "return_msg": "OK",
        "fee_type": "CNY",
        "mch_id": "1473426802",
        "cash_fee": "1",
        "out_trade_no": "1999",
        "cash_fee_type": "CNY",
        "appid": "wx8397f8696b538317",
        "total_fee": "1",
        "trade_state_desc": "支付成功",
        "trade_type": "NATIVE",
        "result_code": "SUCCESS",
        "attach": "",
        "time_end": "20200218153715",
        "is_subscribe": "N",
        "return_code": "SUCCESS"
    }
}

6、查看控制台输出,有一个支付结果通知

六、MQ消息中间件监听

微信服务返回的支付状态,发送给MQ消息中间件

1、在支付系统中导入依赖



    org.springframework.boot
    spring-boot-starter-amqp

2、配置文件application.yml中添加信息

 rabbitmq:
 	host: 服务器地址
 	port: 端口
	username: 用户名
	password: 密码
#位置支付交换机和队列
mq:
  pay:
    exchange:
      order: exchange.order
    queue:
      order: queue.order
    routing:
      key: queue.order

实际开发中登录“服务器地址:15672”手动创建交换机和队列

3、创建队列绑定交换机配置

/**
 * @Author TeaBowl
 * @Date 2021/2/3 11:26
 * @Version 1.0
 */
@Configuration
public class MQConfig {
     

    /**
     * 读取配置文件中的信息
     */
    @Autowired
    private  Environment env;

    /**
     * 创建队列
     * @return
     */
    @Bean
    public Queue OrderQueue (){
     
        //参数:队列名
        return new Queue(env.getProperty("mq.pay.queue.order"));
    }

    /**
     * 创建交换机
     * @return
     */
    @Bean
    public Exchange OrderExchange (){
     
        //参数:交换机名、是否持久化、是否自动删除
        return new DirectExchange(env.getProperty("mq.pay.exchange.order"),true,false);
    }

    /**
     * 队列绑定交换机
     * @param orderQueue:队列
     * @param orderExchange:交换机
     * @return
     */
    @Bean
    public Binding orderQueueExchange(Queue orderQueue,Exchange orderExchange){
     
        //队列绑定交换机  
        return BindingBuilder.bind(orderQueue).to(orderExchange).with(env.getProperty("mq.pay.routing.key")).noargs();
    }

}

4、controller中注入MQ操作对象

//注入MQ操作对象
@Autowired
private RabbitTemplate rabbitTemplate;

5、修改controller中支付结果通知回调方法

/**
     * 支付结果通知回调方法
     * @param request
     * @return
     */
    @RequestMapping(value = "/notify/url")
    public String notifyurl(HttpServletRequest request) throws Exception {
     
        //获取网络输入流,也就是网络输入流格式的通知结果
        ServletInputStream inputStream = request.getInputStream();

        //创建一个OutputStream输出流->输入文件
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        //定义缓冲区
        byte[] buffer = new byte[1024];

        //初始化一个数据长度
        int len = 0;

        //往缓冲区里读文件,数据长度 不等于-1说明有数据
        while ((len = inputStream.read(buffer))!=-1){
     
            //缓冲区中的数据  写入到   输出流对象中
            //从0开始读到长度最后一位
            byteArrayOutputStream.write(buffer,0,len);
        }

        //将byteArrayOutputStream字节流转为字节数组
        //这就是微信支付结果的字节数组
        byte[] byteArray = byteArrayOutputStream.toByteArray();

        //字节数组  转为  xml字符串
        String xmlResult = new String(byteArray, "Utf-8");
        System.out.println("xmlResult:\n"+xmlResult);

        //xml字符串  转为  Map
        Map<String, String> resultMap = WXPayUtil.xmlToMap(xmlResult);
        System.out.println("resultMap:\n"+resultMap);

        //发送支付结果给MQ
        rabbitTemplate.convertAndSend("exchange.order","queue.order", JSON.toJSONString(resultMap));

        //返回结果
        String result = "";
        return result;
    }

订单系统监听MQ消息

1、在订单系统中导入依赖



    org.springframework.boot
    spring-boot-starter-amqp

2、配置文件application.yml中添加信息

 rabbitmq:
    host: 服务器地址
    port: 端口
    username: 用户名
    password: 密码
#位置支付交换机和队列
mq:
  pay:
    #交换机
    exchange:
      order: exchange.order
    #队列
    queue:
      order: queue.order
    routing:
      key: queue.order

3、创建监听MQ信息配置

/**
 * @Author TeaBowl
 * @Date 2021/2/3 12:02
 * @Version 1.0
 * 监听MQ信息
 */
@Component
@RabbitListener(queues = "${mq.pay.queue.order}")   //监听队列
public class OrderMessageListener {
     
    /**
     * 支付结果监听
     * @param message:支付结果
     */
    @RabbitHandler
    public void getMeaaage(String message){
     
        //支付结果回调通知,Json格式转为Map
        Map<String, String> resultMap = JSON.parseObject(message, Map.class);
        System.out.println("监听到的支付结果信息:\n"+resultMap);

        //从MQ消息中间件中获取 支付操作的通信状态
        //通信标识:return_code      状态:SUCCESS/FAIL
        String return_code = resultMap.get("return_code");

        //如果支付操作的通信成功
        if (return_code.equals("SUCCESS")){
     
            //从MQ消息中间件中获取 支付操作的业务结果
            //业务结果:result_code     状态:SUCCESS/FAIL
            String result_code = resultMap.get("result_code");

            //商户订单号:out_trade_no
            String out_trade_no = resultMap.get("out_trade_no");

            //如果支付操作的业务结果为成功    修改订单状态
            if (result_code.equals("SUCCESS")){
     
                //从MQ消息中间件中获取信息
                //微信支付订单号:transaction_id
                String transaction_id = resultMap.get("transaction_id");
            }else {
     
                //如果支付失败,关闭支付,取消订单,回滚库存

            }
        }
    }
}

4、创建二维码实

a. 浏览器请求地址:http://19453k43d4.51vip.biz:32375/weixin/pay/create/native?outtradeno=1769&totalfee=1

{
     
    "flag": true,
    "code": 20000,
    "message": "创建二维码预付订单成功!",
    "data": {
     
        "nonce_str": "QlLrzt4vdsKNck1d",
        "code_url": "weixin://wxpay/bizpayurl?pr=MjNPE2Dzz",
        "appid": "wx8397f8696b538317",
        "sign": "CD80E7E68014CF70C36535E231E0FF14",
        "trade_type": "NATIVE",
        "return_msg": "OK",
        "result_code": "SUCCESS",
        "mch_id": "1473426802",
        "return_code": "SUCCESS",
        "prepay_id": "wx03125509016851a5fca270399354320000"
    }
}

b. 修改pay.html中的支付地址为code_url地址

<html>
<head>
<title>二维码入门小demotitle>

<script src="qrious.js"> script>
head>
<body>
	<img id="myqrious" >
body>
	<script>
	   var qrious = new QRious({
      
			 element:document.getElementById("myqrious"),// 指定的是图片所在的DOM对象
			 size:250,//指定图片的像素大小
			 level:'H',//指定二维码的容错级别(H:可以恢复30%的数据)
			 value:'weixin://wxpay/bizpayurl?pr=MjNPE2Dzz'//指定二维码图片代表的真正的值
	   })
	script>
html>

c. 二维码图片
微信二维码支付_第2张图片
5、扫码支付后。查看浏览器RabbitMQ后台:“服务器地址:15672/#/queues”
查看消息:
微信二维码支付_第3张图片
微信二维码支付_第4张图片

七、修改订单状态

1、在订单工程中进行修改

应用层接口(OrderService)中,添加接口

/**
 * 修改订单状态
 * @param outtradeno:用户订单号
 * @param paytime:支付时间
 * @param transactionid:交易流水号
 */
void updataStatus(String outtradeno,String paytime,String transactionid) throws  Exception;

应用层接口实现类(OrderServiceImpl)中,添加方法实现

/**
     * 修改订单状态
     * @param outtradeno:用户订单号
     * @param paytime:支付时间
     * @param transactionid:交易流水号
     */
    @Override
    public void updataStatus(String outtradeno, String paytime, String transactionid) throws Exception {
     
        //使用时间转换工具,转换时间格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        Date payTimeInfo = simpleDateFormat.parse(paytime);

        //根据用户订单号,查询订单      order订单信息封装类
        Order order = orderMapper.selectByPrimaryKey(outtradeno);
        //修改订单信息
        //设置交易时间
        order.setPayTime(payTimeInfo);
        //设置支付状态:0未支付,1已支付,2支付失败
        order.setPayStatus("1");
        //设置交易流水号
        order.setTransactionId(transactionid);

        //信息更新到数据库订单表中
        orderMapper.updateByPrimaryKeySelective(order);
    }

2、删除订单,回滚库存

在订单支付后,如果支付失败,订单数据表中的订单信息就没必要保留了,商品库存也需要回滚到原来的数量;
为了方便二次查询,订单并不是真的删除了,而是修改了状态,这叫逻辑删除。

应用层接口(OrderService)中,添加接口

/**
 * 支付失败,删除[修改状态]订单,回滚库存
 * @param outtradeno:用户订单号
 */
void deleteOrder(String outtradeno);

应用层接口实现类(OrderServiceImpl)中,添加方法实现

/**
     * 支付失败,删除[修改状态]订单,回滚库存
     * @param outtradeno:用户订单号
     */
    @Override
    public void deleteOrder(String outtradeno) {
     
        //根据用户订单号,查询订单      order订单信息封装类
        Order order = orderMapper.selectByPrimaryKey(outtradeno);

        //修改状态
        //设置更新时间
        order.setUpdateTime(new Date());
        //设置支付状态:0未支付,1已支付,2支付失败
        order.setPayStatus("2");
        //信息更新到数据库订单表中
        orderMapper.updateByPrimaryKeySelective(order);

        //回滚库存->调用商品微服务     暂略
    }

3、对接监听

修改MQ信息监听配置OrderMessageListener

注入订单应用的操作对象

@Autowired
private OrderService orderService;

修改支付结果监听方法

/**
     * 支付结果监听
     * @param message:支付结果
     */
    @RabbitHandler
    public void getMeaaage(String message) throws Exception {
     
        //支付结果回调通知,Json格式转为Map
        Map<String, String> resultMap = JSON.parseObject(message, Map.class);
        System.out.println("监听到的支付结果信息:\n"+resultMap);

        //从MQ消息中间件中获取 支付操作的通信状态
        //通信标识:return_code      状态:SUCCESS/FAIL
        String return_code = resultMap.get("return_code");

        //如果支付操作的通信成功
        if (return_code.equals("SUCCESS")){
     
            //从MQ消息中间件中获取 支付操作的业务结果
            //业务结果:result_code     状态:SUCCESS/FAIL
            String result_code = resultMap.get("result_code");

            //商户订单号:out_trade_no
            String out_trade_no = resultMap.get("out_trade_no");

            //如果支付操作的业务结果为成功    修改订单状态
            if (result_code.equals("SUCCESS")){
     
                //修改订单状态
                //参数:用户订单号、支付完成时间、交易流水号
                orderService.updataStatus(out_trade_no,resultMap.get("time_end"),resultMap.get("transaction_id"));
            }else {
     
                //如果支付失败,关闭支付,取消订单,回滚库存
                //关闭支付  暂略

                //支付失败,删除[修改状态]订单,回滚库存
                orderService.deleteOrder(out_trade_no);
            }
        }
    }

4、测试

创建二维码信息,浏览器输入请求:http://localhost:18090/weixin/pay/create/native?outtradeno=1355321180126445568&totalfee=1

{
     
    "flag": true,
    "code": 20000,
    "message": "创建二维码预付订单成功!",
    "data": {
     
        "nonce_str": "Dc7zjYlcdvPxienu",
        "code_url": "weixin://wxpay/bizpayurl?pr=s2V4HM3zz",
        "appid": "wx8397f8696b538317",
        "sign": "7D75E71E44AD669496C14684A66D8501",
        "trade_type": "NATIVE",
        "return_msg": "OK",
        "result_code": "SUCCESS",
        "mch_id": "1473426802",
        "return_code": "SUCCESS",
        "prepay_id": "wx04014823728571d0a1350cf856a41e0000"
    }
}

修改pay.html的支付地址

<html>
<head>
<title>二维码入门小demotitle>

<script src="qrious.js"> script>
head>
<body>
	<img id="myqrious" >
body>
	<script>
	   var qrious = new QRious({
      
			 element:document.getElementById("myqrious"),// 指定的是图片所在的DOM对象
			 size:250,//指定图片的像素大小
			 level:'H',//指定二维码的容错级别(H:可以恢复30%的数据)
			 value:'weixin://wxpay/bizpayurl?pr=s2V4HM3zz'//指定二维码图片代表的真正的值
	   })
	script>
html>

双击pay.html生成二维码
微信二维码支付_第5张图片

扫码支付成功后,已经监听到了信息
微信二维码支付_第6张图片

数据库中的订单表,也根据监听到的消息进行了改变

你可能感兴趣的:(Java,微信)