您的位置:首页 > 移动开发 > 微信开发

微信支付 JAVA实现

2016-08-31 17:15 295 查看
1.请求前的拼包

[java] view
plain copy







// api支付拼包------------------------------------------------------------------------------

RequestHandler reqHandler = new RequestHandler(request, response);

// TenpayHttpClient httpClient = new TenpayHttpClient();

// TreeMap<String, String> outParams = new TreeMap<String,String>();

// 初始化

reqHandler.init();

reqHandler.init(APP_ID,APP_SECRET, APP_KEY,PARTNER_KEY);

// 当前时间 yyyyMMddHHmmss

String currTime = TenpayUtil.getCurrTime();

// 8位日期

String strTime = currTime.substring(8, currTime.length());

// 四位随机数

String strRandom = TenpayUtil.buildRandom(4) + "";

// 10位序列号,可以自行调整。

String strReq = strTime + strRandom;

// 订单号,此处用时间加随机数生成,商户根据自己情况调整,只要保持全局唯一就行

String out_trade_no = strReq;

// 设置package订单参数

SortedMap<String, String
20000
> packageParams = new TreeMap<String, String>();

packageParams.put("bank_type", "WX"); // 支付类型

packageParams.put("body", "商品名称"); // 商品描述

packageParams.put("fee_type", "1"); // 银行币种

packageParams.put("input_charset", "UTF-8"); // 字符集

packageParams.put("notify_url", "通知地址,接收交易结果,并进行业务处理,例如:http://abc.com/buy/buy.do"); // 通知地址

packageParams.put("out_trade_no", out_trade_no); // 商户订单号

packageParams.put("partner", PARTNER_ID); // 设置商户号

packageParams.put("total_fee", "交易金额"); // 商品总金额,以分为单位

packageParams.put("spbill_create_ip", request.getRemoteAddr()); // 订单生成的机器IP,指用户浏览器端IP

// 获取package包

String packageValue = reqHandler.genPackage(packageParams);

String noncestr = Sha1Util.getNonceStr();

String timestamp = Sha1Util.getTimeStamp();

// 设置支付参数

SortedMap<String, String> signParams = new TreeMap<String, String>();

signParams.put("appid", appid);

signParams.put("noncestr", noncestr);

signParams.put("package", packageValue);

signParams.put("timestamp", timestamp);

signParams.put("appkey", appkey);

// 生成支付签名,要采用URLENCODER的原始值进行SHA1算法!

String sign = Sha1Util.createSHA1Sign(signParams);

// 增加非参与签名的额外参数

signParams.put("paySign", sign);

signParams.put("signType", "SHA1");

// ------------------------------------微信js

// api支付拼包结束------------------------------------

// --------------------------------本地系统生成订单-------------------------------------

//

// --------------------------------生成完成---------------------------------------------

request.setAttribute("appid", appid);

request.setAttribute("timestamp", timestamp);

request.setAttribute("noncestr", noncestr);

request.setAttribute("package", packageValue);

request.setAttribute("paysign", sign);

request.setAttribute("czje", czje);

英文全大写带下划线的,各位申请微信支付的时候都会给你的。

注意:微信demo里面RequestHandler 在设置商户key和appkey有点问题,ResponseHandler连postData都没获取到,下面把我修正后的贴出来做参考(注:其它java类没什么问题)

RequestHandler:

[java] view
plain copy







package com.zk.common.wxpay;

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.SortedMap;

import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import com.zk.common.wxpay.util.MD5Util;

import com.zk.common.wxpay.util.TenpayUtil;

/*

'微信支付服务器签名支付请求请求类

'============================================================================

'api说明:

'init(app_id, app_secret, partner_key, app_key);

'初始化函数,默认给一些参数赋值,如cmdno,date等。

'setKey(key_)'设置商户密钥

'getLasterrCode(),获取最后错误号

'GetToken();获取Token

'getTokenReal();Token过期后实时获取Token

'createMd5Sign(signParams);生成Md5签名

'genPackage(packageParams);获取package包

'createSHA1Sign(signParams);创建签名SHA1

'sendPrepay(packageParams);提交预支付

'getDebugInfo(),获取debug信息

'============================================================================

'*/

public class RequestHandler {

/** Token获取网关地址地址 */

private String tokenUrl;

/** 预支付网关url地址 */

private String gateUrl;

/** 查询支付通知网关URL */

private String notifyUrl;

/** 商户参数 */

private String appid;

private String appkey;

private String partnerkey;

private String appsecret;

private String key;

/** 请求的参数 */

private SortedMap parameters;

/** Token */

private String Token;

private String charset;

/** debug信息 */

private String debugInfo;

private String last_errcode;

private HttpServletRequest request;

private HttpServletResponse response;

/**

* 初始构造函数。

*

* @return

*/

public RequestHandler(HttpServletRequest request,

HttpServletResponse response) {

this.last_errcode = "0";

this.request = request;

this.response = response;

this.charset = "GBK";

this.parameters = new TreeMap();

// 验证notify支付订单网关

notifyUrl = "https://gw.tenpay.com/gateway/simpleverifynotifyid.xml";

}

/**

* 初始化函数。

*/

public void init(String app_id, String app_secret, String app_key,

String partner_key) {

this.last_errcode = "0";

this.Token = "token_";

this.debugInfo = "";

this.appkey = app_key;

this.appid = app_id;

this.partnerkey = partner_key;

this.key = partner_key;//原demo没有,手动加上

this.appsecret = app_secret;

}

public void init() {

}

/**

* 获取最后错误号

*/

public String getLasterrCode() {

return last_errcode;

}

/**

*获取入口地址,不包含参数值

*/

public String getGateUrl() {

return gateUrl;

}

/**

* 获取参数值

*

* @param parameter

* 参数名称

* @return String

*/

public String getParameter(String parameter) {

String s = (String) this.parameters.get(parameter);

return (null == s) ? "" : s;

}

//设置密钥

public void setKey(String key) {

this.partnerkey = key;

}

//设置微信密钥

public void setAppKey(String key){

this.appkey = key;

}

// 特殊字符处理

public String UrlEncode(String src) throws UnsupportedEncodingException {

return URLEncoder.encode(src, this.charset).replace("+", "%20");

}

// 获取package的签名包

public String genPackage(SortedMap<String, String> packageParams)

throws UnsupportedEncodingException {

String sign = createSign(packageParams);

StringBuffer sb = new StringBuffer();

Set es = packageParams.entrySet();

Iterator it = es.iterator();

while (it.hasNext()) {

Map.Entry entry = (Map.Entry) it.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

sb.append(k + "=" + UrlEncode(v) + "&");

}

// 去掉最后一个&

String packageValue = sb.append("sign=" + sign).toString();

System.out.println("packageValue=" + packageValue);

return packageValue;

}

/**

* 创建md5摘要,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。

*/

public String createSign(SortedMap<String, String> packageParams) {

StringBuffer sb = new StringBuffer();

Set es = packageParams.entrySet();

Iterator it = es.iterator();

while (it.hasNext()) {

Map.Entry entry = (Map.Entry) it.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

if (null != v && !"".equals(v) && !"sign".equals(k)

&& !"key".equals(k)) {

sb.append(k + "=" + v + "&");

}

}

sb.append("key=" + this.getKey());

System.out.println("md5 sb:" + sb);

String sign = MD5Util.MD5Encode(sb.toString(), this.charset)

.toUpperCase();

return sign;

}

/**

* 创建package签名

*/

public boolean createMd5Sign(String signParams) {

StringBuffer sb = new StringBuffer();

Set es = this.parameters.entrySet();

Iterator it = es.iterator();

while (it.hasNext()) {

Map.Entry entry = (Map.Entry) it.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

if (!"sign".equals(k) && null != v && !"".equals(v)) {

sb.append(k + "=" + v + "&");

}

}

// 算出摘要

String enc = TenpayUtil.getCharacterEncoding(this.request,

this.response);

String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();

String tenpaySign = this.getParameter("sign").toLowerCase();

// debug信息

this.setDebugInfo(sb.toString() + " => sign:" + sign + " tenpaySign:"

+ tenpaySign);

return tenpaySign.equals(sign);

}

//输出XML

public String parseXML() {

StringBuffer sb = new StringBuffer();

sb.append("<xml>");

Set es = this.parameters.entrySet();

Iterator it = es.iterator();

while(it.hasNext()) {

Map.Entry entry = (Map.Entry)it.next();

String k = (String)entry.getKey();

String v = (String)entry.getValue();

if(null != v && !"".equals(v) && !"appkey".equals(k)) {

sb.append("<" + k +">" + getParameter(k) + "</" + k + ">\n");

}

}

sb.append("</xml>");

return sb.toString();

}

/**

* 设置debug信息

*/

protected void setDebugInfo(String debugInfo) {

this.debugInfo = debugInfo;

}

public void setPartnerkey(String partnerkey) {

this.partnerkey = partnerkey;

}

public String getDebugInfo() {

return debugInfo;

}

public String getKey() {

return key;

}

}

ResponseHandler:

[java] view
plain copy







package com.zk.common.wxpay;

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.PrintWriter;

import java.io.Reader;

import java.io.UnsupportedEncodingException;

import java.util.ArrayList;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.SortedMap;

import java.util.TreeMap;

import com.zk.common.Parameters;

import com.zk.common.wxpay.util.Sha1Util;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.jdom.JDOMException;

import com.sun.org.apache.xalan.internal.xsltc.runtime.Hashtable;

import com.zk.common.wxpay.util.MD5Util;

import com.zk.common.wxpay.util.TenpayUtil;

import com.zk.common.wxpay.util.XMLUtil;

/**

* 微信支付服务器签名支付请求应答类 api说明: getKey()/setKey(),获取/设置密钥

* getParameter()/setParameter(),获取/设置参数值 getAllParameters(),获取所有参数

* isTenpaySign(),是否财付通签名,true:是 false:否 getDebugInfo(),获取debug信息

*/

public class ResponseHandler {

private static final String appkey = APP_KEY;

/** 密钥 */

private String key;

/** 应答的参数 */

private SortedMap parameters;

/** debug信息 */

private String debugInfo;

private HttpServletRequest request;

private HttpServletResponse response;

private String uriEncoding;

private Hashtable xmlMap;

private SortedMap smap;

public SortedMap getSmap() {

return smap;

}

private String k;

/**

* 构造函数

*

* @param request

* @param response

*/

public ResponseHandler(HttpServletRequest request,

HttpServletResponse response) {

this.request = request;

this.response = response;

this.smap = new TreeMap<String, String>();

this.key = "";

this.parameters = new TreeMap();

this.debugInfo = "";

this.uriEncoding = "";

Map m = this.request.getParameterMap();

Iterator it = m.keySet().iterator();

while (it.hasNext()) {

String k = (String) it.next();

String v = ((String[]) m.get(k))[0];

this.setParameter(k, v);

}

BufferedReader reader =null;

try{

reader = new BufferedReader(new InputStreamReader(request.getInputStream()));

StringBuilder sb = new StringBuilder();

String line = null;

while ((line = reader.readLine()) != null) {

sb.append(line);

}

Document doc = DocumentHelper.parseText(sb.toString());

Element root = doc.getRootElement();

for (Iterator iterator = root.elementIterator(); iterator.hasNext();) {

Element e = (Element) iterator.next();

smap.put(e.getName(), e.getText());

}

}catch (Exception e) {

// TODO: handle exception

e.printStackTrace();

}

}

/**

* 获取密钥

*/

public String getKey() {

return key;

}

/**

* 设置密钥

*/

public void setKey(String key) {

this.key = key;

}

/**

* 获取参数值

*

* @param parameter

* 参数名称

* @return String

*/

public String getParameter(String parameter) {

String s = (String) this.parameters.get(parameter);

return (null == s) ? "" : s;

}

/**

* 设置参数值

*

* @param parameter

* 参数名称

* @param parameterValue

* 参数值

*/

public void setParameter(String parameter, String parameterValue) {

String v = "";

if (null != parameterValue) {

v = parameterValue.trim();

}

this.parameters.put(parameter, v);

}

/**

* 返回所有的参数

*

* @return SortedMap

*/

public SortedMap getAllParameters() {

return this.parameters;

}

public void doParse(String xmlContent) throws JDOMException, IOException {

this.parameters.clear();

// 解析xml,得到map

Map m = XMLUtil.doXMLParse(xmlContent);

// 设置参数

Iterator it = m.keySet().iterator();

while (it.hasNext()) {

String k = (String) it.next();

String v = (String) m.get(k);

this.setParameter(k, v);

}

}

/**

* 是否财付通签名,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。

*

* @return boolean

*/

public boolean isValidSign() {

StringBuffer sb = new StringBuffer();

Set es = this.parameters.entrySet();

Iterator it = es.iterator();

while (it.hasNext()) {

Map.Entry entry = (Map.Entry) it.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

if (!"sign".equals(k) && null != v && !"".equals(v)) {

sb.append(k + "=" + v + "&");

}

}

sb.append("key=" + this.getKey());

// 算出摘要

String enc = TenpayUtil.getCharacterEncoding(this.request,

this.response);

String sign = MD5Util.MD5Encode(sb.toString(), enc).toLowerCase();

String ValidSign = this.getParameter("sign").toLowerCase();

// debug信息

this.setDebugInfo(sb.toString() + " => sign:" + sign + " ValidSign:"

+ ValidSign);

System.out.println("财付通签名:"+this.getDebugInfo());

return ValidSign.equals(sign);

}

/**

* 判断微信签名

*/

public boolean isWXsign() {

StringBuffer sb = new StringBuffer();

String keys = "";

SortedMap<String, String> signParams = new TreeMap<String, String>();

Set es = this.smap.entrySet();

Iterator it = es.iterator();

while (it.hasNext()) {

Map.Entry entry = (Map.Entry) it.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

if (k != "SignMethod" && k != "AppSignature") {

signParams.put(k.toLowerCase(), v);

}

}

signParams.put("appkey", this.appkey);

Set set = signParams.entrySet();

Iterator pit = set.iterator();

while (pit.hasNext()) {

Map.Entry entry = (Map.Entry) pit.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

if (sb.length() == 0) {

sb.append(k + "=" + v);

} else {

sb.append("&" + k + "=" + v);

}

}

String sign = Sha1Util.getSha1(sb.toString()).toString().toLowerCase();

this.setDebugInfo(sb.toString() + " => SHA1 sign:" + sign);

return sign.equals(this.smap.get("AppSignature"));

}

// 判断微信维权签名

public boolean isWXsignfeedback() {

StringBuffer sb = new StringBuffer();

Hashtable signMap = new Hashtable();

Set es = this.parameters.entrySet();

Iterator it = es.iterator();

while (it.hasNext()) {

Map.Entry entry = (Map.Entry) it.next();

String k = (String) entry.getKey();

String v = (String) entry.getValue();

if (k != "SignMethod" && k != "AppSignature") {

sb.append(k + "=" + v + "&");

}

}

signMap.put("appkey", this.appkey);

// ArrayList akeys = new ArrayList();

// akeys.Sort();

while (it.hasNext()) {

String v = k;

if (sb.length() == 0) {

sb.append(k + "=" + v);

} else {

sb.append("&" + k + "=" + v);

}

}

String sign = Sha1Util.getSha1(sb.toString()).toString().toLowerCase();

this.setDebugInfo(sb.toString() + " => SHA1 sign:" + sign);

return sign.equals(this.smap.get("AppSignature"));

}

/**

* 返回处理结果给财付通服务器。

*

* @param msg

* Success or fail

* @throws IOException

*/

public void sendToCFT(String msg) throws IOException {

String strHtml = msg;

PrintWriter out = this.getHttpServletResponse().getWriter();

out.println(strHtml);

out.flush();

out.close();

}

/**

* 获取uri编码

*

* @return String

*/

public String getUriEncoding() {

return uriEncoding;

}

/**

* 设置uri编码

*

* @param uriEncoding

* @throws UnsupportedEncodingException

*/

public void setUriEncoding(String uriEncoding)

throws UnsupportedEncodingException {

if (!"".equals(uriEncoding.trim())) {

this.uriEncoding = uriEncoding;

// 编码转换

String enc = TenpayUtil.getCharacterEncoding(request, response);

Iterator it = this.parameters.keySet().iterator();

while (it.hasNext()) {

String k = (String) it.next();

String v = this.getParameter(k);

v = new String(v.getBytes(uriEncoding.trim()), enc);

this.setParameter(k, v);

}

}

}

/**

* 获取debug信息

*/

public String getDebugInfo() {

return debugInfo;

}

/**

* 设置debug信息

*/

protected void setDebugInfo(String debugInfo) {

this.debugInfo = debugInfo;

}

protected HttpServletRequest getHttpServletRequest() {

return this.request;

}

protected HttpServletResponse getHttpServletResponse() {

return this.response;

}

}

2.Jsapi调用

在第一步中已拼好包放入request中了,第二部js调用微信api,看代码:

[javascript] view
plain copy







<script type="text/javascript">

function callpay(){

WeixinJSBridge.invoke('getBrandWCPayRequest',{

"appId" : "${appid}","timeStamp" : "${timestamp}", "nonceStr" : "${noncestr}", "package" : "${package}","signType" : "SHA1", "paySign" : "${paysign}"

},function(res){

WeixinJSBridge.log(res.err_msg);

if(res.err_msg == "get_brand_wcpay_request:ok"){

alert("微信支付成功");

}else if(res.err_msg == "get_brand_wcpay_request:cancel"){

alert("用户取消支付");

}else{

alert("支付失败");

}

});

}

</script>

点击支付按钮,调用callpay 即可。

3.微信支付后的通知接口

支付成功了,微信根据你提供的notify_url,来通知你支付成功与否,虽然js里知道了结果,但这里需要正式通知,并处理业务,下面是我的代码片段:

[java] view
plain copy







System.out.println("-----------------微信支付来消息啦--------------------------");

ResponseHandler resHandler = new ResponseHandler(request,response);

resHandler.setKey(PARTNER_KEY);

if (resHandler.isValidSign() == true) {

if (resHandler.isWXsign() == true) {

// 商户订单号

String out_trade_no = resHandler

.getParameter("out_trade_no");

// 财付通订单号

String transaction_id = resHandler

.getParameter("transaction_id");

// 金额,以分为单位

String total_fee = resHandler.getParameter("total_fee");

// 如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee

String discount = resHandler.getParameter("discount");

// 支付结果

String trade_state = resHandler

.getParameter("trade_state");

System.out.println("支付的订单号:" + out_trade_no);

// 判断签名及结果

if ("0".equals(trade_state)) {

System.out.println("哈哈,微信支付成功了");

// ------------------------------

// 即时到账处理业务开始

// ------------------------------

// 处理数据库逻辑

// 注意交易单不要重复处理

// 注意判断返回金额

// ------------------------------

// 即时到账处理业务完毕

// ------------------------------

System.out.println("success 后台通知成功");

// 给财付通系统发送成功信息,财付通系统收到此结果后不再进行后续通知

resHandler.sendToCFT("success");

} else {// sha1签名失败

System.out.println("fail -SHA1 failed");

resHandler.sendToCFT("fail");

}

} else {// MD5签名失败

System.out.println("fail -Md5 failed");

}

}

到这里OK了,支付接口完成了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: