最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java SpringMVC實現(xiàn)PC端網(wǎng)頁微信掃碼支付(完整版)

 更新時間:2016年11月01日 16:16:13   投稿:mrr  
這篇文章主要介紹了Java SpringMVC實現(xiàn)PC端網(wǎng)頁微信掃碼支付(完整版)的相關資料,非常不錯具有一定的參考借鑒價值,需要的朋友可以參考下

一:前期微信支付掃盲知識

前提條件是已經(jīng)有申請了微信支付功能的公眾號,然后我們需要得到公眾號APPID和微信商戶號,這個分別在微信公眾號和微信支付商家平臺上面可以發(fā)現(xiàn)。其實在你申請成功支付功能之后,微信會通過郵件把Mail轉給你的,有了這些信息之后,我們就可以去微信支付服務支持頁面:https://pay.weixin.qq.com/service_provider/index.shtml

打開這個頁面,點擊右上方的鏈接【開發(fā)文檔】會進入到API文檔說明頁面,看起來如下

選擇紅色圓圈的掃碼支付就是我們要做接入方式,鼠標移動到上面會提示你去查看開發(fā)文檔,如果這個都不知道怎么查看,可以洗洗睡了,你真的不合適做程序員,地址如下:

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1 在瀏覽器中打開之后會看到

我們重點要關注和閱讀的內容我已經(jīng)用紅色橢圓標注好了,首先閱讀【接口規(guī)則】里面的協(xié)議規(guī)范,開玩笑這個都不讀你就想做微信支付,這個就好比你要去泡妞,得先收集點基本背景信息,了解對方特點,不然下面還怎么溝通。事實證明只有會泡妞得程序員才是好銷售。跑題了我們接下來要看一下【場景介紹】中的案例與規(guī)范,只看一下記得一定要微信支付的LOGO下載下來,是為了最后放到我們自己的掃碼支付網(wǎng)頁上,這樣看上去比較專業(yè)一點。之后重點關注【模式二】

我們這里就是要采用模式二的方式實現(xiàn)PC端頁面掃碼支付功能。

微信官方對模式二的解釋是這樣的“商戶后臺系統(tǒng)先調用微信支付的統(tǒng)一下單接口,微信后臺系統(tǒng)返回鏈接參數(shù)code_url,商戶后臺系統(tǒng)將code_url值生成二維碼圖片,用戶使用微信客戶端掃碼后發(fā)起支付。注意:code_url有效期為2小時,過期后掃碼不能再發(fā)起支付”??疵靼琢税删褪俏覀兪紫纫{用微信提供統(tǒng)一下單接口,得到一個關鍵信息code_url(至于這個code_url是什么鬼,我也不知道),然后我們通過自己的程序把這個URL生成一個二維碼,生成二維碼我這里用了Google的zxing庫。然后把這個二維碼顯示在你的PC端網(wǎng)頁上就行啦。這樣終端用戶一掃碼就支付啦,支付就完成啦,看到這里你肯定很激動,發(fā)現(xiàn)微信支付如此簡單,等等還有個事情我們還不知道,客戶知道付錢了,我們服務器端還不知道呢,以微信開發(fā)人員的智商他們早就想到這個問題了,所以讓你在調用統(tǒng)一下單接口的時候其中有個必填的參數(shù)就是回調URL,就是如果客戶端付款成功之后微信會通過這個URL向我們自己的服務器提交一些數(shù)據(jù),然后我們后臺解析這些數(shù)據(jù),完成我們自己操作。這樣我們才知道客戶是否真的已經(jīng)通過微信付款了。這樣整個流程才結束,這個就是模式二。微信用一個時序圖示這樣表示這個過程的。

表達起來比較復雜,看上去比較吃力,總結一下其實我們服務器該做的事情就如下件:

1. 通過統(tǒng)一下單接口傳入正確的參數(shù)(當然要包括我們的回調URL)與簽名驗證,從返回數(shù)據(jù)中得到code_url的對應數(shù)據(jù)

2. 根據(jù)code_url的數(shù)據(jù)我們自己生成一個二維碼圖片,顯示在瀏覽器網(wǎng)頁上

3. 在回調的URL中添加我們自己業(yè)務邏輯處理。

至此掃盲結束了,你終于知道掃碼支付什么個什么樣的流程了,下面我們就一起來扒扒它的相關API使用,做好每步處理。

二:開發(fā)過程

在開發(fā)代碼之前,請先準備幾件事情。

1. 添加ZXing的maven依賴

2. 添加jdom的maven依賴

3.下載Java版本SDK演示程序,地址在這里

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

我們需要MD5Util.java和XMLUtil.java兩個文件

4. 我們使用HttpClient版本是4.5.1,記得添加Maven依賴

上面準備工作做好以后,繼續(xù)往下看:

首先我們要調用微信的統(tǒng)一下單接口,我們點擊【API列表】中的統(tǒng)一下單會看到這樣頁面:

以本人調用實際情況為例,如下的參數(shù)是必須要有的,為了大家的方便我已經(jīng)把它變成一個POJO的對象, 代碼如下:

public class UnifiedorderDto implements WeiXinConstants {
private String appid;
private String body;
private String device_info;
private String mch_id;
private String nonce_str;
private String notify_url;
private String openId;
private String out_trade_no;
private String spbill_create_ip;
private int total_fee;
private String trade_type;
private String product_id;
private String sign;
public UnifiedorderDto() {
this.appid = APPID;
this.mch_id = WXPAYMENTACCOUNT;
this.device_info = DEVICE_INFO_WEB;
this.notify_url = CALLBACK_URL;
this.trade_type = TRADE_TYPE_NATIVE;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getDevice_info() {
return device_info;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public String getOpenId() {
return openId;
}
public void setOpenId(String openId) {
this.openId = openId;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getSpbill_create_ip() {
return spbill_create_ip;
}
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
}
public int getTotal_fee() {
return total_fee;
}
public void setTotal_fee(int total_fee) {
this.total_fee = total_fee;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getProduct_id() {
return product_id;
}
public void setProduct_id(String product_id) {
this.product_id = product_id;
}
public String generateXMLContent() {
String xml = "<xml>" +
"" + this.appid + "</appid>" + 
"" + this.body + "" + 
"<device_info>WEB</device_info>" + 
"<mch_id>" + this.mch_id + "</mch_id>" + 
"<nonce_str>" + this.nonce_str + "</nonce_str>" +
"<notify_url>" + this.notify_url + "</notify_url>" + 
"<out_trade_no>" + this.out_trade_no + "</out_trade_no>" + 
"<product_id>" + this.product_id + "</product_id>" +
"<spbill_create_ip>" + this.spbill_create_ip+ "</spbill_create_ip>" +
"<total_fee>" + String.valueOf(this.total_fee) + "</total_fee>" + 
"<trade_type>" + this.trade_type + "</trade_type>" + 
"<sign>" + this.sign + "</sign>" + 
"</xml>";
return xml;
}
public String makeSign() {
String content ="appid=" + this.appid + 
"&body=" + this.body + 
"&device_info=WEB" + 
"&mch_id=" + this.mch_id + 
"&nonce_str=" + this.nonce_str + 
"?ify_url=" + this.notify_url +
"&out_trade_no=" + this.out_trade_no + 
"&product_id=" + this.product_id + 
"&spbill_create_ip=" + this.spbill_create_ip+
"&total_fee=" + String.valueOf(this.total_fee) +
"&trade_type=" + this.trade_type;
content = content + "&key=" + WeiXinConstants.MD5_API_KEY;
String esignature = WeiXinPaymentUtil.MD5Encode(content, "utf-8");
return esignature.toUpperCase();
}
}

其中各個成員變量的解釋可以參見【統(tǒng)一下單接口】的說明即可。

有這個之后我們就要要設置的內容填寫進去,去調用該接口得到返回數(shù)據(jù),從中拿到code_url的數(shù)據(jù)然后據(jù)此生成一個二維圖片,把圖片的地址返回給PC端網(wǎng)頁,然后它就會顯示出來,這里要特別說明一下,我們自己PC端網(wǎng)頁在點擊微信支付的時候就會通過ajax方式調用我們自己后臺的SpringMVC Controller然后在Controller的對應方法中通過HTTPClient完成對微信統(tǒng)一下單接口調用解析返回的XML數(shù)據(jù)得到code_url的值,生成二維碼之后返回給前臺網(wǎng)頁。Controller中實現(xiàn)的代碼如下:

Map<string,object> result=new HashMap<string,object>();
UnifiedorderDto dto = new UnifiedorderDto();
if(cash == null || "".equals(cash)) {
result.put("error", "cash could not be zero");
return result;
}
int totalfee = 100*Integer.parseInt(cash);
logger.info("total recharge cash : " + totalfee);
dto.setProduct_id(String.valueOf(System.currentTimeMillis()));
dto.setBody("repair");
dto.setNonce_str(String.valueOf(System.nanoTime()));
LoginInfo loginInfo = LoginInfoUtil.getLoginInfo();
// 通過我們后臺訂單號+UUID為身份識別標志
dto.setOut_trade_no("你的訂單號+關鍵信息,微信回調之后傳回,你可以驗證");
dto.setTotal_fee(totalfee);
dto.setSpbill_create_ip("127.0.0.1");
// generate signature
dto.setSign(dto.makeSign());
logger.info("sign : " + dto.makeSign());
logger.info("xml content : " + dto.generateXMLContent());
try {
HttpClient httpClient = HttpClientBuilder.create().build(); 
HttpPost post = new HttpPost(WeiXinConstants.UNIFIEDORDER_URL);
post.addHeader("Content-Type", "text/xml; charset=UTF-8");
StringEntity xmlEntity = new StringEntity(dto.generateXMLContent(), ContentType.TEXT_XML);
post.setEntity(xmlEntity);
HttpResponse httpResponse = httpClient.execute(post);
String responseXML = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
logger.info("response xml content : " + responseXML);
// parse CODE_URL CONTENT
Map<string, string=""> resultMap = (Map<string, string="">)XMLUtil.doXMLParse(responseXML);
logger.info("response code_url : " + resultMap.get("code_url"));
String codeurl = resultMap.get("code_url");
if(codeurl != null && !"".equals(codeurl)) {
String imageurl = generateQrcode(codeurl);
result.put("QRIMAGE", imageurl);
}
post.releaseConnection();
} catch(Exception e) {
e.printStackTrace();
}
result.put("success", "1");
return result;</string,></string,></string,object></string,object>

生成二維碼的代碼如下:

private String generateQrcode(String codeurl) {
File foldler = new File(basePath + "qrcode");
if(!foldler.exists()) {
foldler.mkdirs();
}
String f_name = UUIDUtil.uuid() + ".png";
try {
File f = new File(basePath + "qrcode", f_name);
FileOutputStream fio = new FileOutputStream(f);
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
Map hints = new HashMap();
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //設置字符集編碼類型
BitMatrix bitMatrix = null;
bitMatrix = multiFormatWriter.encode(codeurl, BarcodeFormat.QR_CODE, 300, 300,hints);
BufferedImage image = toBufferedImage(bitMatrix);
//輸出二維碼圖片流
ImageIO.write(image, "png", fio);
return ("qrcode/" + f_name);
} catch (Exception e1) {
e1.printStackTrace();
return null;
} 
}

此時如何客戶端微信掃碼之后,微信就會通過回調我們制定URL返回數(shù)據(jù)給我們。在回調方法中完成我們自己的處理,這里要特別注意的是你的回調接口必須通過HTTP POST方法實現(xiàn),否則無法接受到XML數(shù)據(jù)?;卣{處理的代碼如下:

@RequestMapping(value = "/your_callback_url", method = RequestMethod.POST)
@ResponseBody
public void finishPayment(HttpServletRequest request, HttpServletResponse response) {
try { logger.info("start to callback from weixin server: " + request.getRemoteHost());
Map<string, string=""> resultMap = new HashMap<string, string="">();
InputStream inputStream = request.getInputStream();
// 讀取輸入流
SAXBuilder saxBuilder= new SAXBuilder();
Document document = saxBuilder.build(inputStream);
// 得到xml根元素
Element root = document.getRootElement();
// 得到根元素的所有子節(jié)點
List list = root.getChildren();
Iterator it = list.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String k = e.getName();
String v = "";
List children = e.getChildren();
if(children.isEmpty()) {
v = e.getTextNormalize();
} else {
v = XMLUtil.getChildrenText(children);
}
resultMap.put(k, v);
}
// 驗證簽名!??!
/*
String[] keys = resultMap.keySet().toArray(new String[0]);
Arrays.sort(keys);
String kvparams = "";
for(int i=0; i<keys.length; i++)="" {="" if(keys[i].equals("esign"))="" continue;="" }="" 簽名算法="" if(i="=" 0)="" kvparams="" +="(keys[i]" "=" + resultMap.get(keys[i]));
} else {
kvparams += (" &"="" keys[i]="" &key=" + WeiXinConstants.MD5_API_KEY;
String md5esign = WeiXinPaymentUtil.MD5Encode(esign, " utf-8");="" if(!md5esign.equals(resultmap.get("sign")))="" return;="" }*="" 關閉流="" 釋放資源="" inputstream.close();="" inputstream="null;" string="" returncode="resultMap.get("return_code");" outtradeno="resultMap.get("out_trade_no");" 以分為單位="" int="" nfee="Integer.parseInt(resultMap.get("total_fee"));" logger.info("out="" trade="" no="" :="" outtradeno);="" logger.info("total_fee="" nfee);="" 業(yè)務處理流程="" if("success".equals(returncode))="" todo:="" your="" business="" process="" add="" here="" response.getwriter().print(xmlutil.getretresultxml(resultmap.get("return_code"),="" resultmap.get("return_code")));="" else="" resultmap.get("return_msg")));="" catch(ioexception="" ioe)="" ioe.printstacktrace();="" catch="" (jdomexception="" e1)="" e1.printstacktrace();="" }

微信官方java版demo用到的xmlutil和md5util的兩個類記得拿過來改一下,演示代碼可以在它的官方演示頁面找到,相關maven依賴如下:

<dependency>
<groupid>jdom</groupid>
jdom</artifactid>
<version>1.1</version>
</dependency>
<dependency>
<groupid>com.google.zxing</groupid>
core</artifactid>
<version>3.3.0</version>
</dependency>

最后要特別注意的是關于簽名,簽名生成MD5的類我是從微信官網(wǎng)直接下載Java版Demo程序獲取的,建議你也是,因為這個是確保MD5簽名是一致的最佳選擇。具體的生成簽名的算法可以查看微信官方文檔,這里也強烈建議大家一定要官方API說明,你開發(fā)中所遇到各種問題90%都是因為不看官方文檔,而是輕信某人博客!這個才是我寫這篇文章的真正目的和用意,根據(jù)官方文檔,用我的Java代碼實現(xiàn),微信PC端網(wǎng)頁掃碼支付必定在你的WEB應用中飛起來。

以上所述是小編給大家介紹的Java SpringMVC實現(xiàn)PC端網(wǎng)頁微信掃碼支付(完整版),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關文章

  • Java中枚舉類型的一種使用方式

    Java中枚舉類型的一種使用方式

    這篇文章主要介紹了Java中枚舉類型的一種使用方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • 什么是Spring Boot

    什么是Spring Boot

    Spring是一個非常受歡迎的Java框架,它用于構建web和企業(yè)應用。本文介紹將各種Spring的配置方式,幫助您了解配置Spring應用的復雜性
    2017-08-08
  • 開發(fā)者在Idea 中常見的配置,你都了解嗎

    開發(fā)者在Idea 中常見的配置,你都了解嗎

    idea這款java開發(fā)工具真是好用無比,不僅好用而且界面也很好看,有黑白主題,功能強大配置簡單,好了不多說了,今天給大家羅列下Idea 中常見的配置,喜歡的朋友一起看看吧
    2021-06-06
  • Java NIO和IO的區(qū)別

    Java NIO和IO的區(qū)別

    這篇文章主要介紹了Java NIO和IO的區(qū)別,需要的朋友可以參考下
    2014-06-06
  • Java中的動態(tài)綁定機制

    Java中的動態(tài)綁定機制

    這篇文章主要介紹了Java中的動態(tài)綁定機制,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • Java從入門到起飛之變量與運算符詳解

    Java從入門到起飛之變量與運算符詳解

    這篇文章主要介紹了Java編程語言中的關鍵字、標識符、變量、基本數(shù)據(jù)類型以及運算符等基本概念和用法,它涵蓋了變量聲明、賦值、類型轉換、字符串操作以及運算符優(yōu)先級等內容,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2025-03-03
  • Java設置Access-Control-Allow-Origin允許多域名訪問的實現(xiàn)方法

    Java設置Access-Control-Allow-Origin允許多域名訪問的實現(xiàn)方法

    這篇文章主要介紹了Java設置Access-Control-Allow-Origin允許多域名訪問的實現(xiàn)方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-10-10
  • springcloud本地配置優(yōu)先方式

    springcloud本地配置優(yōu)先方式

    這篇文章主要介紹了springcloud本地配置優(yōu)先方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • 解決使用this.getClass().getResource()獲取文件時遇到的坑

    解決使用this.getClass().getResource()獲取文件時遇到的坑

    這篇文章主要介紹了解決使用this.getClass().getResource()獲取文件時遇到的坑問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • 教你用JAVA寫文本編輯器(一)

    教你用JAVA寫文本編輯器(一)

    對于學習java編程的小伙伴們,常常需要編寫一個類似文本編輯器的東西,下面這篇文章主要給大家介紹了關于如何用JAVA寫文本編輯器的相關資料,需要的朋友可以參考下
    2021-11-11

最新評論

红安县| 修文县| 甘南县| 牙克石市| 上蔡县| 安庆市| 房山区| 临武县| 清丰县| 望都县| 英德市| 天镇县| 深圳市| 夏河县| 鲁甸县| 乐亭县| 莱阳市| 旌德县| 都匀市| 东宁县| 阳朔县| 桂平市| 兴国县| 南江县| 仙桃市| 襄樊市| 天等县| 新源县| 卢龙县| 开阳县| 涡阳县| 漳州市| 吉林省| 大理市| 昭通市| 工布江达县| 柳州市| 辽源市| 越西县| 麻江县| 彭州市|