/**
* 【图文详情】用微信支付图文详情
*/
public void weixinBuyTuwen(){
Record result = new Record().set("code", "0").set("msg", "支付失败!");
Map<String, Object> map = new HashMap<String, Object>();
String orderNumber=getPara("order_id");//订单号
String money=getPara("money");//用户金额
int _money = (int)(Double.valueOf(money)*100);
String orderUrl= weixinPay.get("weixinBuyTuwenSucceed");//回调地址
String nonce_str = RandCharsUtils.getRandomString(16);//随机字符串
String body = "图文详情";//商品描述
String trade_type = "APP";//交易类型
String time_start = RandCharsUtils.timeStart();//交易起始时间
String time_expire = RandCharsUtils.timeExpire();//交易结束时间
String spbill_create_ip = getPara("ip", "127.0.0.1");//终端IP
SortedMap<Object,Object> parameters= WeChartPaySignUtil.getSortedMap(appid, mch_id, nonce_str, body, orderUrl, orderNumber, _money, time_start, time_expire, trade_type, spbill_create_ip);
String sign = WXSignUtils.createSign("UTF-8", parameters);
Unifiedorder unifiedorder=WeChartPaySignUtil.getUnifiedorder(appid,mch_id,nonce_str,sign,body,orderNumber,_money,spbill_create_ip,time_start,time_expire,orderUrl,trade_type);
String xmlInfo = HttpXmlUtils.xmlInfo(unifiedorder);
String timestamp = String.valueOf(System.currentTimeMillis()).substring(0, 10);
String weixinPost = HttpXmlUtils.httpsRequest(wxUrl, method, xmlInfo).toString();
UnifiedorderResult unifiedorderResult = JdomParseXmlUtils.getUnifiedorderResult(weixinPost.toString());
SortedMap<Object,Object> parameters2 =WeChartPaySignUtil.getSortedMap2(appid,mch_id,unifiedorderResult.getPrepay_id(),"Sign=WXPay",nonce_str,timestamp);
String sign2 = WXSignUtils.createSign("UTF-8", parameters2);
if("SUCCESS".equals(unifiedorderResult.getResult_code()) && "SUCCESS".equals(unifiedorderResult.getReturn_code())){
Record wxRecord=WeChartPaySignUtil.getWxRecord(unifiedorderResult,nonce_str,timestamp,sign2);
result.set("code", "1");
result.set("msg","发起支付成功!");
result.set("data", wxRecord);
}else {
result.set("data", map);
result.set("msg","发起支付失败");
}
renderJson(result);
}
/**
* 微信支付图文详情成功(回调)
* @see 订单状态 status 改为 1
*/
public void weixinBuyTuwenSucceed(){
HttpServletRequest request = getRequest();
HttpServletResponse response = getResponse();
try{
BufferedReader reader = request.getReader();
String line = "";
StringBuffer inputString = new StringBuffer();
try{
PrintWriter writer = response.getWriter();
while ((line = reader.readLine()) != null) {
inputString.append(line);
}
if(reader!=null){
reader.close();
}
if(!StringUtils.isEmpty(inputString.toString())){
WXPayResult wxPayResult = JdomParseXmlUtils.getWXPayResult(inputString.toString());
if("SUCCESS".equalsIgnoreCase(wxPayResult.getReturn_code())){
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", wxPayResult.getAppid());
parameters.put("attach", wxPayResult.getAttach());
parameters.put("bank_type", wxPayResult.getBank_type());
parameters.put("cash_fee", wxPayResult.getCash_fee());
parameters.put("fee_type", wxPayResult.getFee_type());
parameters.put("is_subscribe", wxPayResult.getIs_subscribe());
parameters.put("mch_id", wxPayResult.getMch_id());
parameters.put("nonce_str", wxPayResult.getNonce_str());
parameters.put("openid", wxPayResult.getOpenid());
parameters.put("out_trade_no", wxPayResult.getOut_trade_no());
parameters.put("result_code", wxPayResult.getResult_code());
parameters.put("return_code", wxPayResult.getReturn_code());
parameters.put("time_end", wxPayResult.getTime_end());
parameters.put("total_fee", wxPayResult.getTotal_fee());
parameters.put("trade_type", wxPayResult.getTrade_type());
parameters.put("transaction_id", wxPayResult.getTransaction_id());
//反校验签名
String sign = WXSignUtils.createSign("UTF-8", parameters);
String orderid = wxPayResult.getOut_trade_no();//订单号
Consult consult = Consult.dao.findState(orderid);
if(sign.equals(wxPayResult.getSign())){
try {
if("SUCCESS".equals(wxPayResult.getResult_code())){
consult.setPayState(2);
consult.setStatus(1);
//修改支付状态 支付成功
consult.update();
}
renderText("success");
} catch (Exception e) {
renderText("fail");
}
}else{
renderText("fail");
}
}else{
renderText("fail");
System.out.println("---------微信支付返回Fail----------"+wxPayResult.getReturn_msg());
}
if(writer!=null){
writer.close();
}
}else{
renderText("fail");
}
}catch(Exception e){
renderText("fail");
e.printStackTrace();
}
}catch(Exception ex){
renderText("fail");
ex.printStackTrace();
}
}
public static String getRandomString(int length) { //length表示生成字符串的长度
String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
Random random = new Random();
StringBuffer sb = new StringBuffer();
int number = 0;
for (int i = 0; i < length; i++) {
number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
public static SortedMap<Object,Object> getSortedMap(String appid,String mch_id,String nonce_str,String body,
String notify_url,String out_trade_no,int total_fee,String time_start,String time_expire,String trade_type,
String spbill_create_ip){
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", appid);
parameters.put("mch_id", mch_id);
parameters.put("nonce_str", nonce_str);
parameters.put("body", body);
parameters.put("notify_url", notify_url);
parameters.put("out_trade_no", out_trade_no);
parameters.put("total_fee", total_fee);
parameters.put("time_start", time_start);
parameters.put("time_expire", time_expire);
parameters.put("trade_type", trade_type);
parameters.put("spbill_create_ip", spbill_create_ip);
return parameters;
}
public static Unifiedorder getUnifiedorder(String appid, String mch_id, String nonce_str, String sign, String body,
String out_trade_no, int money, String spbill_create_ip, String time_start, String time_expire, String helpUrl,
String trade_type) {
Unifiedorder unifiedorder = new Unifiedorder();
unifiedorder.setAppid(appid);
unifiedorder.setMch_id(mch_id);
unifiedorder.setNonce_str(nonce_str);
unifiedorder.setSign(sign);
unifiedorder.setBody(body);
unifiedorder.setOut_trade_no(out_trade_no);
unifiedorder.setTotal_fee(money);
unifiedorder.setSpbill_create_ip(spbill_create_ip);
unifiedorder.setTime_start(time_start);
unifiedorder.setTime_expire(time_expire);
unifiedorder.setNotify_url(helpUrl);
unifiedorder.setTrade_type(trade_type);
return unifiedorder;
}
/**
* 构造xml参数
* @param xml
* @return
*/
public static String xmlInfo(Unifiedorder unifiedorder){
//构造xml参数的时候,至少又是个必传参数
/*
* <xml>
<appid>wxa82ebc1b2707b708</appid>
<body>1</body>
<mch_id>1448088402</mch_id>
<nonce_str>P05j6hut0CTSmPeT</nonce_str>
<out_trade_no>20170315114348485205</out_trade_no>
<spbill_create_ip>8.8.8.8</spbill_create_ip>
<time_expire>20170315121348</time_expire>
<time_start>20170315114348</time_start>
<total_fee>1</total_fee>
<trade_type>APP</trade_type>
<sign>C42CD95FE24C21D7636CE1335F19BD7D</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("<detail><![CDATA[");
// bf.append(unifiedorder.getDetail());
// bf.append("]]></detail>");
//
// bf.append("<attach><![CDATA[");
// bf.append(unifiedorder.getAttach());
// bf.append("]]></attach>");
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("<time_expire><![CDATA[");
bf.append(unifiedorder.getTime_expire());
bf.append("]]></time_expire>");
bf.append("<time_start><![CDATA[");
bf.append(unifiedorder.getTime_start());
bf.append("]]></time_start>");
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("<sign><![CDATA[");
bf.append(unifiedorder.getSign());
bf.append("]]></sign>");
bf.append("</xml>");
System.out.println("最终的提交xml:"+bf.toString());
return bf.toString();
}
return "";
}
/**
* post请求并得到返回结果
* @param requestUrl
* @param requestMethod
* @param output
* @return
*/
public static String httpsRequest(String requestUrl, String requestMethod, String output) {
try{
System.out.println("开始发送请求:"+output);
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 "";
}
/**
* 1、统一下单获取微信返回
* 解析的时候自动去掉CDMA
* @param xml
*/
@SuppressWarnings("unchecked")
public static UnifiedorderResult getUnifiedorderResult(String xml){
UnifiedorderResult unifieorderResult = new UnifiedorderResult();
try {
StringReader read = new StringReader(xml);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
// 创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
// 通过输入源构造一个Document
Document doc;
doc = (Document) sb.build(source);
Element root = doc.getRootElement();// 指向根节点
List<Element> list = root.getChildren();
if(list!=null&&list.size()>0){
for (Element element : list) {
/*
* <xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wx2421b1c4370ec43b]]></appid>
<mch_id><![CDATA[10000100]]></mch_id>
<nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
<sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
<trade_type><![CDATA[JSAPI]]></trade_type>
</xml>
*/
System.out.println("key是:"+element.getName()+",值是:"+element.getText());
if("return_code".equals(element.getName())){
unifieorderResult.setReturn_code(element.getText());
}
if("return_msg".equals(element.getName())){
unifieorderResult.setReturn_msg(element.getText());
}
if("appid".equals(element.getName())){
unifieorderResult.setAppid(element.getText());
}
if("mch_id".equals(element.getName())){
unifieorderResult.setMch_id(element.getText());
}
if("nonce_str".equals(element.getName())){
unifieorderResult.setNonce_str(element.getText());
}
if("sign".equals(element.getName())){
unifieorderResult.setSign(element.getText());
}
if("result_code".equals(element.getName())){
unifieorderResult.setResult_code(element.getText());
}
if("prepay_id".equals(element.getName())){
unifieorderResult.setPrepay_id(element.getText());
}
if("trade_type".equals(element.getName())){
unifieorderResult.setTrade_type(element.getText());
}
}
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
return unifieorderResult;
}
public static SortedMap<Object, Object> getSortedMap2(String appid, String mch_id, String prepay_id, String packages,
String nonce_str, String timestamp) {
SortedMap<Object,Object> parameters2 = new TreeMap<Object,Object>();
parameters2.put("appid", appid);
parameters2.put("partnerid", mch_id);
parameters2.put("prepayid", prepay_id);
parameters2.put("package", packages);
parameters2.put("noncestr", nonce_str);
parameters2.put("timestamp", timestamp);
return parameters2;
}
/**
* 微信支付签名算法sign
* @param characterEncoding
* @param parameters
* @return
*/
@SuppressWarnings("rawtypes")
public static String createSign(String characterEncoding,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=" + Key);
System.out.println("字符串拼接后是:"+sb.toString());
String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
return sign;
}
package com.doctor.utils;
/**
* 统一下单微信返回的参数组
*/
public class UnifiedorderResult {
private String appid;//appid
private String mch_id;//商家id
private String device_info;//设备号
private String nonce_str;//随机字符串
private String sign;//签名
private String result_code;//错误码
private String err_code;//错误代码
private String err_code_des;//错误返回的信息描述
private String trade_type;//调用接口提交的交易类型,取值如下:JSAPI,NATIVE,APP
private String prepay_id;//微信生成的预支付回话标识,用于后续接口调用中使用,该值有效期为2小时
private String code_url;//trade_type为NATIVE是有返回,可将该参数值生成二维码展示出来进行扫码支付
private String return_code;//返回状态码SUCCESS/FAIL此字段是通信标识,非交易标识,交易是否成功需要查看result_code来判断
private String return_msg;//返回信息
private String scene_info;//返回信息
public String getScene_info() {
return scene_info;
}
public void setScene_info(String scene_info) {
this.scene_info = scene_info;
}
public String getAppid() {
return appid;
}
public String getMch_id() {
return mch_id;
}
public String getDevice_info() {
return device_info;
}
public String getNonce_str() {
return nonce_str;
}
public String getSign() {
return sign;
}
public String getResult_code() {
return result_code;
}
public String getErr_code() {
return err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public String getTrade_type() {
return trade_type;
}
public String getPrepay_id() {
return prepay_id;
}
public String getCode_url() {
return code_url;
}
public void setAppid(String appid) {
this.appid = appid;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public void setSign(String sign) {
this.sign = sign;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
public void setCode_url(String code_url) {
this.code_url = code_url;
}
public String getReturn_code() {
return return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
}
public static Record getWxRecord(UnifiedorderResult unifiedorderResult,String nonce_str,String timestamp,String sign2) {
Record wxRecord=new Record();
wxRecord.set("appid", unifiedorderResult.getAppid());
wxRecord.set("partnerid", unifiedorderResult.getMch_id());
wxRecord.set("prepayid", unifiedorderResult.getPrepay_id());
wxRecord.set("package", "Sign=WXPay");
wxRecord.set("noncestr", nonce_str);
wxRecord.set("timestamp", timestamp);
wxRecord.set("sign", sign2);
return wxRecord;
}
/**
* 2、微信回调后参数解析
* 解析的时候自动去掉CDMA
* @param xml
*/
@SuppressWarnings("unchecked")
public static WXPayResult getWXPayResult(String xml){
WXPayResult wXPayResult = new WXPayResult();
try {
StringReader read = new StringReader(xml);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
// 创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
// 通过输入源构造一个Document
Document doc;
doc = (Document) sb.build(source);
Element root = doc.getRootElement();// 指向根节点
List<Element> list = root.getChildren();
if(list!=null&&list.size()>0){
for (Element element : list) {
System.out.println("key是:"+element.getName()+",值是:"+element.getText());
if("return_code".equals(element.getName())){
wXPayResult.setReturn_code(element.getText());
}
if("return_msg".equals(element.getName())){
wXPayResult.setReturn_msg(element.getText());
}
if("appid".equals(element.getName())){
wXPayResult.setAppid(element.getText());
}
if("mch_id".equals(element.getName())){
wXPayResult.setMch_id(element.getText());
}
if("nonce_str".equals(element.getName())){
wXPayResult.setNonce_str(element.getText());
}
if("sign".equals(element.getName())){
wXPayResult.setSign(element.getText());
}
if("result_code".equals(element.getName())){
wXPayResult.setResult_code(element.getText());
}
if("openid".equals(element.getName())){
wXPayResult.setOpenid(element.getText());
}
if("attach".equals(element.getName())){
wXPayResult.setAttach(element.getText());
}
if("bank_type".equals(element.getName())){
wXPayResult.setBank_type(element.getText());
}
if("cash_fee".equals(element.getName())){
wXPayResult.setCash_fee(Integer.parseInt(element.getText()));
}
if("fee_type".equals(element.getName())){
wXPayResult.setFee_type(element.getText());
}
if("is_subscribe".equals(element.getName())){
wXPayResult.setIs_subscribe(element.getText());
}
if("out_trade_no".equals(element.getName())){
wXPayResult.setOut_trade_no(element.getText());
}
if("time_end".equals(element.getName())){
wXPayResult.setTime_end(element.getText());
}
if("total_fee".equals(element.getName())){
wXPayResult.setTotal_fee(Integer.parseInt(element.getText()));
}
if("trade_type".equals(element.getName())){
wXPayResult.setTrade_type(element.getText());
}
if("transaction_id".equals(element.getName())){
wXPayResult.setTransaction_id(element.getText());
}
}
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
return wXPayResult;
}