微信支付

微信支付

二维码

概述

	二维码又称QR Code,QR全称Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的Bar Code条形码能存更多的信息,也能表示更多的数据类型。
	二维条码/二维码(2-dimensional bar code)是用某种特定的几何图形按一定规律在平面(二维方向上)分布的黑白相间的图形记录数据符号信息的;在代码编制上巧妙地利用构成计算机内部逻辑基础的“0”、“1”比特流的概念,使用若干个与二进制相对应的几何形体来表示文字数值信息,通过图象输入设备或光电扫描设备自动识读以实现信息自动处理:它具有条码技术的一些共性:每种码制有其特定的字符集;每个字符占有一定的宽度;具有一定的校验功能等。同时还具有对不同行的信息自动识别功能、及处理图形旋转变化点。

QRCode使用

下载QRCode.js

使用

var qrcode = new QRCode(document.getElementById("qrcode"), {
    width : 250,
    height : 250
});
qrcode.makeCode(response.data.code_url);

微信支付

介绍

	微信扫码支付是商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。该模式适用于PC网站支付、实体店单品或订单支付、媒体广告支付等场景。

申请步骤

1.注册公众号(服务号-企业才能注册)
2.认证公众号(认证费300元/年)
3.提交资料申请微信支付

4.开户成功,登录商户平台进行验证
公众号/与商户号支付信息获取

  • appid
  • mch_id
  • partnerkey

5.启用Native

微信支付API

支付流程

添加pom依赖
<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>0.0.3</version>
</dependency>
WXPayUtil
获取随机字符串
	WXPayUtil.generateNonceStr()
MAP转换为XML字符串(自动添加签名)
	 WXPayUtil.generateSignedXml(param, partnerkey)
XML字符串转换为MAP
	WXPayUtil.xmlToMap(result)

结算支付

在pay.html页面当中添加vue相关JS

<script type="text/javascript" src="plugins/vue/vuejs-2.5.16.js"></script>
<script type="text/javascript" src="plugins/vue/axios-0.18.0.js"></script>
<script type="text/javascript" src="plugins/vue/qs.js"></script>
<script type="text/javascript" src="plugins/qrcode.min.js"></script>

页面加载完毕后,获取支付信息

定义属性


new Vue({
    el:"#app",
    data:{
        money:0, //支付金额
        out_trade_no:'' //支付订单号
    },
    createNative: function () {
		let _this = this;
		axios.post("/pay/createNative.do")
				.then(function (response) {
					//显示订单号和金额
					_this.money= (response.data.total_fee/100).toFixed(2);
					_this.out_trade_no=response.data.out_trade_no;
					console.log(response.data);
					var qrcode = new QRCode(document.getElementById("qrcode"), {
						width : 250,
						height : 250
					});
					qrcode.makeCode(response.data.code_url);
					_this.queryPayStatus();//调用查询支付结果
				}).catch(function (reason) {
					console.log(reason);
				});
	},
	queryPayStatus:function(){
		let _this = this;
		axios.get('/pay/queryPayStatus.do?out_trade_no='+_this.out_trade_no)
				.then(function (response) {
					if(response.data.success){
						location.href="paysuccess.html#?money="+_this.money;
					}else{
						if(response.data.message=='二维码超时'){
							this.createNative();//重新生成二维码
						}else{
							location.href="payfail.html";
						}
					}
				}).catch(function (reason) {
			console.log(reason);
		});
	}
});

支付接口

interface/PayService

    public interface PayService {
        /**
         * 获取支付信息
         * @param outTradeNo 订单号
         * @param totalFee  支付金额
         * @return   支付信息
         */
        public Map createNative(String outTradeNo, String totalFee);
    
        /**
         * 根据订单号, 查询支付状态
         * @param out_trade_no
         * @return
         */
        public Map queryPayStatus(String out_trade_no);
    }

service_buyer/PayServiceImpl

在properties/weixinpay.properties添加支付商户信息
    appid=
    partner=
    partnerkey=
    notifyurl=
加载商户信息
@Service
public class PayServiceImpl implements PayService {
    //微信公众账号或开放平台APP的唯一标识
    @Value("${appid}")
    private String appid;

    //财付通平台的商户账号
    @Value("${partner}")
    private String partner;

    //财付通平台的商户密钥
    @Value("${partnerkey}")
    private String partnerkey;

    //回调地址
    @Value("${notifyurl}")
    private String notifyurl;
}
获取微信支付信息
@Override
public Map createNative(String outTradeNo, String totalFee) {
​	//1.创建参数
​	Map<String,String> param=new HashMap();//创建参数
​	param.put("appid", appid);//公众号
​	param.put("mch_id", partner);//商户号
​	param.put("body", "myxq");//商品描述
​	param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
​	param.put("out_trade_no", outTradeNo);//商户订单号
​	param.put("total_fee",totalFee);//总金额(分)
​	param.put("spbill_create_ip", "127.0.0.1");//IP
​	param.put("notify_url", "http://www.baidu.com");//回调地址(随便写)
​	param.put("trade_type", "NATIVE");//交易类型
​	try {
​		//2.生成要发送的xml , 调用微信sdk的api接口将封装的map数据自动转换成xml格式字符串
​		String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
​		System.out.println(xmlParam);
​		HttpClient client=new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
​		client.setHttps(true);
​		client.setXmlParam(xmlParam);
​		client.post();
​		//3.获得结果
​		String result = client.getContent();
​		System.out.println(result);
​		//调用微信sdk的api接口将xml格式字符串自动转换成Java对象
​		Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
​		Map<String, String> map=new HashMap<>();
​		map.put("code_url", resultMap.get("code_url"));//支付地址
​		map.put("total_fee", totalFee);//总金额
​		map.put("out_trade_no",outTradeNo);//订单号
​		return map;
​	} catch (Exception e) {
​		e.printStackTrace();
​		return new HashMap<>();
​	}
}

查询支付状态

@Override
public Map queryPayStatus(String out_trade_no) {
​	Map param=new HashMap();
​	param.put("appid", appid);//公众账号ID
​	param.put("mch_id", partner);//商户号
​	param.put("out_trade_no", out_trade_no);//订单号
​	param.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
​	String url="https://api.mch.weixin.qq.com/pay/orderquery";
​	try {
​		String xmlParam = WXPayUtil.generateSignedXml(param, partnerkey);
​		HttpClient client=new HttpClient(url);
​		client.setHttps(true);
​		client.setXmlParam(xmlParam);
​		client.post();
​		String result = client.getContent();
​		Map<String, String> map = WXPayUtil.xmlToMap(result);
​		System.out.println(map);
​		return map;
​	} catch (Exception e) {
​		e.printStackTrace();
​		return null;
​	}
}

web_portal/PayController

支付接口

@RestController
@RequestMapping("/pay")
public class PayController {
    @Reference
    private OrderService orderService;
    @Reference
    private PayService payService;

    /**
    *  支付信息接口
     * 获取当前登录用户名,
     * 根据用户名获取redis中的支付日志对象,
     * 根据支付日志对象中的支付单号和总金额
     * 调用微信统一下单接口, 生成支付链接返回
     * @return
     */
    @RequestMapping("/createNative")
    public Map createNative() {
        //1. 获取当前登录用户的用户名
        String userName = SecurityContextHolder.getContext().getAuthentication().getName();
        //2. 根据用户名获取支付日志对象
        PayLog payLog = orderService.getPayLogByUserName(userName);
        if (payLog != null) {
            //3. 调用统一下单接口生成支付链接
            Map map = payService.createNative(payLog.getOutTradeNo(), "1");
            return map;
        }
        return new HashMap();
    }

    /**
     * 支付状态查询接口
     * 调用查询订单接口, 查询是否支付成功
     * @param out_trade_no
     * @return
     */
    @RequestMapping("/queryPayStatus")
    public Result queryPayStatus(String out_trade_no) {
        String userName = SecurityContextHolder.getContext().getAuthentication().getName();
        Result result = null;
        int flag = 1;
        while(true) {
            //1. 判断支付单号等于null
            if (out_trade_no == null) {
                result = new Result(false, "二维码超时");
                break;
            }
            //2. 调用查询接口查询支付是否成功
            Map map = payService.queryPayStatus(out_trade_no);
            if ("SUCCESS".equals(map.get("trade_state"))) {
                result = new Result(true, "支付成功!");
                //3. 如果支付成功, 支付日志表和订单表的支付状态改为已支付, redis的支付日志对象删除
                orderService.updatePayStatus(userName);
                break;
            }
            try {
                Thread.sleep(3000);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //如果5分钟没有支付则支付超时
            if (flag > 100) {
                result = new Result(false, "二维码超时");
                break;
            }
            flag++;
        }
        return result;
    }
}

posted @ 2019-10-21 16:42  海韵༒听心  阅读(558)  评论(1编辑  收藏  举报