文档章节

微信JSAPI支付

我不是方头捷达
 我不是方头捷达
发布于 2017/02/09 22:26
字数 3135
阅读 119
收藏 0

 

一、要想做微信JSAPI的支付,首先得有一些准备工作:

1、有一个服务号,该服务号必须开通微信支付,公众号都有的两个参数:APPID和APPSECRET;开通微信支付后会有以下参数:MCHID(商户号),KEY(商户支付密钥)

2、配置公众号微信支付,我们需要配置微信公众号支付的地址(测试目录,就是你的微信支付js页面对应的连接,也就是所在地址)和测试白名单(比如你要测试微信支付,你的微信号得配置到支付白名单中,不然没办法测试,会出现redirect_uri参数错误),如果你的支付对应的方法或者支付js页面的地址为https://ayo.tunnel.qydev.com/anyou/customize/toCreateOrder,那么此处只需要配置成https://ayo.tunnel.qydev.com/anyou/customize/即可;

二、接下来我们就开始开发

首先上个图,让大家对微信支付的开发先有个思路,知道其中的业务逻辑:

我们要做的就是实现上图红色的部分;

微信公众号支付的总体其实很简单,大致就分为三步。第一步需要获取用户授权;第二步调用统一下单接口获取预支付id;第三步H5调起微信支付的内置的js。下面介绍具体每一步的开发流程:

一)首先要明确微信公众号支付属于网页版支付,所以相较于app的直接调取微信支付要多一步微信授权。也就是需要获取用户的openid。微信公众号使用的交易类型是JSAPI,所以统一下单接口的文档明确的写到

因此我们必须去获取openid,同时也可以处理一些我们需要的逻辑。获取用户授权有两种方式:scope=snsapi_base;scope=snsapi_userinfo。下面是授权的代码:其中的snsapi_userinfo就代表第二种授权方式,可以改成snsapi_base,自己根据情况进行选择,说一下这两种的区别:

1、以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页的。用户感知的就是直接进入了回调页(往往是业务页面)

2、以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。但这种授权需要用户手动同意,并且由于用户同意过,所以无须关注,就可在授权后获取该用户的基本信息。 

3、用户管理类接口中的“获取用户基本信息接口”,是在用户和公众号产生消息交互或关注后事件推送后,才能根据用户OpenID来获取用户基本信息。这个接口,包括其他微信接口,都是需要该用户(即openid)关注了公众号后,才能调用成功的。 

微信工具类WexinUtil:



import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.iambuyer.entity.WxUser;
import net.sf.json.JSONObject;

/**
 * 
 * @ClassName: WexinUtil
 * @Company: http://an.you.cn/
 * @Description:微信的工具类 
 * @author ayo 
 * @date 2016年10月26日 下午9:57:35
 */
public class WexinUtil {
	/**
	 * 
	 * @Title: isWechat
	 * @Description: 判断请求是否来自于微信客户端
	 * @param request
	 * @return
	 * @return boolean
	 * @throws
	 */
	public static boolean isWechat(HttpServletRequest request){
		String agent = request.getHeader("user-Agent").toLowerCase();
		if(agent.contains("micromessenger")){
			return true;
		}
		return false;
	}
	/**
	 * 
	* @Title: getBaseUrl 
	* @Description: TODO(判断是否是客户端请求) 
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String getBaseUrl(HttpServletRequest request){
		String path = request.getContextPath();
		String url = "";
		String _port = ":"+request.getServerPort();
		if(_port.equals(":80")||_port.equals(":443"))_port = "";
		url = request.getScheme()+"://"+request.getServerName()+_port+path;
		return url;
	}
	/**
	 * 
	* @Title: getUrlParameter 
	* @Description: TODO(参数封装) 
	* @param @return    设定文件 
	* @return String    返回类型 
	* @throws
	 */
	public static String getUrlParameter(HttpServletRequest request){
		
		Map<String, String[]> map = request.getParameterMap();
		String pul = "";
		if(map.size() > 0){
			pul += "?";
			for (String key : map.keySet()) {
				String value = map.get(key)[0];
				pul += key + "=" + value +"&";
			}
			pul = pul.substring(0, pul.length()-1);
		}
		return pul;
	}
	/**
	 * @throws UnsupportedEncodingException 
	 * 
	* @Title: oauthByGet 
	* @Description: TODO(获取微信用户的信息) 
	* @param @param user
	* @param @param code
	* @param @return    设定文件 
	* @return WxUser    返回类型 
	* @throws
	 */
	public static WxUser oauthByGet(WxUser user,String code) throws UnsupportedEncodingException{
		/**
		 * 获取网页授权的access_token
		 */
		String _url = WexinUrlConst.getWEXIN_USER_TOKEN(WxConfigure.getAPPID(),
				WxConfigure.getAPPSECRET(), code);
		/**
		 * https请求忽略证书
		 */
		String resp = new Con2http().httpsRequest(_url, "GET", null);
		if (!resp.contains("errcode")) {
			JSONObject object = JSONObject.fromObject(resp);
			String openid = object.getString("openid");
			user.setOpenid(openid);
			String access_token = object.getString("access_token");
			String userUrl = WexinUrlConst.getWEXIN_USER_USERINFO(access_token,
					openid);
			String userInfo = new Con2http().httpsRequest(userUrl, "GET", null);
			if (!userInfo.contains("errcode")) {
				JSONObject _user = JSONObject.fromObject(userInfo);
				user.setCity(_user.getString("city"));
				user.setCountry(_user.getString("country"));
				user.setCreateTime(new Date());
				user.setHeadImgUrl(_user.getString("headimgurl"));
				String filterEmoji = EmojiFilter.filterEmoji(_user.getString("nickname"));
				user.setNickname(filterEmoji);
				user.setProvince(_user.getString("province"));
			}
		}
		return user;
	}
	/**
	 * 
	* @Title: oauthResp 
	* @Description: TODO(微信授权) 
	* @param @param response
	* @param @param url
	* @param @throws UnsupportedEncodingException
	* @param @throws IOException    设定文件 
	* @return void    返回类型 
	* @throws
	 */
	public static void oauthResp(HttpServletRequest request, HttpServletResponse response,String url)
			throws UnsupportedEncodingException, IOException {
		/**
		 * 授权后回调的url
		 */
		String reqUrl = getBaseUrl(request)+url+getUrlParameter(request);
		reqUrl = URLEncoder.encode(reqUrl, "utf-8");
		/**
		 * 获取code
		 */
		String _url = WexinUrlConst.getWEXIN_USER_GETCODE(
				WxConfigure.getAPPID(), reqUrl, "code", "snsapi_userinfo",
				"qawine");
		/**
		 * 重定向到这个路径去获取code
		 */
		response.sendRedirect(_url);
	}
}

使用方法:

            String code = request.getParameter("code");
			String state = request.getParameter("state");
			if(code != null && state != null){
				wxuser = new WxUser();
				wxuser = WexinUtil.oauthByGet(wxuser, code);
				request.getSession().setAttribute("wxuser", wxuser);
				customizeService.queryAndAddOrUpdateWxUser(wxuser);
				return "redirect:/customize/"+shopCode+"/toCustomizeIndex";
			}
			else{
				WexinUtil.oauthResp(request, response, "/customize/"+shopCode+"/toCustomizeIndex");
				return null;
			}

至此openid已经通过授权获得!

二)我们获取了openid后,就可以进行下一步的统一下单的开发了。微信上统一下单接口的文档写的比较详细了,具体的参数含义我就不多做介绍了。下面直接贴最直观的代码。

1、微信支付统一下单

/**
	 * 微信支付统一下单
	 * 
	 * @param o
	 *            订单
	 * @param spBillCreateIP
	 *            客户端ip
	 * @param notifyUrl
	 *            异步通知
	 * @return 下单的xml数据
	 */
	public static String wxpay(Order o, String spBillCreateIP) {
		String body = "iambuyer";
		String outTradeNo = o.getOrderCode();
		double d = o.getTotalMoney();
		int feeTotal = (int) (d * 100);
		String tradeType = "JSAPI";
		String timeStart = DateUtil.getTimes(o.getCreateTime());
		String timeExpire = DateUtil.getTimes(o.getCreateTime(), 1000 * 60 * 60
				* 24 * 7);// 测试失效时间为7天
		String openid = o.getuId();
		String attach = o.getId() + "";
		String notifyUrl = NOTIFYURL;
		WebPayReqData web = new WebPayReqData(body, outTradeNo, feeTotal,
				spBillCreateIP, timeStart, timeExpire, notifyUrl, tradeType,
				openid, attach);
		String xml = getWXPAY(web);
		return xml;
	}

2、获取微信支付统一下单返回数据

/**
	 * 获取微信支付统一下单返回数据
	 * 
	 * @param o
	 * @param spBillCreateIP
	 * @param notifyUrl
	 * @return
	 */
	@SuppressWarnings("static-access")
	public static Map<String, String> reqWxpay(Order o, String spBillCreateIP) {

		// 组合请求的数据
		String data = wxpay(o, spBillCreateIP);
		System.out.println("请求的数据" + data);
		String url = URL_TYXD;
		String resp = "";
		try {
			resp = new JavaConnetInternet().sendHttpPostRequestxj(url, data);
		} catch (IOException e) {
			e.printStackTrace();
		}
		TreeMap<String, String> map = parse(resp);
		return map;
	}

3、拼接jsapi数据

/**
	 * 拼接jsapi数据
	 * 
	 * @param map
	 * @return
	 */
	public static String getJsapiJson(String prepay_id) {
		Map<String, Object> treeMap = new TreeMap<String, Object>();
		treeMap.put("appId", APPID);
		treeMap.put("timeStamp", (int) (System.currentTimeMillis() / 1000) + "");
		treeMap.put("nonceStr", RandomUtil.getRandom(32));
		String pack = "prepay_id=" + prepay_id;
		treeMap.put("package", pack);
		treeMap.put("signType", "MD5");
		String sign = getSign(treeMap);
		treeMap.put("paySign", sign);
		return JsonUtil.getJsonString4JavaPOJO(treeMap);
	}

4、去往微信js所在的页面调起微信支付

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport"
	content="width=device-width,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache, must-revalidate">
<meta http-equiv="expires" content="0">

<title>-支付</title>
<script src="https://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
<script type="text/javascript">
	//调用微信JS api 支付
	
	function onBridgeReady() {
		var jsapi = ${jsapiData};
		WeixinJSBridge
				.invoke(
						'getBrandWCPayRequest',jsapi,
						function(res) {
							WeixinJSBridge.log(res.err_msg);
							if (res.err_msg == "get_brand_wcpay_request:ok") {
								window.location.href = "<%=path%>/rong/paySuc?type=web&id=${order.id}";
							} else {
								//返回跳转到订单详情页面
								alert("支付失败");
								window.location.href = "<%=path%>/rong/myOrder?type=web";
								
								
							}
						});
	}
	function callpay() {
		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();
		}
	}
</script>
</head>


<body>

	<div class="vpay vorder">

		<p></p>

		<p>
			支付金额:<span><i>¥</i>${order.totalMoney}</span>
		</p>
		<div class="half_line half_line_top"></div>
	</div>
	<div class="vpay_sub">
		<a onclick="callpay()">微信支付</a>
	</div>
</body>
</html>


微信支付工具类如下,里面设计到支付的所有方法:




import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Formatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.TreeMap;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.iambuyer.entity.Order;
import com.iambuyer.utils.DateUtil;
import com.iambuyer.utils.MD5;
import com.iambuyer.utils.Tools;
import com.iambuyer.utils.consts.Const;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer;
import com.thoughtworks.xstream.io.xml.XppDriver;


@SuppressWarnings("unused")
public class WxPayUtil {

	private static ResourceBundle resb1 = ResourceBundle.getBundle("properties/wxpayapi");
	// APPID
	private static String APPID = resb1.getString("APPID");
	// MCHID
	private static String MCHID = resb1.getString("MCHID");
	// KEY
	private static String KEY = resb1.getString("KEY");
	// APPID
	private static String APPSECRET = resb1.getString("APPSECRET");
	// 统一下单接口
	private static String URL_TYXD = resb1.getString("URL_TYXD");
	// 查询订单
	private static String URL_CXDD = resb1.getString("URL_CXDD");
	// 关闭订单
	private static String URL_GBDD = resb1.getString("URL_GBDD");
	// 查询退款
	private static String URL_CXTK = resb1.getString("URL_CXTK");
	// 申请退款
	private static String URL_SQTK = resb1.getString("URL_SQTK");
	// 对账单
	private static String URL_DOWNORDER = resb1.getString("URL_DOWNORDER");
	// 测速
	private static String URL_TEST = resb1.getString("URL_TEST");
	// 融咖啡微信支付异步通知地址
	private static String NOTIFYURL = resb1.getString("NOTIFYURL");
	/**
	 * 获取数字签名
	 * 
	 * @param o
	 * @return
	 * @throws IllegalAccessException
	 */
	public static String getSign(Map<String, Object> map) {
		ArrayList<String> list = new ArrayList<String>();
		for (Map.Entry<String, Object> entry : map.entrySet()) {
			if (entry.getValue() != "") {
				list.add(entry.getKey() + "=" + entry.getValue() + "&");
			}
		}
		int size = list.size();
		String[] arrayToSort = list.toArray(new String[size]);
		Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < size; i++) {
			sb.append(arrayToSort[i]);
		}
		String result = sb.toString();
		result += "key=" + WxPayUtil.KEY;
		result = MD5.md5(result).toUpperCase();
		return result;
	}

	/**
	 * 微信支付统一下单
	 * 
	 * @param o
	 *            订单
	 * @param spBillCreateIP
	 *            客户端ip
	 * @param notifyUrl
	 *            异步通知
	 * @return 下单的xml数据
	 */
	public static String wxpay(Order o, String spBillCreateIP) {
		String body = "iambuyer";
		String outTradeNo = o.getOrderCode();
		double d = o.getTotalMoney();
		int feeTotal = (int) (d * 100);
		String tradeType = "JSAPI";
		String timeStart = DateUtil.getTimes(o.getCreateTime());
		String timeExpire = DateUtil.getTimes(o.getCreateTime(), 1000 * 60 * 60
				* 24 * 7);// 测试失效时间为7天
		String openid = o.getuId();
		String attach = o.getId() + "";
		String notifyUrl = NOTIFYURL;
		WebPayReqData web = new WebPayReqData(body, outTradeNo, feeTotal,
				spBillCreateIP, timeStart, timeExpire, notifyUrl, tradeType,
				openid, attach);
		String xml = getWXPAY(web);
		return xml;
	}
	/**
	 * 封装微信统一下单数据成XML格式字符串
	 * @param web
	 * @return
	 */
	private static String getWXPAY(WebPayReqData web){
		String xml = WxPayUtil.webWxpayToXml(web);
		return xml;
	}
	/**
	 * 获取微信支付统一下单返回数据
	 * 
	 * @param o
	 * @param spBillCreateIP
	 * @param notifyUrl
	 * @return
	 */
	@SuppressWarnings("static-access")
	public static Map<String, String> reqWxpay(Order o, String spBillCreateIP) {

		// 组合请求的数据
		String data = wxpay(o, spBillCreateIP);
		System.out.println("请求的数据" + data);
		String url = URL_TYXD;
		String resp = "";
		try {
			resp = new JavaConnetInternet().sendHttpPostRequestxj(url, data);
		} catch (IOException e) {
			e.printStackTrace();
		}
		TreeMap<String, String> map = parse(resp);
		return map;
	}
	/**
	 * 通过微信支付请求数据,获取返回
	 * @param web
	 * @return
	 */
	public static Map<String, String> reqWxpay(WebPayReqData web) {
		String data = getWXPAY(web);
		String url = URL_TYXD;
		String resp = "";
		try {
			new JavaConnetInternet();
			resp = JavaConnetInternet.sendHttpPostRequestxj(url, data);
		} catch (IOException e) {
			e.printStackTrace();
		}
		TreeMap<String, String> map = parse(resp);
		return map;
	}
	/**
	 * 拼接jsapi数据
	 * 
	 * @param map
	 * @return
	 */
	public static String getJsapiJson(String prepay_id) {
		Map<String, Object> treeMap = new TreeMap<String, Object>();
		treeMap.put("appId", APPID);
		treeMap.put("timeStamp", (int) (System.currentTimeMillis() / 1000) + "");
		treeMap.put("nonceStr", RandomUtil.getRandom(32));
		String pack = "prepay_id=" + prepay_id;
		treeMap.put("package", pack);
		treeMap.put("signType", "MD5");
		String sign = getSign(treeMap);
		treeMap.put("paySign", sign);
		return JsonUtil.getJsonString4JavaPOJO(treeMap);
	}

	/**
	 * 获取查询订单的支付结果
	 * 
	 * @param request
	 * @param orderNum
	 * @return
	 */
	public static Map<String, String> getSearchOrder(String orderNum) {
		Map<String, Object> map = new HashMap<String, Object>();
		String nonce_str = RandomUtil.getRandom(32);
		map.put("appid", APPID);
		map.put("mch_id", MCHID);
		map.put("out_trade_no", orderNum);
		map.put("nonce_str", nonce_str);
		String sign = getSign(map);
		map.put("sign", sign);
		String xml = objectToXml(map);
		String serverUrl = URL_CXDD;
		String respoXml = null;
		try {
			respoXml = JavaConnetInternet.sendHttpPostRequestxj(serverUrl, xml);
		} catch (IOException e) {
			e.printStackTrace();
		}
		Map<String, String> _map = parse(respoXml);
		return _map;
	}

	/**
	 * 判断签名是否正确
	 * 
	 * @param map
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static String isSign(Map map) {
		String sign = (String) map.get("sign");
		map.remove("sign");
		String _sign = getSign(map);
		if (sign.equals(_sign)) {
			return "OK";
		}
		return "签名错误";
	}

	/**
	 * 解析参数成xml格式的字符串
	 */
	public static String getXMLString(TreeMap<String, String> map) {
		StringBuffer sb = new StringBuffer();
		sb.append("<xml>");
		for (Map.Entry<String, String> entry : map.entrySet()) {
			sb.append("\r\t<").append(entry.getKey()).append(">")
					.append(entry.getValue()).append("</")
					.append(entry.getKey()).append(">");
		}
		sb.append("\r</xml>");
		return sb.toString();
	}

	private static XStream xstream = new XStream(new XppDriver(
			new XmlFriendlyReplacer("_-", "_")));

	public static String musicMessageToXml(TreeMap<String, String> map) {
		xstream.alias("xml", map.getClass());
		return xstream.toXML(map);
	}

	/**
	 * 同意下单数据封装成xml
	 * 
	 * @param obj
	 * @return
	 */
	public static String webWxpayToXml(WebPayReqData obj) {
		xstream.alias("xml", obj.getClass());
		return xstream.toXML(obj);
	}

	/**
	 * java对象转换成xml
	 * 
	 * @param obj
	 * @return
	 */
	public static String objectToXml(Object obj) {
		xstream.alias("xml", obj.getClass());
		return xstream.toXML(obj);
	}

	public static String generate(String return_code, String return_msg) {
		String xml = "<xml><return_code><![CDATA[%1$s]]></return_code><return_msg><![CDATA[%2$s]]></return_msg></xml>";
		return String.format(xml, return_code, return_msg);
	}

	/**
	 * 解析成数组
	 * 
	 * @param data
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static TreeMap<String, String> parse(String data) {
		TreeMap<String, String> map = new TreeMap<String, String>();
		try {
			Document document = DocumentHelper.parseText(data);
			List<Element> elements = document.getRootElement().elements();
			for (Element e : elements) {
				map.put(e.getName(), e.getText());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 解析request中的xml数据
	 * 
	 * @param args
	 */
	public static TreeMap<String, String> parseXml(HttpServletRequest request)
			throws Exception {
		// 将解析结果存储在HashMap中
		TreeMap<String, String> map = new TreeMap<String, String>();

		// 从request中取得输入流
		InputStream inputStream = request.getInputStream();
		// 读取输入流
		SAXReader reader = new SAXReader();
		Document document = reader.read(inputStream);
		// 得到xml根元素
		Element root = document.getRootElement();
		// 得到根元素的所有子节点

		@SuppressWarnings("unchecked")
		List<Element> elementList = root.elements();

		// 遍历所有子节点
		for (Element e : elementList)
			map.put(e.getName(), e.getText());

		// 释放资源
		inputStream.close();
		inputStream = null;

		return map;
	}

	/**
	 * jsapi 数字签名
	 * @param jsapi_ticket
	 * @param url
	 * @return
	 */
	public static Map<String, String> jsSign(String url) {
		Map<String, String> ret = new HashMap<String, String>();
		String jsapi_ticket = "";
		String str = Tools.readTxtFile(Const.WXCONFIG);//获取配置信息
		if(null != str&& !"".equals(str)){
			String strIW[] = str.split(",hc360,");
			if(strIW.length == 5 ){
				jsapi_ticket = strIW[4];
				ret = jsApiData(jsapi_ticket, url);
			}
		}
		return ret;
	}
	/**
	 * jsapi数据拼合
	 * @param jsapi_ticket
	 * @param url
	 * @return
	 */
	public static Map<String, String> jsApiData(String jsapi_ticket, String url) {
		Map<String, String> ret = new HashMap<String, String>();
		String nonce_str = RandomUtil.getRandom(32);
		String timestamp = create_timestamp();
		String string1;
		String signature = "";

		// 注意这里参数名必须全部小写,且必须有序
		string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str
				+ "&timestamp=" + timestamp + "&url=" + url;
		System.out.println(string1);

		try {
			MessageDigest crypt = MessageDigest.getInstance("SHA-1");
			crypt.reset();
			crypt.update(string1.getBytes("UTF-8"));
			signature = byteToHex(crypt.digest());
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}

		ret.put("url", url);
		ret.put("jsapi_ticket", jsapi_ticket);
		ret.put("nonceStr", nonce_str);
		ret.put("timestamp", timestamp);
		ret.put("signature", signature);
		String str = Tools.readTxtFile(Const.WXCONFIG);//获取配置信息
		String strIW[] = str.split(",hc360,");
		ret.put("appId", strIW[0]);
		return ret;
	}
	private static String byteToHex(final byte[] hash) {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }
	
	/**
	 * 获取当前时间秒数
	 * @return
	 */
	private static String create_timestamp() {
		return Long.toString(System.currentTimeMillis() / 1000);
	}

	public static void main(String[] args) {
	}
}

三)至此,微信的JSAPI支付已经开发完成!

© 著作权归作者所有

我不是方头捷达

我不是方头捷达

粉丝 15
博文 38
码字总数 36837
作品 0
焦作
后端工程师
私信 提问
ThinkPHP开发微信小程序微信支付分享

首先你得有一个已经认证并且开通了微信支付的小程序。建议有认证公众号的直接用公众号创建,这样可以及时生效,避免重新走微信认证的审核机制花好几天。 1.在小程序后台和微信商户后台拿到下...

ijry
2017/05/11
166
0
YunGouOS 1.0.1 版本发布,微信官方个人支付接口

YunGouOS 微信官方个人接口1.0.1版本发布了。 YunGouOS是一款开源的微信官方个人接口SDK,主要集成微信官方扫码支付、JSAPI支付、订单查询、退款等相关支付接口,开发者只需要一个架包即可完...

YunGouOS
05/05
0
1
YunGouOS 1.0.5 版本发布,基于微信官方渠道的个人支付接口

YunGouOS 是一款开源的基于微信官方个人支付接口开发的支付SDK,主要集成微信官方扫码支付、JSAPI支付、小程序支付、订单查询、退款等相关支付接口,开发者只需要一个架包即可完成微信支付对...

YunGouOS
06/02
0
0
PHP应用如何对接微信公众号JSAPI支付

微信支付的产品有很多,1. JSAPI支付 2. APP支付 3. Native支付 4.付款码支付 5. H5支付。 其中基于微信公众号开发的应用选择“JSAPI支付“产品,其他APP支付需要“微信开放平台”,H5支付可...

小谜弟
05/16
0
0
确定能用的微信支付jsapi

`微信支付分为四步:1、获取code2、获取opendi3、获取相应数据得到商品订单数组4、支付返回(js 判断)PHP语言:include("includes/modules/payment/WxPayPubHelper.php");//使用jsapi接口$js...

林伟盛
2016/07/03
65
0

没有更多内容

加载失败,请刷新页面

加载更多

基础工具类

package com.atguigu.util;import java.sql.Connection;import java.sql.SQLException;import java.util.Properties;import javax.sql.DataSource;import com.alibaba.druid......

architect刘源源
今天
43
0
P30 Pro劲敌!DxO官宣新机:排行榜又要变

5月26日晚间,DxOMark官方推特预告,将在5月27日公布一款新机型的DxOMark评分,猜猜是哪款? 网友猜想的机型有:红米K20、谷歌Pixel 3a、索尼Xperia 1、诺基亚9 PureView等。 DxOMark即将公布...

linux-tao
昨天
15
0
Ubuntu18.04.2窗口过小不能自适应(二次转载)

解决Ubuntu在虚拟机窗口不能自适应 2018年09月06日 16:20:08 起不了名儿 阅读数 855 此博文转载:https://blog.csdn.net/nuddlle/article/details/77994080(原地址) 试了很多办法这个好用 ...

tahiti_aa
昨天
2
0
死磕 java同步系列之CountDownLatch源码解析

问题 (1)CountDownLatch是什么? (2)CountDownLatch具有哪些特性? (3)CountDownLatch通常运用在什么场景中? (4)CountDownLatch的初始次数是否可以调整? 简介 CountDownLatch,可以...

彤哥读源码
昨天
6
0
Nginx提供下载apk服务

有时候我们可能需要提供文件或者其他apk下载链接,通过 nginx 配置可以很简单地实现。 server {    listen 80;    server_name download.xxx.com;    root app;    locati...

Jack088
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部