Loading... # 实现思路 `前端发起支付申请` > `后端获取支付地址发给前端` > `前端接收支付地址跳转支付` > `客户支付` > `支付成功后跳转到到订单检测页` > `检测页检测订单状态` 其中,跳转支付后原页面提供 `用户手动刷新订单状态` 按钮,以便减轻服务器压力。 # 前期准备 ## 下载支付宝开放平台密钥工具 > 用于生成密钥,包括 `应用公钥` 和 `应用私钥` 下载地址: [https://opendocs.alipay.com/common/02kipk](https://opendocs.alipay.com/common/02kipk) 加密方法选择 `密钥` ,加密算法选择 `RSA2` ,生成后保存好,下面或者以后要用到。 ### 大坑警告: > 这里生成的 `应用私钥` ,一定要转为 `PKCS8 或 PKCS1 格式` ,否则会出现开发时正常,但build打包部署到服务器后报错!!! > `支付宝开放平台密钥工具` 里有 `格式转换` 功能! ## 配置支付宝沙箱 官方沙箱应用地址: [https://open.alipay.com/develop/sandbox/app](https://open.alipay.com/develop/sandbox/app) 接口加签方式选择 `自定义密钥` 的 `公钥模式` ,粘贴 `支付宝开放平台密钥工具` 生成的 `应用公钥` ,保存。 # 基于沙箱开发 ## [必装] alipay-sdk ``` npm install alipay-sdk --save ``` 项目安装该依赖后,在 `server/utils` 文件夹下创建 `useAipaySDK.ts` 文件 以下配置均可在 `支付宝开放平台密钥工具` 和 `官方沙箱应用地址` 里找到 ``` // server/utils/useAipaySDK.ts // 支付宝 Node SDK 配置 import AlipaySdk from "alipay-sdk"; const alipaySdk = new AlipaySdk.default({ appId: "", // APPID signType: "", // 签名类型,一般是RSA2 gateway: "", // 网关地址 alipayPublicKey: "", // 支付宝公钥 privateKey: "", // 应用私钥 }); export default () => { return alipaySdk; }; ``` 注意事项: ① 官方文档推荐的是 `const AlipaySdk=require('alipay-sdk').default` ,但是Nuxt3中只能采用ES6 `import` 语法,即 `import AlipaySdk from "alipay-sdk"`。 ② 而迷之问题是我这边采用 `import AlipaySdk from "alipay-sdk"` 导入时 `defalut` 没有按预期自动分配给`AlipaySdk`,所以解决方案只能在`初始化`时去`.defalut` ## 获取支付地址 我这里采用的是 `AlipayFormData` ### 大坑警告: > !!! 这里引入 `AlipayFormData` 的时候,一定要加 `.js` 即: ` import AlipayFormData from "alipay-sdk/lib/form.js";` > 否则build打包后会出 `Cannot find module '..../' \alipay-sdk\lib\form' imported from ...` 的情况!!! ``` // server/api/pay/alipay/pay.post.ts // AlipayFormData import AlipayFormData from "alipay-sdk/lib/form.js"; export default defineEventHandler(async (event: any) => { // 获取参数 const query = await readBody(event); let returnData = {} as any; const formData = new AlipayFormData.default(); formData.setMethod("get"); formData.addField("return_url", "https://timebk.cn/"); // 支付完成后打开的地址 // 需要的参数,更多参数请自行阅读:https://opendocs.alipay.com/open/028r8t?scene=22&pathHash=8e24911d const bizContent = { out_trade_no: "", // 商户订单号 total_amount: "", // 订单总金额 subject: "", // 订单标题 body: "", // 订单附加信息 product_code: "", // 产品码 }; formData.addField("bizContent", bizContent); // 获取支付地址 try { const result = await useAipaySDK().exec( "", // 接口名称,例如电脑网站支付的接口名称:alipay.trade.create {}, { formData: formData } ); returnData.payUrl = result; returnData.code = 200; } catch (err) { // 获取支付地址失败 returnData.msg = err; returnData.code = -1; } return returnData; }); ``` 然后,我们前端访问这个接口就能获取到 `支付地址` ![获得支付地址](https://timebk.cn/usr/uploads/2023/04/3615296110.png) 访问这个 `支付地址` ,我们就可以对订单进行支付了,支付成功后也会自动跳转到我们在 `return_url` 设置的地址 ## 检测订单支付状态 这里我们只需要用到 `alipay.trade.query` 接口 ``` // server/api/pay/alipay/check.post.ts // 验证订单支付状态 // AlipayFormData import AlipayFormData from "alipay-sdk/lib/form.js"; export default defineEventHandler(async (event: any) => { // 获取参数 const query = await readBody(event); let returnData = {} as any; const formData = new AlipayFormData.default(); formData.setMethod("get"); // 参数一般推荐 trade_no ,不推荐 out_trade_no,但发起订单支付的时候验证支付状态请使用 out_trade_no const bizContent = { trade_no: query.trade_no, // 订单交易号 out_trade_no: query.out_trade_no, // 商户订单号 }; formData.addField("bizContent", bizContent); try { // 获取订单支付信息检测地址 const orderInfoUrl = (await useAipaySDK().exec( "alipay.trade.query", // 接口名称 {}, { formData: formData } )) as any; // 获取订单支付信息 const orderInfoReturn = (await useAxios({ url: orderInfoUrl, })) as any; returnData.code = 200; // 进行订单支付状态检测 returnData.type = orderInfoReturn.alipay_trade_query_response.trade_status; switch (orderInfoReturn.alipay_trade_query_response.trade_status) { case "WAIT_BUYER_PAY": returnData.msg = "等待买家付款"; break; case "TRADE_CLOSED": returnData.msg = "订单超时关闭"; break; case "TRADE_SUCCESS": returnData.msg = "订单支付成功"; break; case "TRADE_FINISHED": returnData.msg = "订单交易结束,不可退款"; break; default: returnData.msg = "订单不存在"; break; } } catch (err) { // 失败 returnData.msg = err; returnData.code = 500; } return returnData; }); ``` 前端效果: ![请输入图片描述](https://timebk.cn/usr/uploads/2023/04/2818393995.png) 最后修改:2023 年 04 月 29 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 分享不易,请老板打赏。