目录
一 前言
最近在做了一个项目,甲方要求在小程序开通会员卡后,用户可以将会员卡领取至微信卡包。原以为1天可以搞定的事情,我竟然花了2周的时间去研究微信官方文档,微信官方文档写的太烂了,以下是微信文档烂的理由。
1 文章零散,介绍卡包的文章很多,但是没有完整讲清楚。
2 领取卡包细节很多都是一笔带过,需要靠不断踩坑,才可以把细节摸清楚。
3 微信开放社区提问,得不到微信官方客服回答。
各位小伙伴可以参考我的实现方式,可以帮助大家减少研究微信操蛋的官方文档。
二 成果展示
效果:用户在小程序付费开通会员后,才可以将会员卡领取至微信卡包,微信会员卡只能在小程序付费用户领取,公众号无法直接领取会员卡。
业务场景
1 付费用户才能领取卡包,卡包必须绑定用户openId
2 自有会员卡体系,微信卡包必须是自定义会员卡code编号
3 微信会员卡激活,跳转回小程序填写用户信息,并激活
微信卡包领取形式分为多种,比如跳转型、一键开卡,本文的项目属于跳转型小程序开通类型,如果小伙伴有相同的业务场景,可以继续往下看我的文章。
三 小程序与微信卡包关系(画重点)
首先有几个概念要搞清楚,非常重要
1 小程序不具备有微信卡包能力(虽然小程序是微信的原生应用,但是可以把小程序当作h5应用、app应用)。
2 微信卡包是属于微信公众号提供服务,微信卡包里的会员卡与卡券的数据是归属于微信公众号。
3 小程序无法直接与卡券数据直接交互,小程序是通过与微信公众号交互,间接地实现会员卡的创建、领取。
四 准备工作
1 小程序主体认证,300元
2 微信公众号主体认证,300元
3 微信开放平台账号注册,开发者认证,300元
微信挣钱手段有一手啊,这个三个账号都必须要主体认证,每个账号主体认证都要300元。尼玛收了钱,微信开放社区就是个吉祥物,压根解决不了问题。
注意事项:
1 小程序与微信公众号认证的主体尽量一致
2 将小程序与微信公众号绑定在同一微信开放平台账号下,后面会说明为什么需要微信开放平台
3 小程序、微信公众号、微信开放平台必须要用3个账号注册
(微信公众号账号也可以关联小程序,但是仅仅只是为了微信公众号菜单或者文章跳转到小程序上,微信公众号与小程序数据不会互通的)
五 微信官方文档避坑
以上是微信官方文档,大部分小伙伴对这个步骤很懵逼,很多细节都没有讲清楚,而且还有部分错误,以下是几个细节。
1 细节-为什么需要微信开放平台
原文:2. 开发者须申请一个开放平台账号,并将小程序和公众号绑定在同一个开放平台账号下,关于开放平台的介绍请参照:微信开放平台;
小程序与公众号的数据不互通,通过微信开放平台将小程序与微信公众号用户账号信息关联,小程序和公众号是不同的账号,都拥有openId,但是openId是不同的。所以通过微信开放平台,使用unionId将小程序和公众号账号信息关联起来,没有在微信开放平台关联小程序和公众号绑定,获取unionId是相同。
小程序openId ->微信开放平台unionId<-微信公众号openId
2 细节-addCard的参数从何而来
原文:4. 在小程序内调用wx.addcard接口并处理领取成功的回调;
第4步骤,wx.addcard这个方法是最迷惑人的地方,没有介绍addcard的参数是怎么来的,wx.addcard api文档缺少参数说明,遇到问题比如如何传递参数、提示参数错误、提示卡券已领完等问题,文章后面会重点讲wx.addcard使用以及解决方法。
3 细节-card_id、code参数从何而来
原文 5. 在第三步中获取到的card_id、code(加密code)请求解码code接口获取真实的code;
第5步骤,card_id、code(加密code)是从第四步addCard返回结果获取的,压根不是第三步,第三步仅仅只能得到一个card_id,官网文章瞎几把写。
4 细节-openId是谁的openId
原文
6. 记录用户小程序内的openid、用户领取的code以及card_id;
7. 处理卡券领取事件,记录用户在公众号内的openid、以及用户领取的code以及card_id
第6步骤讲到小程序内的openid,第7步骤又讲到公众号内的openid,那addcard参数到底是哪个openId, 领取会员卡openId是微信公众号的openId,和小程序openId没有关系。细节1讲到微信开放平台,使用小程序的openId换取微信公众号openId,如何换取openId,在下文中会写到。
小程序领取卡券的微信文档就是个辣鸡,好像每个流程都介绍了,但是每个步骤都巨坑,腿都折断了,辣鸡文档。
六 小程序接入卡包教程(比官网还专业)
接下来,具体分步讲解接入教程,每个步骤争取把核心点讲清楚,具体实现思路后面慢慢补。
1 开通微信小程序、开通微信公众号、开通微信开放平台
这三个账号的开通就不赘述了,以下将下三个账号分别需要的信息
微信小程序:appId、appSecret
微信公众号:appId、appSecret
微信开放平台:关联微信小程序和微信公众号
微信小程序与公众号都有appId、appSecret,那是使用小程序的appId还是使用微信公众号的appId?
以下列了几项重要接口是依赖小程序还是微信公众号
动作 | 小程序appId、appSecret | 小程序openId | 公众号appId、appSecret | 公众号openId | 获取结果 |
api创建卡券接口 | ✘ | ✘ | ✔ | ✘ | 会员卡cardId |
构建addcard参数 | ✘ | ✘ | ✔ | ✔ | addcard密钥参数 |
api_ticket接口 | ✘ | ✘ | ✔ | ✘ | api_ticket |
小程序登陆接口 | ✔ | ✘ | ✘ | ✘ | 获取小程序openId与开放平台unionId |
公众号粉丝获取 | ✘ | ✘ | ✔ | ✘ | 公众号所有粉丝openId与开放平台unionId |
总的一句话,谁提供的能力,就用谁的appId与appSecret。
如果暂时还未开通微信公众号以及微信开放平台,但是不影响小伙伴们的开发,微信提供了微信测试者平台,可以在测试者平台注册个账号。这个测试账号相当于微信公众号,可以使用这个测试账号做卡包领取测试,最终我们还是把微信公众号、微信开放平台开通。
测试账号地址(微信就喜欢把好东西藏着,mmp)
http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
2 小程序与微信卡包交互流程图
上图为小程序与微信卡包交互的时序图,首先大体解释下上图的几个名词
小程序客户端:微信小程序,就是手机微信客户端的小程序app。
公众号客户端:就是手机微信客户端的公众号组件,虽然小程序和微信公众号都在一个微信客户端上,但是再次强调小程序和公众号的数据不直接交互。
自建服务器:也就是小程序的后端服务器,小程序直接与自建服务器交互,获取相关业务数据。
微信服务器:微信自家服务器,提供用户账号数据、微信卡包、微信支付等能力。
公众号客户端与自建服务器关系?
公众号客户端无法直接与自建服务器交互,公众号客户端与微信服务器发送功能请求,微信服务器再将数据以消息事件的方式通知自建服务器,以公众号回复消息为例。
小程序客户端与公众号卡包关系?
小程序客户端无法直接与公众号卡包直接交互,需要通过请求自建服务器,自建服务器使用微信公众号appId和appsecret请求公众号能力数据,以小程序激活会员卡为例。
将在以下的章节详细讲解时序图。
3 小程序与微信公众号关系维护
各位小伙伴在开发时候,经常会有一个疑问,如何使用小程序的openId去换取公众号的openId?一开始我的思路是,直接使用unionId去请求公众号的openId。
1)小程序获取openId与unionId
2)小程序unionId和公众号appId换取公众号的openId
很遗憾,微信压根没有使用unionId查询公众号openId接口,微信接口api很操蛋。最终方案是自建服务器本地将小程序openId与公众号openId关联在一起。
从上图小程序与微信公众号交互时序图看,用户要先关注微信公众号,用户才会在微信公众号下产生openId,用户关注公众号的事件会以事件通知的方式通知自建服务器,自建服务器将微信公众号用户数据落在表中。相同用户登陆小程序,也会产生openId与unionId,自建服务器也将小程序openId与unionId落在表中,使用uninoId做关联。
以下为表结构
id | unionId | 小程序openId | 公众号openId |
1 | 111111 | 222222 | 333333 |
自建服务器将在本地数据库中将公众号与小程序openId存储起来,并且建立映射关系。
注意事项:
1) 使用unionId关联,用户必须要关注微信公众号,不然无法使用微信卡包
2)小程序与微信公众号必须绑在同一个微信开放平台,这样两个账号的uionId才会相同
具体的实现方案,后面单独出几篇文章具体讲述,包括《如何全量\增量拉去公众号粉丝账号信息》、《小程序openId获取公众号openId实现方案》、《不依赖微信开放平台,如何关联小程序与公众号用户》
4 卡券api创建
卡券创建分成两种方式,第一种方式是通过微信公众号后台手工创建卡券,第二种方式是通过api接口方式创建卡券,api接口创建卡券对比手工创建卡券,可以设置更多的属性,比如要创建自定义卡号的会员卡、为用户设置会员卡不同的有效时间、为指定用户发放会员卡。
api创建卡券接口,post内容体是JSON结构,有很多的参数可以设置,就不一一介绍了,重点看官网创建卡券第四章文档的参数解释。
需要花点时间去研究这些参数,自定义一份属于你自己的卡券JSON。
官网有几个关键参数也没有讲清楚,以下介绍下本项目中用到几个比较关键的参数设置。
本文中的项目有几个关键的功能点
1)用户购买会员卡才可以领取卡包
2)微信卡包激活,需要在跳转至小程序完善信息
3)为每个用户设置不同的会员卡过期时间
业务流程:用户下单购买会员卡-》订单确认发放内置会员卡-》用户领取会员卡-》会员激活会员卡-》会员完善信息
功能点 | 卡券api参数 | 参数值 | 说明 |
用户购买会员卡才可以领取卡包 | use_custom_code | true | 使用自定义的卡号,用户无法从其他渠道领取会员卡,购买会员卡是唯一领取会员卡渠道 |
bind_openid | true | 每一张发放的会员卡必须要和用户绑定,这里openId是指公众号的openId | |
can_give_friend | false | 会员卡不可以分享给朋友 | |
sku.quantity | 9999999 | 会员卡数量 | |
微信卡包激活,需要在跳转至小程序完善信息 | activate_app_brand_user_name | 小程序账号 | 会员卡领取后,点击激活可以跳转到对应开卡小程序 |
activate_app_brand_pass | 小程序页面路径 | 该页面填写用户的信息,完善信息后,通过后端api接口直接激活会员卡。 必须通过自建服务器校验信息,激活会员卡。 | |
为每个用户设置不同的会员卡过期时间 | date_info.type | DATE_TYPE_FIX_TERM | 设置会员卡日期模式为日期可调整模式,type类型一共3种,DATE_TYPE_PERMANENT、 DATE_TYPE_FIX_TERM_RANGE、 DATE_TYPE_FIX_TERM 坑爹的微信没有在文档写这三种的使用方法,后续在另外文章介绍《微信卡包有效期3种模式》。 |
fixed_term | 365 | 会员卡的有效天数,比如领取卡片2020/10/01,有效期则是到2021/10/01。 如果需要为每个用户设置不同的过期时间,那可以在接口激活的时间设置相应过期时间。 在另外文章介绍《不同用户设置会员卡不同过期时间实现方案》 | |
fixed_begin_term | 0 | 会员卡的生效时间,设置为0表示马上生效。 |
以上表格参数是比较关键的参数,开卡的方式是由这三个参数activate_url、auto_activate和wx_activate决定,后续在单独文章介绍《activate_url、auto_activate和wx_activate参数区别》。
注意:
1)调用创建卡券api的accessToken,必须是微信公众号的appId换取accessToken
5 领取会员卡
领取会员卡是微信卡包的重点,我在这块花了很长的时间研究微信文档,微信文档有很多坑,大家可以重新看看第5节微信官方文档避坑的细节,可以帮大家解决微信卡包领取90%的问题。
以下是微信卡包领取的流程。
1)wx.addcard文档残缺
添加微信卡包,需要小程序wx.addCard组件,addCard微信文档并介绍清楚小程序卡包的ext参数,这个就是最坑的地方,完全不知道调起微信卡包的错误原因,以下具体介绍微信会员卡ext参数。
ext参数 | 说明 |
nonce_str | 随机参数,目的用于signature签名加密使用,项目中是使用10位随机字符串 |
code | 自定义卡号,由于建卡api时use_custom_code为true,在添加卡包时必须要有卡号 |
timestamp | 时间戳,单位为秒。和nonce_str一样,用于签名加密使用。 |
openid | 用户的微信公众号openid,这个是最最最坑的地方,必须是微信公众号的openid,不然addcard会提示参数错误。 上文提到在自建服务器维护了小程序openid和微信公众号的openid关系,通过这种方式获取到微信公众号openid |
apiTicket | 签名凭证,这个就是腾讯文档最骚的地方,压根没有提这个参数,加密时需要使用apiTicket。 获取ticket_api,可以从通过这个接口查询到api_ticket,使用公众号的accessToken请求。 |
card_id | 卡券id,api创建卡券时,会返回新建卡券的card_id |
signature | 加密签名,这个是重头戏,我是用试了N了遍,才摸清楚这个签名组成,是使用nonce_str、code、timestamp、openid、apiTicket、card_id的6个参数,多一个参数少一个参数都不行,顺序SHA加密得到的。 |
如何判断signature加密对不对,可以使用工具调试平台测试,有这么好用的工具也不在微信文档提到,实属坑爹。
2)卡包addcard参数错误
由于addcard ext参数不对,导致卡包界面提示卡包已领完、卡包参数错误,这种是比较常见的错误,如果按照上一节的参数赋值,基本没有错误。但是还是重点讲讲卡包领取错误该怎么排查。
微信后端校验addcard ext参数,优先校验每个参数的合法型,最后再校验singature签名的正确性。
举几个我踩坑的例子:
- addcard传入小程序的openid,尽管参数不全,但是卡包领取界面提示的错误是已领完,而不是参数错误。
- signature的6个参数nonce_str、code、timestamp、openid、apiTicket、card_id,多一个参数少一个参数,提示参数错误。
微信单独写过一篇文章,《如何排查卡券签名错误》,但是一篇公众号文章,微信官方就不能好好地把有用文档整理到一起。
3)领取卡包后,直接打开激活界面
- 目前卡券领取后会自动返回小程序页面,若开发者鼓励用户领卡后继续在卡面上进行下一步操作,须在wx.addcard的函数回调内调用wx.opencard;
- wx.addcard成功后返回的参数中code为加密字段,须解密后才能调用wx.opencard
这里直接引用微信官方文档,在wx.addcard回调成功后,直接调起wx.opencard组件。wx.addcard回调成功会返回加密后的code,加密后的code解密后,就是自建服务器上的卡号。
4)接收微信卡包领取消息
api激活卡包前,用户需要先领取会员卡,那自建服务器是如何知道用户已领取会员卡?
是通过微信服务器的消息事件通知,详细请见《领取事件推送》。
由于本文章章节有限,后续会单独写一篇《微信事件接收遇到的坑》。
6 激活会员卡
会员卡支持3种激活方式,包括接口激活、一键激活、自动激活。由于本项目要求购买会员卡后激活,所以需要使用api方式激活会员卡,保证小程序是唯一的开卡渠道。
API激活《会员接口激活》相比领取卡片简单很多,,重点介绍下会员卡过期参数的设置。
参数 | 说明 |
activate_begin_time | 激活后的有效起始时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 |
activate_end_time | 激活后的有效截至时间。若不填写默认以创建时的 data_info 为准。Unix时间戳格式。 |
当api创建卡券的type设置为DATE_TYPE_FIX_TERM,activate_begin_time、activate_end_time有效期参数生效,不然默认使用date_info有效日期。
七 总结
以上是实现微信卡包过程中总结的经验,希望能够帮助大家在接入卡包过程中解决问题。本文文章篇幅有限,有些功能点实现也写的比较细碎,比如为会员卡设置不同的过期时间等,大家理解起来比较费劲,后续单独针对这些问题,单独写具体实现方案实现文章。
如果大家有需要接入微信卡包、微信支付,有偿为大家提供微信卡包、微信支付接入技术指导与技术支持。