微信支付功能(代码开发)
上一篇文章已经告诉大家如何配置来获取微信提供的参数。在这里再问问自己是否拿到以下参数:
1.开发者ID(AppID)
2.商户ID
3.支付key(需要加密的MD5)
PS(已通过微信认证的公众号,必须通过ICP备案域名(否则会报支付失败))
以下图了解一下大概流程就行了,能完全掌握更好。
如果都拿到了就开始把支付的代码嵌入到项目中来调起支付接口(眼睛擦干净点啊,下面的参数都是有规则滴 区分大小写,我就是在这里卡了我很久,enmmmmmmmp不知该讲不讲唉)
在这里感谢提供文章帮助我的大神,就不一一道谢了
涉及到相关帮助文章或者下载地址
1、https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140(PS:由于微信支付时调试,不能用浏览器打开微信路径,会提示要求你在微信浏览器打开该路径,所以去下载微信web开发者工具)
2、https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=3_1 (微信支付开发文档,好好看看这里面的支付相关规则)
3、https://blog.youkuaiyun.com/xb12369/article/details/50512633 (微信支付,body不是UTF-8)
4、https://pay.weixin.qq.com/wiki/doc/api/danpin.php?chapter=9_102&index=2# (统一下单API)
5、https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1 (微信支付接口签名校验工具)
流程如下:
1.在用户点击下单后,创建完订单成功后,返回到JS里面进行跳转时,路径为以下:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=xxxxxxxxxxxxxxxx&redirect_uri=http://m.xxxxxxx.com/xxxxxx/xxxxxx/selectpay.html?ord_id="+ret.body.ord_id+"&response_type=code&scope=snsapi_base&state=STATE&connect_redirect=1#wechat_redirect
具体而言,这一步是用来获取code,但必须用户同意网页授权后才能得到code值(为什么要code后面再来解释)在微信中打开这个授权链接,会进入到如下图所示页面:
单击取消或允许按钮,都会进入到上面设置的回调页面。如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。若用户禁止授权,则重定向后不会带上code参数,仅会带上state参数redirect_uri?state=STATE
【code说明 】:
code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
【参数说明】:
|
分解路径:
appid:填写开发者ID
redirect_uri:重定向页面,跳转到你需要进行支付的页面
ord_id:订单ID需要查询
可自己参考
https://www.cnblogs.com/goflee/p/3484561.html
这时候已经拿到code了,还有其他参数。我的重定向是selectpay.html。
2.在selectpay.html页面 js里面获取code还有其他参数(根据自己代码去写)
ajaxGetJson({
url:"json.html?formatId=byypOrderSelectPayTrade",
data:{"ord_id":URLParams.get("ord_id")},
success:function(ret){
if(ret.head.code == "0000"){
$("#selectpay").html(template("tpl-selectpay",ret.body));
getWXUserOpenId();
}else{
jDialog.confirm("支付数据加载失败!",function(r){
if(r){
myLocationReload();
}else{
location.href = './ucenter/myorder.html';
}
},false,"重试","返回订单");
}
}
});
将数据绑定好在来获取code相关参数
//获取用户的openId
function getWXUserOpenId(){
var access_code = getQueryString('code');
if(access_code != null){
code = access_code;
}
}
//获取微信url回调参数
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = location.search.substr(1).match(reg);
if (r != null)
return unescape(decodeURI(r[2]));
return null;
}
code在用户点击支付时会提交到后台去。
var appId = "";
var timeStamp = "";
var nonceStr = "";
var signType = "";
var paySign = "";
var code = "";
var openId = "";
var pg = "";
var trade_no = "";
$(document).on("click","#go-pay-btn",function(){
if(code != ""){
ajaxGetJson({
url:"json.html?formateId=generateByypGoodsPayment",
data:{"ord_id":URLParams.get("ord_id"),"code":code},
error: function(textStatus){alert('系统错误~');},
success:function(msg){
/*if(msg.head.code == "0000"){
location.href = "./paysuccess.html?ord_id="+URLParams.get("ord_id");
}else{
location.href = "./payfail.html?ord_id="+URLParams.get("ord_id");
}*/
if(msg.head.code == "0000"){
if(msg!=null){
appId = msg.body.appid;
timeStamp = msg.body.timestamp;
nonceStr = msg.body.nonceStr;
signType = msg.body.signType;
paySign = msg.body.sign;
pg = msg.body.package;
trade_no = msg.body.out_trade_no;
//唤起微信支付
if(appId!=''){
pay();
}
}
}else{
location.href = "./payfail.html?ord_id="+URLParams.get("ord_id");
}
}
})
}else{
alert("授权失败,请联系技术人员!");
}
});
//唤起微信支付
function pay(){
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();
}
}
//开始支付
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : appId, //公众号名称,由商户传入
"timeStamp": timeStamp+"", //时间戳,自1970年以来的秒数
"nonceStr" : nonceStr, //随机串
"package" : pg,
"signType" : signType, //微信签名方式:
"paySign" : paySign, //微信签名
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
//alert("支付成功"); // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。
//回到用户订单列表
//location.href = "./yppaynotice.html";
//location.href = "./paysuccess.html?ord_id="+URLParams.get("ord_id");
updateByypOrderInfo(URLParams.get("ord_id"),trade_no);
}else if (res.err_msg == "get_brand_wcpay_request:cancel") {
//alert("支付过程中用户取消");
location.href = "./sensorweb/mall/ucenter/mybyyporder.htmlmyorder.html?ord_status=11";
}else{
//支付失败
alert(JSON.stringify(res));
alert(res.err_msg)
}
}
);
}
3.再控制器里面生成微支付需要的参数返回在js页面(话不多说直接贴代码)
//log.info("微信生成支付码开始");
// String user_id = MemUserConstant.getUserId(ctx);
String ord_id=ctx.getPostString("ord_id");//1.获取传入数据 得到商品详情
String code=ctx.getPostString("code");//code
//out_trade_no商户订单号 以下是组成是由规则的,查看微信开发文档,基本上要是数字
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
String randomDate = format.format(new Date());
int randomNum = (int) (Math.random() * 1000000);
String out_trade_no = ("190008"+randomDate+randomNum).toString();
System.out.println("商户号是:"+out_trade_no);
Map<String, String> jsonObject = new HashMap<String,String>();
WxConfig wxConfig = new WxConfig();
//根据用户授权后 页面传入code到后台 获取openId
String openid = HttpXmlUtils.getOpenId(code);
System.out.println("openid是:"+openid);
//getSumTotal 微信的价格单位是分(x100),所以intValue 不存在精度丢失的问题
// int total_fees = (trans.getTotal().intValue() - userBonus - userYqh)*100;
int total_fee = 1;//一分钱测试
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 (统一下单开发文档,参数规则)
//String detail = "{goods_id:商品编码,wxpay_goods_id:1001,goods_name:充电宝,quantity: 1,price: 528800}"; //测试数据格式
String wxPayResult = WxPayUnifiedResult.getWxPayUnifiedResult("111","2222","3333",out_trade_no, total_fee, "119.123.66.183",openid);
Map<String, String> oppidObj = WXPayUtil.xmlStr2Map(wxPayResult);//将xml字符串解析为map
//1.生成签名后,这里需要得到状态是否成功,如果不成功则提示信息(等测试通过后在来设置)
//2.再检查是否有sing签名
//log.info("生成签名:"+wxPayResult);
String timestamp = String.valueOf(new Date().getTime()/1000);
String nonceStr = oppidObj.get("nonce_str").toString();
System.out.println(nonceStr);
String prepay_id = oppidObj.get("prepay_id").toString(); //需要获得prepay_id(能得到它,离成功越来越近了)
System.out.println(prepay_id);
//参数:开始生成签名
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appId", wxConfig.getAppid()); //区分大小写的,
parameters.put("timeStamp", timestamp);
parameters.put("signType", "MD5");
parameters.put("nonceStr", nonceStr);
parameters.put("package", "prepay_id="+prepay_id);
String sign = WXSignUtils.createSign(parameters);
System.out.println("预支付id相关参数是:"+jsonObject.toString());
Map<String,Object> body = new HashMap<String,Object>();
body.put("appid", wxConfig.getAppid());
body.put("timestamp", timestamp);
body.put("signType", "MD5");
body.put("nonceStr", nonceStr);
body.put("package", "prepay_id="+prepay_id);
body.put("sign", sign);
body.put("prepay_id", prepay_id);
body.put("out_trade_no", out_trade_no);
RsjConstant.setSuccess(ctx, body);//5.返回数据
注意事项:
这里要看清楚了,生成签名时key是区分大小写的,生成签名时key是区分大小写的,生成签名时key是区分大小写的,重要的事情要说3遍。否则会提示你参数有误(本人就被这个坑了很久)
以下是一些公共类,也给你们贴出来
WxConfig.java
// 应用APPID【appid】
public String appid;
// 微信支付商户号【mch_id】
public String mch_id;
// 回调地址
public String notify_url;
public String getAppid() {
return "wxb550b5eda3fa1234";
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMch_id() {
return "1498876564";
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNotify_url() {
return "http://m.buysensor.com/sensor/mall/yppaynotice.do";支付成功回调方法,成功后微信会调用这个方法,要在控制器里面写一个方法
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
HttpXmlUtil.java
页面上获取code就是用在这里来获取用户openId(可以先用main方法来测试 是否可以得到)
//根据提供的code查询得到openId
public static String getOpenId(String code) throws ServletException, IOException {
String appid = "wxb550be2d43a48142"; //开发者ID
String secret = "df2dtt2rw3e4fghha11073b4dfca559c"; //开发者密码(如果忘记密码了就重置就好了)
//这个路径可以改动,只要是微信有的接口都行
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+appid+"&secret="+secret+"&code="+code+"&grant_type=authorization_code";
//第一次请求 获取access_token 和 openid
// System.out.println(requestUrl);
String oppid = null;
try {
oppid = new HttpXmlUtils().doGet(requestUrl);
} catch (Exception e) {
e.printStackTrace();
}
JSONObject oppidObj =JSONObject.fromObject(oppid); //根据不同的返回结果,读取不同key
String openid = (String) oppidObj.get("openid");
return openid;
}
/**
* post请求并得到返回结果
* @param requestUrl
* @param requestMethod
* @param output
* @return
*/
public static String httpsRequest(String requestUrl, String requestMethod, String output) {
try{
URL url = new URL(requestUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setRequestMethod(requestMethod);
if (null != output) {
OutputStream outputStream = connection.getOutputStream();
outputStream.write(output.getBytes("UTF-8"));
outputStream.close();
}
// 从输入流读取返回内容
InputStream inputStream = connection.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = bufferedReader.readLine()) != null) {
buffer.append(str);
}
bufferedReader.close();
inputStreamReader.close();
inputStream.close();
inputStream = null;
connection.disconnect();
return buffer.toString();
}catch(Exception ex){
ex.printStackTrace();
}
return "";
}
/**
* 微信htpp传输,并返回数据
*/
public String doGet(String url) throws Exception {
URL localURL = new URL(url);
URLConnection connection = openConnection(localURL);
HttpURLConnection httpURLConnection = (HttpURLConnection)connection;
httpURLConnection.setRequestProperty("Accept-Charset", charset);
httpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
InputStream inputStream = null;
InputStreamReader inputStreamReader = null;
BufferedReader reader = null;
StringBuffer resultBuffer = new StringBuffer();
String tempLine = null;
if (httpURLConnection.getResponseCode() >= 300) {
throw new Exception("HTTP Request is not success, Response code is " + httpURLConnection.getResponseCode());
}
try {
inputStream = httpURLConnection.getInputStream();
inputStreamReader = new InputStreamReader(inputStream,"UTF-8");
reader = new BufferedReader(inputStreamReader);
while ((tempLine = reader.readLine()) != null) {
resultBuffer.append(tempLine);
}
} finally {
if (reader != null) {
reader.close();
}
if (inputStreamReader != null) {
inputStreamReader.close();
}
if (inputStream != null) {
inputStream.close();
}
}
return resultBuffer.toString();
}
private URLConnection openConnection(URL localURL) throws IOException {
URLConnection connection;
if (proxyHost != null && proxyPort != null) {
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
connection = localURL.openConnection(proxy);
} else {
connection = localURL.openConnection();
}
return connection;
}
private String charset = "utf-8";
private Integer connectTimeout = null;
private Integer socketTimeout = null;
private String proxyHost = null;
private Integer proxyPort = null;
public static String xmlInfo(UnifiedOrder unifiedorder){
//构造xml参数的时候,至少有10个必传参数
/*
* <xml>
<appid>wx2421b1c4370ec43b</appid>
<attach>支付测试</attach>
<body>JSAPI支付测试</body>
<mch_id>10000100</mch_id>
<nonce_str>1add1a30ac87aa2db72f57a2375d8fec</nonce_str>
<notify_url>http://wxpay.weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url>
<openid>oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid>
<out_trade_no>1415659990</out_trade_no>
<spbill_create_ip>14.23.150.211</spbill_create_ip>
<total_fee>1</total_fee>
<trade_type>JSAPI</trade_type>
<sign>0CB01533B8C1EF103065174F50BCA001</sign>
</xml>
*/
if(unifiedorder!=null){
StringBuffer bf = new StringBuffer();
bf.append("<xml>");
bf.append("<appid><![CDATA[");
bf.append(unifiedorder.getAppid());
bf.append("]]></appid>");
bf.append("<body><![CDATA[");
bf.append(unifiedorder.getBody());
bf.append("]]></body>");
bf.append("<mch_id><![CDATA[");
bf.append(unifiedorder.getMch_id());
bf.append("]]></mch_id>");
bf.append("<nonce_str><![CDATA[");
bf.append(unifiedorder.getNonce_str());
bf.append("]]></nonce_str>");
bf.append("<notify_url><![CDATA[");
bf.append(unifiedorder.getNotify_url());
bf.append("]]></notify_url>");
bf.append("<openid><![CDATA[");
bf.append(unifiedorder.getOpenid());
bf.append("]]></openid>");
bf.append("<out_trade_no><![CDATA[");
bf.append(unifiedorder.getOut_trade_no());
bf.append("]]></out_trade_no>");
bf.append("<spbill_create_ip><![CDATA[");
bf.append(unifiedorder.getSpbill_create_ip());
bf.append("]]></spbill_create_ip>");
bf.append("<total_fee><![CDATA[");
bf.append(unifiedorder.getTotal_fee());
bf.append("]]></total_fee>");
bf.append("<trade_type><![CDATA[");
bf.append(unifiedorder.getTrade_type());
bf.append("]]></trade_type>");
bf.append("<detail><![CDATA[");
bf.append(unifiedorder.getDetail());
bf.append("]]></detail>");
bf.append("<attach><![CDATA[");
bf.append(unifiedorder.getAttach());
bf.append("]]></attach>");
bf.append("<time_start><![CDATA[");
bf.append(unifiedorder.getTime_start());
bf.append("]]></time_start>");
bf.append("<time_expire><![CDATA[");
bf.append(unifiedorder.getTime_expire());
bf.append("]]></time_expire>");
bf.append("<sign><![CDATA[");
bf.append(unifiedorder.getSign());
bf.append("]]></sign>");
bf.append("</xml>");
return bf.toString();
}
return "";
}
WxPayUnifiedResult.java
/**
* @param body
* @param detail
* @param attach
* @param out_trade_no 商户号(自定义生成 必须数字组成 30个数字内)
* @param total_fee
* @param spbill_create_ip 提交ip地址
* @param openid 用户ID
* 获得prepay_id(得到这个参数支付功能成功一半)
* @return
*/
public static String getWxPayUnifiedResult(String body,String detail,String attach,String out_trade_no,int total_fee,String spbill_create_ip,String openid){
WxConfig wxConfig = new WxConfig();
try{
//应用APPID【appid】
String appid = wxConfig.getAppid();
System.out.println("appid是:"+appid);
//微信支付商户号【mch_id】
String mch_id = wxConfig.getMch_id();
System.out.println("mch_id是:"+mch_id);
//回调地址
String notify_url = wxConfig.getNotify_url();
System.out.println("回调地址是:"+notify_url);
//随机字符串
String nonce = UUID.randomUUID().toString().substring(0,30);
String nonce_str = nonce;
System.out.println("随机字符串是:"+nonce_str);
SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
//交易起始时间
Date stDate = new Date();
String time_start = format.format(stDate);
System.out.println(time_start);
//交易结束时间
Calendar calendar = Calendar.getInstance();
calendar.setTime(stDate);
calendar.add(Calendar.MINUTE, 30); //设置为30分钟
String time_expire = format.format(calendar.getTime());
System.out.println(time_expire);
//交易类型
String trade_type = "JSAPI";//JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里
//body = "黑色手拿包";
//参数:开始生成签名
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", appid);
System.out.println("body是:"+body);
//body = Utf8EncodeUtils.getUTF8XMLString(body);
parameters.put("body", body.toString());
parameters.put("mch_id", mch_id);
parameters.put("nonce_str", nonce_str);
parameters.put("notify_url", notify_url); //回调地址
parameters.put("openid", openid); //用戶ID
parameters.put("out_trade_no", out_trade_no); //商户系统内部订单号
parameters.put("spbill_create_ip", spbill_create_ip);
parameters.put("total_fee", total_fee); //现金支付金额订单现金支付金额
parameters.put("trade_type", trade_type); //交易类型 JSAPI
//detail = Utf8EncodeUtils.getUTF8XMLString(detail);
System.out.println("detail是:"+detail);
parameters.put("detail", detail.toString());
parameters.put("attach", attach); // 商家数据包 attach 否 String(128) 123456 商家数据包,原样返回
parameters.put("time_start", time_start);
parameters.put("time_expire", time_expire); //结束时间
//开始签名
String sign = WXSignUtils.createSign(parameters);
System.out.println("签名是:"+sign);
//log.debug("微信支付签名:"+sign);
UnifiedOrder unifiedorder = new UnifiedOrder();
unifiedorder.setAppid(appid);
unifiedorder.setMch_id(mch_id);
unifiedorder.setNonce_str(nonce_str);
unifiedorder.setSign(sign);
unifiedorder.setBody(body);
unifiedorder.setDetail(detail);
unifiedorder.setAttach(attach);
unifiedorder.setOut_trade_no(out_trade_no);
unifiedorder.setTotal_fee(total_fee);
unifiedorder.setSpbill_create_ip(spbill_create_ip);
unifiedorder.setTime_start(time_start);
unifiedorder.setTime_expire(time_expire);
unifiedorder.setNotify_url(notify_url);
unifiedorder.setTrade_type(trade_type);
unifiedorder.setOpenid(openid);
//构造xml参数
String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);
System.out.println("构造xml参数:"+xmlInfo);
//System.out.println("xml参数编码:"+new String(xmlInfo.toString().getBytes("utf-8"),"iso8859-1"));
String wxUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder"; //统一访问地址
String method = "POST";
String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
System.out.println("weixinPost:"+weixinPost);
//log.debug("微信支付返回:"+weixinPost);
return weixinPost.toString();
}catch(Exception ex){
ex.printStackTrace();
//log.debug("微信支付:"+ex.getMessage());
}
return null;
}
WXSignUtil.java
/**
* 微信支付签名算法sign(动态参数)
* @param characterEncoding
* @param parameters
* @return
*/
@SuppressWarnings("rawtypes")
public static String createSign(SortedMap<Object,Object> parameters){
StringBuffer sb = new StringBuffer();
Set es = parameters.entrySet();//所有参与传参的参数按照accsii排序(升序)
Iterator it = es.iterator();
while(it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String k = (String)entry.getKey();
Object v = entry.getValue();
if(null != v && !"".equals(v)
&& !"sign".equals(k) && !"key".equals(k)) {
sb.append(k + "=" + v + "&");
}
}
sb.append("key=" + "C5628D57CAB6C2D93DG29566ADFB1B31CB"); //这个就是商户号API证书
System.out.println("字符串拼接后是:"+sb.toString());
String sign = DigestUtils.md5Hex(sb.toString()).toUpperCase();
return sign;
}
WXPayUtil.java (org.dom4j.Document、org.dom4j.Element来接收)
//xml形式的字符串转换为map集合
public static Map<String,String> xmlStr2Map(String xmlStr){
Map<String,String> map = new HashMap<String,String>();
Document doc = null;
try {
doc = DocumentHelper.parseText(xmlStr); // 将字符串转为XML
Element rootElt = doc.getRootElement(); // 获取根节点
List<Element> list = rootElt.elements();//获取根节点下所有节点
for (Element element : list) { //遍历节点
map.put(element.getName(), element.getText()); //节点的name为map的key,text为map的value
}
} catch (DocumentException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
最后一步,支付成功后微信就会执行你给它的回调地址,这个时候你需要接收他的消息然后回复它,不回复它他会一直发消息共8次
/**
* 微信支付回调页面
* @throws IOException
*/
public void byypWechatPayNotify(AreaContext ctx) throws IOException{
log.info("开始处理支付返回请求");
String resXml = ""; //反馈给微信服务器
String bodystr;
try {
/*InputStream inputStream;
StringBuffer sb = new StringBuffer();
inputStream = ctx.getRequest().getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream,"UTF-8"));
while((s = in.readLine()) != null){
sb.append(s);
}
inputStream.close();
in.close();
bodystr= sb.toString();
log.info("微信支付回调返回:"+bodystr);*/
Map<String, String> map = WechatMerchantFactory.getCallbackParams(ctx.getRequest()); //微信支付系统发送的数据
log.info("微信支付系统发送的数据:"+map);
//在这里还需要验证签名
if(!map.isEmpty()){
if (map.get("result_code").toString().equalsIgnoreCase("SUCCESS")) {
String orderId = map.get("out_trade_no");
System.out.println(orderId);
//这里写成功后的业务逻辑
// orderService.updateConfirm(orderId);
//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了
log.info("支付成功!");
resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml> ";
}else{
log.info("支付失败,错误信息:"+map.get("result_code"));
resXml = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[报文为空]]></return_msg></xml> ";
}
}
} catch (Exception e) {
e.printStackTrace();
log.error("微信支付回掉异常!",e);
}
resXml = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
//通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了
WechatMerchantFactory.writeMessageToResponse(ctx.getResponse(), resXml.toString());
log.info("回复微信服务器成功!");
Map<String,Object> body = new HashMap<String,Object>();
body.put("body", null);
RsjConstant.setSuccess(ctx, body);//5.返回数据
}
WechatMerchantFactory.java
/**
* 获取请求参数
*/
public static Map<String, String> getCallbackParams(HttpServletRequest request)
throws Exception {
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);
}
System.out.println("~~~~~~~~~~~~~~~~获取请求参数~~~~~~~~~");
outSteam.close();
inStream.close();
String result = new String(outSteam.toByteArray(), "utf-8");
System.out.println(result);
if(result != ""){
return WXPayUtil.xmlToMap(result);
}else{
return null;
}
}
/**
* 将xml参数解析为map返回出来 ,直接调用key(另一种方法)
*/
public static SortedMap<Object, Object> getCallbackParamsTest(HttpServletRequest request) throws Exception{
// SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>(); 读取申明
//读取参数
InputStream inputStream;
StringBuffer sb = new StringBuffer();
inputStream = request.getInputStream();
String s;
BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
while ((s = in.readLine()) != null) {
sb.append(s);
}
in.close();
inputStream.close();
//解析xml成map
Map<String, String> m = new HashMap<String, String>();
m = WXPayUtil.xmlToMap(sb.toString());
//过滤空 设置 TreeMap
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
Iterator it = m.keySet().iterator();
while (it.hasNext()) {
String parameter = (String) it.next();
String parameterValue = m.get(parameter);
String v = "";
if (null != parameterValue) {
v = parameterValue.trim();
}
packageParams.put(parameter, v);
}
return packageParams;
}
/**
* 微信回调给平台,平台将消息返回给微信服务器
*/
public static void writeMessageToResponse(HttpServletResponse response, String message) {
PrintWriter writer = null;
try {
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
writer = response.getWriter();
writer.write(message);
writer.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (writer != null)
writer.close();
}
}
所有的公共方法都贴出来了,我自己在做的时候 找别人的代码都没怎么详细 缺斤少两的 方法全靠自己去找出来。
控制台的生成参数基本上已经可以了,吧参数返回出去就可以调起支付界面了。(PS:生成好的参数,一定要去检验查看参数是不是通过的)
最后返回给页面的参数模板
timestamp": "1521618904","
prepay_id": "wx20180321155336e666c3445a420336916025","
signType": "MD5","
package": "prepay_id=wx20180321155336e666c3445a420336916025","
appid": "wxb550b534224445a8142","
nonceStr": "gebFuy5LKwjQqVZa"
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=20_1
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1(支付场景介绍,可以看看自己是否这样)
注意事项:再页面调起支付有问题,去查找以下地方
1.按照我上一篇文章检查一下是否配置是否正确
2.检查返回的参数是否正确(参数区分大小写的,不要搞错了,不然会提示你JSAPI缺少:total或者xxxx参数)
终于写完了,我也是怕忘记所以贴出来,同时也是为了其他同志们不要像我怎么苦逼的去找,心塞哦。如果还有其他方法没有贴出来,评论告诉我看到了会马上回复你的。如果对你有用的话请在评论区回复Thanks♪(・ω・)ノ嘿嘿