前言
近来项目中有要求接入 微信和支付宝 H5 的支付的接入,由于是第一次接入,也遇到了不少的坑。
支付宝支付的接入
前端如何接入,并唤起支付宝客户端进行支付
前端的接入,有两种方式
- 后端返回一个form 表单字符串,我们插入到页面中进行提交即可,页面会跳转到支付宝的一个中间页,由这个中间页来唤起支付宝客户端进行支付
- 后端返回一个地址,前端直接如下代码即可
1
| window.location.href="xxxx"
|
一开始,后端返回一个支付相关信息字符串回来,由前端进行form 表单生成并提交。我也如实做了如下的封装
payInfo 的处理
1 2 3 4 5 6 7
| const querystring = require("querystring"); const url = require("url"); export function getSearchParamsByUrl(urlString: string): any { const searchString = url.parse(urlString).query; return querystring.parse(searchString); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| const submitAliForm = (payInfo: any) => { const formStr = ` <form action="https://openapi.alipay.com/gateway.do?charset=${payInfo.charset}" target="_blank" method="post" class="form"> <input type="text" name="app_id" value=${payInfo.app_id}> <input type="text" name="method" value=${payInfo.method}> <input type="text" name="format" value="JSON"> <input type="text" name="charset" value=${payInfo.charset}> <input type="text" name="sign" value=${payInfo.sign}> <input type="text" name="sign_type" value=${payInfo.sign_type}> <input type="text" name="version" value=${payInfo.version}> <input type="text" name="notify_url" value=${payInfo.notify_url}> <input type="text" name="biz_content" value=${payInfo.biz_content}> </form>`; const divDom = document.createElement("div");
divDom.style.display = "none"; divDom.innerHTML = formStr; document.body.appendChild(divDom); const timeInput = document.createElement("input"); timeInput.value = payInfo.timestamp.replace("+", " "); timeInput.name = "timestamp"; document.forms[0].appendChild(timeInput);
document.forms[0].submit();
};
|
但是提交支付宝的支付网关,却报了错,签名错误,排除了后端的错误,最后发现是前端的解码出了问题,我也不知道支付宝做了什么处理,找了很多资料也没看到,网上的大部分都是在后端生成,前端提交。最后,我只能采取采用第二种方式提交
1
| window.location.href="https://openapi.alipay.com/gateway.do?charset后端返回的支付宝参数,return_url=前端页面的回调地址",
|
微信jsApi 支付接入
前端发起授权请求,获取code,发送给后端,存到openId 到本地
提交订单信息和openId 给后端,换取微信支付信息,然后前端,调用微信客户端暴露出的支付接口
微信授权
首先页面第一次进入微信的时候,发送 如下链接,然后就会弹出授权框,问你是否需要授权,如果点确定,就会跳转至redirect_uri
,然后在redirect_uri中带上code
1 2
| const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect`; window.location.href=authUrl
|
解析跳转地址中 url,获取code,发送给后端,取得openId,存于本地,以便下次进入页面,不需要授权,下面为部分代码
1 2 3 4 5 6 7 8 9 10 11 12
| import Cookies from "js-cookie"; const queryString = getSearchString(); const code=queryString.code,
getOpenId(code).then(res=>{
Cookies.set("openId", res.openid, { expires: 7 }); })
|
下次进入页面不需要授权
1 2 3 4
| if(!Cookies.get("openId")){ }
|
完整授权参考代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| import React from "react"; import { isWeiXin } from "utils/envCheck"; import getSearchString from "utils/searchString"; import { getOpenId } from "./apply/service"; import { Toast } from "antd-mobile"; import { CenterContainer } from "components"; import Cookies from "js-cookie"; export default function withWeiXinAuth( WrapperComponent: React.FunctionComponent ) { return class WeiXinAuth extends React.Component {
componentDidMount() { const queryString = getSearchString();
if (isWeiXin && !Cookies.get("openId") && !queryString.code) { const appid = "微信appid"; const redirect_uri = encodeURIComponent(window.location.href); const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appid}&redirect_uri=${redirect_uri}&response_type=code&scope=snsapi_userinfo&state=123#wechat_redirect`; window.location.href = authUrl; } if (isWeiXin && queryString.code) { getOpenId(queryString.code, queryString.oem) .then(res => { Cookies.set("openId", res.openid, { expires: 7 }); this.setState({ loading: false }); }) .catch(e => { this.forceUpdate() Toast.fail(e.cnmsg); }); } }
render() {
if (isWeiXin && !Cookies.get("openId")) { return <CenterContainer>等待授权中~</CenterContainer>; }
return ( <> <WrapperComponent {...this.props} /> </> ); } }; }
|
微信H5支付
我们只需要如下操作即可
1
| window.location.href="后端返回的url"
|