微信扫码支付 - Native支付

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

扫码支付分两种模式

【模式一】:商户后台系统根据微信支付规则链接生成二维码,链接中带固定参数productid(可定义为产品标识或订单号)。用户扫码后,微信支付系统将productid和用户唯一标识(openid)回调商户后台系统(需要设置支付回调URL),商户后台系统根据productid生成支付交易,最后微信支付系统发起用户支付流程。模式一适用于线下单品支付
【模式二】:商户后台系统调用微信支付【统一下单API】生成预付交易,将接口返回的链接生成二维码,用户扫码后输入密码完成支付交易。注意:该模式的预付单有效期为2小时,过期后无法支付。模式二适用于线上支付

以下介绍常用的线上扫码支付,即模式二

先看下业务流程吧:
在这里插入图片描述
业务流程说明:

(1)商户后台系统根据用户选购的商品生成订单。

(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;

(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。

(4)商户后台系统根据返回的code_url生成二维码。

(5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。

(6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。

(7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。

(8)微信支付系统根据用户授权完成支付交易。

(9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。

(10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况(回调地址在notify_url设置),通知微信后台系统不再发送该单的支付通知。用户付款后需要向商户后台查询数据,如果已支付,再把付款信息,产品信息存放到数据库

(11)未收到支付通知的情况,商户后台系统调用【查询订单API】。

(12)商户确认订单已支付后给用户发货。

主要代码:

public class Pay {
//  公众账号id
	private String appid;
//	商户号
	private String mch_id;
//	商品描述
	private String body;
//	随机字符串
	private String nonce_str;
//	签名
	private String sign;
//	商户订单号
	private String out_trade_no;
//	标价金额(单位为分)
	private int total_fee;
//	终端IP	
	private String spbill_create_ip;
//	通知地址(用户付款完跳转的地址,该页面包括用户付款信息,结果等),前提要在商户平台设置合法域名,否则无法通知
	private String notify_url;
//	交易类型
	private String trade_type;
//	用户标识(trade_type=JSAPI时(即JSAPI支付),此参数必传)
	private String openid;
//	商品ID(trade_type=NATIVE时,此参数必传)
	private String product_id;
	}

主程序:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.zz.config.Parameter;
import com.zz.entity.Pay;
import com.zz.util.HttpsUtil;
import com.zz.util.PayUtil;
import com.zz.util.QRCodeUtil;
import com.zz.util.Sign;
import com.zz.util.XStreamUtil;
import com.zz.util.XmlUtil;

@RestController
@RequestMapping("pay")
public class PayController {
/**
	 * NATIVE支付:生成的二维码链接有效期为两个小时,可以提醒用户订单在两个小时内付款
	 * @return
	 */
	@RequestMapping("nativePay")
	public static Map<String,Object> getNativePay(){
         int total_fee=62;
         String product_id=PayUtil.getRandomString(15);
		String nonce_str=PayUtil.getRandomString(20);
		String out_trade_no=PayUtil.getCurrentTime()+PayUtil.getRandomString(5);
		
		SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
		parameters.put("appid", Parameter.appID);
		parameters.put("mch_id", Parameter.mch_id);
		parameters.put("nonce_str", nonce_str);
		parameters.put("body", Parameter.body);
		parameters.put("out_trade_no", out_trade_no);
		parameters.put("total_fee", total_fee);
		parameters.put("spbill_create_ip", Parameter.spbill_create_ip);
		parameters.put("notify_url", Parameter.notify_url);
		parameters.put("trade_type", "NATIVE");
		parameters.put("product_id", product_id);
		String sign=Sign.sign(parameters);
		
		Pay pay=new Pay();
		pay.setAppid(Parameter.appID);
		pay.setMch_id(Parameter.mch_id);
		pay.setNonce_str(nonce_str);
		pay.setBody(Parameter.body);
		pay.setOut_trade_no(out_trade_no);
		pay.setTotal_fee(total_fee);
		pay.setSpbill_create_ip(Parameter.spbill_create_ip);
		pay.setNotify_url(Parameter.notify_url);
		pay.setTrade_type("NATIVE");
		pay.setProduct_id(product_id);
		pay.setSign(sign);
		
		
		XStreamUtil.xstream.alias("xml", Pay.class);
		String reqXml=XStreamUtil.xstream.toXML(pay);
		reqXml=reqXml.replaceAll("__", "_");
		
		
		String code_url=null;
		try {
			String resXml=HttpsUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", reqXml);
			//此时的code_url可以直接支付的,可以在前端按钮链接里设置href=code_url,类似与h5调起支付,然后对结果是否支付成功处理。
			code_url=XmlUtil.parseXml(resXml, "code_url");
			System.out.println(code_url);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//展示使用 JavaScript 生成二维码链接参考:https://www.runoob.com/w3cnote/javascript-qrcodejs-library.html
		//下面通过生成base格式的二维码图片返回到前端,前端通过以下便签便可显示二维码
		// <img src="https://img-blog.csdnimg.cn/2022010618365355506.jpg" class="images" border="5px"/>
		QRCodeUtil qr_codeutil=new QRCodeUtil();
		String qr_code= qr_codeutil.getImage(code_url);
		Map<String,Object> map=new HashMap<String,Object>();
		map.put("qr_code", qr_code);
		return map;
	}
	
	/**
	 * 扫码支付回调
	 * 
	 * @param request
	 * @return
	 * @throws NumberFormatException
	 * @throws Exception
	 */
	@RequestMapping("dealwith")
	public String dealwith(HttpServletRequest request) throws NumberFormatException, Exception {
		//获取回调信息
		InputStream inputStream=null;
		inputStream=request.getInputStream();
		StringBuffer sb=new StringBuffer();
		BufferedReader in=new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
		String s;
		while(null!=(s=in.readLine())){
			sb.append(s);
		}
		in.close();
		inputStream.close();
		String resXml=sb.toString();
		System.out.println("------------:"+resXml);
		
		// 解析xml成map
		Map<String,String> map = new HashMap<>();
		map = XmlUtil.parseAllXml(resXml);
		
		//设置 TreeMap
		SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
		packageParams.putAll(map);
		
		// 判断签名是否正确
		Boolean isSign=Sign.isSign(packageParams);
		if(isSign){
			// ------------------------------
			// 处理业务开始
			// ------------------------------
			if ("SUCCESS".equals(XmlUtil.parseXml(resXml, "result_code"))) {
				System.out.println("支付成功");
				//顾客具体信息,地址存入数据库,提供发货,通知用户下单成功
				//向工作人员发送支付成功消息等(消息回复,模板消息)
				// 执行自己的业务逻辑

				System.out.println("验签成功");
				String orderId = (String) packageParams.get("out_trade_no");
				String transactionId = (String) packageParams.get("transaction_id");
				if (orderId != null) {
//					ReturnBody body = orderService.pay(orderId, transactionId, "微信支付");
				}

				// 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
				resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
						+ "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

			} else {
				System.out.println("支付失败,错误信息:" + packageParams.get("err_code"));
				resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
						+ "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
			}
			// ------------------------------
			// 处理业务完毕
			// ------------------------------
			return resXml;
		} else {
			System.out.println("通知签名验证失败");
		}
		return "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
		 + "<return_msg><![CDATA[OK]]></return_msg>"+"</xml>";
	}
	public static void main(String[] args) {
		getNativePay();
	}
}

html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="js/nativePay.js"></script>
</head>
<body id="qrcode">
<h1>啥也不是</h1>

<!-- <img src="https://img-blog.csdnimg.cn/2022010618365380128.jpg" class="images" border="5px"/> -->
</body>
</html>

js

$(document).ready(function(){
	
//	Native支付
	 $.getJSON("pay/nativePay/",function(json){
		 console.log(json.qr_code);
		 $("#qrcode").append("<img src='https://img-blog.csdnimg.cn/2022010618365380128.jpg"+json.qr_code+"' class='images' border='5px'/>")
	 })
	
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值