# 支持微信登录支付
FinClip 提供了支持小程序复用微信登录支付的能力, 针对 wx.login
, wx.getUserProfile
, button - getphonenumber
, requestPayment
等常用功能,当小程序运行在 FinClip 中时,在配置了之后,可以自动跳转的微信对应的小程序去获取相关的数据,完成业务闭环。
# 1. 快速开始
# 第一步:添加跳转页面
添加跳转页面至微信小程序中,并将微信小程序发布上线。跳转页面作为 FinClip 小程序与微信小程序的通信桥梁,FinClip 目前提供了模板页面快速集成,可以通过以下两种方式获取:
# 方式一:通过 开发者工具自动集成
在 开发者工具中打开小程序工程,选择小程序页面目录-右键-新增授权页,开发者工具将会自动插入相关页面
# 方式二:自行手动集成
将 小程序授权页面资源 (opens new window) 下载并解压到小程序中,并将页面路径添加到 app.json
# 第二步:配置关联
前往 FinClip 管理后台【小程序管理-我的小程序-微信关联支持-关联微信小程序】进行配置
配置参数
小程序原始id:可在微信公众平台-设置-基本设置-页面底部-原始 id
关联页面:第一步中添加的对应页面路径
# 第三步:APP 实现接口
集成微信开放 SDK,实现打开小程序以及接受回调
# 方式一
集成 FinClip 微信扩展 SDK
# 方式二
# iOS 示例代码
// 注入登录方法
[[FATClient sharedClient] registerExtensionApi:@"login" handler:^(FATAppletInfo *appletInfo, id param, FATExtensionApiCallback callback) {
NSString *wxid = appletInfo.wechatLoginInfo[@"wechatOriginId"];
NSString *path = appletInfo.wechatLoginInfo[@"profileUrl"];
BOOL canWXLogin = [WXApi isWXAppInstalled] && [wxid length] > 0 && [path length] > 0;
if (!canWXLogin) {
callback(FATExtensionCodeFailure, @{@"errMsg" : @"login:fail"});
return;
}
self.callback = callback;
WXLaunchMiniProgramReq *req = [WXLaunchMiniProgramReq object];
req.userName = wxid;
req.path = path;
req.miniProgramType = WXMiniProgramTypeRelease;
[WXApi sendReq:req completion:^(BOOL success) {
NSLog(@"打开微信:%d", success);
}];
}];
// 注入支付方法
[[FATClient sharedClient] registerExtensionApi:@"requestPayment" handler:^(FATAppletInfo *appletInfo, id param, FATExtensionApiCallback callback) {
FATAppletInfo *appInfo = [[FATClient sharedClient] currentApplet];
NSDictionary *info = appInfo.wechatLoginInfo;
NSDictionary *dataDic = param;
NSString *payString = [NSString stringWithFormat:@"?appId=%@&nonceStr=%@&package=%@&paySign=%@&signType=%@&timeStamp=%@&type=%@", dataDic[@"appId"], dataDic[@"nonceStr"], dataDic[@"package"], dataDic[@"paySign"], dataDic[@"signType"], dataDic[@"timeStamp"], dataDic[@"type"]];
WXLaunchMiniProgramReq *launchMiniProgramReq = [WXLaunchMiniProgramReq object];
launchMiniProgramReq.userName = info[@"wechatOriginId"];
launchMiniProgramReq.path = [NSString stringWithFormat:@"%@%@", info[@"paymentUrl"], payString];
if (appInfo.appletVersionType == FATAppletVersionTypeRelease) {
launchMiniProgramReq.miniProgramType = WXMiniProgramTypeRelease; //正式版
} else if (appInfo.appletVersionType == FATAppletVersionTypeTrial) {
launchMiniProgramReq.miniProgramType = WXMiniProgramTypePreview; //开发版
} else {
launchMiniProgramReq.miniProgramType = WXMiniProgramTypePreview; //体验版
}
[WXApi sendReq:launchMiniProgramReq completion:^(BOOL success) {
NSLog(@"打开微信:%d", success);
}];
}];
//微信结果回调
- (void)onResp:(BaseResp *)resp {
FATExtensionCode code = FATExtensionCodeSuccess;
if (resp.errCode != WXSuccess) {
code = FATExtensionCodeFailure;
}
if ([resp isKindOfClass:[WXLaunchMiniProgramResp class]]) {//打开小程序
NSString *extMsg = ((WXLaunchMiniProgramResp *)resp).extMsg;
if (extMsg.length <= 0) {
self.callback(FATExtensionCodeFailure, nil);
}
else {
self.callback(code, [self dictionaryWithJsonString:extMsg]);
}
}
}
//字符串转成字典
- (NSDictionary *)dictionaryWithJsonString:(NSString *)jsonString {
if (jsonString == nil) return nil;
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *err;
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err];
if(err) {
NSLog(@"json解析失败:%@",err);
return nil;
}
return dic;
}
# Android 示例代码
class WxModule(context: Context) : AppletApi(context) {
private var globalWechatLoginCallback: ICallback? = null
override fun apis(): Array<String> {
return arrayOf("login", "requestPayment")
}
override fun invoke(appId: String, event: String, param: JSONObject, callback: ICallback) {
val finAppInfo = appletApiManager.getAppletInfo(appId)
if (finAppInfo == null) {
callback.onFail()
return
}
val wechatLoginInfo = finAppInfo.wechatLoginInfo
if (wechatLoginInfo == null || TextUtils.isEmpty(wechatLoginInfo.wechatOriginId)) {
callback.onFail()
return
}
globalWechatLoginCallback = callback
when (event) {
"login"-> login(wechatLoginInfo)
"requestPayment"-> requestPayment(wechatLoginInfo, param)
}
}
private fun login(wechatLoginInfo: WechatLoginInfo){
val req = WXLaunchMiniProgram.Req()
// 微信小程序原始id
req.userName = wechatLoginInfo.wechatOriginId
// 拉起小程序页面的可带参路径,不填默认拉起小程序首页
req.path = wechatLoginInfo.profileUrl ?: ""
// 可选打开 开发版,体验版和正式版
req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE
val done = WXAPiHandler.wxApi?.sendReq(req)
}
private fun requestPayment(wechatLoginInfo: WechatLoginInfo, param: JSONObject){
val req = WXLaunchMiniProgram.Req()
// 微信小程序原始id
req.userName = wechatLoginInfo.wechatOriginId
// 拉起小程序页面的可带参路径,不填默认拉起小程序首页
// 此处拼接上支付所需的参数
val profileUrlSB = StringBuilder(wechatLoginInfo.paymentUrl)
profileUrlSB.append("?type=${param.optString("type")}")
profileUrlSB.append("&appId=${param.optString("appId")}")
profileUrlSB.append("&nonceStr=${param.optString("nonceStr")}")
profileUrlSB.append("&package=${param.optString("package")}")
profileUrlSB.append("&paySign=${param.optString("paySign")}")
profileUrlSB.append("&signType=${param.optString("signType")}")
profileUrlSB.append("&timeStamp=${param.optString("timeStamp")}")
req.path = profileUrlSB.toString()
// 可选打开 开发版,体验版和正式版
req.miniprogramType = WXLaunchMiniProgram.Req.MINIPTOGRAM_TYPE_RELEASE
val done = WXAPiHandler.wxApi?.sendReq(req)
}
}
/**
* 微信回调
*
* 此示例中无论是login还是requestPayment,都是通过微信小程序去执行,
* 因此只需处理 WXLaunchMiniProgram 这一种类型的响应即可。
*/
override fun onResp(resp: BaseResp) {
if (resp is WXLaunchMiniProgram.Resp && !TextUtils.isEmpty(resp.extMsg)) {
val json = JSONObject()
json.put("result", resp.extMsg)
globalWechatLoginCallback?.onSuccess(json)
} else {
globalWechatLoginCallback?.onFail()
}
}
# 2. 原理说明
具体流程图如下所示。
如上图所示,本功能的实现方式如下:
- FinClip 小程序调用接口(
wx.login
,wx.getUserProfile
,wx.getPhoneNumber
,wx.requestPayment
); - App 端注入接口(
wx.login
,wx.getUserProfile
,wx.getPhoneNumber
,wx.requestPayment
); - App端引入 wx 端 openSDK,获取管理后台配置的微信登录小程序相关信息;
- 执行
WXLaunchMiniProgram
方法打开微信登录小程序的授权页面; - 小程序根据 App 的参数执行相关的微信接口获取信息,并返回 App;
- App 把接口数据回传给 FinClip 小程序。
请注意
微信官方公告 (opens new window),自 2021 年 12 月 27 日后不再向开发者输出用户昵称与头像信息,您可能需要自行处理获取用户头像与昵称的相关逻辑。
# 3. 帮助
若您需要使用帮助,可使用 FinClip 中的工单功能,或加入开发者社群获得更多帮助与支持。
您也可以查看我们的官方 DEMO 项目(iOS (opens new window),Android (opens new window)),获得更多代码示例。