微信公众号支付开发全过程

微信公众号支付开发全过程

需求:把游戏里的商城转移到微信公众号上

微信公众号支付开发全过程_第1张图片

微信公众号支付开发的准备过程:

需要注册一个公众号,然后开通微信支付功能(需要5个工作日左右),然后就可以得到APPID,APP_SECRET,商户号,商户key等参数。

开始开发:

1. 调用统一下单接口,获取预支付ID

/**
 * 用户提交支付,获取微信支付订单接口
 */
@RequestMapping(value="/pay")
public ModelAndView pay(HttpServletRequest request,HttpServletResponse response){
    ModelAndView mv = new ModelAndView();
    String GZHID = "wxfd7c065eee11112222";// 微信公众号id
    String GZHSecret = "b5b3a627f5d1f8888888888888";// 微信公众号密钥id
    String SHHID = "111111111";// 财付通商户号
    String SHHKEY = "mmmmmmmmmmmmmmm";// 商户号对应的密钥

    /*------1.获取参数信息------- */
    //商户订单号
    String out_trade_no= request.getParameter("state"); 
    //价格
    String money = request.getParameter("money");
    //金额转化为分为单位
    String finalmoney = WeChat.getMoney(money);
    //获取用户的code
    String code = request.getParameter("code");

    /*------2.根据code获取微信用户的openId和access_token------- */
    //注: 如果后台程序之前已经得到了用户的openId 可以不需要这一步,直接从存放openId的位置或session中获取就可以。
    //toPay.jsp页面中提交的url路径也就不需要再经过微信重定向。写成:http://localhost:8080/项目名/wechat/pay?money=${sumPrice}&state=${orderId}
    String openid=null;
    try {
        List list = accessToken(code);
        openid=list.get(1).toString();
    } catch (IOException e) {
        logger.error("根据code获取微信用户的openId出现错误", e);
        mv.setViewName("error");
        return mv;
    }

    /*------3.生成预支付订单需要的的package数据------- */
    //随机数 
    String nonce_str= MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());
    //订单生成的机器 IP
    String spbill_create_ip = request.getRemoteAddr();
    //交易类型 :jsapi代表微信公众号支付
    String trade_type = "JSAPI";
    //这里notify_url是 微信处理完支付后的回调的应用系统接口url。
    String notify_url ="http://69a6a38e.ngrok.natapp.cn/heyi-console/wechat/weixinNotify";

    SortedMap packageParams = new TreeMap();
    packageParams.put("appid",  GZHID);  
    packageParams.put("mch_id",  SHHID);  
    packageParams.put("nonce_str", nonce_str);  
    packageParams.put("body", "费用");  
    packageParams.put("out_trade_no", out_trade_no);  
    packageParams.put("total_fee", finalmoney);  
    packageParams.put("spbill_create_ip", spbill_create_ip);  
    packageParams.put("notify_url", notify_url);  
    packageParams.put("trade_type", trade_type); 
    packageParams.put("openid", openid); 

    /*------4.根据package数据生成预支付订单号的签名sign------- */
    RequestHandler reqHandler = new RequestHandler(request, response);
    reqHandler.init( GZHID,  GZHSecret,  SHHKEY);
    String sign = reqHandler.createSign(packageParams);

    /*------5.生成需要提交给统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder 的xml数据-------*/
    String xml=""+
            ""+ GZHID+""+
            ""+ SHHID+""+
            ""+nonce_str+""+
            ""+sign+""+
            ""+
            ""+out_trade_no+""+
            ""+finalmoney+""+
            ""+spbill_create_ip+""+
            ""+notify_url+""+
            ""+trade_type+""+
            ""+openid+""+
            "";

    /*------6.调用统一支付接口https://api.mch.weixin.qq.com/pay/unifiedorder 生产预支付订单----------*/
    String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
    String prepay_id="";
    try {
        prepay_id = GetWxOrderno.getPayNo(createOrderURL, xml);
        if(prepay_id.equals("")){
            mv.addObject("ErrorMsg", "支付错误");
            mv.setViewName("error");
            return mv;
        }
    } catch (Exception e) {
        logger.error("统一支付接口获取预支付订单出错", e);
        mv.setViewName("error");
        return mv;
    }
    /*将prepay_id存到库中*/
    PageData p = new PageData();
    p.put("shopId", out_trade_no);
    p.put("prePayId", prepay_id);
    activityService.updatePrePayId(p);


    /*------7.将预支付订单的id和其他信息生成签名并一起返回到jsp页面 ------- */
    nonce_str= MD5.getMessageDigest(String.valueOf(new Random().nextInt(10000)).getBytes());
    SortedMap finalpackage = new TreeMap();
    String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
    String packages = "prepay_id="+prepay_id;
    finalpackage.put("appId",  GZHID);  
    finalpackage.put("timeStamp", timestamp);  
    finalpackage.put("nonceStr", nonce_str);  
    finalpackage.put("package", packages);  
    finalpackage.put("signType", "MD5");
    String finalsign = reqHandler.createSign(finalpackage);

    mv.addObject("appid",  GZHID);
    mv.addObject("timeStamp", timestamp);
    mv.addObject("nonceStr", nonce_str);
    mv.addObject("packageValue", packages);
    mv.addObject("paySign", finalsign);
    mv.addObject("success","ok");
    mv.setViewName("wechat/pay");
   return mv;
} 
  

2. H5调起微信支付的内置JS

3.支付成功之后跳转回自己的系统的某个页面

遇到的问题:

1.在微信商户平台里面需要设置api秘钥(paternerKey),所谓paternerKey意思就是伙伴的秘钥,也就是合作商的秘钥。

需要自定义一个字符串,然后用MD5加密成32位的字符串,然后设置。

微信公众号支付开发全过程_第2张图片

2.统一下单接口的容易出错的参数:

1)trade_type==交易类型==取值如下:JSAPI,NATIVE,APP。我们这里使用的JSAPI。标题已经说了,是微信公众号支付。他们的区别,请参考https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_2。

ps:JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里。MICROPAY--刷卡支付,刷卡支付有单独的支付接口,不调用统一下单接口。

2)notify_url==通知地址==接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数。

3)sign==签名==官方给的签名算法。https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_3。获取预支付ID时,如果返回值是【签名错误】。那真是的你的签名错了,请仔细核对生成sign的参数名称、参数值和调用统一下单接口的参数名称和参数值

3.要想支付成功,需要在商户号设置支付授权目录。路径应为支付页面的上一级路径。

======================================大功告成=============================================

 

 

你可能感兴趣的:(移动开发,微信开发)