首页 > 作文

微信公众平台和微信开放平台的区别(2者区别对比分析)

更新时间:2023-04-05 15:43:29 阅读: 评论:0

上一篇文章中总结了支付宝支付前后端实现,本篇将对其竞争对手——微信支付进行详细讲解。其中涉及代码来源于目前正在开发的项目,这个项目涉及pc端、h5移动端及app三类用户界面,app基于flutter开发,前后端目前都由我一人完成,后续将对这个项目中涉及到的技术进行一步步的总结,感兴趣的小伙伴可以关注一下。

1. 微信支付概述

对于线上应用来说,微信支付方式无外乎以下五种:

app:适用于第三方app调用微信支付;pc网站:适用于pc网站发起的微信支付,又称native支付,展示一个二维码页面,供用户通过微信客户端扫描后支付。微信内浏览器:即通过微信浏览器打开的页面,通过jsapi进行支付,可以直接打开微信支付进行直接。这种方式适应于通过微信公众号打开的页面,或者是通过微信分享的链接点击后直接在微信内浏览器打开的场景。小程序:小程序内的支付。移动端非微信浏览器:通过h5支付方式,可直接跳转微信进行支付。

本文主要讲述pc网站、微信内浏览器及移动端非微信浏览器上的支付实现。

2. 开发前准备

微信体系目前比较混乱,据我目前了解的,除qq之外,微信自己都有三个不同的管理平台:微信公众平台、微信开放平台和微信支付商户平台, 但这三个平台更多的是业务上的区分。我们需要先登录公众平台,申请微信支付,同时配置业务域名、js接口安全域名等,如图所示:

公众号设置

然后登录微信支付商户平台,将商户与微信公众号做关联。

如果要使用移动app进行支付,需要登录微信开放平台创建应用:https://open.weixin.qq.com/

在此可以创建app、网站应用、小程序等,同时可以绑定公众平台中的公众号应用。

开放平台配置

我这个项目当前使用的都是公众平台应用来进行支付的,不需要登录开放平台进行配置;目前正在开发app,因此也开始在开放平台上申请了一个移动应用,等待腾讯审核。

配置完后就可以通过公众平台获取到应用id及cret,并在商户平台中获取商户号,在后续的开发中会使用到。

3. 微信支付简要流程

一个简单的微信支付流程如下所示(按我的项目来的,实际每个项目的下单流程肯定会不一样,但关于微信支付的部分基本是一致的):

微信支付流程用户购买商品;后端生成订单号订单信息确认,用户下单后端生成订单,同时调用微信接口生成微信端订单,并返回订单信息给前端前端根据微信订单信息跳转微信支付页面(或者加载二维码)用户支付完成微信端跳转到支付前页面(如未指定重定向页面),同时会推送支付结果给后端应用

4. 支付过程示例图如下所示:

商品选择

商品选择生成订单号并确认

订单确认支付界面(pc)

pc扫码支付支付界面(微信内)

微信内支付

5. 具体实现

考虑代码量太大影响展示,因此下面会将无关代码隐藏,如果有问题可以私信。

5.1 前端订单确认与下单

<template>  <div class="buy-vip-confirm-page p-1">    <template v-if="!plan.paymoney">订单已失效或已支付完成</template>    <template v-el>      <van-cell-group title="订单信息">        <van-cell title="订单号" :value="orderno" />    锋味江湖之决战食神    <van-cell title="订单金额(元)" :value="plan.refillmoney" />        <van-cell          title="获得t币"          :value="plan.paymoney * (plan.isvip ? 1.5 : 1)"        />      </van-cell-group>      <div class="buttons">        <van-button type="primary" @click="dobuy" class="mb-1"          >确认并支付</van-button        >        <van-button @click="$goback()">取消</van-button>      </div>    </template>  </div></template><script>export default {  components: {},  data() {    return {      plan: {},      orderno: "",      paychannel: "wx",     };   },  mounted() {    this.plan = this.$route.query || {};    // 生成订单号    this.$get("/trade/generate-order-no").then((resp) => {      this.orderno = resp;     });   },  methods: {    dobuy() {      var platform = 0;      // 0表示pc支付,1表示微信内支付; 2表示mweb支付      // 此处是h5端的页面,因此没有0的情况,0的情况的pc端处理      platform = this.$iswx() ? 1 : 2;      this.$post("/pay/refill", {        orderno: this.orderno,        fee: this.plan.refillmoney,        channel: this.paychannel === "wx" ? 2 : 1,        tbamount: this.plan.paymoney,        tbntamount: this.plan.isvip ? this.plan.paymoney * 0.5 : 0,        platform: platform,       }).then((resp) => {        // 生成支付表单成功后跳转支付页面        resp.platform = platform;        this.$gopath("/ur/pay/wx-pay", resp);       });     },   },};</script>

注意iswx是全局的判断是否是微信浏览器的方法,实现如下:

// 判断是否是微信浏览器 vue.prototype.$iswx = () => {  let ua = navigator.uragent.tolocalelowerca();  return ua.indexof("micromesnger") !== -1;}

用户在确认订单后点击“发起订单并支付”,将调用后台/pay/refill接口生成订单。

5.2 后台订单生成

开发之前需要先下载微信提供的sdk(https://pay.weixin.qq.com/wiki/doc/api/wxpay/ch/pages/sdk.shtml),然后在maven中进行配置:

<dependency>  <groupid>com.github.wxpay</groupid>  <artifactid>wxpay-sdk</artifactid>  <version>0.0.3</version>  <scope>system</scope>  <systempath>${project.badir}/src/main/resources/jar/wxpay-sdk-0.0.3.jar</systempath></dependency>

然后定义wxpayconfigimpl类如下:

package com.ttcn.front.common.config;import com.github.wxpay.sdk.wxpayconfig;import java.io.inputstream;public class wxpayconfigimpl implements wxpayconfig {  public wxpayconfigimpl() {   }  public string getappid() {    return "***";   }  public string getmchid() {    return "***";   }  public string getkey() {    return "***";   }  public inputstream getcertstream() {    return null;   }  public int gethttpconnecttimeoutms() {    return 10000;   }  public int gethttpreadtimeoutms() {    return 0;   }}

注意需要将appid及商户号、key配置成从公众平台、商户平台中获取的值。

完成后就可以继续编码了。

/pay/refill接口实现如下:

/**   * 充值   *   * @param refill 充值   * @return 支付相关信息   */  @preauthorize("isauthenticated()")  @postmapping("/refill")  public paydto refill(@requestbody @validated refilldto refill) {    urdto ur = this.getloginurorthrow();    if (null == tradervice.findbyno(refill.getorderno())) {      // 保存订单      tradedto tradedto = new tradedto();       ...      tradervice.save(ur, tradedto);     }    // 获取支付二维码    string openid = ur.getwxopenid();    if (refill.getplatform().equals(1)) {      openid = ur.getmpopenid();     }    return wxpayrvice.getpayurl(openid, refill.getorderno(), refill.getfee(), tradetype.refill, refill.getplatform());   }

wxpayrvice.getpayurl即用于调用微信接口生成微信端订单,实现如下:

/**   * 查询支付页面地址   *   * @param platform 0 : web端;1: 微信内支付;2: mweb支付(即移动端非微信内支付)   * @return 支付页面地址   */  public paydto getpayurl(string openid, string orderno, double fee, tradetype tradetype, integer platform) {    platform = optional.ofnullable(platform).orel(0);    boolean isjspay = platform.equals(1);    string ip;    try {      ip = inetaddress.getlocalhost().gethostaddress();     } catch (unknownhostexception e) {      logger.error("获取ip地址失败", e);      throw businesxception.create("生成支付二维码失败,请稍后重试");     }    string feestr = string.format("%.0f", fee * 100d);    map<string, string> params = mapenhancer.<string, string>create()         .put("body", tradetype.getname())         .put("nonce_str", orderno)         .put("out_trade_no", orderno)         .put("total_fee", feestr)         .put("spbill_create_ip", ip)         .put("notify_url", notifyurl)         .put("trade_type", isjspay ? "jsapi" : (platform == 0 ? "native" : "mweb"))         .putnotnull("openid", isjspay ? openid : null)         .put("product_id", string.valueof(tradetype.ordinal()))         .get();    if (logger.isdebugenabled()) {      logger.debug("微信支付下单参数: {}", params);     }    map<string, string> result;    try {      result = wxpay.unifiedorder(params);     } catch (exception e) {      logger.error("生成微信支付二维码失败", e);      throw businesxception.create("生成微信支付二维码失败,请稍候重试");     }    if (logger.isdebugenabled()) {      logger.debug("发送微信支付订单结果: {}", result);     }    string resultcode = maputils.getstring(result, "result_code");    if ("success".equals(resultcode)) {      if (logger.isdebugenabled()) {        logger.debug("发送订单成功");       }      paydto paydto = new paydto();      paydto.tfee(fee);      paydto.torderno(orderno);      paydto.tcodeurl(maputils.getstring(result, isjspay ? "prepay_id" : (platform == 0 ? "code_url" : "mweb_url")));      // 如果是jspay      if (isjspay) {        // 需要组装参数并签名        // 签名        map<string, string> signparams = new treemap<>();        signparams.put("appid", config.getappid());        signparams.put("timestamp", string.valueof(localdatetime.now().toepochcond(zoneofft.ofhours(8))));        signparams.put("noncestr", uuid.randomuuid().tostring().replaceall("-", ""));        signparams.put("package", "prepay_id=" + maputils.getstring(result, "prepay_id"));        signparams.put("signtype", "md5");        try {          string sign = wxpayutil.generatesignature(signparams, config.getkey());          signparams.put("paysign", sign);         } catch (exception e) {          logger.error("签名失败", e);          throw businesxception.create("签名失败");         }        paydto.tparams(signparams);       }      return paydto;     }    logger.error("发送微信支付订单失败,返回结果:{}", result);    throw businesxception.create("生成微信支付二维码失败,请重试或联系管理员");   }

可以看到上面主要是组装参数然后调用wxpay.unifiedorder接口生成支付表单;

涉及的参数如下:

body商品简单描述nonce_str随机字符串,长度要求在32位以内out_trade_no商户系统内部订单号,要求32个字符内公路安全保护条例,且在同一个商户号下唯一 接收支付结果通知时会包括这个参数,因此可以将通知结果与之前的订单关联上; total_fee订单总金额,单位为分spbill_create_ip支持ipv4和ipv6两种格式的ip地址。用户的客户端ipnotify_url异步接收微信支付结果通知的回调地址,通知url必须为外网可访问的url,不能携带参数。 需要在微信公众平台中配置相关域名,否则会报异常trade_type交易类型,jsapi/native/app/mweb等 jsapi用于微信内浏览器打开的界面支付 native用于pc端支付 app用于单独的app应用中进行的支付 mweb用于h5在非微信浏览器中打开的支付openidtrade_type=jsapi时(即jsapi支付),此参数必传,此参数为微信用户在商户对应appid下的唯一标识。 注意只有在微信浏览器支付中才传输该值,其它的不要传,否则会报异常 product_idtrade_type=native时,此参数必传。此参数为二维码中包含的商品id,商户自行定义。

其它参数请参考:/d/file/titlepic/404.html {nonce_str=hcf8vr2sg5xnakfy, code_url=weixin://wxpay/bizpayurl?pr=viarg6jzz, appid=**, sign=***, trade_type=native, return_msg=ok, result_code=success, mch_id=1501105441, return_code=success, prepay_id=wx2020212657557887ba533cfa23a2be0000}

5.3 前端跳转支付界面

在5.1中调用/pay/refill接口并返回后,会带上返回的支付表单信息跳转到新的界面:

this.$post("/pay/refill", {        ...}).then((resp) => {  resp.platform = platform;  this.$gopath("/ur/pay/wx-pay", resp);});

跳转后的wx-pay界面实现如下:

<template>  <div class="wx-pay-page">    <div class="code-image p-1 mt-2">      <div class="bottom">         请确认支付已完成,如有异议,请在<span          @click="$gopath('/feedback')"          class="underline"          >服务中心</span        >中进行反馈      </div>    </div>  </div></template> <script>export default {  components: {},  props: [],  data() {    return {      getresultinterval: null,      paydialogvisible: fal,      orderno: null,      iswx: fal,      payinfo: null,      params: null,     };   },  mounted() {    this.iswx = this.$iswx();    this.orderno = this.$route.query.orderno;    this.payinfo = this.$route.query.codeurl;    // 支付方式,1:微信内支付,2:mweb支付    this.platform = this.$route.query.platform;    this.params = this.$route.query.params;    this.dopay();   },  destroyed() {    if (this.getresultinterval) {      clearinterval(this.getresult舞动梦想interval);     }   },  methods: {    dopay() {      if (this.platform === 1 || this.platform === "1") {        // 微信内支付        if (typeof weixinjsbridge == "undefined") {          if (document.addeventlistener) {            document.addeventlistener(              "weixinjsbridgeready",              this.onbridgeready,              fal             );           } el if (document.attachevent) {            document.attachevent(              "weixinjsbridgeready",              this.onbridgeready             );            document.attachevent(              "onweixinjsbridgeready",              this.onbridgeready             );           }         } el {          this.onbridgeready();         }       } el {         // 非微信内支付(mweb)        var url = this.payinfo;        window.open(url, "_lf");       }     },    onbridgeready() {      let _this = this;      window.weixinjsbridge.invoke(        "getbrandwcpayrequest",        this.params,        function (res) {          if (res.err_msg == "get_brand_wcpay_request:ok") {            // 使用以上方式判断前端返回,微信团队郑重提示:            //res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。            alert(              "支付成功,您可以在账户中心/消费记录中查看历史订单"             );            _this.$gopath("/ur");           }         }       );     },   },};</script> 

对于微信内支付,可以通过其浏览器的weixinjsbridge对象调起微信支付界面。

非微信浏览器,将表单中codeurl(二维码)加载到页面中即可。 (目前我的项目代码在移动端非微信浏览器中展示的仍旧是二维码,暂未做改造,所以上面非微信浏览器的与pc端处理基本一样,后续会对这部分进行改造)

到此就等用户支付完成即可。

5.4 接收支付结果

当用户支付完成后,会跳转到支付前的页面,这个时候可以在这个页面中做一些操作,来查询订单状态并展示给用户。

在5.2生成订单的参数中,我们指定了not一路上有你作文ify_url,那么在支付成功后微信也会同时往这个所配的地址推送支付结果,代码实现如下:

/**   * 接收微信支付结果通知   *   * @param body 微信支付结果   */@postmapping("wx-notify")public string wxnotify(@requestbody string西游记故事 body) {  wxpayrvice.parandsavetraderesult(body);  return "success";}
/**   * 支付结果解析   */public void parandsavetraderesult(string body) {  try {    if (logger.isdebugenabled()) {      logger.debug("接收到微信支付结果通知: {}", body);     }    map<string, string> map = wxpayutil.xmltomap(body);    string tradeno = maputils.getstring(map, "out_trade_no");    if (stringutils.impty(tradeno)) {      logger.warn("微信通知消息中订单号为空");      return;     }    tradedto trade = tradervice.findbyno(tradeno);    if (null == trade) {      logger.warn("交易不存在,通知消息:{}", body);      return;     }    if (trade.getstate() == 1) {      if (logger.isdebugenabled()) {        logger.debug("订单已成功: {}", body);       }      return;     }    string result = maputils.getstring(map, "result_code", "");    if ("success".equals(result)) {      // 支付成功      tradervice.tradesuccess(trade);     } el {      logger.warn("支付失败,返回消息:{}", body);      tradervice.tradefailed(trade);     }   } catch (exception e) {    logger.error("返回结果:{}", body);    logger.error("xml转换成map异常", e);   }}

接收到消息后更新订单状态,并进行其它一些如账户余额修改等处理。

本文发布于:2023-04-05 15:43:26,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/9fbd61d60461d856eaede3fb2f7586a5.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:微信公众平台和微信开放平台的区别(2者区别对比分析).doc

本文 PDF 下载地址:微信公众平台和微信开放平台的区别(2者区别对比分析).pdf

标签:订单   商户   平台   页面
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图