Skip to content

微信内H5调起支付

一个微商城的项目,前端用的是vue.js,涉及到微信支付的前端代码大概是这样子的:

js
const mixinPay = {
  computed: {
    ...mapGetters(["l", "user", "config", "mock"]),
  },
  methods: {
    payByWechat({ shoppingOrderId, successCallback }) {
      const _this = this;
      const endPoint = "/pay/getWeixinPayInfo.action";
      _this.wait(true);
      const requestData = {
        openId: _this.user.openid,
        id: shoppingOrderId,
      };
      return doPost(endPoint, requestData)
        .done((data) => {
          if (data.status === "200" && !data.errorCode) {
            const options = {
              appId: data.responseBody.appid,
              timeStamp: data.responseBody.timestamp,
              nonceStr: data.responseBody.nonceStr,
              package: data.responseBody.package,
              signType: "MD5",
              paySign: data.responseBody.paySign,
            };
            // _this.alert({ text: JSON.stringify(options) })
            if (typeof window.WeixinJSBridge === "undefined") {
              if (window.document.addEventListener) {
                window.document.addEventListener(
                  "WeixinJSBridgeReady",
                  onBridgeReady.bind(null, options),
                  false,
                );
              } else if (window.document.attachEvent) {
                window.document.attachEvent(
                  "WeixinJSBridgeReady",
                  onBridgeReady.bind(null, options),
                );
                window.document.attachEvent(
                  "onWeixinJSBridgeReady",
                  onBridgeReady.bind(null, options),
                );
              }
            } else {
              onBridgeReady(options);
            }
          } else if (data.errorCode) {
            _this.alert({ text: `${data["errorMsg" + _this.l]}` });
          } else {
            _this.alert({
              text:
                _this.l === "En"
                  ? "Server responds abnormally"
                  : "服务器响应异常",
            });
          }
        })
        .fail((jqXHR, textStatus, errorThrown) => {
          _this.alert({
            text:
              _this.l === "En"
                ? "Failed to payment parameters"
                : "微信支付参数失败",
          });
        })
        .always(() => {
          _this.wait(false);
        });

      function onBridgeReady(options) {
        window.WeixinJSBridge.invoke(
          "getBrandWCPayRequest",
          options,
          function (data) {
            if (data && data.err_msg === "get_brand_wcpay_request:ok") {
              _this.toUpdateReceipt(shoppingOrderId, successCallback);
            } else if (
              data &&
              (data.err_msg === "get_brand_wcpay_request:cancel" ||
                data.err_msg === "get_brand_wcpay_request:fail")
            ) {
              _this.alert({
                text: _this.l === "En" ? "Failed to pay" : "未成功支付",
              });
            } else if (data && data.err_desc) {
              _this.alert({ text: data.err_desc });
            } else {
              _this.alert({
                text: _this.l === "En" ? "Failed to pay" : "支付失败",
              });
            }
          },
        );
      }
    },
    toUpdateReceipt(shoppingOrderId, successCallback) {
      const _this = this;
      const endPoint = "/orderInfo/updateReceipt.action";
      _this.wait(true);
      const requestData = {
        id: shoppingOrderId,
        status: 4,
      };
      doPost(endPoint, requestData)
        .done((data) => {
          if (data.status === "200" && !data.errorCode) {
            _this.alert({
              text: _this.l === "En" ? "Paid successfully" : "支付成功",
              callback() {
                if (successCallback && typeof successCallback === "function") {
                  successCallback();
                }
              },
            });
          } else {
            _this.alert({
              text:
                _this.l === "En"
                  ? "Paied successfully, but failed to update order status, please contact the service"
                  : "付款成功,送货单状态更新失败,请联系客服",
              callback() {
                if (successCallback && typeof successCallback === "function") {
                  successCallback();
                }
              },
            });
          }
          // else if (data.errorCode) {
          //   _this.alert({ text: `${data['errorMsg' + _this.l]}` })
          // } else {
          //   _this.alert({ text: JSON.stringify(data) })
          // }
        })
        .fail(() => {
          _this.alert({
            text:
              _this.l === "En"
                ? "Paied successfully, but failed to update order status, please contact the service"
                : "付款成功,送货单状态更新失败,请联系客服",
            callback() {
              if (successCallback && typeof successCallback === "function") {
                successCallback();
              }
            },
          });
        })
        .always(() => {
          _this.wait(false);
        });
    },
    ...mapActions(["alert", "wait"]),
  },
};

这里的【微信内H5调起支付】的官网参考文档地址为https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7\_7&index=6&pass\_ticket=EiPbYJmbbMTWltjRY8XQq5dwQ4DbztpbsIE0i11BE6JDeykgQ3arpgnA55tR3RZC 大体的支付流程:

  1. 前端用送货单id和openid从后台获取支付信息(后台通过请求统一制服下单接口获取这些信息);
  2. 前端根据支付信息采用【微信内H5调起支付】的方式进行微信支付,支付成功后修改送货单状态为【支付中】;
  3. 后端回调根据微信返回信息作判断,只有送货单状态为【支付中】时进行状态更新,将送货单的状态更新为【已支付】或【未支付】。
  4. 后续在管理平台上增加一个操作,对【支付中】的送货单,可以手动查询送货单状态。

这里说点前端碰到的问题,就是支付时微信提示【当前页面的URL未注册:http://www.example.com/a/b/c/d/index.html#/home/index】,然而在微信公众号平台上配置的支付目录已经是【http://www.example.com/a/b/c/d/】(末尾有个斜杠),并无错误。联想到以前在公司项目里写过类似的代码但是没有问题,但是那个项目是在微信菜单上的地址是那种微信跳转地址,而且自己另外试了下发现只要我的项目地址index.html后面加上一些随便什么都行的查询参数就可以支付了,于是让修改微信菜单地址为index.html后面加上一些随意的查询参数(不走微信跳转,每次都走影响访问速度,只在本地没有用户openid时由js发起页面跳转,跳到微信跳转地址上以便获得code进而查询openid)。这样修改后页面就能正常进行微信支付了。成功的原因,目测应该是http://www.example.com/a/b/c/d/index.html#/home/index这样的地址里,可能微信会把锚后面的斜杠这些都作为路径进行识别,导致与我们配置的支付目录不一致,从而无法成功支付。加上问号后,微信不再将问号后面的部分视为路径,从而可以成功支付。

天上的神明与星辰,人间的艺术和真纯,我们所敬畏和热爱的,莫过于此。