微信公众号微信支付(需具备微信支付权限 - https://mp.weixin.qq.com申请)
1、【基本配置】配置开发者服务器
2、右上角点击公众号名称,【功能设置】业务域名、JS接口安全域名
3、【接口权限】-【网页账号】设置域名
4、【微信支付】-【开发配置】-【支付授权目录】,配置你支付页面所在路径
比如我的路径是 http://XXXX/third_pay/weixin/wxpay_test.html;需要在此处配置 http://XXXX/third_pay/weixin
(如果是配置测试授权目录,还需要配置测试白名单,就是你要进行微信支付测试的帐号)
APP微信支付(需具备微信支付权限 - https://open.weixin.qq.com申请)
以下内容复制完,应该就能行了~
1、服务端方法
Controller
@RequestMapping("/initWechatConfig.xhtml")
public void initWechatConfig(HttpServletRequest request, HttpServletResponse response) throws Exception {
try {
String initType = getParams("initType");//request.getParameter("initType");
if (CommonUtil.isNull(initType)) {
throw new BizException(ErrorMsg.PARAMS_NULL);
}
if ("jsapi".equals(initType)) {//只有公众号微信支付才会调用该类型
HashMap<String, Object> respMap = new HashMap<String, Object>();
String initUrl = getParams("initUrl");//当前网页地址
if (CommonUtil.isNull(initUrl)) {
throw new BizException(ErrorMsg.PARAMS_NULL);
}
String noncestr = WxPayUtil.CreateNoncestr();
String timestamp = DateUtil.getTimestampWx();
String signature = null;
//获取
String appId = Constants.GZH_APPID;
Ticket ticket = getJsapiTicket(appId);
signature = SHA1Util.signForJsapiTicket(ticket.getTicket(), noncestr, timestamp, initUrl);
respMap.put("appId", appId);
respMap.put("timestamp", timestamp);
respMap.put("nonceStr", noncestr);
respMap.put("signature", signature);
writeSuccMsg(response, respMap);
} else if ("pay".equals(initType) || "appPay".equals(initType)) {//pay 网页端;appPay app端
//校验必要参数
String outTradeNo = getParams("outTradeNo");
//根据outTradeNo获取订单信息
//...
Double totalFee = 0.01;
String body = "body";
//校验必要参数
//根据支付类型生成预订单
String openId = <span style="font-family: Arial, Helvetica, sans-serif;">getParams</span><span style="font-family: Arial, Helvetica, sans-serif;">("openId");</span>
if ("pay".equals(initType) && CommonUtil.isNull(openId)) {//网页端微信支付,必定有openId
throw new BizException(ErrorMsg.PARAMS_NULL);
}
String createIp = null//获取IP地址;
//封装信息后,初始化微信预订单
log.info("********************************************************************");
String appId = null;
String mchId = null;
String key = null;
String tradeType = null;
if ("pay".equals(initType)) {
tradeType = "JSAPI";
appId = Constants.GZH_APPID;
mchId = Constants.GZH_PAY_MCHID;
key = Constants.GZH_PAY_KEY;
} else if ("appPay".equals(initType)) {
tradeType = "APP";
appId = Constants.APP_APPID;
mchId = Constants.APP_PAY_MCHID;
key = Constants.APP_PAY_KEY;
}
String notify_url = Constants.UNIFIED_THIRD_PAY_NOTIFY_BROKER;
log.info("微信支付 - 回调地址:" + notify_url);
ThirdPayVo payVo = WxPayUtil.getPayElement(initType, appId, mchId, key, tradeType, outTradeNo, body, createIp, openId, totalFee, notify_url);
if (CommonUtil.isNull(payVo)) {
throw new BizException(ErrorMsg.PAY_INIT_FAIL);
}
writeSuccMsg(response, payVo);
} else {
throw new BizException(ErrorMsg.PARAMS_NULL);
}
} catch (Exception e) {
log.error("初始化微信配置 异常:", e);
writeErrorMsg(response, e.getMessage());
}
}
获取access_token、jsapi_ticket等就自己去看API了,很简单~
(获取access_token需要注意区分全局access_token和绑定openid的access_token)
writeSuccMsg
response.setCharacterEncoding("utf-8");
response.setContentType("text/json");
PrintWriter out = null;
try {
out = response.getWriter();
} catch (Exception e) {
throw new RuntimeException(e);
}
String jsonstr = JSON.toJSONString(jsonEntity);
out.print(jsonstr);
-----------------------------------------------util包----------------------------------------------------
1、SHA1Util方法
public class SHA1Util {
public static String signForJsapiTicket(String jsapiTicket, String noncestr, String timestamp, String initUrl) {
String signature = null;
// 注意这里参数名必须全部小写,且必须有序 jsapi_ticket=JSAPI_TICKET&noncestr=NONCESTR×tamp=TIMESTAMP&url=INIT_URL
String signatureStr = Constants.ticket_url_params;
signatureStr = signatureStr.replace("JSAPI_TICKET", jsapiTicket);
signatureStr = signatureStr.replace("NONCESTR", noncestr);
signatureStr = signatureStr.replace("TIMESTAMP", timestamp);
signatureStr = signatureStr.replace("INIT_URL", initUrl);
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(signatureStr.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return signature;
}
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;
}
}
3、WxPayUtil
public class WxPayUtil {
/**
*
*/
protected final static Logger log = LoggerFactory.getLogger(WxPayUtil.class);
public static String CreateNoncestr(int length) {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < length; i++) {
Random rd = new Random();
res += chars.indexOf(rd.nextInt(chars.length() - 1));
}
return res;
}
public static String CreateNoncestr() {
String chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
String res = "";
for (int i = 0; i < 16; i++) {
Random rd = new Random();
res += chars.charAt(rd.nextInt(chars.length() - 1));
}
return res;
}
public static String FormatQueryParaMap(HashMap<String, String> parameters) throws SDKRuntimeException {
String buff = "";
try {
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(parameters.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
if (item.getKey() != "") {
buff += item.getKey() + "=" + URLEncoder.encode(item.getValue(), "utf-8") + "&";
}
}
if (buff.isEmpty() == false) {
buff = buff.substring(0, buff.length() - 1);
}
} catch (Exception e) {
throw new SDKRuntimeException(e.getMessage());
}
return buff;
}
public static String FormatBizQueryParaMap(HashMap<String, String> paraMap, boolean urlencode)
throws SDKRuntimeException {
String buff = "";
try {
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(paraMap.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey().toString());
}
});
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
// System.out.println(item.getKey());
if (item.getKey() != "") {
String key = item.getKey();
String val = item.getValue();
if (urlencode) {
val = URLEncoder.encode(val, "utf-8");
}
buff += key.toLowerCase() + "=" + val + "&";
}
}
if (buff.isEmpty() == false) {
buff = buff.substring(0, buff.length() - 1);
}
} catch (Exception e) {
throw new SDKRuntimeException(e.getMessage());
}
return buff;
}
public static boolean IsNumeric(String str) {
if (str.matches("\\d *")) {
return true;
} else {
return false;
}
}
public static String toXml(Map<String, String> arr) {
String xml = "<xml>";
Iterator<Entry<String, String>> iter = arr.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, String> entry = iter.next();
String key = entry.getKey();
String val = entry.getValue();
if (IsNumeric(val)) {
xml += "<" + key + ">" + val + "</" + key + ">";
} else
xml += "<" + key + "><![CDATA[" + val + "]]></" + key + ">";
}
xml += "</xml>";
return xml;
}
public static String mapToXMl(Map<String, String> map) {
Document doc = DocumentHelper.createDocument();
Element root = doc.addElement("xml");
Set<String> set = map.keySet();
for (String s : set) {
Element e = root.addElement(s);
e.addCDATA(map.get(s));
}
try {
//return new String(doc.asXML().getBytes(), "utf-8");
return new String(doc.asXML().getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// return doc.asXML();
return null;
/*return doc.asXML();*/
}
public static String GetBizSign(Map<String, String> bizObj, String key) throws SDKRuntimeException {
HashMap<String, String> bizParameters = new HashMap<String, String>();
List<Map.Entry<String, String>> infoIds = new ArrayList<Map.Entry<String, String>>(bizObj.entrySet());
Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
return (o1.getKey()).toString().compareTo(o2.getKey());
}
});
for (int i = 0; i < infoIds.size(); i++) {
Map.Entry<String, String> item = infoIds.get(i);
if (!"".equals(item.getKey())) {
bizParameters.put(item.getKey().toLowerCase(), item.getValue());
}
}
if (key == "") {
throw new SDKRuntimeException("key为空!");
}
String bizString = FormatBizQueryParaMap(bizParameters, false);
return MD5SignUtil.Sign(bizString, key);
}
/**
* 公众号微信支付
* @author ershuai
* @date 2016年7月18日 下午3:53:52
* @version V1.0
* @param appId
* @param noncestr
* @param packagestr
* @param singType
* @param timestamp
* @param key
* @return
* @throws SDKRuntimeException
*/
public static String GetPaySignForGzh(String appId, String noncestr, String packagestr, String singType, String timestamp, String key) throws SDKRuntimeException {
String payString = "appId="+appId+"&nonceStr="+noncestr+"&package="+packagestr+"&signType="+singType+"&timeStamp="+timestamp;
log.info("公众号支付签名串:" + payString);
return MD5SignUtil.Sign(payString, key);
}
/**
* APP微信支付
* @author ershuai
* @date 2016年7月18日 下午3:55:21
* @version V1.0
* @param appId
* @param noncestr
* @param packagestr
* @param partnerId
* @param prepayId
* @param timestamp
* @param key
* @return
* @throws SDKRuntimeException
*/
public static String GetPaySignForApp(String appId, String noncestr, String packagestr, String partnerId, String prepayId, String timestamp, String key) throws SDKRuntimeException {
//String payString = "appId="+appId+"&nonceStr="+noncestr+"&package="+packagestr+"&partnerId="+partnerId+"&prepayId="+prepayId+"&timeStamp=" + timestamp;
String payString = "appid="+appId+"&noncestr="+noncestr+"&package="+packagestr+"&partnerid="+partnerId+"&prepayid="+prepayId+"×tamp=" + timestamp;
log.info("APP支付签名串:" + payString);
return MD5SignUtil.Sign(payString, key);
}
/**
*
* @author ershuai
* @date 2016年7月5日 上午11:22:24
* @version V1.0
* @param resultCode
* @param returnMsg
* @return
*/
public static String getXMLString(String resultCode, String returnMsg) {
Map<String, String> map = new HashMap<String, String>();
map.put("return_code", resultCode);
map.put("return_msg", returnMsg);
return getXMLString(map);
}
/**
* map转xml
* @author ershuai
* @date 2016年7月5日 上午11:21:55
* @version V1.0
* @param map
* @return
*/
public static String getXMLString(Map<String, String> map) {
// Pattern pattern = Pattern.compile("^[0-9.]$");
StringBuffer sb = new StringBuffer();
sb.append("<xml version=\"1.0\" encoding=\"utf-8\">");
// String sign = map.get("sign");
if (map != null && !map.isEmpty()) {
Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
String key = it.next();
String value = map.get(key);
// if(!pattern.matcher(value).matches()){
sb.append("<" + key + ">").append(value).append("</" + key + ">");
// }else{
// sb.append("<" + key +
// ">").append("<![CDATA["+value+"]]>").append("</" + key +
// ">");
// }
}
}
// sb.append("<sign>").append(sign).append("</sign>");
sb.append("</xml>");
try {
return new String(sb.toString().getBytes(), "utf-8");
} catch (UnsupportedEncodingException e) {
}
String xmlStr = sb.toString();
log.info("getXMLString:" + xmlStr);
return xmlStr;
}
/**
* 统一xml解析
* @author ershuai
* @date 2016年7月5日 上午11:18:45
* @version V1.0
* @param request
* @return
* @throws Exception
*/
public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map<String, String> map = new HashMap<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());
log.info("e.getName():"+e.getName());
log.info("e.getText():"+e.getText());
}
// 释放资源
inputStream.close();
inputStream = null;
return map;
}
/**
* 生成预订单
* @author ershuai
* @date 2016年7月20日 下午4:07:09
* @version V1.0
* @param initType
* @param appId
* @param mchId
* @param key
* @param tradeType
* @param outTradeNo
* @param body
* @param createIp
* @param openId
* @param totalFee
* @param notifyUrl
* @return
* @throws Exception
*/
public static ThirdPayVo getPayElement(String initType, String appId, String mchId, String key, String tradeType, String outTradeNo, String body, String createIp, String openId, Double totalFee, String notifyUrl) throws Exception {
Map<String,String> params = new HashMap<String, String>();
String noncestr = CreateNoncestr();
params.put("appid", appId);
params.put("mch_id", mchId);
params.put("nonce_str", noncestr);
params.put("body", body);
params.put("input_charset", "UTF-8");
params.put("out_trade_no", outTradeNo);
params.put("total_fee", NumberUtil.formatNumber(totalFee * 100, NumberUtil.NUMBER_IN));
params.put("spbill_create_ip", createIp);
//params.put("notify_url", !CommonUtil.isNull(notifyUrl) ? notifyUrl : notifyUrl);
params.put("notify_url", notifyUrl);
params.put("trade_type", tradeType);
params.put("fee_type", "CNY");
if (!CommonUtil.isNull(openId)) {
params.put("openid", openId);
}
String sign = GetBizSign(params, key);
params.put("sign", sign);
log.info("微信预订单参数:" + params);
String xmlStr = toXml(params);
String result = HttpClientUtil.httpsRequest(Constants.unified_order_url_v3, xmlStr);
log.info("\n wechat getPayElement json \n:" + result + " \n");
Document document = DocumentHelper.parseText(result);
Element res = document.getRootElement().element("prepay_id");
ThirdPayVo initVo = null;
if (!CommonUtil.isNull(res)) {
initVo = new ThirdPayVo();
initVo.setPrepayId(res.getText());
initVo.setOutTradeNo(outTradeNo);
initVo.setTimestamp(DateUtil.getTimestampWx());//Long.toString(System.currentTimeMillis() / 1000)
initVo.setNonceStr(noncestr);
initVo.setSignType(Constants.SING_TYPE);//MD5
String paySign = null;
if ("pay".equals(initType)) {
initVo.setPackagestr("prepay_id=" + initVo.getPrepayId());
//获取签名
paySign = GetPaySignForGzh(appId, noncestr, initVo.getPackagestr(), initVo.getSignType(), initVo.getTimestamp(), key);
} else if ("appPay".equals(initType)) {//app微信支付,需要返回mchId和appId
initVo.setAppId(appId);
initVo.setMchId(mchId);
initVo.setPackagestr("Sign=WXPay");//<span style="font-family: Arial, Helvetica, sans-serif;">APP微信支付是写死的;</span>
//获取签名
paySign = GetPaySignForApp(appId, noncestr, initVo.getPackagestr(), initVo.getMchId(), initVo.getPrepayId(), initVo.getTimestamp(), key);
}
initVo.setPaySign(paySign);
log.info("返回内容:" + JSON.toJSONString(initVo));
}
return initVo;
}
}
2、MD5SignUtil
public class MD5SignUtil {
public static String Sign(String content, String key)
throws SDKRuntimeException {
String signStr = "";
if ("".equals(key)) {
throw new SDKRuntimeException("签名key不能为空!");
}
if ("".equals(content)) {
throw new SDKRuntimeException("签名内容不能为空!");
}
signStr = content + "&key=" + key;
return MD5Util.MD5(signStr).toUpperCase();
}
public static boolean VerifySignature(String content, String sign, String md5Key) {
String signStr = content + "&key=" + md5Key;
String calculateSign = MD5Util.MD5(signStr).toUpperCase();
String tenpaySign = sign.toUpperCase();
return (calculateSign == tenpaySign);
}
}
3、MD5Util
public class MD5Util {
public final static String MD5(String s) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
try {
//中文md5不一致
//byte[] btInput = s.getBytes();
//中文md5不一致
//中文md5一致
byte[] btInput=null;
try {
btInput = s.getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//中文md5一致
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String md5Str = MD5Util.MD5("中文-我长得帅");
System.out.println("加密:" + md5Str);
}
}
4、SDKRuntimeException
public class SDKRuntimeException extends Exception {
private static final long serialVersionUID = 1L;
public SDKRuntimeException(String str) {
super(str);
}
}
-----------------------------------------------util包----------------------------------------------------
微信支付回调
@RequestMapping(value = "/notifyWxPay.xhtml")
public void notifyWxPay(final HttpServletRequest request,final HttpServletResponse response) {
String resultCode = "FAIL";
String resultMsg = "this's error";
try {
log.info("**************************** 微信 服务订单 回调 开始 "+(new Timestamp(System.currentTimeMillis()))+" ************************************");
//获取微信回调信息
Map<String, String> requestParams = WxPayUtil.parseXml(request);
//return_code
String return_code = requestParams.get("return_code");
//result_code
String result_code = requestParams.get("result_code");
log.info("return_code:" + return_code);
log.info("result_code:" + result_code);
if ("SUCCESS".equals(result_code)&&"SUCCESS".equals(return_code)) {//成功回调
log.info("SUCCESS");
} else {//错误回调
log.info("FAIL");
}
} catch (Exception e) {
log.error("notifyInsurancePay 微信支付 服务订单 回调 异常:", e);
}
if ("SUCCESS".equals(resultCode)) {
log.info("**************************** 服务订单 回调成功 "+(new Timestamp(System.currentTimeMillis()))+" **********************");
} else {
log.info("**************************** 服务订单 回调失败 "+(new Timestamp(System.currentTimeMillis()))+" **********************");
}
log.info("resultCode:" + resultCode);
log.info("resultMsg:" + resultMsg);
Map<String, String> map = new HashMap<String, String>();
map.put("return_code", resultCode);
map.put("return_msg", resultMsg);
String notifyXml = WxPayUtil.toXml(map);
log.info("notifyXml after:" + notifyXml);
try {
notifyXml = new String(notifyXml.getBytes(), "ISO8859-1");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
log.error("notifyInsurancePay 微信支付 服务订单 回调 返回编码 异常:", e);
}
log.info("notifyXml:" + notifyXml);
writeSuccMsg(response, notifyXml);
}
上面的搞完了,服务端就完事了
接下来写网页
1、wxpay_test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<meta name="author" content="ershuai" />
<link rel="shortcut icon" href="../../images/zds.ico" type="image/x-icon">
<title>二帅</title>
<script type="text/javascript" src="../../scripts/common/common.js"></script>
<script type="text/javascript" src="../../scripts/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script><!-- 必须引入的JS文件 -->
<script type="text/javascript" src="../../scripts/common/weixin/weixin_common.js"></script>
<link type="text/css" href="../../styles/common/common_phone.css" rel="stylesheet" />
</head>
<body>
<input type="button" id="test_pay" value="微信支付测试" />
</body>
<script type="text/javascript">
$("#test_pay").on("click", function() {
console.log('微信支付测试…begin…');
var initUrl = window.location.href;
initOrder(initUrl, '测试订单ID');
});
</script>
</html>
2、common.js
/**
* 获取参数
* @param paramsName
* @returns
*/
function GetParams(paramsName) {
var addr = window.location;
if (addr != null && addr != '') {
var reg = new RegExp("(^|&)" + paramsName + "=([^&]*)(&|$)");
var r = addr.search.substr(1).match(reg);
if (r != null && r != '') {
return decodeURI(r[2]);
} else {
null;
}
} else {
return null;
}
}
/**
* 判断是否微信浏览器
* @returns {Boolean}
*/
function isWeiXin() {
var ua = window.navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i) == 'micromessenger'){
return true;
} else {
return false;
}
}
3、weixin_common.js
/**
* 初始化 微信支付 jsapi
* @param initUrl 当前初始化网页地址
* @param outTradeNo 需要支付订单ID
*/
function initOrder(initUrl, outTradeNo) {
if (!isWeiXin()) {
hintDiv(null, '请在微信浏览器中打开');
return false;
}
//弹起遮盖
loading('正在初始化,请稍后…');
$.ajax({
async: false,
type : "post",
url : weixin_conf_url,
data : {
"initUrl" : initUrl,
"initType" : "jsapi"
},
dataType : "json",
error : function(request) {
alert('初始化失败');
},
success : function(ajaxRes) {
closeAllIndex();
var state = ajaxRes.state;
if (state == 1) {
var data = ajaxRes.data;
//初始化微信配置
wxPayConfig(data.appId, data.timestamp, data.nonceStr, data.signature);
//支付准备
return wxPayReady(outTradeNo);
} else {
hintDiv(null, ajaxRes.msg);
return false;
}
}
});
};
/**
* 初始化微信配置
* @param appId
* @param timestamp
* @param nonceStr
* @param signature
*/
function wxPayConfig(appId, timestamp, nonceStr, signature) {
wx.config({
debug: true,
appId: appId,
timestamp: timestamp,
nonceStr: nonceStr,
signature: signature,
jsApiList: [
'checkJsApi',
'chooseWXPay',
]
});
wx.error(function (res) {
alert(res.errMsg);
});
}
/**
* 支付准备
* @param data
*/
function wxPayReady(outTradeNo) {
var openId = GetParams("openId");
if (openId == null || openId == '') {
hintDiv(null, '校验错误,请在微信端打开');
return;
}
//弹起遮盖
loading('正在生成预订单,请稍后…');
$.ajax({
async: false,
type : "post",
url : weixin_conf_url,
data : {
"outTradeNo" : outTradeNo,
"initType" : "pay",
"payWay" : "jsapi",
"openId": openId
},
dataType : "json",
error : function(request) {
hintDiv(null, '生成预订单失败');
return;
},
success : function(ajaxRes) {
closeAllIndex();
if (ajaxRes.state == 1) {
var data = ajaxRes.data;
wx.chooseWXPay({
timestamp: data.timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: data.nonceStr, // 支付签名随机串,不长于 32 位
package: data.packagestr, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***)
signType: data.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: data.paySign, // 支付签名
success: function (res) {
if(res.errMsg == "chooseWXPay:ok" ) {
//hintDiv(null, '支付成功');
return true;
} else {
//hintDiv(null, '支付错误:' + res.errMsg);
return false;
}
}
});
} else {
hintDiv(null, ajaxRes.msg);
return false;
}
}
});
}