微信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请参考我另外一篇博客,博客地址如下: