微信小程序支付(java后端)

第一步

进入小程序,下单,请求下单支付,调用小程序登录API来获取Openid(https://mp.weixin.qq.com/debug/w....html#wxloginobject),生成商户订单,这些都是在小程序端完成的业务。

小程序端代码

//pages/pay/pay.js

varapp=getApp();

Page({

data:{},

onLoad:function(options){

//页面初始化options为页面跳转所带来的参数

},

/*微信支付*/

wxpay:function(){

varthat=this

//登陆获取code

wx.login({

success:function(res){

console.log(res.code)

//获取openid

that.getOpenId(res.code)

}

});

},

getOpenId:function(code){

varthat=this;

wx.request({

url:"https://api.weixin.qq.com/sns/jscode2session?appid=wxa142513e524e496c&secret=5d6a7d86048884e7c60f84f7aa85253c&js_code="+code+"&grant_type=authorization_code",

data:{},

method:'GET',

success:function(res){

console.log('返回openId')

console.log(res.data)

that.generateOrder(res.data.openid)

},

fail:function(){

//fail

},

complete:function(){

//complete

}

})

},

/**生成商户订单*/

generateOrder:function(openid){

varthat=this

//统一支付

wx.request({

url:'http://localhost:8070/RMS/pay_pay.action',

method:'GET',

data:{

total_fee:'5',

body:'支付测试',

attach:'真假酒水'

},

success:function(res){

console.log(res)

varpay=res.data

//发起支付

vartimeStamp=pay[0].timeStamp;

console.log("timeStamp:"+timeStamp)

varpackages=pay[0].package;

console.log("package:"+packages)

varpaySign=pay[0].paySign;

console.log("paySign:"+paySign)

varnonceStr=pay[0].nonceStr;

console.log("nonceStr:"+nonceStr)

varparam={"timeStamp":timeStamp,"package":packages,"paySign":paySign,"signType":"MD5","nonceStr":nonceStr};

that.pay(param)

},

})

},

/*支付*/

pay:function(param){

console.log("支付")

console.log(param)

wx.requestPayment({

timeStamp:param.timeStamp,

nonceStr:param.nonceStr,

package:param.package,

signType:param.signType,

paySign:param.paySign,

success:function(res){

//success

console.log("支付")

console.log(res)

wx.navigateBack({

delta:1,//回退前delta(默认为1)页面

success:function(res){

wx.showToast({

title:'支付成功',

icon:'success',

duration:2000

})

},

fail:function(){

//fail

},

complete:function(){

//complete

}

})

},

fail:function(res){

//fail

console.log("支付失败")

console.log(res)

},

complete:function(){

//complete

console.log("paycomplete")

}

})

}

})

复制代码

第二步

调用支付统一下单API来获取prepay_id,并将小程序调起支付数据需要签名的字段appId,timeStamp,nonceStr,package再次签名(https://pay.weixin.qq.com/wiki/d...ter=7_7&index=3)

后台代码

packagecn.it.shop.action;

importjava.io.ByteArrayInputStream;

importjava.io.InputStream;

importjava.io.UnsupportedEncodingException;

importjava.text.SimpleDateFormat;

importjava.util.Date;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

importorg.dom4j.Document;

importorg.dom4j.DocumentException;

importorg.dom4j.Element;

importorg.dom4j.io.SAXReader;

importcn.it.shop.util.MessageUtil;

importcn.it.shop.util.PayUtil;

importcn.it.shop.util.PaymentPo;

importcn.it.shop.util.UUIDHexGenerator;

importnet.sf.json.JSONArray;

importnet.sf.json.JSONObject;

/**

*@author

*@version创建时间:2017年1月21日下午4:59:03

*小程序端请求的后台action,返回签名后的数据传到前台

*/

publicclassPayAction{

privateStringtotal_fee;//总金额

privateStringbody;//商品描述

privateStringdetail;//商品详情

privateStringattach;//附加数据

privateStringtime_start;//交易起始时间

privateStringtime_expire;//交易结束时间

privateStringopenid;//用户标识

privateJSONArrayjsonArray=newJSONArray();

publicStringpay()throwsUnsupportedEncodingException,DocumentException{

body=newString(body.getBytes("UTF-8"),"ISO-8859-1");

Stringappid="替换为自己的小程序ID";//小程序ID

Stringmch_id="替换为自己的商户号";//商户号

Stringnonce_str=UUIDHexGenerator.generate();//随机字符串

Stringtoday=newSimpleDateFormat("yyyyMMddHHmmss").format(newDate());

Stringcode=PayUtil.createCode(8);

Stringout_trade_no=mch_id+today+code;//商户订单号

Stringspbill_create_ip="替换为自己的终端IP";//终端IP

Stringnotify_url="http://www.weixin.qq.com/wxpay/pay.php";//通知地址

Stringtrade_type="JSAPI";//交易类型

Stringopenid="替换为用户的openid";//用户标识

/**/

PaymentPopaymentPo=newPaymentPo();

paymentPo.setAppid(appid);

paymentPo.setMch_id(mch_id);

paymentPo.setNonce_str(nonce_str);

Stringnewbody=newString(body.getBytes("ISO-8859-1"),"UTF-8");//以utf-8编码放入paymentPo,微信支付要求字符编码统一采用UTF-8字符编码

paymentPo.setBody(newbody);

paymentPo.setOut_trade_no(out_trade_no);

paymentPo.setTotal_fee(total_fee);

paymentPo.setSpbill_create_ip(spbill_create_ip);

paymentPo.setNotify_url(notify_url);

paymentPo.setTrade_type(trade_type);

paymentPo.setOpenid(openid);

//把请求参数打包成数组

MapsParaTemp=newHashMap();

sParaTemp.put("appid",paymentPo.getAppid());

sParaTemp.put("mch_id",paymentPo.getMch_id());

sParaTemp.put("nonce_str",paymentPo.getNonce_str());

sParaTemp.put("body",paymentPo.getBody());

sParaTemp.put("out_trade_no",paymentPo.getOut_trade_no());

sParaTemp.put("total_fee",paymentPo.getTotal_fee());

sParaTemp.put("spbill_create_ip",paymentPo.getSpbill_create_ip());

sParaTemp.put("notify_url",paymentPo.getNotify_url());

sParaTemp.put("trade_type",paymentPo.getTrade_type());

sParaTemp.put("openid",paymentPo.getOpenid());

//除去数组中的空值和签名参数

MapsPara=PayUtil.paraFilter(sParaTemp);

Stringprestr=PayUtil.createLinkString(sPara);//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串

Stringkey="&key=替换为商户支付密钥";//商户支付密钥

//MD5运算生成签名

Stringmysign=PayUtil.sign(prestr,key,"utf-8").toUpperCase();

paymentPo.setSign(mysign);

//打包要发送的xml

StringrespXml=MessageUtil.messageToXML(paymentPo);

//打印respXml发现,得到的xml中有“__”不对,应该替换成“_”

respXml=respXml.replace("__","_");

Stringurl="https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单API接口链接

Stringparam=respXml;

//Stringresult=SendRequestForUrl.sendRequest(url,param);//发起请求

Stringresult=PayUtil.httpRequest(url,"POST",param);

//将解析结果存储在HashMap中

Mapmap=newHashMap();

InputStreamin=newByteArrayInputStream(result.getBytes());

//读取输入流

SAXReaderreader=newSAXReader();

Documentdocument=reader.read(in);

//得到xml根元素

Elementroot=document.getRootElement();

//得到根元素的所有子节点

@SuppressWarnings("unchecked")

ListelementList=root.elements();

for(Elementelement:elementList){

map.put(element.getName(),element.getText());

}

//返回信息

Stringreturn_code=map.get("return_code");//返回状态码

Stringreturn_msg=map.get("return_msg");//返回信息

System.out.println("return_msg"+return_msg);

JSONObjectJsonObject=newJSONObject();

if(return_code=="SUCCESS"||return_code.equals(return_code)){

//业务结果

Stringprepay_id=map.get("prepay_id");//返回的预付单信息

StringnonceStr=UUIDHexGenerator.generate();

JsonObject.put("nonceStr",nonceStr);

JsonObject.put("package","prepay_id="+prepay_id);

LongtimeStamp=System.currentTimeMillis()/1000;

JsonObject.put("timeStamp",timeStamp+"");

StringstringSignTemp="appid="+appid+"&nonceStr="+nonceStr+"&package=prepay_id="+prepay_id+"&signType=MD5&timeStamp="+timeStamp;

//再次签名

StringpaySign=PayUtil.sign(stringSignTemp,"&key=替换为自己的密钥","utf-8").toUpperCase();

JsonObject.put("paySign",paySign);

jsonArray.add(JsonObject);

}

return"pay";

}

publicStringgetTotal_fee(){

returntotal_fee;

}

publicvoidsetTotal_fee(Stringtotal_fee){

this.total_fee=total_fee;

}

publicStringgetBody(){

returnbody;

}

publicvoidsetBody(Stringbody){

this.body=body;

}

publicJSONArraygetJsonArray(){

returnjsonArray;

}

publicvoidsetJsonArray(JSONArrayjsonArray){

this.jsonArray=jsonArray;

}

publicStringgetDetail(){

returndetail;

}

publicvoidsetDetail(Stringdetail){

this.detail=detail;

}

publicStringgetAttach(){

returnattach;

}

publicvoidsetAttach(Stringattach){

this.attach=attach;

}

publicStringgetTime_start(){

returntime_start;

}

publicvoidsetTime_start(Stringtime_start){

this.time_start=time_start;

}

publicStringgetTime_expire(){

returntime_expire;

}

publicvoidsetTime_expire(Stringtime_expire){

this.time_expire=time_expire;

}

publicStringgetOpenid(){

returnopenid;

}

publicvoidsetOpenid(Stringopenid){

this.openid=openid;

}

}

复制代码

后台业务逻辑涉及到的工具类及参数封装类

MessageUtil

packagecn.it.shop.util;

importjava.io.IOException;

importjava.io.Writer;

importjava.util.HashMap;

importjava.util.List;

importjavax.servlet.http.HttpServletRequest;

importorg.dom4j.Document;

importorg.dom4j.Element;

importorg.dom4j.io.SAXReader;

importcom.thoughtworks.xstream.XStream;

importcom.thoughtworks.xstream.core.util.QuickWriter;

importcom.thoughtworks.xstream.io.HierarchicalStreamWriter;

importcom.thoughtworks.xstream.io.xml.PrettyPrintWriter;

importcom.thoughtworks.xstream.io.xml.XppDriver;

publicclassMessageUtil{

publicstaticHashMapparseXML(HttpServletRequestrequest)throwsException,IOException{

HashMapmap=newHashMap();

//通过IO获得Document

SAXReaderreader=newSAXReader();

Documentdoc=reader.read(request.getInputStream());

//得到xml的根节点

Elementroot=doc.getRootElement();

recursiveParseXML(root,map);

returnmap;

}

privatestaticvoidrecursiveParseXML(Elementroot,HashMapmap){

//得到根节点的子节点列表

ListelementList=root.elements();

//判断有没有子元素列表

if(elementList.size()==0){

map.put(root.getName(),root.getTextTrim());

}

else{

//遍历

for(Elemente:elementList){

recursiveParseXML(e,map);

}

}

}

privatestaticXStreamxstream=newXStream(newXppDriver(){

publicHierarchicalStreamWritercreateWriter(Writerout){

returnnewPrettyPrintWriter(out){

//对所有xml节点都增加CDATA标记

booleancdata=true;

publicvoidstartNode(Stringname,Classclazz){

super.startNode(name,clazz);

}

protectedvoidwriteText(QuickWriterwriter,Stringtext){

if(cdata){

writer.write("writer.write(text);

writer.write("]]>");

}else{

writer.write(text);

}

}

};

}

});

publicstaticStringmessageToXML(PaymentPopaymentPo){

xstream.alias("xml",PaymentPo.class);

returnxstream.toXML(paymentPo);

}

}

PaymentPo//封装支付参数实体

packagecn.it.shop.util;

/**

*@author

*@version创建时间:2017年1月21日下午4:20:52

*类说明

*/

publicclassPaymentPo{

privateStringappid;//小程序ID

privateStringmch_id;//商户号

privateStringdevice_info;//设备号

privateStringnonce_str;//随机字符串

privateStringsign;//签名

privateStringbody;//商品描述

privateStringdetail;//商品详情

privateStringattach;//附加数据

privateStringout_trade_no;//商户订单号

privateStringfee_type;//货币类型

privateStringspbill_create_ip;//终端IP

privateStringtime_start;//交易起始时间

privateStringtime_expire;//交易结束时间

privateStringgoods_tag;//商品标记

privateStringtotal_fee;//总金额

privateStringnotify_url;//通知地址

privateStringtrade_type;//交易类型

privateStringlimit_pay;//指定支付方式

privateStringopenid;//用户标识

publicStringgetAppid(){

returnappid;

}

publicvoidsetAppid(Stringappid){

this.appid=appid;

}

publicStringgetMch_id(){

returnmch_id;

}

publicvoidsetMch_id(Stringmch_id){

this.mch_id=mch_id;

}

publicStringgetNonce_str(){

returnnonce_str;

}

publicvoidsetNonce_str(Stringnonce_str){

this.nonce_str=nonce_str;

}

publicStringgetSign(){

returnsign;

}

publicvoidsetSign(Stringsign){

this.sign=sign;

}

publicStringgetBody(){

returnbody;

}

publicvoidsetBody(Stringbody){

this.body=body;

}

publicStringgetOut_trade_no(){

returnout_trade_no;

}

publicvoidsetOut_trade_no(Stringout_trade_no){

this.out_trade_no=out_trade_no;

}

publicStringgetTotal_fee(){

returntotal_fee;

}

publicvoidsetTotal_fee(Stringtotal_fee){

this.total_fee=total_fee;

}

publicStringgetNotify_url(){

returnnotify_url;

}

publicvoidsetNotify_url(Stringnotify_url){

this.notify_url=notify_url;

}

publicStringgetTrade_type(){

returntrade_type;

}

publicvoidsetTrade_type(Stringtrade_type){

this.trade_type=trade_type;

}

publicStringgetOpenid(){

returnopenid;

}

publicvoidsetOpenid(Stringopenid){

this.openid=openid;

}

publicStringgetSpbill_create_ip(){

returnspbill_create_ip;

}

publicvoidsetSpbill_create_ip(Stringspbill_create_ip){

this.spbill_create_ip=spbill_create_ip;

}

publicStringgetDevice_info(){

returndevice_info;

}

publicvoidsetDevice_info(Stringdevice_info){

this.device_info=device_info;

}

publicStringgetDetail(){

returndetail;

}

publicvoidsetDetail(Stringdetail){

this.detail=detail;

}

publicStringgetAttach(){

returnattach;

}

publicvoidsetAttach(Stringattach){

this.attach=attach;

}

publicStringgetFee_type(){

returnfee_type;

}

publicvoidsetFee_type(Stringfee_type){

this.fee_type=fee_type;

}

publicStringgetTime_start(){

returntime_start;

}

publicvoidsetTime_start(Stringtime_start){

this.time_start=time_start;

}

publicStringgetTime_expire(){

returntime_expire;

}

publicvoidsetTime_expire(Stringtime_expire){

this.time_expire=time_expire;

}

publicStringgetGoods_tag(){

returngoods_tag;

}

publicvoidsetGoods_tag(Stringgoods_tag){

this.goods_tag=goods_tag;

}

publicStringgetLimit_pay(){

returnlimit_pay;

}

publicvoidsetLimit_pay(Stringlimit_pay){

this.limit_pay=limit_pay;

}

}

PayUtil

packagecn.it.shop.util;

importjava.io.BufferedReader;

importjava.io.InputStream;

importjava.io.InputStreamReader;

importjava.io.OutputStream;

importjava.io.UnsupportedEncodingException;

importjava.net.HttpURLConnection;

importjava.net.URL;

importjava.util.ArrayList;

importjava.util.Collections;

importjava.util.HashMap;

importjava.util.List;

importjava.util.Map;

importorg.apache.commons.codec.digest.DigestUtils;

/**

*@author

*@version创建时间:2017年1月17日下午7:46:29类说明

*/

publicclassPayUtil{

/**

*签名字符串

*@paramtext需要签名的字符串

*@paramkey密钥

*@paraminput_charset编码格式

*@return签名结果

*/

publicstaticStringsign(Stringtext,Stringkey,Stringinput_charset){

text=text+key;

returnDigestUtils.md5Hex(getContentBytes(text,input_charset));

}

/**

*签名字符串

*@paramtext需要签名的字符串

*@paramsign签名结果

*@paramkey密钥

*@paraminput_charset编码格式

*@return签名结果

*/

publicstaticbooleanverify(Stringtext,Stringsign,Stringkey,Stringinput_charset){

text=text+key;

Stringmysign=DigestUtils.md5Hex(getContentBytes(text,input_charset));

if(mysign.equals(sign)){

returntrue;

}else{

returnfalse;

}

}

/**

*@paramcontent

*@paramcharset

*@return

*@throwsSignatureException

*@throwsUnsupportedEncodingException

*/

publicstaticbyte[]getContentBytes(Stringcontent,Stringcharset){

if(charset==null||"".equals(charset)){

returncontent.getBytes();

}

try{

returncontent.getBytes(charset);

}catch(UnsupportedEncodingExceptione){

thrownewRuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:"+charset);

}

}

/**

*生成6位或10位随机数paramcodeLength(多少位)

*@return

*/

publicstaticStringcreateCode(intcodeLength){

Stringcode="";

for(inti=0;i<codeLength;i++){

code+=(int)(Math.random()*9);

}

returncode;

}

privatestaticbooleanisValidChar(charch){

if((ch>='0'&&ch<='9')||(ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))

returntrue;

if((ch>=0x4e00&&ch<=0x7fff)||(ch>=0x8000&&ch<=0x952f))

returntrue;//简体中文汉字编码

returnfalse;

}

/**

*除去数组中的空值和签名参数

*@paramsArray签名参数组

*@return去掉空值与签名参数后的新签名参数组

*/

publicstaticMapparaFilter(MapsArray){

Mapresult=newHashMap();

if(sArray==null||sArray.size()<=0){

returnresult;

}

for(Stringkey:sArray.keySet()){

Stringvalue=sArray.get(key);

if(value==null||value.equals("")||key.equalsIgnoreCase("sign")

||key.equalsIgnoreCase("sign_type")){

continue;

}

result.put(key,value);

}

returnresult;

}

/**

*把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串

*@paramparams需要排序并参与字符拼接的参数组

*@return拼接后字符串

*/

publicstaticStringcreateLinkString(Mapparams){

Listkeys=newArrayList(params.keySet());

Collections.sort(keys);

Stringprestr="";

for(inti=0;i<keys.size();i++){

Stringkey=keys.get(i);

Stringvalue=params.get(key);

if(i==keys.size()-1){//拼接时,不包括最后一个&字符

prestr=prestr+key+"="+value;

}else{

prestr=prestr+key+"="+value+"&";

}

}

returnprestr;

}

/**

*

*@paramrequestUrl请求地址

*@paramrequestMethod请求方法

*@paramoutputStr参数

*/

publicstaticStringhttpRequest(StringrequestUrl,StringrequestMethod,StringoutputStr){

//创建SSLContext

StringBufferbuffer=null;

try{

URLurl=newURL(requestUrl);

HttpURLConnectionconn=(HttpURLConnection)url.openConnection();

conn.setRequestMethod(requestMethod);

conn.setDoOutput(true);

conn.setDoInput(true);

conn.connect();

//往服务器端写内容

if(null!=outputStr){

OutputStreamos=conn.getOutputStream();

os.write(outputStr.getBytes("utf-8"));

os.close();

}

//读取服务器端返回的内容

InputStreamis=conn.getInputStream();

InputStreamReaderisr=newInputStreamReader(is,"utf-8");

BufferedReaderbr=newBufferedReader(isr);

buffer=newStringBuffer();

Stringline=null;

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

buffer.append(line);

}

}catch(Exceptione){

e.printStackTrace();

}

returnbuffer.toString();

}

publicstaticStringurlEncodeUTF8(Stringsource){

Stringresult=source;

try{

result=java.net.URLEncoder.encode(source,"UTF-8");

}catch(UnsupportedEncodingExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}

returnresult;

}

}

UUIDHexGenerator

packagecn.it.shop.util;

importjava.net.InetAddress;

/**

*@author

*@version创建时间:2017年1月17日下午7:45:06类说明

*/

publicclassUUIDHexGenerator{

privatestaticStringsep="";

privatestaticfinalintIP;

privatestaticshortcounter=(short)0;

privatestaticfinalintJVM=(int)(System.currentTimeMillis()>>>;

privatestaticUUIDHexGeneratoruuidgen=newUUIDHexGenerator();

static{

intipadd;

try{

ipadd=toInt(InetAddress.getLocalHost().getAddress());

}catch(Exceptione){

ipadd=0;

}

IP=ipadd;

}

publicstaticUUIDHexGeneratorgetInstance(){

returnuuidgen;

}

publicstaticinttoInt(byte[]bytes){

intresult=0;

for(inti=0;i<4;i++){

result=(result<<-Byte.MIN_VALUE+(int)bytes;

}

returnresult;

}

protectedstaticStringformat(intintval){

Stringformatted=Integer.toHexString(intval);

StringBufferbuf=newStringBuffer("00000000");

buf.replace(8-formatted.length(),8,formatted);

returnbuf.toString();

}

protectedstaticStringformat(shortshortval){

Stringformatted=Integer.toHexString(shortval);

StringBufferbuf=newStringBuffer("0000");

buf.replace(4-formatted.length(),4,formatted);

returnbuf.toString();

}

protectedstaticintgetJVM(){

returnJVM;

}

protectedsynchronizedstaticshortgetCount(){

if(counter<0){

counter=0;

}

returncounter++;

}

protectedstaticintgetIP(){

returnIP;

}

protectedstaticshortgetHiTime(){

return(short)(System.currentTimeMillis()>>>32);

}

protectedstaticintgetLoTime(){

return(int)System.currentTimeMillis();

}

publicstaticStringgenerate(){

returnnewStringBuffer(36).append(format(getIP())).append(sep).append(format(getJVM())).append(sep)

.append(format(getHiTime())).append(sep).append(format(getLoTime())).append(sep)

.append(format(getCount())).toString();

}

/**

*@paramargs

*/

publicstaticvoidmain(String[]args){

Stringid="";

UUIDHexGeneratoruuid=UUIDHexGenerator.getInstance();

/*

for(inti=0;i<100;i++){

id=uuid.generate();

}*/

id=uuid.generate();

System.out.println(id);

}

}

复制代码

转自解放号社区:http://bbs.jointforce.com/topic/25765

相关推荐