java微信公众号支付

来源:互联网 发布:php查询系统源码 编辑:程序博客网 时间:2024/06/04 20:13

用最近在学习使用java开发微信公众号,在学习过程中踩了很多坑,确实费了不少劲,先来分享一下微信公众号的支付流程,已提供给朦朦胧胧的小伙伴们看看,顺便给自己整理了一下以便后续使用,这是博主第一次写博客,有毛病的地方还望指出来,谢谢!

本此开发使用的框架为springboot,开发分为三个步骤。
在开发前强烈推荐各位客官先看看开发文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_1

一 定 要 看!!!


一、准备阶段

具备条件:已认证微信号,且通过微信支付认证,这个可以看微信文档,会有详细的解析,这里就不再重复了。

开发前,我们先登录自己的服务号,点击微信支付——>开发配置(目前开发配置已经迁移到商户平台了)

先进入商户平台—->产品中心—->开发配置
这里写图片描述

最下面有这个支付配置框,请配置好小伙伴们想使用的支付授权目录
这里写图片描述

配置API密匙,在商户平台中账户中心—->API安全
这里写图片描述

接下来要从公众号—->基本配置,拿到微信支付中所需要使用的参数AppId、AppSecret
这里写图片描述


二、前端页面

下面是我在做支付测试时使用的测试页面,为了方便,只做了一个支付按钮并且有点奇怪,直接上代码吧!

<html>    <head>        <meta charset="UTF-8">        <title></title>    </head>    <body>        <a href="javascript:void(0);" onclick="pay();" class="button">支付</a>    </body></html>
//这儿是相关的JS代码<script type="text/javascript" src="../js/jquery-1.10.2.min.js"></script>    <script type="application/javascript">        var appid;        var nonceStr;        var myPackage = "prepay_id=";        var tmp ;        var sign;        function pay() {            $.ajax({                url: "/web/wxpay/"+1000,                async: false,                dataType: "json",                success: function(resp) {                    appid=resp.appId;                    nonceStr=resp.nonceStr;                    tmp=resp.timeStamp;                    myPackage=myPackage+resp.pg;                    sign=resp.paySign;                    alert(appid);                    alert(nonceStr);                    alert(tmp);                    callpay();                }            });        }                function onBridgeReady() {                    WeixinJSBridge.invoke(                        'getBrandWCPayRequest', {                            "appId": appid, //公众号名称,由商户传入                                 "timeStamp": tmp, //时间戳,自1970年以来的秒数                                 "nonceStr": nonceStr, //随机串                                 "package": myPackage,                            "signType": "MD5", //微信签名方式:                                 "paySign": sign //微信签名                         },                        function(res) {                            if (res.err_msg == "get_brand_wcpay_request:ok") {                                alert('支付成功');                            } else if (res.err_msg == "get_brand_wcpay_request:cancel") {                                alert('支付过程中用户取消');                            } else if (res.err_msg == "get_brand_wcpay_request:fail") {                                alert('支付失败');                            } else {                                alert('未知异常');                            } // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。                         }                    );                }        function callpay() {            if (typeof WeixinJSBridge == "undefined") {                alert("WeixinJSBridge");                if (document.addEventListener) {                    alert("addEventListener");                    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);                } else if (document.attachEvent) {                    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);                    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);                }            } else {                onBridgeReady();            }        }    </script>

页面结果:
这里写图片描述

哈哈哈,当然不是这个按钮啦,这是项目中的按钮,别介意,作用还是差不多的!!


三、后端实现

首先,需要下载微信公众平台上提供的SDK,然后将SDK打成jar包,并在pom.xml添加依赖。
这里写图片描述

这是博主使用来统一下单的类

import java.math.BigDecimal;import java.util.HashMap;import java.util.Map;import java.util.Random;import javax.servlet.http.HttpServletRequest;import org.apache.commons.codec.digest.DigestUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import com.alibaba.fastjson.JSON;import com.github.wxpay.sdk.WXPay;import com.github.wxpay.sdk.WXPayUtil;import com.zt.dao.PrintDao;import com.zt.dao.UserDao;import com.zt.domain.User;public class MyWXPay {    public String strJson;    public Map<String, String> resp = new HashMap<String, String>();    public Map<String, String> payMap = new HashMap<String, String>();      public String str=getOutTradeNo();    public MyWXPay(HttpServletRequest request,String openid,BigDecimal money,long useIntegral) throws Exception {//      WXPayUtil wxPayUtile=new WXPayUtil();        MyConfig config = new MyConfig();        WXPay wxpay = new WXPay(config);        //这里生产预支付订单签名        Map<String, String> data = new HashMap<String, String>();        String theMoney =String.valueOf(money.multiply(new BigDecimal(100)).intValue()) ;//微信支付  total_fee不能出现小数   必须转换为分以整数形式传递数据        String timeStampStr=String.valueOf(System.currentTimeMillis());        String timeStamp=timeStampStr.substring(0, 10);        data.put("appid","");//填写AppId        data.put("mch_id","");//填写商户号        data.put("body", "");//商品描述        data.put("out_trade_no", str);//商户订单号,博主是用随机生成的方式生成        data.put("device_info", "WEB");//设备号        data.put("fee_type", "CNY");//人名币类型        data.put("total_fee", theMoney);//支付金额        data.put("openid", openid);//支付者的openId        data.put("timeStamp", timeStamp);//时间戳        data.put("spbill_create_ip", request.getRemoteAddr());//终端IP        data.put("notify_url", "http://wechat.gdssn.top/web/notify");//通知地址        data.put("nonce_str", str);//随机字符串        data.put("trade_type", "JSAPI");  // 此处指定为公众号支付        //这里生成支付订单        try {            resp = wxpay.unifiedOrder(data);            String timeStampStr2=String.valueOf(System.currentTimeMillis());            String timeStamp2=timeStampStr2.substring(0, 10);            payMap.put("appId", config.getAppID());              payMap.put("timeStamp", timeStamp2);              payMap.put("nonceStr", getOutTradeNo());              payMap.put("signType", "MD5");              payMap.put("package", "prepay_id=" + resp.get("prepay_id"));             String paySign = WXPayUtil.generateSignature(payMap, config.getKey());                payMap.put("pg", resp.get("prepay_id"));              payMap.put("paySign", paySign);             strJson = JSON.toJSONString(payMap);              System.out.println("resp="+resp);            System.out.println("strJson="+strJson);        } catch (Exception e) {            e.printStackTrace();        }    }    //生成随机的32位字符串,用于商户订单号,随机字符串    public static String getOutTradeNo() {         String base = "abcdefghijklmnopqrstuvwxyz0123456789";             Random random = new Random();             StringBuffer sb = new StringBuffer();             for (int i = 0; i < 32; i++) {                 int number = random.nextInt(base.length());                 sb.append(base.charAt(number));             }             return sb.toString();          }  }

这是博主自己重写的配置参数的类,上面的类中的AppId、mchId等等参数是从这里获取的

import com.github.wxpay.sdk.WXPayConfig;import java.io.*;public class MyConfig implements WXPayConfig{    public String keyPath ="";    public String mchId="";    public String ApiSecret="";     public String appId="";    private byte[] certData;    public MyConfig() throws Exception {        File file = new File(keyPath);        InputStream certStream = new FileInputStream(file);        this.certData = new byte[(int) file.length()];        certStream.read(this.certData);        certStream.close();    }    public String getAppID() {        return appId;    }    public String getMchID() {        return mchId;    }    public String getKey() {        return ApiSecret;    }    public InputStream getCertStream() {        ByteArrayInputStream certBis = new ByteArrayInputStream(this.certData);        return certBis;    }    public int getHttpConnectTimeoutMs() {        return 8000;    }    public int getHttpReadTimeoutMs() {        return 10000;    }}

最后是编写微信支付的接口

    String result;//返回给微信的回调数据    MyWXPayRefund myWXPayRefund;     @RequestMapping("/wxpay/{money:.+}")   //{money:.+}  这种写法可以接收小数点!    public void WxPay(@PathVariable(name = "money", required = false)String money,HttpServletRequest request,HttpServletResponse response,ModelMap model){        String openId=request.getSession().getAttribute("openid").toString();        MyWXPay myWxPay;        BigDecimal theMoneyBD=new BigDecimal(money);         BigDecimal theIntegral=new BigDecimal(0);        theMoneyBD=theMoneyBD.setScale(2, BigDecimal.ROUND_UNNECESSARY );        try {            myWxPay = new MyWXPay(request,openId,theMoneyBD.subtract(theIntegral));            CommonUtils.writeJson(myWxPay.payMap, response);        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }    @RequestMapping("/notify")    public String notify(@RequestBody String notifyData) {//           String notifyData = "...."; // 支付结果通知的xml格式数据        try{            MyConfig config = new MyConfig();             WXPay wxpay = new WXPay(config);             Map<String,String> resultData=new HashMap<>();             Map<String, String> notifyMap = WXPayUtil.xmlToMap(notifyData);  // 转换成map             if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {                 LOGGER.info("签名正确!");                 // 签名正确                 // 进行处理。                 // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功             }             else {                 resultData.put("return_code", "FAIL");                 resultData.put("return_msg", "签名失败");                 result = WXPayUtil.mapToXml(resultData);                 // 签名错误,如果数据里没有sign字段,也认为是签名错误             }             if(notifyMap.get("result_code").equals("SUCCESS")){                 myWXPayRefund=new MyWXPayRefund(notifyMap);                 if(myWXPayRefund.resp.get("isSuccess") != null&&myWXPayRefund.resp.get("isSuccess").equals("true")){                     LOGGER.info("交易状态成功!return_code= "+notifyMap.get("result_code"));                     resultData.put("return_code", "SUCCESS");                     resultData.put("return_msg", "OK");                     result = WXPayUtil.mapToXml(resultData);                     return result;                 }else{                     LOGGER.info("交易状态失败!return_code= "+notifyMap.get("result_code"));                     resultData.put("return_code", "fail");                     resultData.put("return_msg", "交易失败");                     result = WXPayUtil.mapToXml(resultData);                 }             }             if(!notifyMap.get("result_code").equals("SUCCESS")){                 LOGGER.info("交易状态失败!return_code= "+notifyMap.get("result_code"));                 resultData.put("return_code", "fail");                 resultData.put("return_msg", "参数格式校验错误");                 result = WXPayUtil.mapToXml(resultData);             }             LOGGER.info("返回给微信后台的result= "+result);        }catch(Exception e){            e.printStackTrace();        }        return result;    }

点击按钮结果:

这里写图片描述      这里写图片描述

到这里就结束啦,如有疑问或有不对的地方请留言,博主会进行解答与改正,谢谢!!

原创粉丝点击