java开发微信公众号支付

最近做了微信公众号支付的开发,由于是第一次做也摸索了几天的时间,也只是达到了实现功能的水平,并没有太多考虑到性能问题,所以这篇文章比较适合初学者。

微信公众号支付的总体其实很简单,大致就分为三步。第一步需要获取用户授权;第二步调用统一下单接口获取预支付id;第三步H5调起微信支付的内置的js。下面介绍具体每一步的开发流程。

一    首先要明确微信公众号支付属于网页版支付,所以相较于app的直接调取微信支付要多一步微信授权。也就是需要获取用户的openid。微信公众号使用的交易类型是JSAPI,所以统一下单接口的文档明确的写到

因此我们必须去获取openid,同时也可以处理一些我们需要的逻辑。获取用户授权有两种方式: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

微信的官方文档也有对各个参数的详细说明,我就关键的参数仔细的说明一下。首先appid就不多说了就是你微信公众号的appid固定写死的,redirect_uri这个参数是最重要的,这个地址是访问你处理的接口地址。你可以在这个链接上拼接上你所需要的参数,一般你是要把订单的金额传到这个接口里的,访问这个链接的时候微信会给你code你需要用它去获取openid,记得要对其进行urlencode处理。state参数可以理解为扩展字段,其他的参数都是固定写法就不在多做介绍了。下面是获取openid的代码片段。

//获取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

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后,就可以进行下一步的统一下单的开发了。微信上统一下单接口的文档写的比较详细了,具体的参数含义我就不多做介绍了。下面直接贴最直观的代码,特别提醒的是一定要注意签名的正确。签名所使用的key并不是AppSecret而是你申请时自己定义的商户key。

//统一下单

            WxPaySendData data = new WxPaySendData();
            data.setAppid(WxPayConfig.APPID);
            data.setAttach("微信支付");
            data.setBody("微信公众号支付");
            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

public class UnifiedorderService {

  private final static Logger logger = LoggerFactory.getLogger(UnifiedorderService.class);

  public static String unifiedOrder(WxPaySendData data,String key){
    //统一下单支付
    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("统一下单xml为:\n" + xml);
      HttpClientUtil util = HttpClientUtil.getInstance();
      returnXml = util.doPostForString("https://api.mch.weixin.qq.com/pay/unifiedorder", null, xml);
      logger.info("返回结果:" + returnXml);
    } catch (Exception e) {
      e.printStackTrace();
    }
    return returnXml;
  }

}

WxSign

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();//所有参与传参的参数按照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回调地址,接收微信支付异步通知回调地址。

三    通过上面的操作我们获得了预支付交易会话标识prepay_id,这样我们就可以进行最后一步的操作了。使用H5调起支付api。

//H5调起支付
              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));

将需要的参数传给页面后,使用微信提供方法调起支付。

<script>
  function getUrlParam(name) {
    //构造一个含有目标参数的正则表达式对象
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
    //匹配目标参数
    var r = window.location.search.substr(1).match(reg);
    //返回参数值
    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", //公众号名称,由商户传入
      "timeStamp" : timeStamp,//"1395712654", //时间戳,自1970年以来的秒数
      "nonceStr" : nonceStr,//"e61463f8efa94090b1f366cccfbbb444", //随机串
      "package" : Package,//"prepay_id=u802345jgfjsdfgsdg888",
      "signType" : signType,//"MD5", //微信签名方式:
      "paySign" : paySign,//"70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名
    }, function(res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回  ok,但并不保证它绝对可靠。
      //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>

在返回结果的地方可以自定义一些自己的返回页面。

总结:由于我也是第一次做,写这篇文章是想记录一下自己的工作成果,和分享给一下也是新手的朋友们可以有一些帮助,最后希望有好的见解朋友可以留言讨论,大家一起学习进步。

以上就是关于java开发微信公众支付的所有内容了,希望大家能够喜欢。

(0)

相关推荐

  • Java通过JsApi方式实现微信支付

    要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回.由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分. 示例代码如下: function onBridgeReady(){ WeixinJSBridge

  • java微信公众号开发(搭建本地测试环境)

    俗话说,工欲善其事,必先利其器.要做微信公众号开发,两样东西不可少,那就是要有一个用来测试的公众号,还有一个用来调式代码的开发环境. 测试公众号 微信公众号有订阅号.服务号.企业号,在注册的时候看到这样的信息,只有订阅号可以个人申请,服务号和企业号要有企业资质才可以.这里所说的微信公众号开发指的是订阅号和服务号. 另外,未认证的个人订阅号有一些接口是没有权限的,并且目前个人订阅号已不支持微信认证,也就是说个人订阅号无法调用一些高级的权限接口,下图就是一个未认证的个人订阅号所具备权限列表,像生成二

  • 微信支付H5调用支付详解(java版)

    最近项目需要微信支付,然后看了下微信公众号支付,,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验. 一.配置公众号微信支付  需要我们配置微信公众号支付地址和测试白名单. 比如:支付JS页面的地址为 http://www.xxx.com/shop/pay/ 那此处配置www.xxx.com/shop/pay/ 二.开发流程 借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/d

  • 微信java开发之实现微信主动推送消息

    1.拉取access_token2.拉取用户信息3.主动推送消息4.接口貌似要申请权限5.依赖httpclient4.2.3 和jackson 2.2.1 复制代码 代码如下: public class WeixinAPIHelper { /**  * 获取token接口  */ private String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=

  • java开发微信分享到朋友圈功能

    微信分享功能开发 用了一天时间,把微信发送给朋友和分享到朋友圈功能开发出来,在这里给大家分享一下,避免大家走弯路. 一.服务器端程序 package com.wiimedia.controller; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.text.ParseException; import

  • java实现微信公众平台自定义菜单的创建示例

    复制代码 代码如下: import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.MalformedURLException;import java.net.URL; import org.json.JSONObject; public class MenuUtil { /**  * 获得ACC

  • java实现微信支付(服务端)

    废话不多说,直接看代码. RequestHandler requestHandler = new RequestHandler(super.getRequest(),super.getResponse()); //获取token //两小时内有效,两小时后重新获取 Token = requestHandler.GetToken(); //更新token 到应用中 requestHandler.getTokenReal(); System.out.println("微信支付获取token=====

  • Java实现仿微信红包分配规则

    最近过年发红包拜年成为一种新的潮流,作为程序猿对算法的好奇远远要大于对红包的好奇,这里介绍一种自己想到的一种随机红包分配策略,还请大家多多指教. 算法介绍 一.红包金额限制 对于微信红包,我们知道没人随机的最小红包是1分,最大金额是200元,这里我们同样来设置红包的范围,下面代码我们统一金钱的单位为分. //最小红包额度 private static final int MINMONEY = 1; //最大红包额度 private static final int MAXMONEY = 200

  • Java开发微信公众号接收和被动回复普通消息

    上篇说完了如何接入微信公众号,本文说一下微信公众号的最基本功能:普通消息的接收和回复.说到普通消息,那么什么是微信公众号所定义的普通消息呢,微信开发者文档中提到的接收的普通消息包括如下几类: 1.文本消息 2.图片消息 3.语音消息 4.视频消息 5.小视频消息 6.地理位置消息 7.链接消息(被动回复的消息) 被动回复的普通消息包括: 1.回复文本消息 2.回复图片消息 3.回复语音消息 4.回复视频消息 5.回复音乐消息 6.回复图文消息 其实接收消息和被动回复消息这两个动作是不分家的,这本

  • Java编程调用微信分享功能示例

    本文实例讲述了Java编程调用微信分享功能.分享给大家供大家参考,具体如下: 这篇文章介绍如何使用java开发微信分享功能,因为工作,已经开发完成,可使用. 如果想要自定义微信的分享功能,首先在自己的页面内首先使用AJAX.下面我具体举例. 首先是在页面内写入请求后台的AJAX /** * 调用微信分享接口 * */ public void WXConfig(){ String url = getPara("href"); WXConfigController scan = new W

  • java微信公众号开发案例

    微信公众号开发一般是针对企业和组织的,个人一般只能申请订阅号,并且调用的接口有限,下面我们就来简单的描述下接入公众号的步骤: 1.首先你需要一个邮箱在微信公众号平台进行注册:      注册的方式有订阅号.公众号.小程序和企业号,个人我们这里只能选择订阅号 2.注册完后,我们登录到公众号平台--->开发--->基本配置,这里需要填写URL和token,URL就是我们使用服务器的接口: 3.Java Web服务器程序编译好且在服务器上部署可以运行的话,可在微信公众号进行在线接口调试: 1).选择

  • 第三方网站微信登录java代码实现

    前两个星期在公司中的项目加上了微信登录.绑定的功能,在这里做个记录! 一.开发前知识 1.微信开放平台与微信公众平台的区别 1.1 微信公众平台: ① 地址:https://mp.weixin.qq.com/cgi-bin/loginpage?t=wxm2-login&lang=zh_CN ② 微信公众平台面向的是普通的用户,比如自媒体和媒体,企业官方微信公众账号运营人员使用,当然你所在的团队或者公司有实力去开发一些内容,也可以调用公众平台里面的接口,比如自定义菜单,自动回复,查询功能. 1.2

随机推荐