欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

微信支付java版本之Native付款

程序员文章站 2024-03-13 16:22:27
最近工作中接触到一些关于微信支付方面的东西,看到给的demo都是php版本的,再加上微信支付文档写的确实不敢恭维,趟过不少坑之后闲下来做个总结。 一、前期准备&nbs...

最近工作中接触到一些关于微信支付方面的东西,看到给的demo都是php版本的,再加上微信支付文档写的确实不敢恭维,趟过不少坑之后闲下来做个总结。

一、前期准备 

做微信开发首先要申请一个公共账号,申请成功后会以邮件形式发给你一些必要信息,公共账号中有开发文档以及开发中必要信息,以及测试的数据查询。

微信支付java版本之Native付款 

微信支付java版本之Native付款

二、工具类
1.md5加密工具类 

package com.pay.utils.weixin;
import java.security.messagedigest;
public class md5util {
 public final static string md5(string s) {
    char hexdigits[]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};    
    try {
      byte[] btinput = s.getbytes();
      // 获得md5摘要算法的 messagedigest 对象
      messagedigest mdinst = messagedigest.getinstance("md5");
      // 使用指定的字节更新摘要
      mdinst.update(btinput);
      // 获得密文
      byte[] md = mdinst.digest();
      // 把密文转换成十六进制的字符串形式
      int j = md.length;
      char str[] = new char[j * 2];
      int k = 0;
      for (int i = 0; i < j; i++) {
        byte byte0 = md[i];
        str[k++] = hexdigits[byte0 >>> 4 & 0xf];
        str[k++] = hexdigits[byte0 & 0xf];
      }
      return new string(str);
    } catch (exception e) {
      e.printstacktrace();
      return null;
    }
 }
}

2.commonutil工具类,用于装换成微信所需xml。以下return new string(xml.tostring().getbytes(),"iso8859-1");将工具类中的utf-8改成iso8859-1,否则微信订单中的中文会出现乱码,改后可以正确显示。 

package com.pay.utils.weixin;

import java.io.unsupportedencodingexception;
import java.net.urlencoder;
import java.util.*;
import java.util.map.entry;

public class commonutil {

 public static string createnoncestr(int length) {
 string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789";
 string res = "";
 for (int i = 0; i < length; i++) {
  random rd = new random();
  res += chars.indexof(rd.nextint(chars.length() - 1));
 }
 return res;
 }

 public static string createnoncestr() {
 string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789";
 string res = "";
 for (int i = 0; i < 16; i++) {
  random rd = new random();
  res += chars.charat(rd.nextint(chars.length() - 1));
 }
 return res;
 }

 public static string formatqueryparamap(hashmap<string, string> parameters)
  throws sdkruntimeexception {

 string buff = "";
 try {
  list<map.entry<string, string>> infoids = new arraylist<map.entry<string, string>>(
   parameters.entryset());

  collections.sort(infoids,
   new comparator<map.entry<string, string>>() {
   public int compare(map.entry<string, string> o1,
    map.entry<string, string> o2) {
    return (o1.getkey()).tostring().compareto(
     o2.getkey());
   }
   });

  for (int i = 0; i < infoids.size(); i++) {
  map.entry<string, string> item = infoids.get(i);
  if (item.getkey() != "") {
   buff += item.getkey() + "="
    + urlencoder.encode(item.getvalue(), "utf-8") + "&";
  }
  }
  if (buff.isempty() == false) {
  buff = buff.substring(0, buff.length() - 1);
  }
 } catch (exception e) {
  throw new sdkruntimeexception(e.getmessage());
 }

 return buff;
 }

 public static string formatbizqueryparamap(hashmap<string, string> paramap,
  boolean urlencode) throws sdkruntimeexception {

 string buff = "";
 try {
  list<map.entry<string, string>> infoids = new arraylist<map.entry<string, string>>(
   paramap.entryset());

  collections.sort(infoids,
   new comparator<map.entry<string, string>>() {
   public int compare(map.entry<string, string> o1,
    map.entry<string, string> o2) {
    return (o1.getkey()).tostring().compareto(
     o2.getkey());
   }
   });

  for (int i = 0; i < infoids.size(); i++) {
  map.entry<string, string> item = infoids.get(i);
  //system.out.println(item.getkey());
  if (item.getkey() != "") {
   
   string key = item.getkey();
   string val = item.getvalue();
   if (urlencode) {
   val = urlencoder.encode(val, "utf-8");

   }
   buff += key.tolowercase() + "=" + val + "&";

  }
  }

  if (buff.isempty() == false) {
  buff = buff.substring(0, buff.length() - 1);
  }
 } catch (exception e) {
  throw new sdkruntimeexception(e.getmessage());
 }
 return buff;
 }

 public static boolean isnumeric(string str) {
 if (str.matches("\\d *")) {
  return true;
 } else {
  return false;
 }
 }

 public static string arraytoxml(hashmap<string, string> arr) {
 string xml = "<xml>";
 
 iterator<entry<string, string>> iter = arr.entryset().iterator();
 while (iter.hasnext()) {
  entry<string, string> entry = iter.next();
  string key = entry.getkey();
  string val = entry.getvalue();
  if (isnumeric(val)) {
  xml += "<" + key + ">" + val + "</" + key + ">";

  } else
  xml += "<" + key + "><![cdata[" + val + "]]></" + key + ">";
 }

 xml += "</xml>";
  try {
  return new string(xml.tostring().getbytes(),"iso8859-1");
 } catch (unsupportedencodingexception e) {
  // todo auto-generated catch block
  e.printstacktrace();
 } 
  return "";
 }

}

3.clientcustomssl工具类,用于生成sign以及创建微信订单package com.pay.utils.weixin;

import java.util.arraylist;
import java.util.collections;
import java.util.comparator;
import java.util.hashmap;
import java.util.list;
import java.util.map;

import org.springframework.util.stringutils;


/**
 * this example demonstrates how to create secure connections with a custom ssl
 * context.
 */
public class clientcustomssl {

 public static string getbizsign(hashmap<string, string> bizobj)
  throws sdkruntimeexception {
 hashmap<string, string> bizparameters = new hashmap<string, string>();

 list<map.entry<string, string>> infoids = new arraylist<map.entry<string, string>>(
  bizobj.entryset());
 system.out.println(infoids);
 collections.sort(infoids, new comparator<map.entry<string, string>>() {
  public int compare(map.entry<string, string> o1,
   map.entry<string, string> o2) {
  return (o1.getkey()).tostring().compareto(o2.getkey());
  }
 });
system.out.println("--------------------");
 system.out.println(infoids);
 for (int i = 0; i < infoids.size(); i++) {
  map.entry<string, string> item = infoids.get(i);
  if (item.getkey() != "") {
  bizparameters.put(item.getkey().tolowercase(), item.getvalue());
  }
 }
 //bizparameters.put("key", "12345678123456781234567812345671");
 string bizstring = commonutil.formatbizqueryparamap(bizparameters,
  false);
 bizstring += "&key=12345678123456781234567812345671";
 system.out.println("***************");
 
 system.out.println(bizstring);

// return sha1util.sha1(bizstring);
 return md5util.md5(bizstring);

 }
 /**
 * 微信创建订单
 * @param noncestr
 * @param orderdescribe
 * @param orderno
 * @param price
 * @param timestart
 * @param timeexpire
 * @return
 * @throws sdkruntimeexception
 */
 public static string createnativepackage(string noncestr,string orderdescribe,string orderno,string price,string timestart,string timeexpire) throws sdkruntimeexception {
 hashmap<string, string> nativeobj = new hashmap<string, string>();
 nativeobj.put("appid", "见公众账号");          //公众账号id
 nativeobj.put("mch_id", "见邮件");    //商户号
 nativeobj.put("nonce_str", noncestr);       //随机字符串
 nativeobj.put("body", orderdescribe);    //商品描述
 nativeobj.put("attach", "tradeno");    //附加数据
 nativeobj.put("out_trade_no", orderno);          //商户订单号(全局唯一)
 nativeobj.put("total_fee", price);   //总金额(单位为分,不能带小数点)
 nativeobj.put("spbill_create_ip","192.168.0.144");     //终端ip
 nativeobj.put("time_start", timestart);          //交易起始时间
 nativeobj.put("time_expire", timeexpire);      //交易结束时间
 nativeobj.put("notify_url", customizedpropertyplaceholderconfigurer.getcontextproperty("wxurl")+"/weixin_callback/weixincallback/init.action");                   //回调通知地址
 nativeobj.put("trade_type", "native");   //交易类型
 
 string sign = getbizsign(nativeobj);
 
 nativeobj.put("sign", sign.touppercase());
 
 return commonutil.arraytoxml(nativeobj);

 }       /**
* 微信订单支付查询
* @param noncestr
* @param orderdescribe
* @param orderno
* @param price
* @param timestart
* @param timeexpire
* @return
* @throws sdkruntimeexception
*/
public static string searchnativepackage(string transactionid,string outtradeno,string noncestr) throws sdkruntimeexception {
hashmap<string, string> nativeobj = new hashmap<string, string>();
nativeobj.put("appid", "见公众共账号"); //公众账号id
nativeobj.put("mch_id", "见邮件");//商户号
nativeobj.put("nonce_str", noncestr);//随机字符串
if(!stringutils.isempty(transactionid)){
nativeobj.put("transaction_id", transactionid); 
}
if(!stringutils.isempty(outtradeno)){
nativeobj.put("out_trade_no", outtradeno);//随机字符串
}
string sign = getbizsign(nativeobj);
nativeobj.put("sign", sign.touppercase()); 
return commonutil.arraytoxml(nativeobj);
 /**
* 微信退款
* @param outtradeno
* @param outrefundno
 * @param totalfee
* @param refundfee
* @return
* @throws sdkruntimeexception
*/
public static string refundnativepackage(string outtradeno,string outrefundno,string totalfee,string refundfee,string noncestr) throws sdkruntimeexception {
hashmap<string, string> nativeobj = new hashmap<string, string>();
nativeobj.put("appid", "见公众账号");//公众账号id
nativeobj.put("mch_id", "见邮件");//商户号
nativeobj.put("nonce_str", noncestr);//随机字符串
nativeobj.put("out_trade_no", outtradeno);//商户订单号(全局唯一)
nativeobj.put("out_refund_no", outrefundno);//商户退款单号(全局唯一)
nativeobj.put("total_fee", totalfee);//总金额(单位为分,不能带小数点)
nativeobj.put("refund_fee", refundfee);//退款金额(单位为分,不能带小数点)
nativeobj.put("op_user_id", "邮件");
string sign = getbizsign(nativeobj);
nativeobj.put("sign", sign.touppercase());
return commonutil.arraytoxml(nativeobj);
}

/**
* 微信待支付
 * @param noncestr
* @param orderdescribe
* @param orderno
* @param price
* @param timestart
* @param timeexpire
* @return
* @throws sdkruntimeexception
*/
public static string createjsapipackage(string noncestr,string orderdescribe,string orderno,string price,string timestart,string timeexpire,string openid) throws sdkruntimeexception {
hashmap<string, string> nativeobj = new hashmap<string, string>();
nativeobj.put("appid", "见公众账号");//公众账号id
nativeobj.put("openid", openid);//公众账号id
nativeobj.put("mch_id", "见邮件")//商户号
nativeobj.put("nonce_str", noncestr);//随机字符串
nativeobj.put("body", orderdescribe);//商品描述
nativeobj.put("attach", "tradeno");//附加数据
nativeobj.put("out_trade_no", orderno);//商户订单号(全局唯一)
nativeobj.put("total_fee", price);//总金额(单位为分,不能带小数点)
nativeobj.put("spbill_create_ip","192.168.0.144");//终端ip
nativeobj.put("time_start", timestart);//交易起始时间
nativeobj.put("time_expire", timeexpire)//交易结束时间
nativeobj.put("notify_url",customizedpropertyplaceholderconfigurer.getcontextproperty("wxurl")+"/weixin_callback/weixincallback/init.action");//通知地址
nativeobj.put("trade_type", "jsapi");//交易类型
string sign = getbizsign(nativeobj);
nativeobj.put("sign", sign.touppercase());
return commonutil.arraytoxml(nativeobj);
}
/**
* 微信关闭订单
* @param noncestr
* @param orderdescribe
* @param orderno
* @param price
* @param timestart
* @param timeexpire
* @param openid
* @return
* @throws sdkruntimeexception
*/
public static string createcloseorder(string outtradeno,string noncestr) throws sdkruntimeexception {
hashmap<string, string> nativeobj = new hashmap<string, string>();
nativeobj.put("appid", "见公众账号");//公众账号id
nativeobj.put("mch_id", "见邮件");//商户号
nativeobj.put("out_trade_no", outtradeno);//商户订单号(全局唯一)
nativeobj.put("nonce_str", noncestr);//随机字符串
 string sign = getbizsign(nativeobj);
nativeobj.put("sign", sign.touppercase());
 return commonutil.arraytoxml(nativeobj);
}
}

4.调用微信支付接口 

package com.pay.controller.weixin;

import java.io.file;
import java.io.fileinputstream;
import java.security.keystore;
import java.text.simpledateformat;
import java.util.date;
import java.util.list;

import javax.net.ssl.sslcontext;
import javax.servlet.http.httpservletrequest;
import javax.servlet.http.httpservletresponse;

import net.sf.json.jsonarray;
import net.sf.json.jsonobject;

import org.apache.http.httpentity;
import org.apache.http.client.methods.closeablehttpresponse;
import org.apache.http.client.methods.httppost;
import org.apache.http.conn.ssl.sslconnectionsocketfactory;
import org.apache.http.conn.ssl.sslcontexts;
import org.apache.http.entity.stringentity;
import org.apache.http.impl.client.closeablehttpclient;
import org.apache.http.impl.client.httpclients;
import org.apache.http.util.entityutils;
import org.dom4j.document;
import org.dom4j.documenthelper;
import org.dom4j.element;
import org.dom4j.io.saxreader;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.http.httpstatus;
import org.springframework.web.bind.annotation.requestbody;
import org.springframework.web.bind.annotation.requestmapping;
import org.springframework.web.bind.annotation.requestmethod;
import org.springframework.web.bind.annotation.responsestatus;
import org.springframework.web.bind.annotation.restcontroller;

import com.pay.bo.payhist;
import com.pay.constants.payhistorypaystatus;
import com.pay.constants.payhistorypaytype;
import com.pay.service.weixinpayservice;
import com.pay.utils.weixin.clientcustomssl;
import com.pay.utils.weixin.closeweixinorderutils;
import com.pay.utils.weixin.customizedpropertyplaceholderconfigurer;


@restcontroller
@requestmapping("/pay")
public class weixinpaycontroller {
 
 
 @autowired
 weixinpayservice weixinpayservice;
 private static long standardtime = 1662652800000l;
 
 /**
 * 返回生成二维码的url
 * @param request
 * @param response
 * @return
 */
 @requestmapping(value="/geturl",method=requestmethod.post)
 @responsestatus(httpstatus.ok)
 public object geturl(httpservletresponse response,@requestbody string body){
 try{
  jsonobject jsono = jsonobject.fromobject(body);
  payhist ph = null;
//  list<map<string,object>> td = weixinpayservice.gettrade(orderno);
  date dt = new date();
  simpledateformat sdf = new simpledateformat("yyyymmddhhmmss");
  string noncestr = sdf.format(dt).tostring();
  date now = new date();
  
  string tradepayno = jsono.get("orderno").tostring()+string.format("%10d",standardtime - now.gettime()).substring(0, 10);
  system.out.println("订单标号orderno======="+jsono.get("orderno").tostring());
  system.out.println("10位随机数======="+string.format("%10d",standardtime - now.gettime()).substring(0, 10));
  string price = math.round(float.valueof(jsono.get("price").tostring())*100)+"";
  long timeexpirestrold = dt.gettime();
  long timenew = long.parselong(customizedpropertyplaceholderconfigurer.getcontextproperty("weixin.send2finish.overtime").tostring());
  long timeexpirenew = timeexpirestrold+timenew;
  date dttimeexpire = new date(timeexpirenew);
  simpledateformat dtsdf = new simpledateformat("yyyymmddhhmmss");
  string timeexpire = dtsdf.format(dttimeexpire).tostring();
  system.out.println("noncestr=="+noncestr);
  system.out.println("orderno=="+jsono.get("orderno").tostring());
  system.out.println("price=="+price);
  system.out.println("timestart=="+noncestr);
  system.out.println("timeexpire=="+timeexpire);
  
  
  jsonobject result = (jsonobject) seturl(noncestr,"订单",tradepayno,price,noncestr,timeexpire);
  
  if(result.get("status").tostring().equals("success")){
  ph = new payhist();
  ph.settradepayurl(result.getstring("weixinpayurl"));//此字段为支付链接,可以此链接生成二维码扫码支付
  ph.setpaytradeno(jsono.get("orderno").tostring());
  ph.settradepayno(tradepayno);
  ph.setpaystatus(payhistorypaystatus.wechat_pay_status_wait);
  ph.setpaytype(payhistorypaytype.wechat);
  ph.setappkey(jsono.getstring("appkey").tostring());
  ph.setpayamount(price);
  
  result.put("paytradeno", ph.getpaytradeno());
  result.put("tradepayno", ph.gettradepayno());
  result.put("paystatus", ph.getpaystatus());
  result.put("paytype", ph.getpaytype());
  
  }  
  return result;
  
  
 }catch(exception e){
  e.printstacktrace();
  jsonobject result = new jsonobject();
  result.put("status","error");
  result.put("msg",e.getmessage());
//  return result.tostring();
 }
 return null;
 
 
 }

 public object seturl(string noncestr,string orderdescribe,string orderno,string price,string timestart,string timeexpire) {
 try{
  
  keystore keystore = keystore.getinstance("pkcs12");
  fileinputstream instream = new fileinputstream(new file(微信证书绝对路径));
  try {
  keystore.load(instream, "商户id".tochararray());
  }finally {
  instream.close();
  }

  // trust own ca and all self-signed certs
  sslcontext sslcontext = sslcontexts.custom().loadkeymaterial(keystore,<span style="font-family: arial, helvetica, sans-serif;">商户id</span>.tochararray()).build();
  // allow tlsv1 protocol only
  sslconnectionsocketfactory sslsf = new sslconnectionsocketfactory(
   sslcontext, new string[] { "tlsv1" }, null,
   sslconnectionsocketfactory.allow_all_hostname_verifier);
  closeablehttpclient httpclient = httpclients.custom()
   .setsslsocketfactory(sslsf).build();
  // httpget httpget = new
  // httpget("https://api.mch.weixin.qq.com/secapi/pay/refund");
  httppost httppost = new httppost(
   "https://api.mch.weixin.qq.com/pay/unifiedorder");
  
  string xml = clientcustomssl.createnativepackage(noncestr,orderdescribe,orderno,price,timestart,timeexpire);
  try {

  
  stringentity se = new stringentity(xml);
  
  httppost.setentity(se);

  system.out.println("executing request" + httppost.getrequestline());

  closeablehttpresponse responseentry = httpclient.execute(httppost);
  try {
   httpentity entity = responseentry.getentity();

   system.out.println("----------------------------------------");
   system.out.println(responseentry.getstatusline());
   if (entity != null) {
   system.out.println("response content length: "
    + entity.getcontentlength());
  /* bufferedreader bufferedreader = new bufferedreader(
    new inputstreamreader(entity.getcontent()));
   string text;
   while ((text = bufferedreader.readline()) != null) {
    system.out.println("======="+text);
   }*/ 
      
   saxreader saxreader = new saxreader();
   document document = saxreader.read(entity.getcontent());
   element rootelt = document.getrootelement();
   system.out.println("根节点:" + rootelt.getname());
   system.out.println("==="+rootelt.elementtext("result_code"));
   system.out.println("==="+rootelt.elementtext("return_msg"));
   string resultcode = rootelt.elementtext("result_code");
   jsonobject result = new jsonobject();  
   
   document documentxml =documenthelper.parsetext(xml);
   element rooteltxml = documentxml.getrootelement();
   
   if(resultcode.equals("success")){
    system.out.println("=================prepay_id===================="+ rootelt.elementtext("prepay_id"));
    system.out.println("=================sign===================="+ rooteltxml.elementtext("sign"));
    result.put("weixinpayurl", rootelt.elementtext("code_url"));
    result.put("prepayid", rootelt.elementtext("prepay_id"));
    result.put("status","success");
    result.put("msg","success");
   }else{
    result.put("status","false");
    result.put("msg",rootelt.elementtext("err_code_des"));
   }
   
   
   return result;

   }
   entityutils.consume(entity);
  }
  finally {
   responseentry.close();
  }
  }
  finally {
  httpclient.close();
  }
  return null;
  
  
 }catch(exception e){
  e.printstacktrace();
  jsonobject result = new jsonobject();
  result.put("status","error");
  result.put("msg",e.getmessage());
  return result;
 }
 }
 
}


httpclient  jar包和json jar包:下载地址

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇: State

下一篇: Java抽奖算法第二例