一、微信公众号支付(微信jsapi支付)
1、开发准备
1.1、公众号需要开通微信支付功能
1.2、到微信商户平台 https://pay.weixin.qq.com 注册一个商户账号,并关联你的公众号,如果需要实现小程序支付的,需要关联小程序
1.3、配置支付授权目录,登录商户平台 -> 产品中心 -> 开发配置 -> JSAPI支付 -> 支付授权目录(当前支付页面域名)
1.4、设置API密钥,登录商户平台 -> 账户中心 -> API安全 -> API密钥
1.5、配置JS接口安全域名与网页授权域名,登录公众平台https://mp.weixin.qq.com -> 公众号设置 -> 功能设置 -> 配置JS接口安全域名和网页授权域名
配置网页授权域名:主要用于获取用户的openId,需要识别这是哪个人。
配置JS接口安全域名:要让我们的页面中弹出输入密码的窗口,需要使用微信提供的JS-SDK工具,如果不配置JS接口安全域名,你的页面无法使用JS-SDK
注意:如果提示访问当前域名出错,则可能是验证文件(例如:MP_verify_9NHz19oBkiqQc3L7.txt)没有下载并上传到域名可访问到的服务器上
const getWeChatCode = () => {
const APPID = ''
const { origin, pathname, search } = window.location const href = origin + pathname + search window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${APPID}&redirect_uri=${encodeURIComponent(href)}&response_type=code&scope=snsapi_base&state=state#wechat_redirect` }
2.2、拿第二部换取到的code,请求后端接口换取token,换取到token写入本地缓存(不强制写入贝蒂缓存,可以每次都重新获取token)
const getAuthToken = async () => {
const { data } = await Apis.GET_JSAPI_AUTH({ code })
if (data?.token) localStorage.setItem('authToken', data.token) }
2.3、点击支付按钮,请求后端预支付接口(相关订单参数和第二步获取的token),返回订单相关参数,通过微信JS-SDK的getBrandWCPayRequest方法调起微信支付窗口,自行处理支付后的回调,参考文档https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_3.shtml
const weixinGzhPay = async (payParams) => {
const authToken = localStorage.getItem('authToken') || '' if (authToken) { const { data } = await Apis.GET_JSAPI_PREORDER({ ...payParams, token: authToken })
if (data?.['token_expired'] === TOKEN_EXPIRED) { localStorage.removeItem('authToken') getWeChatCode() return false
}
const { app_id: appId, timestamp: timeStamp, nonce_str: nonceStr, package: pack, sign_type: signType, pay_sign: paySign } = data
const result: any = await weChatPay({ appId, timeStamp: `${timeStamp}`, nonceStr, package: pack, signType, paySign })
console.log('pay_result', result)
if (result?.['err_msg'] === 'get_brand_wcpay_request:ok') {
Toast.info('支付成功', 2) } else { Toast.info('支付失败', 2) }
} else {
getWeChatCode()
}
}
const weChatPay = (WechatPayParams) => { console.log('wechatPayParams', wechatPayParams) return new Promise((resolve, reject) => { function onBridgeReady() { // 记录支付参数,用户取消支付时,则直接使用 window.WeixinJSBridge.invoke('getBrandWCPayRequest', wechatPayParams, function(res) { if (res.err_msg === 'get_brand_wcpay_request:ok') { // 使用以上方式判断前端返回,微信团队郑重提示: // res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。 resolve(res) } else { console.log('res.err_msg:', res.err_msg) reject(res) } }) } if (typeof window.WeixinJSBridge === 'undefined') { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false) } else if (document['attachEvent']) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady) document.attachEvent('onWeixinJSBridgeReady', onBridgeReady) } } else { onBridgeReady() } }) }
2.4、非首次访问页面
缓存了token:查看本地缓存的token是否过期,过期则执行2.1、2.2,支付走2.3
未缓存token:直接只从2.1、2.2,支付走2.3
二、支付宝内部支付(支付宝jsapi支付)
支付宝jsapi引入地址://gw.alipayobjects.com/as/g/h5-lib/alipayjsapi/3.1.1/alipayjsapi.min.js
1、开发准备
账号申请、开发配置
2、前端开发
2.1、首次进入页面,请求支付宝指定地址换取code,参考文档:https://opendocs.alipay.com/open/284/web
const getAliPayCode = () => { const ALIPAY_APPID = '' const href = origin + pathname + search window.location.href = `https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=${ALIPAY_APPID}&scope=auth_base&redirect_uri=${encodeURIComponent(href)}&state=state#apipay_redirect` }
2.2、拿第二部换取到的code,请求后端接口换取需要的参数
let userId = ''
const getAliOauth = async () => { const { data } = await Apis.GET_ALI_OAUTH({ grant_type: 'authorization_code', code: AUTH_CODE }) if (data?.user_id) userId = data.user_id
}
2.3、点击支付按钮,请求后端预支付接口(相关订单参数和第二步获取的参数),返回订单相关参数trado_no,通过支付宝的alipayjsapi的tradePay方法调起支付宝支付窗口,自行处理支付后的回调参考文档:https://myjsapi.alipay.com/alipayjsapi/util/pay/tradePay.html
const aliJsApiPay = async payParams => { if (userId) { const { data } = await Apis.POST_PHONE_PAY({ alipay_uid: userId, { ...payParams } })if (data?.trade_no) { try { const res = await aliPay(data.trade_no) if (res?.resultCode === ALI_PAY_SUCCESS) { Toast.info('支付成功', 2, () => { const { origin } = window.location window.location.replace(`${origin}${REDIRECT_URL_MAP[paySource]}?chl_click_id=${chlClickId}&biz_order=${data.order_id}&phoneNum=${phone}&userId=${userId}`) }) } else { Toast.info('支付失败') } } catch { Toast.info('支付失败') } } } }
const aliPay = tradeNo => { return new Promise((resolve, reject) => { window['ap'].tradePay({ tradeNO: tradeNo }, function (res) { resolve(res) }, function (err) { reject(err) }) }) }
三、h5支付
1、微信h5支付,参考文档:https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_2.shtml
1.1、开发前准备,配置H5支付域名,登录商户平台 -> 产品中心 -> 开发配置 -> H5支付 -> H5支付域名(当前支付页面域名)
1.2、前端开发,请求后端预支付接口,获取相关支付链接,前端跳转到此链接进行支付
/** * h5支付(微信h5、支付宝h5) * payParams: 支付接口参数 */ const h5Pay = async payParams => { const { data } = await Apis.POST_PRE_ORDER({ ...payParams }) if (data?.['mweb_url'] !== '') window.location.href = data.mweb_url }
1.3、后端配置支付回跳地址页面,在回跳页面查询当前订单是否支付成功
2、支付宝h5支付
同微信h5支付流程,配置H5支付域名略有不同