美文网首页
微信内网站微信支付对接

微信内网站微信支付对接

作者: 东陂人 | 来源:发表于2019-04-06 17:40 被阅读0次

    文章包括以下内容

    • 支付场景简介

    • 第一步:申请微信支付申请(注册微信支付商户号)

    • 第二步:获取商户号的支付参数

    • 第三步:SDK下载(java版本)

    • 第四步:支付过程了解第五步:开始设计和编码

    支付场景介绍

    目前微信支付有6个场景,分别是以下6个(2019-04-06)

    • 我有线下场所

    • 我有公众号

    • 我有小程序

    • 我有pc网站

    • 我有App

    • 我有企业微信

    image

    https://pay.weixin.qq.com/static/applyment_guide/applyment_index.shtml

    第一步:申请微信支付申请(注册微信支付商户号)

    这一步完成后那么就拥有了支付接口权限了。

    我的支付场景是公众号支付,所以首先你先要有一个公众号。有了公众号之后就可以申请付款码支付和JSAPI支付产品了,我习惯成这个产品为支付接口。也就是有了2个支付接口权限了,

    根据自身的属性申请准备对应的申请材料

    交申请费用(目前几百就行了)

    3个申请流程

    image

    image

    image

    https://pay.weixin.qq.com/static/applyment_guide/applyment_detail_public.shtml

    第二步:获取商户号的支付参数

    支付参数都是登录商户号页面里面获取的,参数用于对接用

    需要4参数:

    appid(appid)

    mchid(商户id)

    key(支付key)

    certPath(证书路径)

    说明:以上参数是sdk需要的参数

    第三步:SDK下载(java版本)

    首先下载微信支付sdk,我选择的是java开发

    下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1

    解压之后的目录是这样的

    image

    文件说明

    src:源代码目录

    pom.xml:该库依赖的第三库

    README.md:微信提供的示例,这个一定要打开看看,里面有关于怎么使用这个sdk的例子。

    把下载下来的代码引入到工程下目录是这样的

    image

    第四步:支付过程了解

    对应的微信支付文档地址:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_3

    下面这个时序图是从用户下单到支付完成过程,涉及的应用包括微信客户端,商户app客户端,上后后台系统,微信支付系统。

    大概的过程是这样的

    • 用户打开商户系统选择商品下单,这时候商户系统后台生成订单和订单明细,记录到数据库中(购物车)

    • 用户向商户系统发送支付请求(带上订单id)

    • 商户系统系统根据订单id计算金额等一些信息(收集一些支付参数)

    • 向微信发起支付请求(生成预支付订单),并且返回预支付参数(用于调起微信支付界面)

    • 商户系统接收微信系统的支付结果推送。

    • 商户系统根据推送结果更新订单状态

    基本上我们关注的是商户系统的开发,比如购物车(生成订单和订单明细),更新订单支付状态这些功能点了

    image

    第五步:开始设计和编码

    了解以上微信支付的过程后接下来要编码就简单多了,

    首先我们需要有个订单和订单明细表,如customer_order,customer_order_detail,

    customer_order主要的字段包括:

    image

    customer_order_detail主要字段包括:

    image

    调用微信统一支付接口代码

    
    public Map<String, String> pay(String orderId,String ip, boolean debug,String openid) throws Exception {
    
    OrderInfo order = orderInfoDao.get(orderId);
    
    if(order == null)
    
    {
    
    throw new ServiceException(ErrorCode.ORDER_ERR3);
    
    }
    
    if(!OrderState.NOT_PAY.getValue().equals(order.getOrderState())){
    
    throw new ServiceException(ErrorCode.ORDER_ERR4);
    
    }
    
    if(!order.getOpenid().equals(openid)){
    
    throw new ServiceException(ErrorCode.ORDER_ERR6);
    
    }
    
    Map<String, String> resp = null;
    
    Map<String, String> res = new HashMap<String, String>();
    
    if(debug){
    
    resp = new HashMap<String, String>();
    
    resp.put("debug", "true");
    
    resp.put("totalFee",order.getTotalFee().toString());
    
    }else{
    
    System.out.println("-----------------appid=" + config.getAppID());
    
    System.out.println("-----------------mchid=" + config.getMchID());
    
    log.debug("--------appid="+config.getAppID());
    
    log.debug("--------mchid="+config.getMchID());
    
    log.debug("--------key="+config.getKey());
    
    config.print();
    
    // 生成微信支付
    
            WXPay wxpay = new WXPay(config);
    
            Map<String, String> wxData = new HashMap<String, String>();
    
            String timeStamp = String.valueOf(new Date().getTime()/1000);
    
            wxData.put("body", order.getTableId());
    
    //         wxData.put("body", "999999999999");
    
            wxData.put("out_trade_no", order.getId());
    
            wxData.put("openid", openid);
    
            wxData.put("device_info","device_info");
    
            wxData.put("fee_type", "CNY");
    
            wxData.put("total_fee", "1");
    
            //wxData.put("total_fee", String.valueOf(Double.valueOf(order.getTotalFee()).intValue()));
    
            log.info("订单金额:" + wxData.get("total_fee"));
    
            wxData.put("spbill_create_ip", ip);
    
            wxData.put("notify_url", notifyUrl);
    
            wxData.put("timeStamp", timeStamp);
    
            wxData.put("openid", openid);
    
            wxData.put("trade_type", "JSAPI");  //
    
            //boolean b = new File("conf/apiclient_cert.p12").exists();
    
            log.info("============正在调用支付接口参数" + wxData);
    
    //         wxData.put("product_id",course.getId());
    
            resp = wxpay.unifiedOrder(wxData);
    
            log.info("下单返回结果:"+resp);
    
            res.put("appId", resp.get("appid"));
    
            res.put("timeStamp", timeStamp);
    
            res.put("nonceStr", resp.get("nonce_str"));
    
            res.put("signType", "MD5");
    
            res.put("package", "prepay_id="+resp.get("prepay_id"));
    
            String paySign = WXPayUtil.generateSignature(res, config.getKey(), SignType.MD5);
    
            res.put("paySign", paySign);
    
    }
    
    order.preUpdate();
    
    int result = orderInfoDao.update(order);
    
    if(result != 1)
    
    {
    
    throw new ServiceException(ErrorCode.COMMON_SYS_BUSY);
    
    }
    
    return res;
    
    }
    
    

    这里要注意的就是返回的结果中要有个对参数进行签名,sdk中提供的是扫描支付号线更没有加入最后一行的签名,我这里遇到了一坑花了好长时间,其实时序图中已经写明了要进行签名,所以吸取个教训,一定要看清楚文档。

    拉起微信支付界面

    这里需要利用上一步的参数,然后调用微信内置浏览器的函数拉起微信支付,所以这里一定要在微信内打开才能拉起支付,在别的手机浏览器或者电脑浏览器打开是不行的。

    
    function onBridgeReady(data) {
    
    var payPare = {
    
    "appId" : data.appId, //公众号名称,由商户传入   
    
    "timeStamp" : data.timeStamp, //时间戳,自1970年以来的秒数   
    
    "nonceStr" : data.nonceStr, //随机串   
    
    "package" : data.package,//"prepay_id=u802345jgfjsdfgsdg888",   
    
    "signType" : "MD5", //微信签名方式:   
    
    "paySign" : data.paySign
    
    //微信签名
    
    };
    
    WeixinJSBridge.invoke('getBrandWCPayRequest', payPare,
    
    function(res) {
    
    if (res.err_msg == "get_brand_wcpay_request:ok") {
    
    // 使用以上方式判断前端返回,微信团队郑重提示:
    
    //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
    
    }
    
    });
    
    }
    
    

    如果程序正常调用该函数应该会拉起微信支付界面,这里值得说下的是维系貌似有提供沙箱模式给开发者测试用的,但是没必要开发过程中可以先把金额调整1分钱就行了,就像下图这样。真实环境开干啊。

    image

    最后一步:更新支付状态(订单状态)

    这里需要说下在调用预支付(统一支付接口)的时候有个参数是设置回调的连接,notify_url,这个连接是用户支付之后微信用这个链接来告诉你支付结果的,这里要注意更新订单的时候要判断下微信是否已经支付过了(判重),好像微信不止推送一次的,如果订单不止未支付和已支付2个状态那么一定要做一下判重。

    
    public AppResponse payResult(HttpServletRequest request) {
    
    boolean debug = "true".equals(Global.getConfig("debug"));
    
    if(debug){
    
    String orderId = request.getParameter("orderId");
    
    orderService.updateOrderByOutTradeNo(orderId,
    
    orderId, "",true);
    
    return new AppResponse(ErrorCode.COMMON_SUCCESS.getKey(),ErrorCode.COMMON_SUCCESS.getMsg(),orderId);
    
    }
    
    loger.debug("收到微信支付成功通知");
    
    InputStream inStream;
    
    String outTradeNo = null;
    
    try {
    
    inStream = request.getInputStream();
    
    int _buffer_size = 1024;
    
    if (inStream == null)
    
    return null;
    
    ByteArrayOutputStream outStream = new ByteArrayOutputStream();
    
    byte[] tempBytes = new byte[_buffer_size];
    
    int count = -1;
    
    while ((count = inStream.read(tempBytes, 0, _buffer_size)) != -1) {
    
    outStream.write(tempBytes, 0, count);
    
    }
    
    tempBytes = null;
    
    outStream.flush();
    
    // 将流转换成字符串
    
    String result = new String(outStream.toByteArray(), "UTF-8");
    
    WXPay wxpay = new WXPay(config);
    
    Map<String, String> notifyMap = WXPayUtil.xmlToMap(result); // 转换成map
    
    if (wxpay.isPayResultNotifySignatureValid(notifyMap)) {
    
    loger.debug("签名成功");
    
    // 签名正确
    
    // 进行处理。
    
    // 注意特殊情况:订单已经退款,但收到了支付结果成功的通知,不应把商户侧订单状态从退款改成支付成功
    
    String payResult = notifyMap.get("return_code");
    
    outTradeNo = notifyMap.get("out_trade_no"); // 商户订单号
    
    String transactionId = notifyMap.get("transaction_id"); // 微信订单号
    
    loger.debug("-------------微信订单号:transaction_id="+transactionId);
    
    loger.debug("-------------outTradeNo:outTradeNo="+outTradeNo);
    
    orderService.updateOrderByOutTradeNo(outTradeNo,
    
    transactionId, payResult,false);
    
    } else {
    
    // 签名错误,如果数据里没有sign字段,也认为是签名错误
    
    }
    
    } catch (ServiceException e) {
    
    e.printStackTrace();
    
    loger.debug(e.getMessage());
    
    } catch (IOException e) {
    
    loger.debug(e.getMessage());
    
    e.printStackTrace();
    
    } catch (Exception e) {
    
    loger.debug(e.getMessage());
    
    e.printStackTrace();
    
    }
    
    return null;
    
    }
    
    

    以上就是基本的支付流程了,我遇到的问题大概就是支付参数获取麻烦(商户号不是我的),和少了次签名,导致花了好多时间。

    完毕,谢谢大家

    相关文章

      网友评论

          本文标题:微信内网站微信支付对接

          本文链接:https://www.haomeiwen.com/subject/fzariqtx.html