JAVA 微信支付 native方式

     最近做了一个微信native方式支付的demo,整理一下。

    首先到微信公众号官网阅读开发文档,虽然文档对于java没有例子,但是也可以作参考。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

    我的demo是用户在商家系统H5页面发起付款申请,商家系统通过H5页面收集相关参数,调用java方法生成支付字符串返回给H5页面,H5页面将支付字符串生成二维码,用户扫描即可支付。我这是最简单的例子。先看页面吧,JSP页面中javascript脚本如下:

<script src="qrcode.js"></script>   

<script>
//这个地址是Demo.java生成的code_url,这个就是java生成的支付字符串,javascript把这个字符串变成二维码显示在页面上,用户即可扫码支付
var url="weixin://wxpay/bizpayurl?pr=30XrslD";
//参数1表示图像大小,取值范围1-10;参数2表示质量,取值范围'L','M','Q','H'
var qr = qrcode(10, 'M');
qr.addData(url);
qr.make();
var dom=document.createElement('DIV');
dom.innerHTML = qr.createImgTag();
var element=document.getElementById("qrcode");
element.appendChild(dom);
</script>

    看过了jsp页面如何使用支付字符串,那么就来看看最关键的如何用java生成这个支付二维码链接字符串。

    1、 首先看java类中需要的变量有哪些

  //微信支付商户开通后 微信会提供appid和appsecret和商户号partner
  private static String appid = ".......";
  private static String appsecret = ".........";
  //商户号,公众号支付申请通过后发给申请人的邮件中有该信息,需要用商户号登录商户平台查看用户已付款订单等等支付信息
  private static String partner = ".......";
  //这个参数partnerkey是在商户后台配置的一个32位的key,微信商户平台-账户设置-安全设置-api安全。是自己设置的,设置后自己记住。我在商户平台没有发现能查看的地方
  private static String partnerkey = "........";
  //微信支付成功后通知地址 必须要求80端口并且地址不能带参数
  private static String notifyurl = "http://localhost:8080/weChatpay/page/back.jsp";

  2、定义一个支付pojo

      

public class WxPayDto {

private String orderId;//订单号
private String totalFee;//金额
private String spbillCreateIp;//订单生成的机器 IP
private String notifyUrl;//这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等
private String body;// 商品描述根据情况修改
private String openId;//微信用户对一个公众号唯一

//getter、setter等方法

}

  3、设置支付所需参数

WxPayDto tpWxPay1 = new WxPayDto();
tpWxPay1.setBody("商品信息");
tpWxPay1.setOrderId(getNonceStr());//这个是订单号,可以根据自己系统实际需要设置,我这里其实设置的是时间戳字符串
tpWxPay1.setSpbillCreateIp("127.0.0.1");
tpWxPay1.setTotalFee("0.01");//用户需要支付的金额,单位是元
String codeurl= getCodeurl(tpWxPay1);//这个codeurl就是需要传给H5页面的支付参数了,大概是这样滴:weixin://wxpay/bizpayurl?pr=30XrslD

 4、生成支付二维码链接字符串方法

    

/**
* 获取微信扫码支付二维码连接
*/
public static String getCodeurl(WxPayDto tpWxPayDto){

// 1 参数
// 订单号
String orderId = tpWxPayDto.getOrderId();
// 附加数据 原样返回
String attach = "";
// 总金额以分为单位,不带小数点
String totalFee =tpWxPayDto.getTotalFee()*100;

// 订单生成的机器 IP
String spbill_create_ip = tpWxPayDto.getSpbillCreateIp();
// 这里notify_url是 支付完成后微信发给该链接信息,可以判断会员是否支付成功,改变订单状态等。
String notify_url = notifyurl;
String trade_type = "NATIVE";

// 商户号
String mch_id = partner;
// 随机字符串
String nonce_str = getNonceStr();//我设置的是时间戳字符串

// 商品描述根据自己系统情况修改
String body = tpWxPayDto.getBody();

// 商户订单号
String out_trade_no = orderId;

SortedMap<String, String> packageParams = new TreeMap<String, String>();
packageParams.put("appid", appid);
packageParams.put("mch_id", mch_id);
packageParams.put("nonce_str", nonce_str);
packageParams.put("body", body);
packageParams.put("attach", attach);
packageParams.put("out_trade_no", out_trade_no);

// 这里写的金额为1 分,根据自己系统实际需要到时修改
packageParams.put("total_fee", totalFee);
packageParams.put("spbill_create_ip", spbill_create_ip);
packageParams.put("notify_url", notify_url);

packageParams.put("trade_type", trade_type);

RequestHandler reqHandler = new RequestHandler(null, null);
reqHandler.init(appid, appsecret, partnerkey);

String sign = reqHandler.createSign(packageParams);
String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"
+ mch_id + "</mch_id>" + "<nonce_str>" + nonce_str
+ "</nonce_str>" + "<sign>" + sign + "</sign>"
+ "<body><![CDATA[" + body + "]]></body>"
+ "<out_trade_no>" + out_trade_no
+ "</out_trade_no>" + "<attach>" + attach + "</attach>"
+ "<total_fee>" + totalFee + "</total_fee>"
+ "<spbill_create_ip>" + spbill_create_ip
+ "</spbill_create_ip>" + "<notify_url>" + notify_url
+ "</notify_url>" + "<trade_type>" + trade_type
+ "</trade_type>" + "</xml>";
String code_url = "";
//统一支付接口
String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
code_url = new GetWxOrderno().getCodeUrl(createOrderURL, xml);
return code_url;//支付二维码链接字符串
}

   这就是最简单的java版本微信公众号扫码native支付方式demo,欢迎你交流经验问题。

  ps:这是GetWxOrderno类的全部代码

package com.utils;


import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;

import com.utils.http.HttpClientConnectionManager;

public class GetWxOrderno
{
public static DefaultHttpClient httpclient;

static
{
httpclient = new DefaultHttpClient();
httpclient = (DefaultHttpClient)HttpClientConnectionManager.getSSLInstance(httpclient);
}


/**
*description:获取预支付id
*@param url
*@param xmlParam
*@return
* @author ex_yangxiaoyi
* @see
*/
public static String getPayNo(String url,String xmlParam){
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
String prepay_id = "";
try {
httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
HttpResponse response = httpclient.execute(httpost);
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
if(jsonStr.indexOf("FAIL")!=-1){
return prepay_id;
}
Map map = doXMLParse(jsonStr);
prepay_id = (String) map.get("prepay_id");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return prepay_id;
}

/**
*description:获取扫码支付连接
*@param url
*@param xmlParam
*@return
* @author ex_yangxiaoyi
* @see
*/
public static String getCodeUrl(String url,String xmlParam){
DefaultHttpClient client = new DefaultHttpClient();
client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
HttpPost httpost= HttpClientConnectionManager.getPostMethod(url);
String code_url = "";
try {
httpost.setEntity(new StringEntity(xmlParam, "UTF-8"));
HttpResponse response = httpclient.execute(httpost);
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
if(jsonStr.indexOf("FAIL")!=-1){
return code_url;
}
Map map = doXMLParse(jsonStr);
code_url = (String) map.get("code_url");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return code_url;
}


/**
* 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
* @param strxml
* @return
* @throws JDOMException
* @throws IOException
*/
public static Map doXMLParse(String strxml) throws Exception {
if(null == strxml || "".equals(strxml)) {
return null;
}

Map m = new HashMap();
InputStream in = String2Inputstream(strxml);
SAXBuilder builder = new SAXBuilder();
Document doc = builder.build(in);
Element root = doc.getRootElement();
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 = getChildrenText(children);
}

m.put(k, v);
}

//关闭流
in.close();

return m;
}
/**
* 获取子结点的xml
* @param children
* @return String
*/
public static String getChildrenText(List children) {
StringBuffer sb = new StringBuffer();
if(!children.isEmpty()) {
Iterator it = children.iterator();
while(it.hasNext()) {
Element e = (Element) it.next();
String name = e.getName();
String value = e.getTextNormalize();
List list = e.getChildren();
sb.append("<" + name + ">");
if(!list.isEmpty()) {
sb.append(getChildrenText(list));
}
sb.append(value);
sb.append("</" + name + ">");
}
}

return sb.toString();
}
public static InputStream String2Inputstream(String str) {
return new ByteArrayInputStream(str.getBytes());
}

}

原文地址:https://www.cnblogs.com/DylanZ/p/5867287.html