1. 程式人生 > >手把手教你--JAVA微信支付(公眾號支付JSAPI)

手把手教你--JAVA微信支付(公眾號支付JSAPI)

自己的第一篇部落格,請各位看官海涵!

JAVA開發微信支付-公眾號支付/微信瀏覽器支付(JSAPI)

    寫這篇文章的目的有2個,一是自己的專案剛開發完微信支付功能,趁熱回個爐溫習一下,二也是幫助像我這樣對微信支付不熟悉,反覆看了多天文件還是一知半解,原理都沒摸清,更不要說實現了。本以為網上的微信開發教程會和“java的重寫與過載”一樣鋪天蓋地,可搜出來的結果,要麼是PHP的教程(微信支付官網推薦就是PHP),要麼星星點點就那麼幾篇,想對比的看看思路都成問題,官網下載的JAVA-SDK-DEMO也恕我技術低下,看的糊里糊塗。等自己開發完的那一刻,才豁然開朗,才知道走通完支付這條路的過程走了多少彎路,我是第一次接觸支付,想必大部分能看這篇文章的兄弟也是被微信官方文件給繞的出不來才出此下策,內容有誤請指正。好了這回真正的正題了:

步驟一:獲取微信支付四大引數

    首先要想支援微信支付,必須擁有兩個賬號:①微信公眾已認證的服務號,並且需要開通微信支付該能(必須是企業才有資格申請,請你找你家產品去申請吧),②微信商戶平臺賬號;這兩個賬號一個不能少。此處已預設你已有上兩個賬號。

    此處是賬號模板,請參考:

    微信公眾平臺:賬戶:con*******om 登入密碼 ******

    公眾APPID:wx15*********a8

    APPSECEPT : c210***************892d7

    微信商戶平臺:賬戶:149**********6742 登入密碼:******

    商戶ID:14******42

    API金鑰:5d5************b35b

其中比較不好找的是商戶的API金鑰:在商戶平臺的賬戶中心下:需要使用者自行下載證書及安裝,(略)

    至此我們需要的APPID(appid),APPSECEPT(appsecret),商戶ID(mch_id),API金鑰(paternerKey),四個重要引數已拿到,括號中是我們程式碼所用的變數名稱請提前熟悉。

步驟二:平臺配置

1.配置支付目錄:商戶平臺:

點選新增

2.配置授權域名:微信公眾平臺:

    支付過程需要獲取使用者openid,必須經過網頁授權配置才可以,要不然獲取不到openid。

點選設定,按說明設定

步驟三:開發流程:

    微信支付原理(說白了就是呼叫官方文件的“統一下單”介面,之後將微信伺服器返回的引數做個加工後,返回到前臺(JSP頁面),就OK了。咱們要做的就是想方設法的湊齊統一下單的所有引數“而已”,“而已”,“而已”,這個而已也就是最大的挑戰)。所有引數解釋請參考:官方文件:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

    咱們只考慮必填引數,其他引數可以就看你的了。

    先來看看所有引數:

其中的必填引數有:

1.        appid APPID (已有)

2.        mch_id 商戶ID (已有)

3.        nonce_str 隨機字串

4.        sign 簽名

5.        body 所支付的名稱

6.        out_trade_no 咱們自己所提供的訂單號,需要唯一

7.        total_fee 支付金額

8.        spbill_create_ip IP地址

9.        notify_url 回撥地址

10.       trade_type 支付型別

11.       openid 支付人的微信公眾號對應的唯一標識

    只要把這11個湊齊就齊活,現在咱們從第3個開始一個一個的獲取;在這之前先從官網把公眾號支付的sdk下載下來,如圖

    主要是用其中的WXPayUtil工具類中的一些方法。當然其他的類我看不懂,要是看懂了,就不至於這麼費勁了。

好了開始咱們的取值之旅了:

1.        appid APPID (已有)

2.        mch_id 商戶ID (已有)

3.        nonce_str 隨機字串用WXPayUtil中的generateNonceStr()即可,就是生成UUID的方法;

4.        sign 簽名 用WXPayUtil中的generateSignature(finalMap<String, String> data, String key)方法,data是將除了sign外,其他10個引數放到map中,key是四大配置引數中的API祕鑰(paternerKey)(這裡不要著急管它,最後處理它);

5.        body 所支付的名稱

6.        out_trade_no 自己後臺生成的訂單號,只要保證唯一就好:如“2018013000001”

7.        total_fee 支付金額 單位:分,為了測試此值給1,表示支付1分錢

8.        spbill_create_ip IP地址 網上很多ip的方法,自己找,此處測試給“127.0.0.1”

9.        notify_url 回撥地址:這是微信支付成功後,微信那邊會帶著一大堆引數(XML格式)請求這個地址多次,這個地址做我們業務處理如:修改訂單狀態,贈送積分等。Ps:支付還沒成功還想這麼遠幹嘛,最後再說。地址要公網可以訪問。

10.    trade_type 支付型別 咱們是公眾號支付此處給“JSAPI”

11.    openid 支付人的微信公眾號對應的唯一標識,每個人的openid在不同的公眾號是不一樣的,這11個引數裡,最費勁的就是他了,其他的幾乎都已經解決,現在開發得到這個引數。

    獲得openid的部分內容應該不屬於微信支付的範疇,屬於微信公眾號網頁授權的東西,詳情請參考微信網頁授權:

獲得openid步驟:

第一步:使用者同意授權,獲取code

https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect

注意:1. redirect_uri引數:授權後重定向的回撥連結地址, 請使用 urlEncode 對連結進行處理。

2. scope:用snsapi_base 

    通過此連結可以獲取code,可以在一個空頁面設定一個a標籤,連結至其redirect_uri的地址。點選a標籤,即可連結到redirect_uri的地址,並攜帶code。

<a href="https://open.weixin.qq.com/connect/oauth2/authorize?
appid=wx15c*********&redirect_uri=http%3a%2f%2fwww.***.com%2fpay.jsp&response_type=code&
scope=snsapi_base#wechat_redirect">去支付頁面pay.jsp並攜帶code</a>

第二步:通過code換取網頁授權access_token(其實微信支付就沒有必要獲取access_token,咱們只要其中openid,不是要使用者資訊,此步結果已經就含有咱們需要的openid了)

獲取code,請求以下連結獲取access_token https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

上一步的code有了,對於此連結的引數就容易了。可是在頁面上如何處理是個問題,我是在pay.jsp頁面載入完成後將獲取code當做引數傳非同步到後臺,在後臺中用http相關類傳送get請求(可以自行網上查詢)。返回的JSON結果為:

{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",//就是它,只要這個值
"scope":"SCOPE" }

    好了,access_token是有了,不過咱們不關心它,咱們關心的是openid,有了它一就回到咱們“統一下單”接口裡,所有的引數已經就位就等傳送了。在回顧下11個必填引數:

1.        appid APPID (已有)

2.        mch_id 商戶ID (已有)

3.        nonce_str 隨機字串用WXPayUtil中的generateNonceStr()即可,就是生成UUID的方法;

4.        sign 簽名 用WXPayUtil中的publicstatic String generateSignature(final Map<String, String> data, Stringkey)方法,data是將除了sign外,其他10個引數放到map中,key是四大配置引數中的API祕鑰(paternerKey)(此時可以處理它了,不過其他10個引數都有了,它就easy,new一個map,依次put其他10個引數,就可以用generateSignature方法了,得到了sign,不要忘記再將sign put到只有10個引數的map,這樣才能湊齊最後的第11個引數。準備召喚神龍吧。);

5.        body 所支付的名稱

6.        out_trade_no 自己後臺生成的訂單號,只要保證唯一就好:如“2018013000001”

7.        total_fee 支付金額 單位:分,為了測試此值給1,表示支付1分錢

8.        spbill_create_ip IP地址 網上很多ip的方法,自己找,此處測試給“127.0.0.1”

9.        notify_url 回撥地址:這是微信支付成功後,微信那邊會帶著一大堆引數(XML格式)請求這個地址多次,這個地址做我們業務處理如:修改訂單狀態,贈送積分等。Ps:支付還沒成功還想這麼遠幹嘛,最後再說。地址要公網可以訪問。

10.    trade_type 支付型別 咱們是公眾號支付此處給“JSAPI”

11.    openid (已有)

    好了,準備工作完成,開始傳送POST請求吧,上面提到網上找到的get請求的方法,此處用到post請求的方法,請求微信"統一下單介面https://api.mch.weixin.qq.com/pay/unifiedorder。傳送前先用WXPayUtil工具類中的public static String mapToXml(Map<String,String> data)方法將有11個引數的map轉成XML格式。傳送後會返回String型別的返回值,如果你夠幸運的話應該會得到XML的字串:

<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
  <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  <mch_id><![CDATA[10000100]]></mch_id>
  <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
  <openid><![CDATA[oUpF8uMuAJO_M2pxb1Q9zNjWeS6o]]></openid>
  <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

    如果你得到了以上的字串,那麼先恭喜你,堅持看到這,說明你的耐心還是不錯的,因為“統一下單”介面呼叫完畢,可是並沒有什麼實際的效果,因為微信裡想出現支付的介面是在前臺完成的現在咱們還在後臺玩耍,前面提到的我是頁面載入完成時非同步到後臺的,咱們要返回非同步的結果了,好了趁熱繼續吧。“統一下單”這麼費勁的完成其實搞那麼麻煩,就是為了得到上面紅色的prepay_id(丫的,就這麼一個引數給咱們搞的都想說***了)。

    先用WXPayUtil類中的public static Map<String, String> xmlToMap(String strXML)方法,將剛才返回的XML格式的字串轉成map(為了方便取值)。map.get(“prepay_id”)就得到了prepay_id的值(比如得到的是:“wx2018…250…9981…666”),記住它,先保留此值。

看看前臺都需要接收哪些值吧。

6個引數,咱們還是一個一個分析:

1.        appId:四大引數之一的APPID;

2.        timestamp:時間戳(newDate()即可)

3.        nonceStr:隨機字串,再次用WXPayUtil中的generateNonceStr()即可;

4.        package:就tm是它用到了prepay_id,但是還不是直接取值,還非要固定格式的,值的格式例如:”prepay_id= wx2018…250…9981…666”

5.        signType:寫MD5就好

6.        paySign:又來了還是簽名演算法 ,按照上面的方法,用WXPayUtil中的publicstatic String generateSignature(final Map<String, String> data, Stringkey)方法,data是將除了paySign外,其他5個引數放到map中,key是四大配置引數中的API祕鑰(paternerKey),得到了paySign,不要忘記再將paySign put到只有5個引數的map,這樣才能湊齊最後的第6個引數。);

注意:此處有個小bug,很多人會被坑的很慘,不注意就掉坑裡,我是掉進去了,就是最關鍵的第4個引數package,眼熟不眼熟,這tm是JAVA的關鍵字,不能用來當變數名。

所有的引數有了,返回給前端的方法有很多,簡易用springMVC的@ResponseBody註解,即可將這個有6個引數的map按json格式傳給前端。好了,後臺工作完成。

    前端的工作就容易多了,格式比較固定因為是微信固定格式,所以直接貼出我的程式碼,你只要更換觸發支付的事件和非同步的地址即可.

前端簡單來說:1.一個空jsp頁面上有個a標籤,用來獲取code,並跳轉到pay.jsp(上面提到過)。

                        2.pay.jsp中需要非同步到後臺需要帶code引數,pay.jsp中頁面的地址上帶著code,想獲取code的方法很多,拋磚引引玉:(定義一個按鈕,按鈕上繫結一個code的屬性值是頁面連結的code的值,用EL表示式取的引數值,點選按鈕觸發點選事件)。

                        3.接收後臺傳過來值,呼叫固定方法。

Pay.jsp中內容只有一個”微信支付”的按鈕,和js的程式碼,以下是js內容(獲取code方法可以修改),其它內容不要修改

<!—pay.jsp中點選”微信支付”按鈕執行pay()方法>

<input id="code"type="button" value="微信支付"onclick="pay()" code="${param.code }"/>
<script type="text/javascript">
var appId,timeStamp,nonceStr,package,signType,paySign;  
 function pay(){
	var code = $("#code").attr("code");//頁面連結上的code引數
	if(code){
		var url = "http://非同步地址?code="+code+";
	  	$.get(url,function(result) {
  				appId = result.appId;
				timeStamp = result.timeStamp;
				nonceStr = result.nonceStr;
				package = result.package;
				signType = result.signType;
				paySign = result.paySign;
				
				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();
				}
			});
		} else {
			alert(“伺服器錯誤”)
		}
	}

function onBridgeReady(){
	  WeixinJSBridge.invoke( 'getBrandWCPayRequest', {
		  "appId":appId,     //公眾號名稱,由商戶傳入     
          "timeStamp":timeStamp,         //時間戳,自1970年以來的秒數     
          "nonceStr":nonceStr, //隨機串     
          "package":package,     
          "signType":signType,         //微信簽名方式:     
          "paySign":paySign //微信簽名 
         }, 
         function(res){      
      	   if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                 console.log('支付成功');
                 //支付成功後跳轉的頁面
             }else if(res.err_msg == "get_brand_wcpay_request:cancel"){
          	   console.log('支付取消');
             }else if(res.err_msg == "get_brand_wcpay_request:fail"){
          	   console.log('支付失敗');
                 WeixinJSBridge.call('closeWindow');
             } //使用以上方式判斷前端返回,微信團隊鄭重提示:res.err_msg將在使用者支付成功後返回ok,但並不保證它絕對可靠。
   });   
}
</script>

以下是後臺部分

/**
	 * @Description 微信瀏覽器內微信支付/公眾號支付(JSAPI)
	 * @param request
	 * @param code
	 * @return Map
	 */
	@RequestMapping(value="orders", method = RequestMethod.GET)
	@ResponseBody
	public Map orders(HttpServletRequest request,String code) {
		try {
			//頁面獲取openId介面
			String getopenid_url = https://api.weixin.qq.com/sns/oauth2/access_token;
			String  param= 
"appid="+你appid+"&secret="+你secret+"&code="+code+"&grant_type=authorization_code";
			//向微信伺服器傳送get請求獲取openIdStr
String openIdStr = HttpRequest.sendGet(getopenid_url, param);
			JSONObject json = JSONObject.parseObject(openIdStr);//轉成Json格式
			String openId = json.getString("openid");//獲取openId
			
			//拼接統一下單地址引數
			Map<String, String> paraMap = new HashMap<String, String>();
			//獲取請求ip地址
			String ip = request.getHeader("x-forwarded-for");
		    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
		        ip = request.getHeader("Proxy-Client-IP");
		    }
		    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
		        ip = request.getHeader("WL-Proxy-Client-IP");
		    }
		    if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
		        ip = request.getRemoteAddr();
		    }
		    if(ip.indexOf(",")!=-1){
		    	String[] ips = ip.split(",");
		    	ip = ips[0].trim();
		    }
			
			paraMap.put("appid", 你appid);  
			paraMap.put("body", "堯舜商城-訂單結算");  
			paraMap.put("mch_id", 你mchId);  
			paraMap.put("nonce_str", WXPayUtil.generateNonceStr());  
			paraMap.put("openid", openId);
			paraMap.put("out_trade_no", 你的訂單號);//訂單號
			paraMap.put("spbill_create_ip", ip);  
			paraMap.put("total_fee",”1”);  
			paraMap.put("trade_type", "JSAPI");  
			paraMap.put("notify_url",www.*******.com/***/**);// 此路徑是微信伺服器呼叫支付結果通知路徑隨意寫
			String sign = WXPayUtil.generateSignature(paraMap, paternerKey);
			paraMap.put("sign", sign);
			String xml = WXPayUtil.mapToXml(paraMap);//將所有引數(map)轉xml格式
						
			// 統一下單 https://api.mch.weixin.qq.com/pay/unifiedorder
			String unifiedorder_url = https://api.mch.weixin.qq.com/pay/unifiedorder;
	
			String xmlStr = HttpRequest.sendPost(unifiedorder_url, xml);//傳送post請求"統一下單介面"返回預支付id:prepay_id
			
			//以下內容是返回前端頁面的json資料
			String prepay_id = "";//預支付id
			if (xmlStr.indexOf("SUCCESS") != -1) {  
				Map<String, String> map = WXPayUtil.xmlToMap(xmlStr);  
				prepay_id = (String) map.get("prepay_id");  
			}
			Map<String, String> payMap = new HashMap<String, String>();
			payMap.put("appId", appid);  
			payMap.put("timeStamp", WXPayUtil.getCurrentTimestamp()+"");  
			payMap.put("nonceStr", WXPayUtil.generateNonceStr());  
			payMap.put("signType", "MD5");  
			payMap.put("package", "prepay_id=" + prepay_id);  
			String paySign = WXPayUtil.generateSignature(payMap, paternerKey);  
			payMap.put("paySign", paySign);
			return payMap;
		} catch (Exception e) {  
			e.printStackTrace();
		}  
		return null;
	}

以下是網上找的一個傳送get和post的類.僅供參考:提前匯入相關jar包可網上查詢(很容易)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;

public class HttpRequest {
    /**
     * 向指定URL傳送GET方法的請求
     * 
     * @param url
     *            傳送請求的URL
     * @param param
     *            請求引數,請求引數應該是 name1=value1&name2=value2 的形式。
     * @return URL 所代表遠端資源的響應結果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            System.out.println(urlNameString);
            URL realUrl = new URL(urlNameString);
            // 開啟和URL之間的連線
            URLConnection connection = realUrl.openConnection();
            // 設定通用的請求屬性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立實際的連線
            connection.connect();
            // 獲取所有響應頭欄位
            Map<String, List<String>> map = connection.getHeaderFields();
            // 遍歷所有的響應頭欄位
            for (String key : map.keySet()) {
                System.out.println(key + "--->" + map.get(key));
            }
            // 定義 BufferedReader輸入流來讀取URL的響應
            in = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("傳送GET請求出現異常!" + e);
            e.printStackTrace();
        }
        // 使用finally塊來關閉輸入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return result;
    }

    /**
     * 向指定 URL 傳送POST方法的請求
     * 
     * @param url
     *            傳送請求的 URL
     * @param param
     *            請求引數,請求引數應該是 name1=value1&name2=value2 的形式。
     * @return 所代表遠端資源的響應結果
     */
    public static String sendPost(String url, String param) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 開啟和URL之間的連線
            URLConnection conn = realUrl.openConnection();
            // 設定通用的請求屬性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestProperty("connection", "Keep-Alive");
            conn.setRequestProperty("user-agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 傳送POST請求必須設定如下兩行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 獲取URLConnection物件對應的輸出流
            out = new PrintWriter(conn.getOutputStream());
            // 傳送請求引數
            out.print(param);
            // flush輸出流的緩衝
            out.flush();
            // 定義BufferedReader輸入流來讀取URL的響應
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("傳送 POST 請求出現異常!"+e);
            e.printStackTrace();
        }
        //使用finally塊來關閉輸出流、輸入流
        finally{
            try{
                if(out!=null){
                    out.close();
                }
                if(in!=null){
                    in.close();
                }
            }
            catch(IOException ex){
                ex.printStackTrace();
            }
        }
        return result;
    }    
}

    ----------------------------------------------------------------------------------

以下是微信支付成功後,向自己專案傳送請求,自己來做一些業務處理。

/**
 * @ClassName WxPayController
 * @Description 微信支付成功後回撥次介面
 * @author wtao [email protected]
 * @date 2018年1月11日 下午3:10:59
 */
//回撥路徑是自己在之前已經填寫過的
@RequestMapping("/pay/")
@Controller
public class WxPayController {
	@Autowired
	private OrdersService ordersService;
	@Autowired
	private AccountService accountService;
	@Autowired
	private PointService pointService;
	
	@RequestMapping("callback")
	public String callBack(HttpServletRequest request,HttpServletResponse response){
		//System.out.println("微信支付成功,微信傳送的callback資訊,請注意修改訂單資訊");
		InputStream is = null;
		try {
			is = request.getInputStream();//獲取請求的流資訊(這裡是微信發的xml格式所有隻能使用流來讀)
			String xml = WXPayUtil.inputStream2String(is, "UTF-8");
			Map<String, String> notifyMap = WXPayUtil.xmlToMap(xml);//將微信發的xml轉map
						
			if(notifyMap.get("return_code").equals("SUCCESS")){  
	                if(notifyMap.get("result_code").equals("SUCCESS")){  
	                String ordersSn = notifyMap.get("out_trade_no");//商戶訂單號 
	                String amountpaid = notifyMap.get("total_fee");//實際支付的訂單金額:單位 分
	                BigDecimal amountPay = (new BigDecimal(amountpaid).divide(new BigDecimal("100"))).setScale(2);//將分轉換成元-實際支付金額:元
	                //String openid = notifyMap.get("openid");  //如果有需要可以獲取
	                //String trade_type = notifyMap.get("trade_type");  
	                
	                /*以下是自己的業務處理------僅做參考
	                 * 更新order對應欄位/已支付金額/狀態碼
	                 */
	                Orders order = ordersService.selectOrdersBySn(ordersSn);
	                if(order != null) {
	                	order.setLastmodifieddate(new Date());
	                	order.setVersion(order.getVersion().add(BigDecimal.ONE));
	                	order.setAmountpaid(amountPay);//已支付金額
	                	order.setStatus(2L);//修改訂單狀態為待發貨
	                	int num = ordersService.updateOrders(order);//更新order
	                	
	                	String amount = amountPay.setScale(0, BigDecimal.ROUND_FLOOR).toString();//實際支付金額向下取整-123.23--123
	                	/*
	                	 * 更新使用者經驗值
	                	 */
	                	Member member = accountService.findObjectById(order.getMemberId());
	                	accountService.updateMemberByGrowth(amount, member);
	                	
	                	/*
	                	 * 新增使用者積分數及新增積分記錄表記錄
	                	 */
	                	pointService.updateMemberPointAndLog(amount, member, "購買商品,訂單號為:"+ordersSn);
	                	
	                }
	                  
	            }  
	        }
			
	        //告訴微信伺服器收到資訊了,不要在呼叫回撥action了========這裡很重要回復微信伺服器資訊用流傳送一個xml即可
	        response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");  
			is.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

    以上純手寫,如有疏漏請聯絡,請大神勿噴.謝謝,以上是公眾號支付(在微信裡),有時間的話我再寫一個H5頁面的微信支付,請期待.

相關推薦

手把手--JAVA支付H5支付

概述 之前說過,有時間把微信支付的H5支付講解下,一直拖了半年時間,最近的專案正好又溫習了支付功能,趁著熱乎,抓緊起來。 微信的H5支付,相對公眾號支付,容易了跟多,很多相似的東西,也有不同之處,這裡只介紹H5支付的關鍵點,其他內容請先去看我的微信支付(公眾號支付)那篇文

手把手--JAVA支付公眾支付JSAPI

自己的第一篇部落格,請各位看官海涵! JAVA開發微信支付-公眾號支付/微信瀏覽器支付(JSAPI)     寫這篇文章的目的有2個,一是自己的專案剛開發完微信支付功能,趁熱回個爐溫習一下,二也是幫助像我這樣對微信支付不熟悉,反覆看了多天文件還是一知半解,原理都沒摸清,更

手把手棋牌源碼 MySQL的前綴索引

行記錄 col .com random post lte com exist nor MySQL的前綴索引 微信棋牌源碼咨詢Q 2171793408 官網地址:http://wowotouba.com/h5 MySQL的前綴索引指的是對指定的欄位的前面幾位建立的索引

三分鐘上手,手把手如何快速爆粉!

當下,在網際網路盛行的環境下,不管是做什麼企業或是產品,引流是必不可少的。缺少引流就缺少客源,缺少客源就沒有轉化率,等於沒有收益。現在,每天都有好多人在問小編,有沒有什麼引流指令碼能快速爆粉。引流指令碼網上有很多,但是使用的沒有幾個,能快速見效的就更加稀缺了。

手把手如何公眾開發“翻譯"功能

    翻譯,我想這個功能已經很常見了,而且很多地方都有實現了,另外,不只是翻譯功能,還可以是語音翻譯等等,這些都是可以實現的,所以,寫這篇文章,主要是介紹如何將公開的介面進行實際的使用。。授人以魚不如授人以漁,就是要深刻明白這個句話的含義。方法一:步驟:(1)去百度開發者中

手把手入門公眾開發

這是一篇關於微信公眾號開發的入門指南,較為詳細地介紹了開發微信公眾號的基本原理,並且有相應的程式碼實現。如果您正打算要做公眾號開發,卻又苦於找不到一份簡潔明瞭的入門級教學文件,那麼這篇部落格應該能解決您的問題。 緣起 近日騰訊釋出2017年中報,報告中

手把手實現小程式中的自定義元件

前言 之前做小程式開發的時候,對於開發來說比較頭疼的莫過於自定義元件了,當時官方對這方面的文件也只是寥寥幾句,一筆帶過而已,所以寫起來真的是非常非常痛苦!! 好在微信小程式的庫從 1.6.3 開始,官方對於自定義元件這一塊有了比較大的變動,首先比較明顯的感覺就是文件

手把手實現小程式客服會話聊天,智慧小程式客服!

如果你是一個經常需要接待使用者的小程式,可能已經給小程式添加了一個簡單的客服功能按鈕,讓使用者更主動和你互動! 客服人員可以直接使用微信公眾平臺網頁版客服工具進行客服訊息回覆。或者使用更智慧的第三方小程式客服,來實現更多多維度的操作! 比如多達 15 中的自動回覆,以及多

知識全聚集 .Net Core 技術突破 | 我用C#手把手自動化一

# 知識全聚集 .Net Core 技術突破 | 我用C#手把手教你玩微信自動化一 # 教程 [01 | 模組化方案一](https://www.cnblogs.com/MrChuJiu/p/13689123.html) [02 | 模組化方案二](https://www.cnblogs.com/M

網頁授權-公眾支付獲取openid、用戶息等

blog red code rect ref true 說明 oauth2 具體細節 名詞解釋: openid 用戶唯一標識,請註意,在未關註公眾號時,用戶訪問公眾號的網頁,也會產生一個用戶和公眾號唯一的OpenID 業務功能描述:實現H

手把手使用simulink配合STM32CUBEMX 生成keil專案實戰

本文的作者在自學過程中發現該類資料的缺少 以及前人敘述不夠完善的情況下 進行了本文的創作 文章將一步一步的講解如何使用simulink將F4的燈點亮 更多的功能我們一起探索 別的型號的 cpu 大家可以類比進行。 1.首先是將MATLAB安裝ST官方的STM32-MAT/TARGET開發庫

手把手打印出PDFfpdf的簡單應用

  正值奧運時期,一覺醒來有種想用PHP列印PDF來記錄各國金牌的想法,即使中國隊那麼不爭氣我也忍了。 今天使用的類叫FPDF,FPDF這個PHP Class允許你採用純PHP(更確切地說就是不需要使用PDFlib)來生成PDF檔案。它以PHP Class展現並且

如何玩轉小程序+公眾手把手JeeWx小程序CMS與公眾關聯

進行 follow .com 使用 更新 官方 功能 net 入口 隨著微信小程序新功能、新入口的不斷更新,小程序的商業價值逐步增強,特別是小程序與公眾號的深度融合,已經讓小程序成為各行業新的營銷渠道。Jeewx平臺專註小程序的開發,逐步完善小程序生態圈,通過簡單操作即

tp5引用js_sdk進行公眾支付

thinkphp5引用微信js_sdk進行公眾號支付 我在這個過程中用的是微信提供的js-sdk( 官方下載地址為:js_sdk下載地址 );  在這裡我們進行的是 1.  以下我實際開發中採用的的是tp5框架 ,我把js-sdk放在了 vendor資料夾下 也就是

名師帶開發Java

IT 視頻 ava 14. ade BE src pict idt ======================================================= 長期更新IT編程視頻教程,資料收集整理不易,需要一點費用 有意者加QQ:277

java 網頁版 找出刪除好友翻譯修改自python指令碼)

使用的微信網頁版介面來源自 gaosen的python 指令碼  ,地址: https://github.com/0x5e/wechat-deleted-friends gaosen的python程式碼中在拉取微信通訊錄的好友介面上沒有加上相關的認證引數,導致該pytho

手把手Chrome瀏覽器安裝Postman含下載雲盤鏈接(轉)

地址欄 用戶 width 選擇 如圖所示 新版 調試 img 發送 文章轉自http://www.ljwit.com/archives/php/278.html 說明: Postman不多介紹,是一款功能強大的網頁調試與發送網頁HTTP請求的Chrome插件。本文主要介紹下

理解小程序的生命周期和運行原理

navi androi bottom 頁面跳轉 onerror 一起 底部tab 更新數據 激活 轉自:http://blog.csdn.net/tsr106/article/details/53052879 寫微信小程序,他的生命周期不能不知道,不知道小程序就會

一站式手把手學習Sublime Text 3插件安裝、html/css速寫、輸入法不跟隨光標

Sublime Text 3 插件安裝 html/css速寫 輸入法不跟隨光標 Sublime Text 是一款流行的代碼編輯器軟件,也是HTML和散文先進的文本編輯器,可運行在Linux,Windows和Mac OS X。也是許多程序員喜歡使用的一款文本編輯器軟件。下面就重點介紹一下Subl

python每天給女朋友說晚安

threading 每次 r.js 圖片 return AC code on() pre 但凡一件事,稍微有些重復。我就考慮怎麽樣用程序來實現它。 這裏給各位程序員朋友分享如何每天給朋友定時微信發送”晚安“,故事,新聞,等等··· ···最好運行在服務器上,這樣後臺掛起來更