拋開微信後臺配置不說,只要認真看一下其他的博文就可以解決
微信就是血坑,翻車了好幾次,加班通宵還幾次,終於解決了
網上都沒有完全的代碼,demo還有償,沒辦法自己研究
js:
$(function () {
zf()
})
function zf(){
$.ajax({
url: rootPath+'a/api/jssdk/wx-config',//調用方法1
type: 'GET',
dataType: 'json',
async:false,
data: {url: location.href.split('#')[0]},//回調地址,這地方測試用
complete:function (xhr,textStatus) {
var data = JSON.parse(xhr.responseText);
console.log(data);
if (data.code+""=="1") {
wx.config({
debug: false,
appId: data.appId,
timestamp:data.timestamp,
nonceStr:data.nonceStr,
signature: data.signature,
jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表
});
wx.ready(function() {
})
//點擊支付按鈕時支付
$("#zfs").click(function() {
//獲取支付金額
var active = $(".active").attr("id");
console.log(active);
//金額爲空時支付一分
if (active == undefined) {
active = "1";
}
//!!!!!!!!!重要!!!支付金額沒有小數 是:當前金額*100
$.ajax({
type: "post",
async: false,
url: rootPath + 'a/api/zf',//方法二
data: {
jes: active,//支付金額
url:location.href.split('#')[0]
}, complete: function (xhr, textStatus) {
var datas = JSON.parse(xhr.responseText);
wx.chooseWXPay({
// "appId": datas.appids.toString(), //公衆號名稱,由商戶傳入
"timestamp": datas.timestampss, //時間戳,自1970年以來的秒數
"nonceStr": datas.nonceStrss, //隨機串
"package": datas.packagess,
"signType": 'MD5', //微信簽名方式:
"paySign": datas.paySignss,
complete:function (xhr,textStatus) {
if (xhr.errMsg == "chooseWXPay:ok") {
console.log(res);
window.location.href=rootPath+"a/personal.html";
var uid=$("#uid").val();
$.ajax({
type:"post",
async:false,
url:rootPath+'xxx.xxx.xxx',
data:{
xxx:xxx
}, complete:function (xhr,textStatus) {
var data = JSON.parse(xhr.responseText);
console.log(data);
var ss=data.results;
if (data.code + "" == "1") {
alert("充值成功!");
window.location.href=rootPath+"xxxxx.xxx";
}else {
alert("充值失敗!");
}
}
})
}
}
});
}
});
})
}
}
})
}
方法1
@RequestMapping(value="/api/jssdk/wx-config")
@ResponseBody
public Map<String, Object> get_wx_config(@RequestParam(name = "url", required = false) String url ) throws ParseException {
//驗證access_token是否在有效期(可以自己寫存到數據庫)
List<Map<String, Object>> list = loginServers.select_token();
Map<String, Object> sss=list.get(0);
String t1 = sss.get("newDate").toString();
String t2 = getBeforeByHourTime(1);
DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date();
String access_token="";
if(sdf.parse(t1).getTime()>sdf.parse(t2).getTime()){
access_token=sss.get("access_token").toString();
}else {
//access_token不在有效期
try {
access_token =weChatJSSDKController.getAccessToken();
} catch (Exception e) {
e.printStackTrace();
}
loginServers.insert_token(access_token);
}
//end 驗證access_token是否在有效期
//定義返回配置JSON對象
JSONObject config = new JSONObject();
//獲取微信js-sdk開發ticket
//注意,jsapi_ticket,有效期7200秒,開發者必須在自己的服務全局緩存jsapi_ticket
//請自行保存到緩存
//本示例僅演示獲取流程
//Ticket jsApiTicket = weixin.getJsApiTicket();
//獲得jsapi_ticket之後,就可以生成JS-SDK權限驗證的簽名了。
//簽名算法
//簽名生成規則如下:
//參與簽名的字段包括noncestr(隨機字符串),有效的jsapi_ticket, timestamp(時間戳), url(當前網頁的URL,不包含#及其後面部分)。
//對所有待簽名參數按照字段名的ASCII 碼從小到大排序(字典序)後,使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串string1。
//這裏需要注意的是所有參數名均爲小寫字符。
//對string1作sha1加密,字段名和字段值都採用原始值,不進行URL轉義。
//對應我們weixin4j的開發,則已經把簽名算法寫好了
String noncestr = UUID.randomUUID().toString().substring(0, 15);
Long timestamp = new Date().getTime();
String sjc=timestamp.toString().substring(0, 10);
//注:本鏈接僅作爲演示,實際鏈接請以自己業務鏈接爲主
//String urls = "http://www.huwangnong.com/index";
Map<String, String> map=new HashMap<>();
map=JsapiTicketUtil.JsapiTicket(access_token);
String string = "jsapi_ticket="+ map.get("ticket").toString() + "&noncestr=" + noncestr + "×tamp=" + sjc + "&url="+ url;
System.out.println(url);
String signature = SHA1.encode(string);
System.out.println(timestamp);
System.out.println(map.get("ticket").toString());
System.out.println(string);
System.out.println(noncestr);
//System.out.println(urls);
System.out.println(signature);
//返回wx.config參數
sss.clear();
sss.put("appId",appids);
sss.put("code", 1);
sss.put("timestamp", sjc);
sss.put("ticket", map.get("ticket").toString());
sss.put("nonceStr", noncestr);
sss.put("signature", signature);
sss.put("url", url);
return sss;
}
方法二:
@Value("${weixin4j.oauth.appids}")
private String appids;
@Value("${weixin4j.oauth.secrets}")
private String appsecret;
@Value("${weixin4j.oauth.mch_id}")
private String mch_id; //商戶id
@Value("${weixin4j.oauth.MerchantKey}")
private String MerchantKey; //商戶密鑰
public Map<String, Object> zf1(String jes,String urls,
HttpServletRequest request, HttpServletResponse response){
//openid 用戶的!我登陸時獲取存到數據庫及session中,便於獲取
HttpSession session= request.getSession();
String openid=session.getAttribute("openid").toString();
Map<String, Object> returnMap=new HashMap<String, Object>();
String appId =appids;
String body = "xxx商品支付";
String merchantId = mch_id;
String tradeNo = String.valueOf(new Date().getTime());
String nonceStr1 = createNonceStr();
String notifyUrl = urls;
String openId = openid;
String totalFee = jes;//不可爲小數,否則報錯
TreeMap<String, String> map = new TreeMap<String, String>();
map.put("appid", appId);
map.put("mch_id", merchantId);
map.put("device_info", "WEB");
map.put("body", body);
map.put("trade_type", "JSAPI");
map.put("nonce_str", nonceStr1);
map.put("notify_url", notifyUrl);
map.put("out_trade_no", tradeNo);
map.put("total_fee", totalFee);
map.put("openid", openId);
String sign = createSign(map);
String xml = "<xml>" +
"<appid>" + appId + "</appid>" +
"<body>" + body +"</body>" +
"<device_info>WEB</device_info>" +
"<mch_id>" + merchantId + "</mch_id>" +
"<nonce_str>" + nonceStr1 + "</nonce_str>" +
"<notify_url>" + notifyUrl +"</notify_url>" +
"<openid>" + openId + "</openid>" +
"<out_trade_no>" + tradeNo + "</out_trade_no>" +
"<total_fee>" + totalFee + "</total_fee>" +
"<trade_type>JSAPI</trade_type>" +
"<sign>" + sign + "</sign>" +
"</xml>";
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String result = null;
result = HttpsUtil.httpsRequestToString(url, "POST", xml);
String reg = "<prepay_id><!\\[CDATA\\[(\\w+)\\]\\]></prepay_id>";
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(result);
String prepayId = "";
while (matcher.find()) {
prepayId = matcher.group(1);
System.out.println("預支付ID:" + prepayId);
}
Date beijingDate = Calendar.getInstance(Locale.CHINA).getTime();
String datassss=String.valueOf(beijingDate.getTime() / 1000);
String nonceStrss =createNonceStr();
//appId, timeStamp, nonceStr, package, signType
//再一次簽名,我看網上的有好多都沒說,是後來報錯了我搜索才發現要重新簽名
String stringAs="appId="+appids+"&nonceStr="+nonceStrss+"&package=prepay_id="+prepayId+"&signType=MD5&timeStamp="+datassss+"&key="+MerchantKey;
System.out.println(stringAs);
String dd = null;
try {
dd = MD5(stringAs).toUpperCase();
} catch (Exception e) {
e.printStackTrace();
}
returnMap.put("paySignss",dd);
returnMap.put("appids",appids);
returnMap.put("timestampss", datassss);
returnMap.put("nonceStrss", nonceStrss);
returnMap.put("packagess", "prepay_id=" + prepayId);
returnMap.put("signTypess", "MD5");
return returnMap;
}
/**
* 生成 MD5
*
* @param data 待處理數據
* @return MD5結果
*/
public static String MD5(String data) throws Exception {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
/**
* 生成隨機數
* <p>算法參考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3</p>
* @return 隨機數字符串
*/
public static String createNonceStr() {
SecureRandom random = new SecureRandom();
int randomNum = random.nextInt();
return Integer.toString(randomNum);
}
/**
* 生成簽名,用於在微信支付前,獲取預支付時候需要使用的參數sign
* <p>算法參考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3</p>
* @param params 需要發送的所有數據設置爲的Map
* @return 簽名sign
*/
public String createSign(TreeMap<String, String> params) {
String signValue = "";
String stringSignTemp = "";
String stringA = "";
//獲得stringA
Set<String> keys = params.keySet();
for (String key : keys) {
stringA += (key + "=" + params.get(key) + "&");
}
stringA = stringA.substring(0, stringA.length() - 1);
//獲得stringSignTemp
stringSignTemp = stringA + "&key=" + MerchantKey;
//獲得signValue
signValue = encryptByMD5(stringSignTemp).toUpperCase();
System.out.println("預支付簽名:" + signValue);
return signValue;
}
/**
* MD5加密
* @param sourceStr
* @return
*/
public static String encryptByMD5(String sourceStr) {
String result = "";
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(sourceStr.getBytes("UTF-8"));
byte b[] = md.digest();
int i;
StringBuffer buf = new StringBuffer("");
for (int offset = 0; offset < b.length; offset++) {
i = b[offset];
if (i < 0)
i += 256;
if (i < 16)
buf.append("0");
buf.append(Integer.toHexString(i));
}
result = buf.toString();
} catch (NoSuchAlgorithmException e) {
System.out.println(e);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
補發工具類:
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import java.io.*;
import java.net.URL;
public class HttpsUtil {
/**
* 以https方式發送請求並將請求響應內容以String方式返回
*
* @param path 請求路徑
* @param method 請求方法
* @param body 請求數據體
* @return 請求響應內容轉換成字符串信息
*/
public static String httpsRequestToString(String path, String method, String body) {
if (path == null || method == null) {
return null;
}
String response = null;
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader bufferedReader = null;
HttpsURLConnection conn = null;
try {
// 創建SSLConrext對象,並使用我們指定的信任管理器初始化
TrustManager[] tm = {new JEEWeiXinX509TrustManager()};
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(null, tm, new java.security.SecureRandom());
// 從上述對象中的到SSLSocketFactory
SSLSocketFactory ssf = sslContext.getSocketFactory();
System.out.println(path);
URL url = new URL(path);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(ssf);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
//設置請求方式(git|post)
conn.setRequestMethod(method);
//有數據提交時
if (null != body) {
OutputStream outputStream = conn.getOutputStream();
outputStream.write(body.getBytes("UTF-8"));
outputStream.close();
}
// 將返回的輸入流轉換成字符串
inputStream = conn.getInputStream();
inputStreamReader = new InputStreamReader(inputStream, "UTF-8");
bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
response = buffer.toString();
} catch (Exception e) {
} finally {
if (conn != null) {
conn.disconnect();
}
try {
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
} catch (IOException execption) {
}
}
return response;
}
}
package com.ruoyi.system.util;
import javax.net.ssl.X509TrustManager;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
class JEEWeiXinX509TrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
知識無價 贊助有價,有疑問可致電郵箱 [email protected]
如果你覺得這篇內容對你挺有啓發請點贊+關注