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

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

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語(yǔ)言 - JAVA教程 - java開(kāi)發(fā)微信公眾號(hào)支付

java開(kāi)發(fā)微信公眾號(hào)支付

2020-01-02 14:08hebedich JAVA教程

這篇文章主要給大家結(jié)合微信支付接口開(kāi)發(fā)的實(shí)踐,從獲取用戶(hù)授權(quán)到各主要接口的使用方法等方面介紹微信支付的關(guān)鍵點(diǎn)技術(shù),有需要的小伙伴可以參考下

最近做了微信公眾號(hào)支付的開(kāi)發(fā),由于是第一次做也摸索了幾天的時(shí)間,也只是達(dá)到了實(shí)現(xiàn)功能的水平,并沒(méi)有太多考慮到性能問(wèn)題,所以這篇文章比較適合初學(xué)者。

    微信公眾號(hào)支付的總體其實(shí)很簡(jiǎn)單,大致就分為三步。第一步需要獲取用戶(hù)授權(quán);第二步調(diào)用統(tǒng)一下單接口獲取預(yù)支付id;第三步H5調(diào)起微信支付的內(nèi)置的js。下面介紹具體每一步的開(kāi)發(fā)流程。

一    首先要明確微信公眾號(hào)支付屬于網(wǎng)頁(yè)版支付,所以相較于app的直接調(diào)取微信支付要多一步微信授權(quán)。也就是需要獲取用戶(hù)的openid。微信公眾號(hào)使用的交易類(lèi)型是JSAPI,所以統(tǒng)一下單接口的文檔明確的寫(xiě)到

java開(kāi)發(fā)微信公眾號(hào)支付

因此我們必須去獲取openid,同時(shí)也可以處理一些我們需要的邏輯。獲取用戶(hù)授權(quán)有兩種方式:1.scope=snsapi_base;2.scope=snsapi_userinfo.我使用的是snsapi_base

Scope為snsapi_base

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=http%3A%2F%2Fchong.qq.com%2Fphp%2Findex.php%3Fd%3D%26c%3DwxAdapter%26m%3DmobileDeal%26showwxpaytitle%3D1%26vb2ctag%3D4_2030_5_1194_60&response_type=code&scope=snsapi_base&state=123#wechat_redirect

Scope為snsapi_userinfo

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxf0e81c3bee622d60&redirect_uri=http%3A%2F%2Fnba.bluewebgame.com%2Foauth_response.php&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect

微信的官方文檔也有對(duì)各個(gè)參數(shù)的詳細(xì)說(shuō)明,我就關(guān)鍵的參數(shù)仔細(xì)的說(shuō)明一下。首先appid就不多說(shuō)了就是你微信公眾號(hào)的appid固定寫(xiě)死的,redirect_uri這個(gè)參數(shù)是最重要的,這個(gè)地址是訪問(wèn)你處理的接口地址。你可以在這個(gè)鏈接上拼接上你所需要的參數(shù),一般你是要把訂單的金額傳到這個(gè)接口里的,訪問(wèn)這個(gè)鏈接的時(shí)候微信會(huì)給你code你需要用它去獲取openid,記得要對(duì)其進(jìn)行urlencode處理。state參數(shù)可以理解為擴(kuò)展字段,其他的參數(shù)都是固定寫(xiě)法就不在多做介紹了。下面是獲取openid的代碼片段。

?
1
2
3
4
5
6
7
8
9
10
//獲取openId
            HttpClientUtil util = HttpClientUtil.getInstance();
            Map<String, String> map = new HashMap<String, String>();
            map.put("appid", WxPayConfig.APPID);
            map.put("secret", WxPayConfig.APPSECRET);
            map.put("code", code);
            map.put("grant_type", WxPayConfig.GRANT_TYPE);
            String returnStr = util.doPostRetString("https://api.weixin.qq.com/sns/oauth2/access_token", null,map);
            logger.info("returnStr:[" + returnStr + "]");
            AccessToken at = JSON.parseObject(returnStr, AccessToken.class);

AccessToken.java

?
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
public class AccessToken {
   
  private String access_token;
  private String expires_in;
  private String refresh_token;
  private String openid;
  private String scope;
  private String unionid;
   
  public String getAccess_token() {
    return access_token;
  }
  public void setAccess_token(String access_token) {
    this.access_token = access_token;
  }
  public String getExpires_in() {
    return expires_in;
  }
  public void setExpires_in(String expires_in) {
    this.expires_in = expires_in;
  }
  public String getRefresh_token() {
    return refresh_token;
  }
  public void setRefresh_token(String refresh_token) {
    this.refresh_token = refresh_token;
  }
  public String getOpenid() {
    return openid;
  }
  public void setOpenid(String openid) {
    this.openid = openid;
  }
  public String getScope() {
    return scope;
  }
  public void setScope(String scope) {
    this.scope = scope;
  }
  public String getUnionid() {
    return unionid;
  }
  public void setUnionid(String unionid) {
    this.unionid = unionid;
  }
  @Override
  public String toString() {
    return "AccessToken [access_token=" + access_token + ", expires_in="
        + expires_in + ", refresh_token=" + refresh_token + ", openid="
        + openid + ", scope=" + scope + ", unionid=" + unionid + "]";
  }
   
   
 
}

二    我們獲取了openid后,就可以進(jìn)行下一步的統(tǒng)一下單的開(kāi)發(fā)了。微信上統(tǒng)一下單接口的文檔寫(xiě)的比較詳細(xì)了,具體的參數(shù)含義我就不多做介紹了。下面直接貼最直觀的代碼,特別提醒的是一定要注意簽名的正確。簽名所使用的key并不是AppSecret而是你申請(qǐng)時(shí)自己定義的商戶(hù)key。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//統(tǒng)一下單
 
            WxPaySendData data = new WxPaySendData();
            data.setAppid(WxPayConfig.APPID);
            data.setAttach("微信支付");
            data.setBody("微信公眾號(hào)支付");
            data.setMch_id(WxPayConfig.MCHID);
            data.setNonce_str(nonceStr);
            data.setNotify_url(WxPayConfig.NOTIFY_URL);
            data.setOut_trade_no(tradeNo);
            data.setTotal_fee((int)(fee*100));//單位:分
            data.setTrade_type("JSAPI");
            data.setSpbill_create_ip(ip);
            data.setOpenid(at.getOpenid());
            String returnXml = UnifiedorderService.unifiedOrder(data,WxPayConfig.KEY);
            WxPayReturnData reData = new WxPayReturnData();
            XStream xs1 = new XStream(new DomDriver());
            xs1.alias("xml", WxPayReturnData.class);
            reData = (WxPayReturnData) xs1.fromXML(returnXml);

UnifiedorderService.java

?
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
public class UnifiedorderService {
   
  private final static Logger logger = LoggerFactory.getLogger(UnifiedorderService.class);
   
  public static String unifiedOrder(WxPaySendData data,String key){
    //統(tǒng)一下單支付
    String returnXml = null;
    try {
      //生成sign簽名
      SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
      parameters.put("appid", data.getAppid());
      parameters.put("attach", data.getAttach());
      parameters.put("body", data.getBody());
      parameters.put("mch_id", data.getMch_id());
      parameters.put("nonce_str", data.getNonce_str());
      parameters.put("notify_url", data.getNotify_url());
      parameters.put("out_trade_no", data.getOut_trade_no());
      parameters.put("total_fee", data.getTotal_fee());
      parameters.put("trade_type", data.getTrade_type());
      parameters.put("spbill_create_ip", data.getSpbill_create_ip());
      parameters.put("openid", data.getOpenid());
      parameters.put("device_info", data.getDevice_info());
      logger.info("SIGN:"+WxSign.createSign(parameters,key));
      data.setSign(WxSign.createSign(parameters,key));
      XStream xs = new XStream(new DomDriver("UTF-8",new XmlFriendlyNameCoder("-_", "_")));
      xs.alias("xml", WxPaySendData.class);
      String xml = xs.toXML(data);
      logger.info("統(tǒng)一下單xml為:\n" + xml);
      HttpClientUtil util = HttpClientUtil.getInstance();
      returnXml = util.doPostForString("https://api.mch.weixin.qq.com/pay/unifiedorder", null, xml);
      logger.info("返回結(jié)果:" + returnXml);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return returnXml;
  }
   
}

WxSign

?
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
public class WxSign {
   
   
  private static String characterEncoding = "UTF-8";
 
  @SuppressWarnings("rawtypes")
  public static String createSign(SortedMap<Object,Object> parameters,String key){
    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=" + key);
    String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase();
    return sign;
  }
   
  public static String getNonceStr() {
    Random random = new Random();
    return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), "UTF-8");
  }
 
  public static String getTimeStamp() {
    return String.valueOf(System.currentTimeMillis() / 1000);
  }
 
}

最后要提一下的是NOTIFY_URL回調(diào)地址,接收微信支付異步通知回調(diào)地址。

三    通過(guò)上面的操作我們獲得了預(yù)支付交易會(huì)話(huà)標(biāo)識(shí)prepay_id,這樣我們就可以進(jìn)行最后一步的操作了。使用H5調(diào)起支付api。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//H5調(diào)起支付
              attr.addAttribute("appId", reData.getAppid());
              attr.addAttribute("timeStamp", WxSign.getTimeStamp());
              attr.addAttribute("nonceStr", reData.getNonce_str());
              attr.addAttribute("package", "prepay_id="+reData.getPrepay_id());
              attr.addAttribute("signType", "MD5");
              SortedMap<Object,Object> signMap = new TreeMap<Object,Object>();
              signMap.put("appId", reData.getAppid());
              signMap.put("timeStamp", WxSign.getTimeStamp());
              signMap.put("nonceStr", reData.getNonce_str());
              signMap.put("package", "prepay_id="+reData.getPrepay_id());
              signMap.put("signType", "MD5");
              logger.info("PaySIGN:"+WxSign.createSign(signMap,WxPayConfig.KEY));
              attr.addAttribute("paySign", WxSign.createSign(signMap,WxPayConfig.KEY));

將需要的參數(shù)傳給頁(yè)面后,使用微信提供方法調(diào)起支付。

?
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
<script>
  function getUrlParam(name) {
    //構(gòu)造一個(gè)含有目標(biāo)參數(shù)的正則表達(dá)式對(duì)象
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    //匹配目標(biāo)參數(shù)
    var r = window.location.search.substr(1).match(reg);
    //返回參數(shù)值
    if (r != null)
      return unescape(r[2]);
    return null;
  }
 
  function onBridgeReady() {
    var appId = getUrlParam('appId');
    var timeStamp = getUrlParam('timeStamp');
    var nonceStr = getUrlParam('nonceStr');
    var Package = getUrlParam('package');
    var signType = getUrlParam('signType');
    var paySign = getUrlParam('paySign');
    WeixinJSBridge.invoke('getBrandWCPayRequest', {
      "appId" : appId,//"wx2421b1c4370ec43b", //公眾號(hào)名稱(chēng),由商戶(hù)傳入  
      "timeStamp" : timeStamp,//"1395712654", //時(shí)間戳,自1970年以來(lái)的秒數(shù)  
      "nonceStr" : nonceStr,//"e61463f8efa94090b1f366cccfbbb444", //隨機(jī)串  
      "package" : Package,//"prepay_id=u802345jgfjsdfgsdg888",
      "signType" : signType,//"MD5", //微信簽名方式:  
      "paySign" : paySign,//"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信簽名
    }, function(res) { // 使用以上方式判斷前端返回,微信團(tuán)隊(duì)鄭重提示:res.err_msg將在用戶(hù)支付成功后返回  ok,但并不保證它絕對(duì)可靠。 
      //alert(res.err_msg);
      if (res.err_msg == "get_brand_wcpay_request:ok") {
        alert("支付成功");
      }
      if (res.err_msg == "get_brand_wcpay_request:cancel") {
        alert("交易取消");
      }
      if (res.err_msg == "get_brand_wcpay_request:fail") {
        alert("支付失敗");
      }
    });
  }
 
  function callPay() {
    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();
    }
  }
</script>

在返回結(jié)果的地方可以自定義一些自己的返回頁(yè)面。

    總結(jié):由于我也是第一次做,寫(xiě)這篇文章是想記錄一下自己的工作成果,和分享給一下也是新手的朋友們可以有一些幫助,最后希望有好的見(jiàn)解朋友可以留言討論,大家一起學(xué)習(xí)進(jìn)步。

以上就是關(guān)于java開(kāi)發(fā)微信公眾支付的所有內(nèi)容了,希望大家能夠喜歡。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国内会所按摩推拿国产 | 亚洲成aⅴ人片在线 | 久久这里只有精品国产精品99 | 99热这里只精品99re66 | 久久久精品成人免费看 | 欧美一卡2卡3卡无卡 | 91嫩草私人成人亚洲影院 | 日韩制服丝袜在线观看 | 亚洲国产精品牛在线 | 黑人巨大和日本娇小中出 | 特级淫片欧美高清视频蜜桃 | 亚洲欧美色综合图小说 | 国产一级毛片国语版 | 亚州笫一色惰网站 | 国产成人精品综合在线观看 | 精品一久久香蕉国产线看观 | 亚洲视频一区网站 | www.亚洲视频 | 国模一区二区三区视频一 | 日本人护士免费xxxx视频 | 日韩日韩日韩手机看片自拍 | 青青青久在线视频免费观看 | 91天堂素人| 手机看片国产免费久久网 | 午夜久久免影院欧洲 | 99热精品在线免费观看 | 天堂在线观看中文字幕 | 日本免费一区二区三区a区 日本免费三片在线观看 | 日本艳鉧动漫1~6在线观看 | 亚洲欧美成人综合 | 精品老司机在线视频香蕉 | 亚洲精品国产精麻豆久久99 | 色一级| 免费一区在线观看 | 亚洲国产一区二区三区青草影视 | 男女视频在线观看 | chinese真实incest| 四虎国产欧美成人影院 | 99久久精品国产综合一区 | 男人晚上适合偷偷看的污污 | 日韩精品一区二区三区毛片 |