微信native支付也叫掃碼原生支付,場景就是用戶用微信的掃一掃,掃描一個商品的二維碼,掃碼成功後會出現支付界面進行付款。然而掃碼原生支付又分爲兩種:靜態native支付和動態native支付。這兩種又有什麼區別呢?通俗來講,靜態native支付就是我們可以將一個商品的信息做成一個二維碼,比如一瓶可口可樂,該商品的信息變成二維碼後多個用戶都可以掃描該二維碼進行付款購買商品。那麼動態native支付又是什麼呢?其實動態native支付也是將一個商品信息變成二維碼,與靜態native支付的區別就是,該二維碼信息中有一個訂單號的信息在裏面,一個用戶付款成功後,該二維碼就不能被其他用戶掃描支付。知道這兩種掃碼原生支付區別,我們可以根據我們自己的需求進行選擇開發。下面我們來進行靜態native支付。
開發之前,我們需要到登陸自己的服務號,進行設置原生支付URL。
步驟請參考官方文檔:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=6_3
該原生支付URL的作用就是接收用戶掃碼二維碼後微信支付系統返回的信息,根據返回的信息進行支付操作。
具體詳細流程和參數意義請參考官方文檔:http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=6_4
參考代碼如下:
package com.wingo.action.config;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts2.ServletActionContext;
import com.wingo.util.CommonUtil;
import com.wingo.util.ConfigUtil;
import com.wingo.util.IpAddressUtil;
import com.wingo.util.PayCommonUtil;
import com.wingo.util.XMLUtil;
/**
*
* @author 李欣樺
* @date 2015-1-6下午5:14:29
*
* 靜態native支付
*/
public class StaticNativeAction {
/**
* @author 李欣樺
* @date 2015-1-15上午10:06:18
* @Description:native靜態支付生成二維碼
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("time_stamp", Long.toString(new Date().getTime()));
parameters.put("nonce_str", PayCommonUtil.CreateNoncestr());
parameters.put("product_id", "No.201401051607001");//商品號要唯一
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String url = "weixin://wxpay/bizpayurl?sign=SIGN&appid=APPID&mch_id=MCHID&product_id=PRODUCTID&time_stamp=TIMESTAMP&nonce_str=NOCESTR";
String result = url.replace("SIGN", sign).
replace("APPID", ConfigUtil.APPID).
replace("MCHID", ConfigUtil.MCH_ID).
replace("PRODUCTID", (String)parameters.get("product_id")).
replace("TIMESTAMP", (String)parameters.get("time_stamp")).
replace("NOCESTR", (String)parameters.get("nonce_str"));
System.out.println("result="+result);
//TODO 將result變成二維碼
}
/**
* @author 李欣樺
* @date 2015-1-15上午10:05:46
* @Description:原生支付URL
* @throws Exception
*/
public void execute() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
HttpServletResponse response = ServletActionContext.getResponse();
/**
* 獲取用戶掃描二維碼後,微信返回的信息
*/
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
String result = new String(outSteam.toByteArray(),"utf-8");
/**
* 獲取返回的信息內容中各個參數的值
*/
Map<Object, Object> map = XMLUtil.doXMLParse(result);
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", map.get("appid"));
parameters.put("openid", map.get("openid"));
parameters.put("mch_id", map.get("mch_id"));
parameters.put("is_subscribe",map.get("is_subscribe"));
parameters.put("nonce_str", map.get("nonce_str"));
parameters.put("product_id", map.get("product_id"));
String sign = PayCommonUtil.createSign("utf-8", parameters);
/**
* 調用統一接口,返回預付id
*/
SortedMap<Object,Object> para = new TreeMap<Object,Object>();
para.put("appid", ConfigUtil.APPID);
para.put("mch_id", ConfigUtil.MCH_ID);
para.put("nonce_str", PayCommonUtil.CreateNoncestr());
para.put("body", "LEO測試NATIVE支付");
para.put("out_trade_no", "20150106003");//商戶訂單號要唯一
para.put("total_fee", "1");
para.put("spbill_create_ip",IpAddressUtil.getIpAddr(request));
para.put("notify_url", ConfigUtil.NOTIFY_URL);//支付成功後回調的action,與JSAPI相同
para.put("trade_type", "NATIVE");
para.put("product_id", map.get("product_id"));
String nativeSign = PayCommonUtil.createSign("UTF-8", para);
para.put("sign", nativeSign);
String requestXML = PayCommonUtil.getRequestXml(para);
String nativeResult =CommonUtil.httpsRequest(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
System.out.println(nativeResult);
Map<Object, Object> resultMap = XMLUtil.doXMLParse(nativeResult);
String returnCode = (String) resultMap.get("return_code");
String resultCode = (String) resultMap.get("result_code");
/**
* 發送信息給微信服務器
*/
SortedMap<Object, Object> toWX = new TreeMap<Object, Object>();
if(returnCode.equalsIgnoreCase("SUCCESS")&&resultCode.equalsIgnoreCase("SUCCESS")){
String prepayId = (String) resultMap.get("prepay_id");
toWX.put("return_code", "SUCCESS");
toWX.put("return_msg", "");
toWX.put("appid", map.get("appid"));
toWX.put("nonce_str", PayCommonUtil.CreateNoncestr());
toWX.put("prepay_id", prepayId);
String toWXSign ="";
if(map.get("sign").equals(sign)){
toWX.put("result_code", "SUCCESS");
toWXSign = PayCommonUtil.createSign("utf-8", toWX);
}else {//else的部分 暫測試未通過
toWX.put("result_code", "FAIL");
toWX.put("err_code_des", "訂單失效"); //result_code爲FAIL時,添加該鍵值對,value值是微信告訴客戶的信息
toWXSign = PayCommonUtil.createSign("utf-8", toWX);
}
toWX.put("sign", toWXSign);
response.getWriter().write(PayCommonUtil.getRequestXml(toWX));
System.out.println(PayCommonUtil.getRequestXml(toWX));
}else {
System.out.println("付款失敗!");
return ;
}
}
}
Mian方法裏是生成二維碼給用戶掃描,execute方法是我的原生支付URL回調地址。
如果不想寫代碼生成二維碼,可以上http://www.3u.cc/將main方法中打印出來的result在網上上生成二維碼。
上述代碼中相關工具類的下載地址如下:
http://download.csdn.net/detail/u011160656/8354883
支付成功後,我們需要更新我們的訂單狀態以及通知微信我們收到付款成功的通知。(調用統一支付接口時傳給微信系統的notify_url的作用體現於此)。參考內容以及如何配置notify_url請參考我另外一篇博客,博客地址如下: