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

详解JAVA后端实现统一扫码支付:微信篇

程序员文章站 2024-03-07 16:37:51
最近做完了一个项目,正好没事做,产品经理就给我安排了一个任务。 做一个像收钱吧这样可以统一扫码收钱的功能。 一开始并不知道是怎么实现的,咨询了好几个朋友,才知道大概的业...

最近做完了一个项目,正好没事做,产品经理就给我安排了一个任务。

做一个像收钱吧这样可以统一扫码收钱的功能。

一开始并不知道是怎么实现的,咨询了好几个朋友,才知道大概的业务流程:先是开一个网页用来判断支付平台,是微信还是支付宝,判断过后就好办了,直接照搬微信支付和支付宝的官方文档。不过微信的文档感觉有点坑,得多花点心思。

现在讲讲怎么实现微信支付网页支付,也就是公众号支付:

1.判断支付平台,在判断是微信平台时,必须使用window.location打开网页,使用其他方法在ios版微信无法打开网页,至少现在的新版微信无法打开。对应的连接是请求获取code的链接。第2步会讲到。

<html>
<head>
 <title>判断客户平台</title>
 <basefont face="微软雅黑" size="2" />
 <meta http-equiv="content-type" content="text/html;charset=utf-8" />
 <meta name="exporter-version" content="evernote windows/303244 (zh-cn, ddl); windows/6.1.7601 service pack 1 (win64);"/>
<script type="text/javascript" src="jquery-3.1.1.min.js"></script>
 <style>
 body, td {
  font-family: 微软雅黑;
  font-size: 10pt;
 }
 </style>
</head>
<body>
<script type="text/javascript"> 

window.onload = function(){
 if(isweixin()){
 window.location='http://www.xxoo.com/interfaceapi/code';
 } else if(iszfb()){
 alert('支付宝即将开放....');
//var p = document.getelementsbytagname('p'); 
//p[0].innerhtml = window.navigator.useragent;
 }else{
 alert('请使用微信或者支付宝app扫码');
 }
} 
function isweixin(){ 
 var ua = window.navigator.useragent.tolowercase();
 if(ua.match(/micromessenger/i) == 'micromessenger'){
 return true;
 }else{
 return false;
 }
} 
function iszfb(){
 var ua = window.navigator.useragent.tolowercase();
 if(ua.match(/alipayclient/i) =='alipayclient'){
  return true;
 }else{
  return false;
  }
}
</script> 
</body></html>

2.这里是获取code,回调地址必须使用urlencoder的utf-8编码,这里最终只获取openid,需要获取userinfo其他信息的自行测试,只需要修改一下 scope 的参数,

@requestmapping({ "code" })
 public void getcode(httpservletrequest request, httpservletresponse response) {
  try {
   //回调地址
   string redirect_uri = urlencoder.encode(
     "http://www.xxoo.com/interfaceapi/openid?codeid=7837283",
     "utf-8");
   string url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid="
     + wechatconfig.app_id
     + "&redirect_uri="
     + redirect_uri
     + "&response_type=code&scope=snsapi_base&state=state#wechat_redirect";
   response.sendredirect(url);
  } catch (exception e) {
   e.printstacktrace();
  }
 }

3.里面有一个codeid的参数,不要在意这个,是用来测试用的。这里只需要openid,下面是使用get方法获取json返回结果,获取到openid后,重定向到支付页面。

@requestmapping({ "openid" })
 public void getopenid(string codeid, string code,
   httpservletresponse response) {
  try {
   string requesturl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="
     + wechatconfig.app_id
     + "&secret="
     + wechatconfig.app_secret
     + "&code="
     + code
     + "&grant_type=authorization_code";
   if (code != null) {
    string json = webutils.get(requesturl, null);
    wechatresult result = new gson().fromjson(json,
      wechatresult.class);
    open_id = result.getopenid();
    system.out.println("====open_id====" + open_id);
    response.sendredirect("http://www.xxoo.com/interfaceapi/pay.html");
   }

  } catch (exception e) {
   e.printstacktrace();
  }
 }

4.在前端支付页面输入要支付的金额,提交到后台

$.ajax({
  
    type: "post",
    datatype: "html",
    url: "http://www.xxoo.com/interfaceapi/weixinpay",
    data: "value="+self.input.value,
    timeout:10000, 
    cache: true,
    async: true,
    error: function(data){
      //alert(data+"---value-->"+self.input.value);
    }, },});

5.后端获取金额然后在后端统一下单,公众号支付有两个地方不一样,一是支付类型要改为 jsapi,二是需要获取openid

 @requestmapping({ "weixinpay" })
 public void weixinpay(httpservletrequest request,
   httpservletresponse response) {
  string value = request.getparameter("value");
  wechattradetest wechat = new wechattradetest();
  string json = wechat.testunifiedorder(integer.valueof(value), open_id);
 //这里返回json到前端
  write(json, response);
 }

6.统一下单成功后返回的结果例子:

<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>
 <openid><![cdata[oupf8umuajo_m2pxb1q9znjwes6o]]></openid>
 <sign><![cdata[7921e432f65eb8ed0ce9755f0e86d72f]]></sign>
 <result_code><![cdata[success]]></result_code>
 <prepay_id><![cdata[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
 <trade_type><![cdata[jsapi]]></trade_type>
</xml>

7.返回的参数需要重新签名并返回到前端,签名方法与统一下单时的签名是一样的!签名时必须要带上微信商户返回是以json格式返回到前端。

public string testunifiedorder(int fee,string openid) {
  wechatunifiedorder request = new wechatunifiedorder();
  request.setbody("测试商品");
  request.setdetail("一个好商品");
  request.setgoods_tag("测试");
  request.setout_trade_no(system.currenttimemillis() + "");
  request.setfee_type("cny");
  request.settotal_fee(1);
  request.setspbill_create_ip("192.168.88.26");
  request.settime_start(system.currenttimemillis() + "");
  request.setopenid(openid);
  //下单成功后返回
  wechatunifiedorder.response response = wechatconfig.getinstance()
    .unifiedorder(request);
  response.settime_start(request.gettime_start());
  weichatdata data = new weichatdata();
  data.setappid(response.getappid());
  data.settimestamp(request.gettime_start());
  data.setnoncestr(response.getnonce_str());
  data.setprepay_id(response.getprepay_id());
  data.setsigntype("md5");
  treemap<string, string> requestmap = new treemap<string, string>();
  requestmap.put("appid", response.getappid());
  requestmap.put("timestamp", response.gettime_start());
  requestmap.put("noncestr", response.getnonce_str());
  requestmap.put("package", "prepay_id="+response.getprepay_id());
  requestmap.put("signtype","md5");
  data.setpaysign(sign(requestmap).touppercase());
  return new gson().tojson(data);
 }

 8.前端需要解析json,获取对应的值,唤醒微信支付 

 success: function(data){
     if(data!=null){
      var obj=eval("("+data+")");
      appid = obj["appid"];
      //timestamp = new date().gettime();
      timestamp = obj["timestamp"];
      noncestr = obj["noncestr"];
      package = obj["prepay_id"];
      paysign = obj["paysign"];
     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();
     }
    }else{
     alert("支付失败");
    }
  },

  //微信回调
  function onbridgeready(){
 weixinjsbridge.invoke(
  'getbrandwcpayrequest', {
   "appid" :appid,
   "timestamp":timestamp,
   "noncestr" :noncestr,
   "package" :"prepay_id="+package,
   "signtype" :"md5",
   "paysign" : paysign
  },
  function(res){  
   if(res.err_msg == "get_brand_wcpay_request:ok" ) {

   }else {

   }
  }
 ); 

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