一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - java實現(xiàn)微信企業(yè)付款到個人功能

java實現(xiàn)微信企業(yè)付款到個人功能

2021-06-02 13:48藍(lán)色格子ren Java教程

這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)微信企業(yè)付款到個人功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下

微信官方提供了微信企業(yè)賬戶付款到微信個人零錢接口,提供企業(yè)向用戶付款的功能,支持企業(yè)通過api接口付款,或通過微信支付商戶平臺網(wǎng)頁功能操作付款。該接口并不是直接所有的商戶都擁有,企業(yè)要開啟必須滿足以下兩個條件:

 1、商戶號已入駐90日
 2、商戶號有30天連續(xù)正常交易

滿足以上條件就可登錄微信支付商戶平臺-產(chǎn)品中心,開通企業(yè)付款。
調(diào)用的鏈接地址:接口鏈接:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
微信官方接口文檔提供的調(diào)用微信企業(yè)付款的參數(shù):

java實現(xiàn)微信企業(yè)付款到個人功能

參數(shù)中最重要是獲取用戶openid和調(diào)用接口ip,獲取openid可以通過公眾號獲取,app端可以直接獲取。具體的代碼實現(xiàn)如下:

封裝請求微信企業(yè)付款的實體類transfers:

java" id="highlighter_548829">
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
public class transfers implements serializable{
  private static final long serialversionuid = 1l;
  /** 商戶賬號appid*/
  public string mch_appid;
  /** 微信支付商戶號*/
  public string mchid;
  /** 隨機串*/
  public string nonce_str;
  /** 簽名*/
  public string sign;
  /** 商戶訂單號*/
  public string partner_trade_no;
  /** 用戶id*/
  public string openid;
  /** 是否校驗用戶姓名 no_check:不校驗真實姓名 force_check:強校驗真實姓名*/
  public string check_name;
  /** 金額 單位:分*/
  public integer amount;
  /** 企業(yè)付款描述信息*/
  public string desc;
  /** ip地址*/
  public string spbill_create_ip;
  public string getmch_appid() {
    return mch_appid;
  }
  public void setmch_appid(string mch_appid) {
    this.mch_appid = mch_appid;
  }
  public string getmchid() {
    return mchid;
  }
  public void setmchid(string mchid) {
    this.mchid = mchid;
  }
  public string getnonce_str() {
    return nonce_str;
  }
  public void setnonce_str(string nonce_str) {
    this.nonce_str = nonce_str;
  }
  public string getsign() {
    return sign;
  }
  public void setsign(string sign) {
    this.sign = sign;
  }
  public string getpartner_trade_no() {
    return partner_trade_no;
  }
  public void setpartner_trade_no(string partner_trade_no) {
    this.partner_trade_no = partner_trade_no;
  }
  public string getopenid() {
    return openid;
  }
  public void setopenid(string openid) {
    this.openid = openid;
  }
  public string getcheck_name() {
    return check_name;
  }
  public void setcheck_name(string check_name) {
    this.check_name = check_name;
  }
  public integer getamount() {
    return amount;
  }
  public void setamount(integer amount) {
    this.amount = amount;
  }
  public string getdesc() {
    return desc;
  }
  public void setdesc(string desc) {
    this.desc = desc;
  }
  public string getspbill_create_ip() {
    return spbill_create_ip;
  }
  public void setspbill_create_ip(string spbill_create_ip) {
    this.spbill_create_ip = spbill_create_ip;
  }
 
}

接口部分代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
private transfers transfers = new transfers();
// 構(gòu)造簽名的map
  private sortedmap<object, object> parameters = new treemap<object, object>();
// 微信的參數(shù)
  private weixinconfigutils config = new weixinconfigutils();
 /**
  * 微信提現(xiàn)(企業(yè)付款)
  */
  @action("weixinwithdraw")
  public string weixinwithdraw(){
    string openid = request.getparameter("openid");
    string ip = request.getparameter("ip");
    string money = request.getparameter("money");
    string doctorid = request.getparameter("doctorid");
    if (stringutils.isnotblank(money) && stringutils.isnotblank(ip) && stringutils.isnotblank(openid) && stringutils.isnotblank(doctorid)) {
    // 參數(shù)組
    string appid = config.appid;
    string mch_id = config.mch_id;
    string nonce_str = randcharsutils.getrandomstring(16);
    //是否校驗用戶姓名 no_check:不校驗真實姓名 force_check:強校驗真實姓名
    string checkname ="no_check";
    //等待確認(rèn)轉(zhuǎn)賬金額,ip,openid的來源
    integer amount = integer.valueof(money);
    string spbill_create_ip = ip;
    string partner_trade_no = uuidutils.getuuid();
    //描述
    string desc = "健康由我醫(yī)師助手提現(xiàn)"+amount/100+"元";
    // 參數(shù):開始生成第一次簽名
    parameters.put("appid", appid);
    parameters.put("mch_id", mch_id);
    parameters.put("partner_trade_no", partner_trade_no);
    parameters.put("nonce_str", nonce_str);
    parameters.put("openid", openid);
    parameters.put("checkname", checkname);
    parameters.put("amount", amount);
    parameters.put("spbill_create_ip", spbill_create_ip);
    parameters.put("desc", desc);
    string sign = wxsignutils.createsign("utf-8", parameters);
    transfers.setamount(amount);
    transfers.setcheck_name(checkname);
    transfers.setdesc(desc);
    transfers.setmch_appid(appid);
    transfers.setmchid(mch_id);
    transfers.setnonce_str(nonce_str);
    transfers.setopenid(openid);
    transfers.setpartner_trade_no(partner_trade_no);
    transfers.setsign(sign);
    transfers.setspbill_create_ip(spbill_create_ip);
    string xmlinfo = httpxmlutils.transferxml(transfers);
    try {
      closeablehttpresponse response = httputil.post(weixinconstant.withdraw_url, xmlinfo, true);
      string transfersxml = entityutils.tostring(response.getentity(), "utf-8");
      map<string, string> transfermap = httpxmlutils.parserefundxml(transfersxml);
      if (transfermap.size()>0) {
        if (transfermap.get("result_code").equals("success") && transfermap.get("return_code").equals("success")) {
          //成功需要進行的邏輯操作,
 
          }
        }
      system.out.println("成功");
    } catch (exception e) {
      log.error(e.getmessage());
      throw new basicruntimeexception(this, "企業(yè)付款異常" + e.getmessage());
    }
    }else {
      system.out.println("失敗");
    }
    return none;
  }

產(chǎn)生隨機串部分代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class randcharsutils {
  private static simpledateformat df = new simpledateformat("yyyymmddhhmmss");
 
  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(); 
  
  }

生成簽名:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class wxsignutils {
  /**
   * 微信支付簽名算法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();//所有參與傳參的參數(shù)按照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=" + weixinconstant.key);
    string sign = md5util.md5encode(sb.tostring(), characterencoding).touppercase();
    return sign;
  }
}

md5部分代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import java.security.messagedigest;
 
public class md5util {
 
  private static string bytearraytohexstring(byte b[]) {
    stringbuffer resultsb = new stringbuffer();
    for (int i = 0; i < b.length; i++)
      resultsb.append(bytetohexstring(b[i]));
 
    return resultsb.tostring();
  }
 
  private static string bytetohexstring(byte b) {
    int n = b;
    if (n < 0)
      n += 256;
    int d1 = n / 16;
    int d2 = n % 16;
    return hexdigits[d1] + hexdigits[d2];
  }
 
  public static string md5encode(string origin, string charsetname) {
    string resultstring = null;
    try {
      resultstring = new string(origin);
      messagedigest md = messagedigest.getinstance("md5");
      if (charsetname == null || "".equals(charsetname))
        resultstring = bytearraytohexstring(md.digest(resultstring
            .getbytes()));
      else
        resultstring = bytearraytohexstring(md.digest(resultstring
            .getbytes(charsetname)));
    } catch (exception exception) {
    }
    return resultstring;
  }
 
  private static final string hexdigits[] = { "0", "1", "2", "3", "4", "5",
    "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
 
}

構(gòu)造xml:

?
1
2
3
4
5
6
7
8
9
10
/**
   * 構(gòu)造企業(yè)付款xml參數(shù)
   * @param xml
   * @return
   */
  public static string transferxml(transfers transfers){
      xstream.autodetectannotations(true);
      xstream.alias("xml", transfers.class);
      return xstream.toxml(transfers);
  }

向微信發(fā)送xml請求(驗證證書)部分代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class httputil {
  /**
   * 發(fā)送post請求
   *
   * @param url
   *      請求地址
   * @param outputentity
   *      發(fā)送內(nèi)容
   * @param isloadcert
   *      是否加載證書
   */
  public static closeablehttpresponse post(string url, string outputentity, boolean isloadcert) throws exception {
    httppost httppost = new httppost(url);
    // 得指明使用utf-8編碼,否則到api服務(wù)器xml的中文不能被成功識別
    httppost.addheader("content-type", "text/xml");
    httppost.setentity(new stringentity(outputentity, "utf-8"));
    if (isloadcert) {
      // 加載含有證書的http請求
      return httpclients.custom().setsslsocketfactory(certutil.initcert()).build().execute(httppost);
    } else {
      return httpclients.custom().build().execute(httppost);
    }
  }
}

加載證書部分代碼:(加載證書需要注意證書放置位置在項目下的webapp中建文件夾,linux單獨防止只要地址配置正確即可。)

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import java.io.file;
import java.io.fileinputstream;
import java.security.keystore;
 
import javax.net.ssl.sslcontext;
 
import org.apache.http.conn.ssl.sslconnectionsocketfactory;
import org.apache.http.ssl.sslcontexts;
 
/**
 * 加載證書的類
 * @author
 * @since 2017/08/16
 */
 
@suppresswarnings("deprecation")
public class certutil {
  private static weixinconfigutils config = new weixinconfigutils();
  /**
   * 加載證書
   */
  public static sslconnectionsocketfactory initcert() throws exception {
    fileinputstream instream = null;
    keystore keystore = keystore.getinstance("pkcs12");
    instream = new fileinputstream(new file(weixinconstant.path));
    keystore.load(instream, config.mch_id.tochararray());
 
    if (null != instream) {
      instream.close();
    }
 
    sslcontext sslcontext = sslcontexts.custom().loadkeymaterial(keystore,config.mch_id.tochararray()).build();
    sslconnectionsocketfactory sslsf = new sslconnectionsocketfactory(sslcontext, new string[]{"tlsv1"}, null, sslconnectionsocketfactory.browser_compatible_hostname_verifier);
 
    return sslsf;
  }
}

加載配置文件部分代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@suppresswarnings("unused")
public class weixinconfigutils {
  private static final log log = logfactory.getlog(weixinconfigutils.class);
  public static string appid;
  public static string mch_id;
  public static string notify_url;
  public static string order_notify_url;
  public static string doctor_notify_url;
  static {
    try{
      inputstream is = weixinconfigutils.class.getresourceasstream("/weixin.properties");
      properties properties = new properties();
      properties.load(is);
      appid = properties.getproperty("weixin.appid");
      mch_id = properties.getproperty("weixin.mch_id");
      notify_url = properties.getproperty("weixin.notify_url");
      order_notify_url = properties.getproperty("weixin.order_notify_url");
      doctor_notify_url = properties.getproperty("weixin.doctor_notify_url");
    }catch(exception ex){
      log.debug("加載配置文件:"+ex.getmessage());
    }
  }
}

獲取返回的xml參數(shù)并解析為map:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
   * 解析申請退款之后微信返回的值并進行存庫操作
   * @throws ioexception
   * @throws jdomexception
   */
  public static map<string, string> parserefundxml(string refundxml) throws jdomexception, ioexception{
    parsexmlutils.jdomparsexml(refundxml);
    stringreader read = new stringreader(refundxml);
    // 創(chuàng)建新的輸入源sax 解析器將使用 inputsource 對象來確定如何讀取 xml 輸入
    inputsource source = new inputsource(read);
    // 創(chuàng)建一個新的saxbuilder
    saxbuilder sb = new saxbuilder();
    // 通過輸入源構(gòu)造一個document
    org.jdom.document doc;
    doc = (org.jdom.document) sb.build(source);
    org.jdom.element root = doc.getrootelement();// 指向根節(jié)點
    list<org.jdom.element> list = root.getchildren();
    map<string, string> refundordermap = new hashmap<string, string>();
    if(list!=null&&list.size()>0){
      for (org.jdom.element element : list) {
        refundordermap.put(element.getname(), element.gettext());
      }
      return refundordermap;
      }
    return null;
  }

調(diào)用時候主要是獲取openid和調(diào)起接口的ip(ip十分重要,微信在收到xml后會校驗傳過去的ip和微信獲取的調(diào)起接口ip是否一致)
在調(diào)用時候當(dāng)返回錯誤碼為“systemerror”時,一定要使用原單號重試,否則可能造成重復(fù)支付等資金風(fēng)險。
微信官方文檔提供有相關(guān)的 參數(shù)錯誤碼

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/github_38924695/article/details/78850704

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 五月天精品视频播放在线观看 | 爽好舒服宝贝添奶吻戏 | hd在线观看免费高清视频 | 被黑人同学彻底征服全文小说阅读 | 九九精品久久 | 91精品国产综合久久福利 | 国产一区二区免费福利片 | 男女性gif抽搐出入视频 | 十六一下岁女子毛片免费 | 极品丝袜小说全集 | 艾秋麻豆果冻传媒老狼仙踪林 | 欧美一级在线视频 | 午夜dj影院在线视频观看完整 | 99久久精品在免费线18 | 嫩草影院国产 | 欧美日韩中文国产一区 | 四虎网站在线 | 二次元美女挤奶漫画 | 精品国产91久久久久久久a | 成人免费一区二区三区在线观看 | 成人精品视频 成人影院 | 蜜桃久久久亚洲精品成人 | 久久精品国产色蜜蜜麻豆国语版 | 天天色综合久久 | a4yy欧美一区二区三区 | 99热精品在线播放 | 欧美国产日本精品一区二区三区 | 秋霞啪啪网 | 国产精品一区二区三区免费 | 动漫美丽妇人1~2在线看 | 五月九九 | 国产精品反差婊在线观看 | 视频一区二区国产无限在线观看 | 国产女王女m视频vk 国产农村一级特黄α真人毛片 | 亚洲一级片在线播放 | 无码AV免费精品一区二区三区 | 成人免费播放器 | 成人软件18免费 | 天堂成人影院 | 秋霞理论一级在线观看手机版 | 亚洲一区二区三区不卡在线播放 |