微信支付

1 PC网页集成 微信支付 native 生成 付款二维码 扫码直接支付 (二维码带价格)

后端 生成 微信返回的 response 中的 code_url

前端 A

将 URL 转换成 二维码 展示即可 或者 后端生成二维码 前端获取该二维码图片 展示
qrcodejs 二维码生成插件

支付结果通知 微信调用 后台接口 后台按照规范应答 或者 后台主动查询订单
对应 后端 Map 参数中 “notify_url”:“供 微信调用的后台接口”

前端 B

支付完成 pay/callback 回调页展示 – XXXX/#/pay/callback

方式一

后端使用 goEasy 推送 给前端 前端跳转 pay/callback socket 发送 接收的 channel 名字 使用 唯一的 订单号

方式二

前端 轮询 后端 得到 跳转 指令 后 前端跳转 pay/callback http

            let timer = null
            if(timer) return
            timer = setInterval(async()=>{
            // 发请求获取用户支付状态
            let result = await API.reqPayStatus(orderId)
            // 如果code===200
            if(result.code===200){
              // 第一步:清除定时器
              clearInterval(timer)
              timer = null
              // 保存支付成功返回的code
              code.value = result.code
              // 关闭弹出框
              msgBox.close()
              // 跳转到下一路由 查询订单操作
              router.push('pay/callback')
            }
          },2000)
    // 组件销毁  也要 清除定时器
    onBeforeUnmount(()=>{
      clearInterval(timer)
      timer = null
    })

2 手机端 微信扫一扫 前端页面 – JSAPI 支付 点击 调用 微信支付框 支付 微信内支付

微信内 支付 没有 openID–code 需要授权获取

这个也分两种

1、跳转授权页
2、静默授权,只获取code,后端凭借code换取openId,也称静默授权 parking为静默

流程

1 看 URL是否有 code 没有需要 授权获取 重定向为当前页 重新获取 code 就可以拿到 可以理解为 先静默后跳转
2 获取code
3 调用 后台接口 传递 code 并且获取 调起支付的 参数

// created阶段   微信内
let openId = null
const ua = window.navigator.userAgent.toLowerCase();
if(ua.match(/MicroMessenger/i) == 'micromessenger'){
  getCode()
}

const getCode = () =>{
   // 服务号id
 const appid = 'XXX'
 const local = window.location.href
 // 截取路径中的 code,如果没有就去微信授权,如果已经获取到了就直接传code给后台获取openId
 // 静默获取 code
 openId = GetUrlParam('code')
 // 获取不到  跳转授权
   if (openId == null || openId === '') {
    window.location.href =
      'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + appid + '&redirect_uri=' + encodeURIComponent(local) + '&response_type=code&scope=snsapi_base&state=#wechat_redirect'
  }
}
// 注意 变量提升  应该放在调用之前
  const GetUrlParam = code => {
  var reg = new RegExp('(^|&)' + code + '=([^&]*)(&|$)')
  let url = window.location.href.split("#")[0]
  let search = url.split('?')[1]
  if (search) {
    var r = search.substr(0).match(reg)
    if (r !== null) return unescape(r[2])
    return null
  } else {
    return null
  }
}
// 调用后台接口 传递 code + 其他参数   并且获取 调起支付的 参数
// 定义 调用 微信支付 的参数
let payInfo = null
// data 内包含 code--openId
findParkingInfo(data).then(({ data }) => {
				if (!data) {
					alert('数据错误,请联系管理员')
					return
				}
				// 车牌 第二个 字符 插入 圆圈··· •
				showInfo.carId = data.carid.replace(/^(.{2})/, '$1 · ')
				showInfo.money = data.money
				showInfo.parkName = data.parkname
				// 赋值  微信支付 数据
				payInfo = data.paystream
			})
			
// onClick-->doPay(payInfo)
// 发起微信支付
const doPay = () => {
  // btnDisabled.value = true
  isIn ? inWeiXin(payInfo) : outWeiXin()
	}

// 微信内支付
const inWeiXin = params => {
	if (typeof WeixinJSBridge === 'undefined') {
		if (document.addEventListener) {
			document.addEventListener(
				'WeixinJSBridgeReady',
				onBridgeReady(params),
				false
			)
		} else if (document.attachEvent) {
			document.attachEvent('WeixinJSBridgeReady', onBridgeReady(params))
			document.attachEvent('onWeixinJSBridgeReady', onBridgeReady(params))
		}
	} else {
		onBridgeReady(params)
	}
}

// 搭桥onBridgeReady()
const onBridgeReady = weChatParameter => {
	// const timestamp = Math.round(weChatParameter.timeStamp).toString()
	window.WeixinJSBridge.invoke(
		'getBrandWCPayRequest',
		{
			debug: false,
			/*
			appId: weChatParameter.appId, // 公众号名称,由商户传入
			timeStamp: timestamp, // 时间戳,自1970年以来的秒数
			nonceStr: weChatParameter.nonceStr, // 随机串
			package: weChatParameter.package,
			signType: weChatParameter.signType, // 微信签名方式:
			paySign: weChatParameter.paySign, // 微信签名
			*/
			...weChatParameter,
			jsApiList: ['chooseWXPay'],
		},
		function (res) {
			// 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
			if (res.err_msg === 'get_brand_wcpay_request:ok') {
				// 支付成功后的操作
				// alert('支付成功')
				router.replace({
					path: '/success',
					query: { message: '支付成功,一路顺风' },
				})
			} else if (res.err_msg === 'get_brand_wcpay_request:cancel') {
				// 取消支付的操作
				// 取消支付
				router.replace({
					path: '/success',
					query: { message: '支付取消,请重新支付' },
				})
			} else {
				// 支付失败
				router.replace({
					path: '/success',
					query: { message: '支付失败,请重新支付' },
				})
			}
		}
	)
}

3 手机端 H5页面 手机端浏览器集成 微信支付 --H5 支付 调用 微信支付框 支付 微信外支付

location.replace(‘后端地址? XXXXX’ 最后拼接 redirect_url = encodeURIComponent(“XXXX/callback”) 需要回调地址 encodeURIComponent

location.href 尽量用 replace

// 微信外支付
const outWeiXin = async () => {
	// 项目支付相关的参数
	// requestPay 后台接口 返回 跳转 URL
	// const { params } = await requestPay()
	// 返回成功  跳转
	if (params) {
		window.location.replace(params)
	} else {
		// '提交订单失败'
	}
}

callback 页面 1 支付完成 2 支付取消 3 5秒不操作 都会跳转 所以此页面应该查询 订单状态 而不是直接显示成功

查询订单操作 后台接口 orderId trade_state :SUCCESS

注意

vue 哈希路由模式,微信回跳会把 # 后全部干掉,等于直回跳个域名,无法跳转 #/callback
解决方案: 可以自己拼接,把#省去,浏览器在访问时,会自动加上

支付宝支付

1 PC端 网页直接调起 支付宝支付

  // 同 QQ 登陆  AAAA-->127.0.0.1:8080
		const redirect = encodeURIComponent(
			'AAAA/pay/callback'
		)
    const payUrl = `${baseURL}pay/aliPay?orderId=${route.query.orderId}&redirect=${redirect}`
  // 新开窗口   支付完后  跳转  AAAA/pay/callback
    const aliPay = () => {
			window.open(payUrl)
		}

查询订单操作 后台接口 orderId trade_state :SUCCESS

2 PC端 二维码支付 同 微信 native 支付

查询订单操作 后台接口 orderId trade_state :SUCCESS

3 手机端 类似 微信 内外 支付宝不区分

getApplyAliPay({
    // 传递的其它参数
    orderNumber: orderNumber,
    // 支付成功之后重定向的地址
    paySuccessUrl: 'xxx'
  }).then(res => {
    const div = document.createElement('div')
    div.id = 'aliPay'
    div.innerHTML = res
    document.body.appendChild(div)
    // 执行后会唤起支付宝
    document.querySelector('#aliPay').children[0].submit()
  })

// paySuccessUrl  -- 查询订单操作

查询订单操作 后台接口 orderId trade_state :SUCCESS

分享 vue-shares

Logo

前往低代码交流专区

更多推荐