微信支付系列(三)之二维码扫码支付

一. 调用微信统一下单接口
1.支付流程
商户后台系统先调用微信支付的统一下单接口,微信后台系统返回链接参数code_url,
商户后台系统将code_url值生成二维码图片
2.调用统一下单接口
https://api.mch.weixin.qq.com/pay/unifiedorder
3.前端安装二维码插件
a.下载依赖 npm install vue-qriously --save-dev
b.找到plugins—nuxt-swiper-plugin.js
import VueQriously from ‘vue-qriously’
Vue.use(VueQriously)
4.查询订单支付状态
a.支付成功之后的流程
b.修改订单表里面的状态
c.往支付记录表里面添加一条记录
5.前端之后成功之后页面跳转
a.通过前端的定时任务(*)
b.通过通知地址回调

二. java代码实现二维码扫码支付
1.微信统一下订单

 //3.微信统一下订单
    @GetMapping("createPayQrCode/{orderNo}")
    //通过订单id创建支付订单
    public RetVal createPayQrCode(@PathVariable String orderNo) throws Exception {
        Map<String, Object> retMap = orderService.createPayQrCode(orderNo);
        return RetVal.success().data(retMap);
    }

2.调用微信下单API,需用到工具类HttpClient

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() {
							// 信任所有
							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.编写service层业务逻辑
注入配置文件中需要传递的信息

@Value("${wx.pay.app_id}")
    private String WX_PAY_APP_ID;
    @Value("${wx.pay.mch_id}")
    private String WX_PAY_MCH_ID;
    @Value("${wx.pay.spbill_create_ip}")
    private String WX_PAY_SPBILL_IP;
    @Value("${wx.pay.notify_url}")
    private String WX_PAY_NOTIFY_URL;
    @Value("${wx.pay.xml_key}")
    private String WX_PAY_XML_KEY;

4.对照微信支付官网,找到必须传递的数据,不是必须的数据看具体业务逻辑添加

 @Override
    public Map<String, Object> createPayQrCode(String orderNo) throws Exception {
        QueryWrapper<EduOrder> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no", orderNo);
        EduOrder order = baseMapper.selectOne(wrapper);


        //把传递的参数封装成一个map结构
        Map<String, String> requestParams = new HashMap<>();
        //公众账号ID	appid
        requestParams.put("appid",WX_PAY_APP_ID);
        //商户号	mch_id
        requestParams.put("mch_id",WX_PAY_MCH_ID);
        //随机字符串	nonce_str
        requestParams.put("nonce_str", WXPayUtil.generateNonceStr());
        //商品描述	body
        requestParams.put("body",order.getCourseTitle());
        //商户订单号	out_trade_no
        requestParams.put("out_trade_no",orderNo);
        //标价金额	total_fee  商品的金额0.01分-->0.01元
        BigDecimal totalFee = order.getTotalFee();
        String totalFeeStr=totalFee.multiply(new BigDecimal(100)).intValue()+"";
        requestParams.put("total_fee",totalFeeStr);
        //终端IP	spbill_create_ip
        requestParams.put("spbill_create_ip",WX_PAY_SPBILL_IP);
        //通知地址	notify_url
        requestParams.put("notify_url",WX_PAY_NOTIFY_URL);
        //交易类型	trade_type	是
        requestParams.put("trade_type","NATIVE");


        //把map接口的参数转换成xml并且签名
        String paramsXml = WXPayUtil.generateSignedXml(requestParams, WX_PAY_XML_KEY);
        //调用微信下单API
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
        httpClient.setXmlParam(paramsXml);
        httpClient.setHttps(true);
        httpClient.post();


        //因为数据太多,为了保证数据安全性,所有有选择地返回数据
        //加返回的数据封装到map中
        String content = httpClient.getContent();
        Map<String, String> txRetVal = WXPayUtil.xmlToMap(content);
        Map<String, Object> retVal = new HashMap<>();
        String qrCodeUrl = txRetVal.get("code_url");
        retVal.put("qrCodeUrl",qrCodeUrl);
        retVal.put("orderNo",orderNo);
        retVal.put("totalFee",order.getTotalFee());
        retVal.put("courseId",order.getCourseId());
        return retVal;
    }

5.扫码支付完成需跳转到支付结果页面,也就是查询支付订单,显示支付成功,并根据业务逻辑显示需要显示的信息,最后跟新订单状态。。。。代码比较简单,我就直接贴在下面

 //4.查询支付订单
    @GetMapping("queryPayState/{orderNo}")
    public RetVal queryPayState(@PathVariable String orderNo) throws Exception {
        Map<String, String> txRetMap = orderService.queryPayState(orderNo);
        //更新订单状态
        if(txRetMap.get("trade_state").equals("SUCCESS")){
            orderService.updateOrderState(txRetMap);
            return RetVal.success().message("支付成功");
        }else{
            return RetVal.error().message("支付失败");
        }

    }

service层

  @Override
    public Map<String, String> queryPayState(String orderNo) throws Exception{
        //把传递的参数封装成一个map结构
        Map<String, String> requestParams = new HashMap<>();
        //公众账号ID	appid
        requestParams.put("appid",WX_PAY_APP_ID);
        //商户号	mch_id
        requestParams.put("mch_id",WX_PAY_MCH_ID);
        //随机字符串	nonce_str
        requestParams.put("nonce_str", WXPayUtil.generateNonceStr());
        //商户订单号	out_trade_no
        requestParams.put("out_trade_no",orderNo);

        //把map接口的参数转换成xml并且签名
        String paramsXml = WXPayUtil.generateSignedXml(requestParams, WX_PAY_XML_KEY);
        //调用微信下单API
        HttpClient httpClient = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
        httpClient.setXmlParam(paramsXml);
        httpClient.setHttps(true);
        httpClient.post();

        String content = httpClient.getContent();
        Map<String, String> txRetVal = WXPayUtil.xmlToMap(content);
        return txRetVal;
    }

    @Override
    public void updateOrderState(Map<String, String> txRetMap) {
        //b.修改订单表里面的状态
        QueryWrapper<EduOrder> wrapper = new QueryWrapper<>();
        String orderNo = txRetMap.get("out_trade_no");
        wrapper.eq("order_no", orderNo);
        EduOrder order = baseMapper.selectOne(wrapper);
        order.setStatus(1);
        baseMapper.updateById(order);
        //c.往支付记录表里面添加一条记录

        QueryWrapper<EduPayLog> logWrapper = new QueryWrapper<>();
        logWrapper.eq("order_no", orderNo);
        EduPayLog existLog = payLogService.getOne(logWrapper);
        if(existLog==null){
            EduPayLog payLog = new EduPayLog();
            payLog.setOrderNo(orderNo);
            payLog.setPayTime(new Date());
            payLog.setTotalFee(order.getTotalFee());
            payLog.setTransactionId(txRetMap.get("transaction_id"));
            payLog.setTradeState(txRetMap.get("trade_state"));
            payLogService.save(payLog);
        }
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值