- 微信支付优惠扣除逻辑
一、优惠券叠加使用逻辑1)不同商户创建的全场优惠(包括券和立减)默认叠加使用 假设:某笔订单可以享受全场优惠a(A商户创建,互斥使用)、全场优惠b(B商户创建,互斥使用)、全场优惠c(C商户创建,互斥使用) 则:该笔订单会同时享受 a + b + c,共3个优惠 2)同一商户创建的全场券可配置叠加使用或互斥使用,单笔订单可以核销同一商户创建的所有叠加券 + 互斥券中的一个 假设:某笔订单可以享受同一商户创建的全场券a(叠加使用)、全场券b(叠加使用)、全场券c(互斥使用)、全场券d(互斥使用) 则:该笔订单会享受 a + b + c或d中的一个,共3个优惠 3)同一商户创建的全场立减可配置叠加使用或互斥使用,单笔订单可以核销同一商户创建的所有叠加立减 + 互斥立减中的一个 假设:某笔订单可以享受同一商户创建的全场立减a(叠加使用)、全场立减b(叠加使用)、全场立减c(互斥使用)、全场立减d(互斥使用) 则:该笔订单会享受 a + b + c或d中的一个,共3个优惠 4)同一商户创建的全场立减和全场券默认叠加使用 假设:某笔订单可以享受同一商户创建的全场券a(互斥使用)、全场立减b(互斥使用) 则:该笔订单会享受 a + b,共2个优惠 5)一笔订单中,同一商品(sku维度)只能享受一个单品优惠(包括券和立减),不同的商品可以享受不同的单品优惠 假设:某笔订单可以享受单品优惠a(sku:01),单品优惠b(sku:02),单品优惠c(sku:02) 则:则该笔订单会享受 a + b或c中的一个,共2个优惠 6)若某笔订单享受了全场优惠(包括券和立减),且其中至少一个全场优惠是叠加使用的,则该笔订单才能叠加使用单品优惠 假设:某笔订单可以享受全场优惠a(叠加使用),全场优惠b(互斥使用),单品优惠c 若该笔订单享受a,则可同时享受c;若该笔订单享受b,则不可同时享受c;若该笔订单享受a+b,则可同时享受c * 指定支付方式(例如指定银行卡)的优惠需关注: 优惠是否可以叠加使用,是以制券商户号维度进行判断的,与批次指定的支付方式无关。若多个指定了支付方式的全场优惠配置了不可叠加使用,即使这几个优惠指定的支付方式不同,用户也只能享受其中一个。 举例:某笔订单可以享受全场优惠a(指定了A银行信用卡,互斥使用),全场优惠b(指定了A银行储蓄卡,互斥使用),则无论主扫或被扫,用户都只能享受a或b中的一个,且由系统指定,用户无法切换优惠。 所以,若同时存在多银行或多卡种的活动,建议将其均配置为 [可叠加使用] 。 二、优惠时的优先级当用户有多个优惠,且多个优惠不能同时使用时,优惠的使用顺序如下: 面额越高优先级越高门槛越高优先级越高过期时间越近优先级越高领券时间越近优先级越高批次ID越小优先级越高 当用户有多个可叠加使用的优惠,但订单无法满足叠加使用的条件时,优惠的使用顺序如下: 面额越高优先级越高门槛越高优先级越高当面额与门槛均相同时,则随机使用顺序,此时不判断过期时间与领取时间。 三、一笔订单最多可使用的优惠数单笔订单最多可以使用20个单品优惠,以及8个全场优惠。 当订单可用的全场券超过8张时,微信支付将筛选可用券中面额最高的8张进行优惠计算,故无法保证得出最优解。
2021-01-16 - 微信支付开发,可以简化到复制+粘贴这种地步
距离上一版(0.3)过去了有几个月了,这几个月没少折腾微信团队,春节前后“突然”利好不断,许多几乎不可能的事项都有显著改善,这也许就是认(一)真(本)做(正)事(经)的回报吧。2月下旬的时候,有一小伙伴,开了个issue#10 反馈,lib在变量重入的时候,存在bug,无法正确获取订单信息。仔细推演之后,决定重构一下,把树形结构[代码]Wechatpay SDK[代码]起个底儿,许多(BT)用法,真的是事后测试用例覆盖时才发现,啪一下吧。 0.4版做了这些改进 [代码]README[代码]文档中文化 重构 [代码]Wechatpay[代码] 类,同时支持 [代码]APIv2&v3[代码] 链式调用 改变 [代码]Wechatpay.client[代码] 返回值为[代码]Wechatpay.client.v3[代码],[代码]Wechatpay.client.v2[代码] 为 [代码]xmlBased[代码] 接口客户端 废弃 [代码]withEntities[代码] 方法,其在链式多次调用时,有可能达不到预期 解决 [代码]AES-GCM[代码]在[代码]Node10[代码]上的解密兼容性问题,程序在[代码]Node10[代码]上有可能崩溃,建议[代码]Node10[代码]用户升级至此版本 支持 企业微信-企业支付 链式调用,需要额外注入签名规则,见用法示例 优化[代码]Wechatpay[代码]在多次实例化时赋值[代码]Symbol(CLIENT)[代码]异常问题,增加[代码]wechatpay.test.js[代码]测试用例覆盖 链式chain调用 这个想法是自0.2版开始,是把[代码]URL.pathname[代码]以[代码]/[代码]做切分,映射成对象属性,0.4版做了极致优化,支持APIv2的[代码]pathname[代码]映射,效果较上一贴 微信支付APIv3的Nodejs版SDK,打印的树形更优美了,效果如下: [代码][Function (anonymous)] { v2: [Function: /v2] { risk: [Function: /v2/risk] { getpublickey: [Function: /v2/risk/getpublickey] }, pay: [Function: /v2/pay] { micropay: [Function: /v2/pay/micropay] }, secapi: [Function: /v2/secapi] { pay: [Function: /v2/secapi/pay] { refund: [Function: /v2/secapi/pay/refund] } }, mmpaymkttransfers: [Function: /v2/mmpaymkttransfers] { sendredpack: [Function: /v2/mmpaymkttransfers/sendredpack], promotion: [Function: /v2/mmpaymkttransfers/promotion] { transfers: [Function: /v2/mmpaymkttransfers/promotion/transfers], paywwsptrans2pocket: [Function: /v2/mmpaymkttransfers/promotion/paywwsptrans2pocket] }, sendworkwxredpack: [Function: /v2/mmpaymkttransfers/sendworkwxredpack] } }, v3: [Function: /v3] { pay: [Function: /v3/pay] { transactions: [Function: /v3/pay/transactions] { native: [Function: /v3/pay/transactions/native], id: [Function: /v3/pay/transactions/id] { '{transaction_id}': [Function: /v3/pay/transactions/id/{transaction_id}] }, outTradeNo: [Function: /v3/pay/transactions/out-trade-no] { '{out_trade_no}': [Function: /v3/pay/transactions/out-trade-no/{out_trade_no}] } } favor: [Function: /v3/marketing/favor] { media: [Function: /v3/marketing/favor/media] { imageUpload: [Function: /v3/marketing/favor/media/image-upload] }, stocks: [Function: /v3/marketing/favor/stocks] { '$stock_id$': [Function: /v3/marketing/favor/stocks/{stock_id}] { useFlow: [Function: /v3/marketing/favor/stocks/{stock_id}/use-flow] } } }, partnerships: [Function: /v3/marketing/partnerships] { build: [Function: /v3/marketing/partnerships/build] } }, smartguide: [Function: /v3/smartguide] { guides: [Function: /v3/smartguide/guides] { '$guide_id$': [Function: /v3/smartguide/guides/{guide_id}] { assign: [Function: /v3/smartguide/guides/{guide_id}/assign] } } } } } [代码] 上述 [代码]/v2[代码] 树节点,是本SDK“创造”出来的,用以区分APIv3调用,默认不是 [代码]/v2[代码]开头的节点,均以APIv3方式调用; 这么做是因为,微信支付APIv3版,[代码]URL.pathname[代码] 目前已知至少有一个不是以 [代码]/v3[代码] 开头的; [代码]/v2[代码] 官方又没用到,咱就先占着用吧,所以如是APIv2版的调用,可以这么 [代码]chain[代码], [代码]v2.pay.micropay = /v2/pay/micropay[代码] 即以XML负载形式请求远端接口; 较0.2版,每个级联对象为APIv2做了改变,每个节点本身是个[代码]Function[代码],链接的是HTTP POST方法,入参接受两个参数 [代码](data, config)[代码],返回值是[代码]Promise[代码]对象; 另外每个节点同时隐式内置了[代码]GET/POST/PUT/PATCH/DELETE[代码] 操作方法链,支持全大写及全小写(未来有可能会删除)两种编码方式,完美支持APIv3的多HTTP verbs协议(目前统计出来,有至少5处蓝瘦的地方,有空了再说)。 怎么用 一句话可能就说完了,实例化后,按[代码]pathname[代码]拆分,然后再执行文档上说的HTTP verbs方法,附带所需参数,然后就没有然后了~ 实例化 [代码]const {Wechatpay, Formatter} = require('wechatpay-axios-plugin') const wxpay = new Wechatpay({ mchid: 'your_merchant_id', serial: 'serial_number_of_your_merchant_public_cert', privateKey: '-----BEGIN PRIVATE KEY-----' + '...' + '-----END PRIVATE KEY-----', certs: { 'serial_number': '-----BEGIN CERTIFICATE-----' + '...' + '-----END CERTIFICATE-----', }, // APIv2参数 >= 0.4.0 开始支持 secret: 'your_merchant_secret_key_string', // 注: 如果不涉及资金变动,如仅收款,merchant参数可选,仅需 `secret` 一个参数,注意其为v2版的。 merchant: { cert: '-----BEGIN CERTIFICATE-----' + '...' + '-----END CERTIFICATE-----', key: '-----BEGIN PRIVATE KEY-----' + '...' + '-----END PRIVATE KEY-----', // or // passphrase: 'your_merchant_id', // pfx: fs.readFileSync('/your/merchant/cert/apiclient_cert.p12'), }, }) [代码] APIv3 Native下单 [代码]wxpay.v3.pay.transactions.native .post({/*文档参数放这里就好*/}) .then(({data: {code_url}}) => console.info(code_url)) .catch(({response: {status, statusText, data}}) => console.error(status, statusText, data)) [代码] APIv3 查询订单 [代码]wxpay.v3.pay.transactions.id['{transaction_id}'] .get({params: {mchid: '1230000109'}, transaction_id: '1217752501201407033233368018'}) .then(({data}) => console.info(data)) .catch(({response: {status, statusText, data}}) => console.error(status, statusText, data)) [代码] APIv3 关单 [代码]wxpay.v3.pay.transactions.outTradeNo['1217752501201407033233368018'] .post({mchid: '1230000109'}) .then(({status, statusText}) => console.info(status, statusText)) .catch(({response: {status, statusText, data}}) => console.error(status, statusText, data)) [代码] APIv3 对账单下载及解析 [代码]const assert = require('assert') const {Hash: {sha1}} = require('wechatpay-axios-plugin') wxpay.v3.bill.tradebill.get({ params: { bill_date: '2021-02-12', bill_type: 'ALL', } }).then(({data: {download_url, hash_value}}) => wxpay.v3.billdownload.file.get({ params: (new URL(download_url)).searchParams, signed: hash_value, responseType: 'arraybuffer', })).then(res => { assert(sha1(res.data.toString()) === res.config.signed, 'verify the SHA1 digest failed.') console.info(Formatter.castCsvBill(res.data)) }).catch(error => { console.error(error) }) [代码] APIv2 Native下单 [代码]wxpay.v2.pay.unifiedorder .post({/*文档参数放这里就好*/}) .then(({data: {code_url}}) => console.info(code_url)) .catch(console.error) [代码] APIv2 付款码(刷卡)支付 [代码]wxpay.v2.pay.micropay({ appid: 'wx8888888888888888', mch_id: '1900000109', nonce_str: Formatter.nonce(), sign_type: 'HMAC-SHA256', body: 'image形象店-深圳腾大-QQ公仔', out_trade_no: '1217752501201407033233368018', total_fee: 888, fee_type: 'CNY', spbill_create_ip: '8.8.8.8', auth_code: '120061098828009406', }) .then(res => console.info(res.data)) .catch(console.error) [代码] APIv2 现金红包 [代码]wxpay.v2.mmpaymkttransfers.sendredpack({ nonce_str: Formatter.nonce(), mch_billno: '10000098201411111234567890', mch_id: '10000098', wxappid: 'wx8888888888888888', send_name: '鹅企支付', re_openid: 'oxTWIuGaIt6gTKsQRLau2M0yL16E', total_amount: 1000, total_num: 1, wishing: 'HAPPY BIRTHDAY', client_ip: '192.168.0.1', act_name: '回馈活动', remark: '会员回馈活动', scene_id: 'PRODUCT_4', }) .then(res => console.info(res.data)) .catch(console.error) [代码] APIv2 企业付款到零钱 [代码]wxpay.v2.mmpaymkttransfers.promotion.transfers({ appid: 'wx8888888888888888', mch_id: '1900000109', partner_trade_no: '10000098201411111234567890', openid: 'oxTWIuGaIt6gTKsQRLau2M0yL16E', check_name: 'FORCE_CHECK', re_user_name: '王小王', amount: 10099, desc: '理赔', spbill_create_ip: '192.168.0.1', nonce_str: Formatter.nonce(), }) .then(res => console.info(res.data)) .catch(console.error) [代码] APIv2 企业付款到银行卡-获取RSA公钥 这个用法,是测试用例发掘出来的,注意请求带了第二个参数 [代码]{baseURL:'https://fraud.mch.weixin.qq.com'}[代码] [代码]wxpay.v2.risk.getpublickey({ mch_id: '1900000109', sign_type: 'MD5', nonce_str: Formatter.nonce(), }, { baseURL: 'https://fraud.mch.weixin.qq.com' }) .then(res => console.info(res.data)) .catch(console.error) [代码] 企业微信 企业微信的企业支付,数据请求包需要额外的签名,仅需做如下简单扩展适配,即可支持;以下签名注入函数所需的两个参数[代码]agentId[代码] [代码]agentSecret[代码]来自企业微信工作台,以下为示例值。 [代码]const agentId = 1001001 const agentSecret = 'from_wework_agent_special_string' const {Hash} = require('wechatpay-axios-plugin') [代码] APIv2 企业红包-注入签名规则 [代码]Wechatpay.client.v2.defaults.transformRequest.unshift(function workwxredpack(data, headers) { const {act_name, mch_billno, mch_id, nonce_str, re_openid, total_amount, wxappid} = data if (!(act_name && mch_billno && mch_id && nonce_str && re_openid && total_amount && wxappid)) { return data } data.workwx_sign = Hash.md5( Formatter.queryStringLike(Formatter.ksort({ act_name, mch_billno, mch_id, nonce_str, re_openid, total_amount, wxappid })), agentSecret, agentId ).toUpperCase() return data }) [代码] APIv2 发放企业红包 [代码]wxpay.v2.mmpaymkttransfers.sendworkwxredpack({ mch_billno: '123456', wxappid: 'wx8888888888888888', sender_name: 'XX活动', sender_header_media_id: '1G6nrLmr5EC3MMb_-zK1dDdzmd0p7cNliYu9V5w7o8K0', re_openid: 'oxTWIuGaIt6gTKsQRLau2M0yL16E', total_amount: 1000, wishing: '感谢您参加猜灯谜活动,祝您元宵节快乐!', act_name: '猜灯谜抢红包活动', remark: '猜越多得越多,快来抢!', mch_id: '1900000109', nonce_str: Formatter.nonce(), }) .then(res => console.info(res.data)) .catch(console.error) [代码] APIv2及APIv3之间的编程体验,几乎是完全一致的了~ 更多用法示例,已经完全中文化发在github上,地址是:https://github.com/TheNorthMemory/wechatpay-axios-plugin 花式开发玩法,下一耙再叙~
2021-03-08 - 小程序官方压测工具上线通知
“小程序压测”工具是微信小程序团队为开发者提供小程序压力测试解决方案,帮助企业最大限度真实还原业务的海量高并发等复杂场景,提早发现并解决问题,大幅降低传统测试成本,高效检验和管理业务性能,为业务保驾护航。 一、应用场景 适用于促销抢购、限量秒杀、直播卖货等流量峰值明显的业务,可模拟海量高并发,提前发现流量峰值问题、降低传统测试成本二、能力优势 真实模拟:微信独家小程序爬虫技术真实模拟微信用户打开小程序的行为,实现全链路压测的功能报告详细:压测报告包含页面加载、网络请求的多种结果指标,帮助开发者更好发现瓶颈、定位问题操作简单:全界面化操作,可灵活配置并发数、压测时间长,支持选择不同版本进行压测,更好地适配不同业务场景三、使用指南 工具免费使用,详情请在PC端访问:https://fuwu.weixin.qq.com/service/detail/000c24bafd0bb8e3794cbfa505c015 操作指南请访问:https://developers.weixin.qq.com/doc/oplatform/service_market/buyer_guideline/tool/use.html
2021-06-17