当前位置: 首页 > news >正文

泊头哪给做网站的好网络营销的四大基础理论

泊头哪给做网站的好,网络营销的四大基础理论,软件开发技术培训中心,宜兴建设局拍卖房产的网站微信支付之小程序支付微信的支付方式有以下几种,不同的支付方式适用于不同的支付场景,而今天要给大家讲的就是 小程序支付 方式 说到支付功能就要涉及到金钱交易,必定是有比较严格的规范及流程,如要求小程序必须具备企业性质&…

   referrerpolicy=

微信支付之小程序支付

微信的支付方式有以下几种,不同的支付方式适用于不同的支付场景,而今天要给大家讲的就是 小程序支付 方式

   referrerpolicy=

说到支付功能就要涉及到金钱交易,必定是有比较严格的规范及流程,如要求小程序必须具备企业性质,必须拥有微信支付商户平台的账号

PS:申请微信支付商户平台需要一个微信小程序或公众号等,建议按照以下流程进行操作

准备工作

1、申请微信小程序账号

申请成功可拿到 AppID(小程序 id)和 AppSecret(小程序密钥)
申请类型为企业性质,否则无法接入微信支付

2、微信小程序认证

通过认证的小程序才能接入微信支付和绑定商户平台

3、申请商户平台账号

需要第一步申请的 AppID
申请成功可拿到 MchID(商户 id)和 MchKey(商户密钥)

4、信小程序关联商户号

微信和商户都认证成功后,在微信后台微信支付菜单中进行关联

5、接入微信支付

在微信后台微信支付菜单中进行接入

小程序支付流程

简要支付流程如下:
  1. 用户发起支付请求
  2. 后端调用统一下单接口得到 prepay_id
  3. 把支付所需参数返回前端
  4. 前端调用支付接口进行支付操作
  5. 支付结果通知
  6. 前端根据不同的支付结果给用户不同的提示

PS:难点在第 2、3、5 步,一定要仔细查看相关接口文档,否则容易出错,接下来我们按照以上 6 个步骤详细讲解在微信小程序中的支付流程

支付前的操作

因为严格意义上来说这不属于支付流程中的步骤,但支付过程中需要用到用户唯一标识openid,所以建议在用户进入小程序时就进行这一步的操作
  1. 调用wx.login()接口获取 code,并把code传到服务器
  2. 后端服务器拿到 code 后调用code2Session 接口获取 openidsession_key
    建议把openid存入数据库,方便随时获取,下面的步骤也会用到
  3. 后端服务器保好 appid, secret, mch_id, mch_key(这些数据分别在小程序后台和商户平台中获得,我是把它们做成 commonjs 模块并保存在config/wx.js文件中以方便调用)

PS:开发者需要自行维护用户登录状态(用户登录状态的维护本文不做展开,请自行查阅相关资料)

1、小程序端:用户向商户服务器发起支付请求

这步没什么好说的,当用户点击支付按钮时,给我们自己的后端接口发起一个请求,携带必要的参数(如:body,total_fee 等),接口地址需要自行编写,如我的接口地址为/payment/order

// http对象为wx.request()的二次封装
import http from "../utils";
​
// 向后端发请请求
const res = await http.post("/payment/order", {body: "腾讯QQ-购买会员", // 商品描述total_fee: 998, // 总金额,单位为分
});
if (res.status === 200) {try {// 得到接口返回的数据,向微信发起支付const result = await wx.requestPayment({...res.data,});wx.showToast({title: "支付成功",});console.log("支付结果:", result);} catch (err) {wx.showToast({title: "支付失败",});}
}

PS:可能会有小伙伴产生疑惑,为什么不直接通过 wx.requestPayment() 在小程序端发起请求而要先请求商户自己的服务器呢?原因很简单,安全性问题,wx.requestPayment()需要 2 个重要参数paySignpackage,需要 appid,secret,openid,mch_key 等私密数据,这些私密的数据不应该在前端暴露出来,而是放在自己的服务器中更安全,所以需要向自己的服务器发起这个请求拿到这些参数,下一步才能真正发起支付。接下来我们来看看后端是如果操作的

2、商户后端服务器:签名+生成预支付标识

后端代码使用 egg 框架(基于 NodeJS+Koa)实现,文中涉及到 egg 用法和 koa 的用法不再额外说明,请自行查阅相关资料

调用统一下单接口获取 预支付会话标识 prepay_id

注意:该接口需要发送 xml 格式参数,同时返回 xml 格式数据,需自行转换(我使用的是xml-js第三方模块)
    • 该接口必填参数:appidmch_idnonce_strsign_typebodyout_trade_nototal_feespbill_create_ipnotify_urltrade_typesign,其中 sign 为前面所有参数加密后的字符
  async order(ctx) {// egg框架写法const { service, request } = ctx;// 获取前端传入参数const { userid, total_fee, body } = request.body;// 引入微信配置参数(上面准备工作中保存的config/wx.js文件,包含小程序id,密钥,商户id,商户密钥)const { config } = require("../../config/wx");// 生成订单号(保证唯一性:我采用时间戳拼6位随机数的方式)const tradeNo = Date.now() + '' + randomCode(100000, 999999);// 统一下单签名参数const orderParams = {appid: config.appid, // 小程序idmch_id: config.mch_id, // 商户idnonce_str: service.wx.randomStr(), // 自定义生成随机字符方法sign_type: "MD5", // 加密类型body, // 商品简单描述,有格式要求out_trade_no: tradeNo, // 订单号total_fee, // 单位:分spbill_create_ip: "121.34.253.98", // 服务器ipnotify_url: "https://你的服务器域名/payment/wxnotify", // 支付成功通知地址trade_type: "JSAPI", // 支付方式(小程序支付选JSAPI)openid: user.openid, // 用户openid,步骤0保存的数据};// 签名:对上面所有参数加密(签名算法请查看接口文档,下同)const orderSign = service.wx.sign(orderParams);// json->xmlconst xmlData = convert.js2xml({ xml: { ...orderParams, sign: orderSign } },{ compact: true });// 调用统一下单接口(接口没说明,但必须为post请求)const { data } = await ctx.curl("https://api.mch.weixin.qq.com/pay/unifiedorder",{method: "post",data: xmlData,});// xml->jsconst result = convert.xml2js(data, { compact: true });if (result.prepay_id) {// 此处可以把订单信息保存到数据库// 返回prepay_id后,接着就是把参数返回前端// =>为了更清晰,我把这里的代码写在下一步// ...}}

3、给前端返回支付参数+签名

    // 支付签名参数const payParams = {appId: config.appid, // 商户 idtimeStamp: Date.now(), // 时间戳nonceStr: this.randomStr(), // 随机字符package: "prepay_id=" + result.prepay_id, //预支付会话标识(格式为:prepay_id=统一下单接口返回数据)signType: "MD5", //签名类型(必须与上面的统一下单接口一致)};// 签名const paySign = service.wx.sign(payParams);
​// 把参数+签名返回给前端ctx.body = formatData({data: {timeStamp: payParams.timeStamp,nonceStr: payParams.nonceStr,package: payParams.package,signType: payParams.signType,paySign,},});
附上封装好的签名方法sign()和生成随机字符串的方法randomStr(),我写在service/wx.js
    "use strict";const { Service } = require("egg");const crypto = require("crypto");// 微信基本配置const { weapp } = require("../../config/wx");class wxService extends Service {randomStr(len = 24) {const str ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";let result = "";for (let i = 0; i < len; i++) {result += str[Math.floor(Math.random() * str.length)];}return result;}sign(data, signType = "MD5") {const keys = [];for (const key in data) {if (data[key] !== undefined) {keys.push(key);}}// 字典排序=>key=valueconst stringA = keys.sort().map((key) => `${key}=${decodeURIComponent(data[key])}`).join("&");// 拼接商户keyconst stringSignTemp = stringA + "&key=" + weapp.mch_key;console.log("stringSignTemp", stringSignTemp);// 加密let hash;if (signType === "MD5") {hash = crypto.createHash("md5");} else {hash = crypto.createHmac("sha256", "laoxie");}hash.update(stringSignTemp);const paySign = hash.digest("hex").toUpperCase();return paySign;}}module.exports = wxService;

4、小程序端:向微信服务器发起请求

第 1 步的数据返回后,向微信服务器接口wx.requestPayment()发请求,唤起支付界面,请查看第一步 try...catch 中的代码

5、微信服务器:支付结果通知

在第 2 步向统一下单接口发起请求时附带了一个notify_url,此地址一定要是可外网访问的接口地址(商户自行编写),由微信服务器调用该接口,不管支付成功与否,此接口都会调用,并返回相应数据(查看接口数据),所以商户可以在此接口中编写相关业务逻辑、如支付成功后写入数据库等操作

注意:商户需要在此接口中做接收处理,并向微信服务器返回应答(按接口规范返回特定数据)。如果微信收到商户的应答不是成功或超时,微信会认为通知失败,微信会通过一定的策略定期重新发起通知,通知频率为:15s/15s/30s/3m/10m/20m/30m/30m/30m/60m/3h/3h/3h/6h/6h,但微信不保证通知最终一定能成功。
  "use strict";
​const Controller = require("egg").Controller;const getRawBody = require("raw-body");const contentType = require("content-type");const { formatData, randomCode, params, formatParams } = require("../utils");
​class PaymentController extends Controller {// 微信支付回调地址async notify(ctx) {const { req } = ctx;
​// 微信调用该接口时传入的数据为xml,所以先转换const data = await getRawBody(req, {length: req.headers["content-length"],limit: "1mb",encoding: contentType.parse(req).parameters.charset,});const result = params.xml2js(data);
​// 验签:微信传入的除sign外的所有数据进行签名,拒后与sign进行对比是否一致// 一致说明支付成功,否则支付失败// 并根据不同的结果通知微信服务器(响应不同的xml数据,如下)const resultSign = result.sign;delete result.sign;const mySign = ctx.service.wx.sign(result);console.log("sign:", resultSign, mySign);
​ctx.set("content-type", "text/plain");
​if (resultSign === mySign) {// 修改商户订单状态const {device_info,openid,trade_type,bank_type,total_fee,settlement_total_fee,fee_type,transaction_id,time_end,attach,} = result;
​// 格式化自定义参数let myattach = {};if (attach) {myattach = params.parse(attach);}
​// 格式化支付时间:20200423161017=>2020/04/23 16:10:17let pay_time = time_end.replace(/(d{4})(d{2})(d{2})(d{2})(d{2})(d{2})/,"$1/$2/$3 $4:$5:$6");pay_time = new Date(pay_time);
​// 根据订单号更新数据库中的订单状态const newData = {device_info,openid,trade_type,bank_type,total_fee,settlement_total_fee,fee_type,transaction_id,pay_time,status: 1,...myattach,};db.update("purchase",{out_trade_no: result.out_trade_no,},{$set: newData,});
​ctx.body = `<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>`;} else {ctx.body = `<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[ERROR]]></return_msg></xml>`;}}}
​module.exports = PaymentController;
附上以上代码中会用的封装好的方法parse()xml2js()js2xml(),我写在utils/index.js
  const params = {parse(queryString) {// 'a=1&b=2' => {a:1,b:2}return queryString.split("&").reduce((res, item) => {const arr = item.split("=");res[arr[0]] = arr[1];return res;}, {});},js2xml(data) {return convert.js2xml({ xml: data }, { compact: true });},xml2js(xml) {const result = convert.xml2js(xml, {compact: true,textKey: "value",cdataKey: "value",}).xml;const data = {};for (const key in result) {data[key] = result[key].value;}return data;},};module.exports = {params}

到此微信支付之小程序支付就完成了,过程比较繁杂,一定要一步步去实现,也许会踩坑,但相信我,这是每个程序员的必经这路,面对它,勇敢地走过去,你对能到达胜利的彼岸。

注意事项

  • appid、appsecret、mchid、mchkey、openid 为小程序或商户私密信息,应保存在服务端
  • 注意参数大小写:每个接口大小写可能不同
  • 签名算法:请查看接口文档
  • 一定要注意看文档,根据我多冷踩坑的经历,90%以上的问题都是没有仔细看文档所致

参考网址与接口

  • 微信支付商户平台:https://pay.weixin.qq.com
  • 微信公众平台:https://mp.weixin.qq.com
  • 微信支付接口:https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html
  • 统一下单接口:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
  • 支付结果通知接口:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8
  • 签名算法:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3

[mp] https://mp.weixin.qq.com

[pay] https://pay.weixin.qq.com

[payment] https://developers.weixin.qq.com/miniprogram/dev/api/open-api/payment/wx.requestPayment.html

[notify] https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_7&index=8

[login] https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html

[unifiedorder] https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1

[code2session] https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html

[sign] https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=4_3

   referrerpolicy=
千锋HTML5学院:如何讲清楚Redux的概念?​zhuanlan.zhihu.com
   referrerpolicy=
千锋HTML5学院:使用 commitizen 规范 Git 提交说明​zhuanlan.zhihu.com
   referrerpolicy=
千锋HTML5学院:如何讲清楚async和await?​zhuanlan.zhihu.com
   referrerpolicy=
http://www.lbrq.cn/news/2577673.html

相关文章:

  • html前端网站开发PPTb站免费建网站
  • 公司网站建设公一键优化表格
  • 可以做家教的网站有哪些网络推广营销方法
  • 帮小公司代账一个月费用优化网站教程
  • 如何后台修改网站联系人购物网站页面设计
  • 做动画上传网站赚钱么企业网站seo服务
  • 网站用什么服务器seo销售好做吗
  • 谷歌广告优化师凌哥seo
  • 鞍山信息港征婚谷歌seo怎么做
  • 建站系统做网站搜索排名影响因素
  • 网站seo 优帮云参考消息网国内新闻
  • 武汉 网站开发市场推广和销售的区别
  • wordpress编程主题搜索引擎优化排名案例
  • 建筑设计专业的网站指数函数
  • 怎么在网站后台做图片新闻网页制作与设计
  • 电影片头在线制作网站免费关键词搜索工具
  • 个人信息网站模板凡科建站登录
  • 焦作做网站哪家好百度服务中心人工客服电话
  • 营销公司网站信息流优化师是做什么的
  • 中企动力做网站要全款深圳百度搜索排名优化
  • 大连网站建设价格百度网盘网页版登录
  • 怎么做自己下单的网站aso优化技巧大aso技巧
  • 郑州设计师网站经典软文案例或软文案例
  • 旅游电商网站有哪些流量购买网站
  • 360网站运营关键词优化教程
  • 北京建设执业资格注册网站成都百度推广排名优化
  • phpstudy如何建设网站快推广app下载
  • 网站仿站大多少钱google收录查询
  • 中学网站系统源码抖音seo排名
  • 用手机搭建网站seo网站建设优化
  • 《前端无障碍设计的深层逻辑与实践路径》
  • Nvidia Orin DK 刷机CUDA TensorRT+硬盘扩容+ROS+Realsense+OpenCV+Ollama+Yolo11 一站式解决方案
  • 烽火HG680-KD_海思MV320处理器-安卓9-原厂系统升级包-针对解决烧录不进系统的问题
  • JAVA国际版同城服务同城信息同城任务发布平台APP源码Android + IOS
  • 再见!三层框架开发
  • 轻量级鼠标右键增强工具 MousePlus