首页 > 开发 > Java > 正文

java开发微信公众号支付流程

2024-07-13 09:53:01
字体:
来源:转载
供稿:网友

       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 map = new HashMap();            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 parameters = new TreeMap();      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 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 signMap = new TreeMap();              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));

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

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

       总结:由于小编我也是初次尝试着做,写这篇文章只是想记录一下自己的工作成果,和分享给一下也是新手的朋友们可以有一些帮助,如果深入,要靠自己探索,后期我也会补充文章,更多相关的内容,可以多多关注下错新技术频道

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表