微信公众号支付-JSAPI支付

JSAPI支付是用户在微信中打开商户的H5页面,商户在H5页面通过调用微信支付提供的JSAPI接口调起微信支付模块完成支付。应用场景有:

◆ 用户在微信公众账号内进入商家公众号,打开某个主页面,完成支付
◆ 用户的好友在朋友圈、聊天窗口等分享商家页面连接,用户点击链接打开商家页面,完成支付
◆ 将商户页面转换成二维码,用户扫描二维码后在微信浏览器中打开页面后完成支付

以下是公众号支付的开发流程:实际写的不多,不难的

注意点:
提交方式:采用POST方法提交
API密钥(前面中用到的key):交易过程生成签名的密钥,仅保留在商户系统和微信支付后台,不会在网络中传播。商户妥善保管该Key,切勿在网络中传输,不能在其他客户端中存储,保证key不会被泄漏。商户可根据邮件提示登录微信商户平台进行设置。也可按以下路径设置:微信商户平台(pay.weixin.qq.com)–>账户中心–>账户设置–>API安全–>密钥设置
微信公众号支付-JSAPI支付_第1张图片

具体步骤:

1、在JSAPI支付文档的统一下单里看下必须传入的参数

//  公众账号id
	private String appid;
//	商户号
	private String mch_id;
//	商品描述
	private String body;
//	随机字符串(32位以内)
	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;
//	用户标识(每个用户的openid不一样)
	private String openid;

2、获取到以上参数后按照以下xml格式发送给文档提供的接口

<xml>
   <appid>wx2421b1c4370ec43b</appid>
   <attach>支付测试</attach>
   <body>JSAPI支付测试</body>
   <mch_id>10000100</mch_id>
   <detail><![CDATA[{ "goods_detail":[ { "goods_id":"iphone6s_16G", "wxpay_goods_id":"1001", "goods_name":"iPhone6s 16G", "quantity":1, "price":528800, "goods_category":"123456", "body":"苹果手机" }, { "goods_id":"iphone6s_32G", "wxpay_goods_id":"1002", "goods_name":"iPhone6s 32G", "quantity":1, "price":608800, "goods_category":"123789", "body":"苹果手机" } ] }]]></detail>
   <nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
   <notify_url>http://wxpay.wxutil.com/pub_v2/pay/notify.v2.php</notify_url>
   <openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
   <out_trade_no>1415659990</out_trade_no>
   <spbill_create_ip>14.23.150.211</spbill_create_ip>
   <total_fee>1</total_fee>
   <trade_type>JSAPI</trade_type>
   <sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>

3、返回结果中获取prepay_id,然后进行准备h5调起支付,查看h5调起支付文档,需要参数如下
微信公众号支付-JSAPI支付_第2张图片
4、将前面五个参数进行前面后,将六个参数发送到h5页面按照以下格式填入信息,注意成功支付后处理,最好通过文档API到商户后台查询时候已支付完成,然后将结果返回给用户

function onBridgeReady(){
   WeixinJSBridge.invoke(
      'getBrandWCPayRequest', {
         "appId":"wx2421b1c4370ec43b",     //公众号名称,由商户传入     
         "timeStamp":"1395712654",         //时间戳,自1970年以来的秒数     
         "nonceStr":"e61463f8efa94090b1f366cccfbbb444", //随机串     
         "package":"prepay_id=u802345jgfjsdfgsdg888",     
         "signType":"MD5",         //微信签名方式:     
         "paySign":"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
      },
      function(res){
      if(res.err_msg == "get_brand_wcpay_request:ok" ){
      // 使用以上方式判断前端返回,微信团队郑重提示:
            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
      } 
   }); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}

5、到微信支付开发文档的开发步骤里,按照要求到商户后台(登录微信支付商户平台(pay.weixin.qq.com)–>产品中心–>开发配置)和公众号后台网页授权配置域名,
微信公众号支付-JSAPI支付_第3张图片
微信公众号支付-JSAPI支付_第4张图片
6、具体代码如下
Pay

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;
//	用户标识
	private String openid;
	}

主程序

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 {
	/**
	 * JSAPI支付
	 * @return
	 */
	@RequestMapping("jsapiPay")
	public static Map<String,Object> getJsapiPay(){
//		openid和金额需要数据库获取
		String openid="从用户信息中获取";
		int total_fee=2;
		
		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", Parameter.trade_type);
		parameters.put("openid", openid);
		//统一下单签名
		String prePaySign=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(Parameter.trade_type);
		pay.setOpenid(openid);
		pay.setSign(prePaySign);
		//生成xml格式
		XStreamUtil.xstream.alias("xml", Pay.class);
		String xml = XStreamUtil.xstream.toXML(pay).replaceAll("__", "_");
		
		System.out.println(xml);
		
		String prepay_id=null;
		try {
			String resXml=HttpsUtil.httpsRequest("https://api.mch.weixin.qq.com/pay/unifiedorder", "POST", xml);
			prepay_id=XmlUtil.parseXml(resXml, "prepay_id");
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		//微信内h5调起支付
		String timeStamp= PayUtil.getTimeStamp();
		String Package="prepay_id="+prepay_id;
		SortedMap<Object,Object> h5parameters = new TreeMap<Object,Object>();
		h5parameters.put("appId", Parameter.appID);
		h5parameters.put("timeStamp",timeStamp);
		h5parameters.put("nonceStr", nonce_str);
		h5parameters.put("package",Package);
		h5parameters.put("signType", "MD5");
		String paySign=Sign.sign(h5parameters);
		
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("appId", Parameter.appID);
		map.put("timeStamp", timeStamp);
		map.put("nonceStr", nonce_str);
		map.put("package", Package);
		map.put("signType", "MD5");
		map.put("paySign", paySign);
		
		return map;
	}


/**
	 * 扫码/JSAPI支付回调
	 * 
	 * @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 = "" + ""
						+ "" + " ";

			} else {
				System.out.println("支付失败,错误信息:" + packageParams.get("err_code"));
				resXml = "" + ""
						+ "" + " ";
			}
			// ------------------------------
			// 处理业务完毕
			// ------------------------------
			return resXml;
		} else {
			System.out.println("通知签名验证失败");
		}
		return "" + ""
		 + ""+"";
	}
	}

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/pay.js"></script>
</head>
<body>

</body>
</html>

js`

$(document).ready(function(){
	
	 $.getJSON("pay/prePay/",function(json){
		 console.log(json);
		 console.log(json.appId);
		 var appId=json.appId;
		 var timeStamp=json.timeStamp;
		 var nonceStr=json.nonceStr;
		 var package1=json.package;
		 var signType=json.signType;
		 var paySign=json.paySign;
		 pay();
		 
		 function onBridgeReady(){
		        WeixinJSBridge.invoke(
			      'getBrandWCPayRequest', {
			         "appId":appId,            //公众号名称,由商户传入     
			         "timeStamp":timeStamp,    //时间戳,自1970年以来的秒数     
			         "nonceStr":nonceStr,      //随机串     
			         "package":package1,     
			         "signType":"MD5",         //微信签名方式:     
			         "paySign":paySign         //微信签名 
			      },
			      function(res){
			      if(res.err_msg == "get_brand_wcpay_request:ok" ){
			          // 使用以上方式判断前端返回,微信团队郑重提示:
			          //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
			    	  //这里填写支付之后的页面跳转(一般要根据API查询接口到商户后台查询结果,然后在该页面显示)
			    	  window.location.href="test.html";
			      } else{
			    	  question = confirm("支付失败,是否重新支付");
			    	  if(question){
			    		  pay();
			    	  }
			      }
			   }); 
	 		}
		 
		 
		 function pay(){
			 if (typeof WeixinJSBridge == "undefined"){
				   if( document.addEventListener ){
				       document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
				   }else if (document.attachEvent){
				       document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
				       document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
				   }
				}else{
				   onBridgeReady();
				}
			}
	 })
	

})

支付链接:

http://域名/pay.html

你可能感兴趣的:(#,支付)