Java編程調(diào)用微信支付功能的方法詳解
本文實(shí)例講述了Java編程調(diào)用微信支付功能的方法。分享給大家供大家參考,具體如下:
微信開(kāi)發(fā)文檔地址:https://mp.weixin.qq.com/wiki/home/
從調(diào)用處開(kāi)始
我的流程: 1.點(diǎn)擊“支付”按鈕,去后臺(tái) —-> 2.后臺(tái)生成支付所需數(shù)據(jù)返回頁(yè)面 —-> 3.頁(yè)面點(diǎn)擊“確認(rèn)支付”調(diào)用微信支付js。完成支付功能。
支付按鈕
<div class="button" id="pay" onclick="payBox()">支付</div>
支付按鈕js
function payBox(){
//獲得支付的錢(qián)數(shù)
var money = $(".money input").val();
//后臺(tái)路徑,加上參數(shù)
location.href = "/XXX/XXX/XXXX/XXXX?money ="+money;
}
后臺(tái)方法(例:index())
注釋?zhuān)?/strong>
getPara( ) == request.getParameter(name);
setAttr( ) == request.setAttribute(name, value);
render() == 我現(xiàn)在所用框架返回頁(yè)面的一種方法。
首先得OpenId;下面是具體方法。
public String getOpenId(){
String code = getPara("code");
String openid = "";
if (StringUtils.isEmpty(openid) && !StringUtils.isEmpty(code)) {
SnsAccessToken token = SnsAccessTokenApi.getSnsAccessToken("你的APPID","你的appsecret密碼",
code);
openid = token.getOpenid();
}
getSession().setAttribute("openandid",openid);
return openid;
}
public void index() throws Exception{
String openid = getOpenId();
//得到金額
String money= getPara("money");
Map<String ,String > map=new HashMap<String,String>();
//獲取隨機(jī)串
String nonceStr=UUID.randomUUID().toString().substring(0, 32);
//可以是支付物品的訂單號(hào)。一個(gè)號(hào)碼,看自己怎么給
String out_trade_no="123456789";
//支付金額。微信默認(rèn)支付是(1=0.01)的比例,下面是將金額換算成微信可識(shí)別的
BigDecimal re1=new BigDecimal(expressCharge);
BigDecimal re2=new BigDecimal(Float.toString(100.00f));
Float aa = re1.multiply(re2).floatValue();
String total_fee = String.valueOf(aa);
String[] smill = total_fee.split("\\.");
total_fee = smill[0];
//微信的appid
String appid="XXXXXXXXXXXXXXXXX";
String mch_id="XXXXXXXXX";//商戶(hù)號(hào)
String body="xxxxxxx";//商品信息,可以自己起最好寫(xiě)英文
//密匙,商戶(hù)平臺(tái)的支付API密匙,注意是商戶(hù)平臺(tái),不是微信平臺(tái)
String key = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX";
long timestamp = System.currentTimeMillis() / 1000;
map.put("appid", appid );
map.put("mch_id", mch_id);
map.put("nonce_str",nonceStr);
map.put("body", body);
map.put("out_trade_no", out_trade_no);
map.put("total_fee", total_fee);
map.put("spbill_create_ip",getRequest().getRemoteAddr());
//這里是支付成功后返回的地址,微信會(huì)以XML形式放回?cái)?shù)據(jù),就是本篇文章的下一類(lèi)(例:wxxml())方法名。
map.put("notify_url", "http://www.XXXX.com/XXXX/XXXX/xxxx/wxxml");
map.put("trade_type", "JSAPI");
map.put("openid", openid);//傳入OpenId
//這里傳入Map集合和key商戶(hù)支付密匙
String paySign=getPayCustomSign(map,key);
map.put("sign",paySign);
//將map轉(zhuǎn)為XML格式
String xml= ArrayToXml(map);
//統(tǒng)一下單,這里不用改
String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
String xmlStr = HttpKit.post(url, xml);
//prepayid由微信返回的 。
String prepayid = "";
if (xmlStr.indexOf("SUCCESS") != -1) {
Map<String, String> map2 = doXMLParse(xmlStr);
prepayid = (String) map2.get("prepay_id");
}
String paySign2=getPayCustomSign(signMap,key);
setAttr("model", model);
setAttr("appId", appid);
setAttr("paytimestamp", String.valueOf(timestamp));
setAttr("paynonceStr", nonceStr);
setAttr("paypackage", "prepay_id="+prepayid);
setAttr("paysignType","MD5");
setAttr("paySign", paySign2);
//去到確認(rèn)支付頁(yè)面,返回頁(yè)面方式不同,(例:pay.html頁(yè)面),下面
render("/XXXX/pay.html");
}
/**
* 獲取支付所需簽名
* @param ticket
* @param timeStamp
* @param card_id
* @param code
* @return
* @throws Exception
*/
public static String getPayCustomSign(Map<String, String> bizObj,String key) throws Exception {
String bizString = FormatBizQueryParaMap(bizObj, false);
return sign(bizString, key);
}
/**
* 字典排序
* @param paraMap
* @param urlencode
* @return
* @throws Exception
*/
public static String FormatBizQueryParaMap(Map<String, String> paraMap,
boolean urlencode) throws Exception {
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());
}
});
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 + "=" + val + "&";
}
}
if (buff.isEmpty() == false) {
buff = buff.substring(0, buff.length() - 1);
}
} catch (Exception e) {
throw new Exception(e.getMessage());
}
return buff;
}
//支付所需簽名處調(diào)用此方法
public static String sign(String content, String key)
throws Exception{
String signStr = "";
signStr = content + "&key=" + key;
return MD5(signStr).toUpperCase();
}
//上一方法,MD5加密處理
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 {
byte[] btInput = s.getBytes();
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;
}
}
//轉(zhuǎn)為XML格式
public static String ArrayToXml(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 boolean IsNumeric(String str) {
if (str.matches("\\d *")) {
return true;
} else {
return false;
}
}
//解析XML
private Map<String, String> doXMLParse(String xml)
throws XmlPullParserException, IOException {
InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
Map<String, String> map = null;
XmlPullParser pullParser = XmlPullParserFactory.newInstance()
.newPullParser();
pullParser.setInput(inputStream, "UTF-8");// 為xml設(shè)置要解析的xml數(shù)據(jù)
int eventType = pullParser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
map = new HashMap<String, String>();
break;
case XmlPullParser.START_TAG:
String key = pullParser.getName();
if (key.equals("xml"))
break;
String value = pullParser.nextText();
map.put(key, value);
break;
case XmlPullParser.END_TAG:
break;
}
eventType = pullParser.next();
}
return map;
}
pay頁(yè)面(上面步驟執(zhí)行完后去的頁(yè)面)
此處是頁(yè)面js代碼,接受后臺(tái)代碼傳回來(lái)的參數(shù)?,F(xiàn)在用的是BSL模板引擎,參數(shù)可以以EL表達(dá)式方式接收??上葘⒑笈_(tái)傳會(huì)的參數(shù),放在幾個(gè)input類(lèi)型type=”hidden”標(biāo)簽標(biāo)簽中。
<input type="hidden" name="appId" value="${appId}" id="appid" />
js中得到值
var appid = $("#appid").val();
js引用
<script type="text/javascript" src="${staticPath}/front/js/weixin.js"></script>
下面是JS代碼,由于是bsl,自己看著傳參數(shù)吧,反正都是后臺(tái)來(lái)的。
<div class="button" id="onlinePayNow">確認(rèn)支付</div>
//先寫(xiě)一個(gè)點(diǎn)擊事件,當(dāng)點(diǎn)擊id為onlinePayNow的按鈕時(shí),觸發(fā)該事件。
$("#onlinePayNow").click(function getpay(){
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{
//如果報(bào)錯(cuò),可用下面方法看看是不是參數(shù)缺少。
/* alert('${appId}');
alert('${paytimestamp}');
alert('${paynonceStr}');
alert('${paypackage}');
alert('${paysignType}');
alert('${paySign}'); */
//調(diào)用下面方法。開(kāi)啟微信支付。
onBridgeReady();
}
})
function onBridgeReady(){
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId" : '${appId}', //公眾號(hào)名稱(chēng),由商戶(hù)傳入
"timeStamp" : '${paytimestamp}', //時(shí)間戳,自1970年以來(lái)的秒數(shù)
"nonceStr" : '${paynonceStr}', //隨機(jī)串
"package" : '${paypackage}',
"signType" : '${paysignType}', //微信簽名方式:
"paySign" : '${paySign}' //微信簽名
}, function(res) {
//alert(res.err_msg); // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:res.err_msg將在用戶(hù)支付成功后返
if(res.err_msg == "get_brand_wcpay_request:ok"){
//支付成功,完成后去到哪個(gè)頁(yè)面。
window.location.href="/XXXX/xxxx.html" rel="external nofollow" ;
}
});
}
在微信公眾平臺(tái)配置,支付授權(quán)目錄。
授權(quán)目錄建議:
http://www.XXXX.com/XXXX/xxx/index/
我覺(jué)得最好寫(xiě)后臺(tái)是action地址就寫(xiě)Action地址,Controller就寫(xiě)Controller地址,如果有Spring注解,就寫(xiě)注解后名稱(chēng)。

我所導(dǎo)入的包(java后臺(tái),就是index方法。)
import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.math.BigDecimal; import java.net.URLEncoder; import java.security.MessageDigest; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import com.jfinal.kit.HttpKit; import com.uitrs.express.common.Constants;
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專(zhuān)題:《Java字符與字符串操作技巧總結(jié)》、《Java數(shù)組操作技巧總結(jié)》、《Java數(shù)學(xué)運(yùn)算技巧總結(jié)》、《Java編碼操作技巧總結(jié)》和《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
java設(shè)計(jì)模式-單例模式實(shí)現(xiàn)方法詳解
單例模式,屬于創(chuàng)建類(lèi)型的一種常用的軟件設(shè)計(jì)模式。通過(guò)單例模式的方法創(chuàng)建的類(lèi)在當(dāng)前進(jìn)程中只有一個(gè)實(shí)例(根據(jù)需要,也有可能一個(gè)線(xiàn)程中屬于單例2021-07-07
Java實(shí)現(xiàn)excel大數(shù)據(jù)量導(dǎo)入
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)excel大數(shù)據(jù)量導(dǎo)入,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
Java實(shí)現(xiàn)快速排序和堆排序的示例代碼
這篇文章主要為大家詳細(xì)介紹了快速排序和堆排序的多種語(yǔ)言的實(shí)現(xiàn)(JavaScript、Python、Go語(yǔ)言、Java、C++),感興趣的小伙伴可以了解一下2022-12-12
SpringCloud集成和使用OpenFeign的教程指南
在微服務(wù)架構(gòu)中,服務(wù)間的通信是至關(guān)重要的,SpringCloud作為一個(gè)功能強(qiáng)大的微服務(wù)框架,為我們提供了多種服務(wù)間通信的方式,其中,OpenFeign是一個(gè)聲明式的Web服務(wù)客戶(hù)端,它使得編寫(xiě)Web服務(wù)客戶(hù)端變得更加簡(jiǎn)單,本文將詳細(xì)介紹如何在SpringCloud項(xiàng)目中集成和使用OpenFeign2024-10-10
Python機(jī)器學(xué)習(xí)三大件之二pandas
這篇文章主要介紹了Python機(jī)器學(xué)習(xí)三大件之二pandas,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)Python的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05
MyBatis的模糊查詢(xún)mapper.xml的寫(xiě)法講解
這篇文章主要介紹了MyBatis的模糊查詢(xún)mapper.xml的寫(xiě)法講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
java過(guò)濾器中Filter的ChainFilter過(guò)濾鏈
這篇文章主要介紹了java過(guò)濾器中Filter的ChainFilter過(guò)濾鏈,發(fā)送請(qǐng)求時(shí),如果有不符合的信息將會(huì)被filter進(jìn)行攔截,如果符合則會(huì)進(jìn)行放行。如果感興趣可以來(lái)學(xué)習(xí)一下2020-07-07

