本文共 20275 字,大约阅读时间需要 67 分钟。
上一篇简单地讲了 ReactNative
如何接入支付宝支付,那么这一篇就介绍如何接入微信API吧。我们实际用到的一般有微信登录、微信分享、微信支付这三个功能。http://jafeney.com/2016/11/18/2016-11-17-wechat/
微信的东西比较支付宝申请起来要略微麻烦点,步骤多,而且有些资质认证要给微信钱,心太黑。废话不多说,登录微信开放平台,创建你的App应用,改填的都填了,提交 —— 审核1~2天 —— 通过 —— 申请微信支付 —— 继续审核 … MD这步一次性通过是有多难 !
微信支付申请通过了会收到一份邮件,里面有你的微信支付商户账号的信息(记得保存),然后用这个账号和密码登录微信商户平台。这里关键的一步是:
进入 账户中心 —> API安全 —> 设置一个32位的密钥
准备工作都做好了,我们就可以开始开发了。
感谢大react-native
社区,为我们这种菜鸟提供了如此全面的微信三方模块react-native-wechat
,完全能满足现阶段的所有微信API需求啊!
react-native-wechat
交流群 336021910 支持npm
安装:
1 | npm install react-native-wechat --save |
ReactNative
完全支持ES7 async
和await
是ES7
比较新的提案,让ReactNative
完全支持stage-0
,首先我们需要安装 babel-preset-react-native-stage-0
模块:
1 | npm install babel-preset-react-native-stage-0 --save-dev |
并设置 .babelrc
1 2 3 | { "presets": [ "react-native-stage-0" ], } |
link
和配置 上一篇已经介绍了 react-native link
命令,可以把客户端所需的模块链接到IOS
和Android
目录里。
1 | react-native link react-native-wechat |
当然,只执行上面的命令还不够。我们还需要手动添加一些配置
IOS
端微信的配置和支付宝差别不大。
(1)添加下面几个framework
和library
:
1 2 3 4 5 | SystemConfiguration.framework CoreTelephony.framework libsqlite3.0 libc++ libz |
注意:
CoreTelephony.framework
、libc++z
、libz
,这三项和支付宝模块的重复,引一次就够了。
(2)添加 URL Schema
,值是你应用的微信appid
(3)给 LSApplicationQueriesSchemes
添加三个值 alipay
、weixin
、wechat
或者直接编辑 Info.plist
:
1 2 3 4 5 6 |
|
注意:如果你不需要支付宝支付,
alipay
可以不加
(4)修改 AppDelegate.m
如果你不需要支付宝支付,这个函数可以这么写:
1 2 3 4 5 6 7 8 | #import "../Libraries/LinkingIOS/RCTLinkingManager.h" - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; } |
如果你既要支付宝支付,也需要微信支付。那么应该这么写:
1 2 3 4 5 6 7 8 9 10 | #import "../Libraries/LinkingIOS/RCTLinkingManager.h" - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { if([[sourceApplication substringToIndex:10] isEqualToString:@"com.alipay"]){ [AlipayModule handleCallback:url]; } return [RCTLinkingManager application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; } |
Android
端 (1) 修改android/settings.gradle
1 2 | include ':RCTWeChat' project( ':RCTWeChat').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-wechat/android') |
(2)修改android/app/build.gradle
1 2 3 | dependencies { compile project(':RCTWeChat') // Add this line only. } |
(3)修改MainActivity.java or MainApplication.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import com.theweflex.react.WeChatPackage; // Add this line before public class MainActivity ... /** * A list of packages used by the app. If the app uses additional views * or modules besides the default ones, add more packages here. */ @Override protected List |
(4)创建一个新的package
取名wxapi
,在里面创建class
取名WXEntryActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | package your. package.wxapi; import android.app.Activity; import android.os.Bundle; import com.theweflex.react.WeChatModule; public class WXEntryActivity extends Activity{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WeChatModule.handleIntent(getIntent()); finish(); } } |
(5)修改AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 | |
(6)修改 proguard-rules.pro
1 2 3 | -keep class com.tencent.mm.sdk.** { *; } |
react-native-wechat
使用前必须初始化一次(有且仅一次)。建议放在项目的入口文件里:
1 2 3 4 | // ...省略 componentDidMount() { WeChat.registerApp( '你的appid') } |
微信登录需要用到的是 WeChat.sendAuthRequest
这个方法。
首先介绍一下它参数:
scope
(必需) 应用授权作用域,如获取用户个人信息则填写 snsapi_userinfo
state
(非必需) 用于保持请求和回调的状态,授权请求后原样带回给第三方。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议第三方带上该参数,可设置为简单的随机数加session进行校验 执行 WeChat.sendAuthRequest
获取CODE:
1 | let code = await WeChat.sendAuthRequest( "snsapi_userinfo", "123"); |
该方法会返回一个字符串,类似 0114sg4t1F1Rc90jSw6t1Cf44t14sg4-
一串CODE。
access_token
包装一个 GET
类型的fetch
请求,URL如下:
1 | https: //api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code |
这个接口会返回 access_token
和 用户的 openid
。示例如下:
1 2 3 4 5 6 7 8 | { "access_token": "JWk5IxV5bFGOdTm2A4zhuGuIB_xGRM5cPbU5nYbkuEihHu6FClMn5zjVZ6QCTYrMv_oCMxW8szuNAOadYIYo6wiOObeesEeNgHeWNvkJolQ", "expires_in": 7200, "refresh_token": "WPhskoRBAmDyM1EbrPRvWSCU8LL3Ndn0Brong9ZG434L1Imkxugu2JKOghfIuP1P3JqcCyB2anxAwXRuFr7EMxP_rygeWy1Noi0zPJue_YU", "openid": "oDwRbw9zFEO36l3Vcq6bHXFWB13k", "scope": "snsapi_userinfo", "unionid": "o3KCIw-vFiuq0SBHe-3bhjbCQY3o" } |
包装一个 GET
类型的fetch
请求,URL如下:
1 | https: //api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID |
这个接口会返回 授权用户的微信基本信息,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 | { "openid": "oDwRbw9zFEO36l3Vcq6bHXFWB13k", "nickname": "思^_^诚", "sex": 1, "language": "zh_CN", "city": "Hangzhou", "province": "Zhejiang", "country": "CN", "headimgurl": "http://wx.qlogo.cn/mmopen/PiajxSqBRaEKujUoq5z4PScxKqQESxMxj6VDYnIHT4ZibVDMmSb69dq6EbLPAUJ15mMH9pIxFNu9JZszyx1F6ibcw/0", "privilege": [], "unionid": "o3KCIw-vFiuq0SBHe-3bhjbCQY3o" } |
微信分享用到的是 WeChat.shareToTimeline(opt)
(分享到朋友圈) 和 WeChat.shareToSession(opt)
(分享给微信好友或微信群),这两个方法的入参是一样的。
为了方便,微信分享我做成了一个react-native
组件, 感兴趣的可以点击看看
thumbImage
分享出去的预览图title
分享标题webpageUrl
分享出去的网页地址 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /** * [分享到朋友圈] * @param {[Object]} opt 入参对象 * @example { thumbImage:'', title: '', webpageUrl: '' } */ async handleShareWeixinCircle(opt) { this.lock = true /* 异步操作锁 */ try { let result = await WeChat.shareToTimeline({ type: "news", ...opt, }); } catch (e) { console.error(e) } finally { this.lock = false this.close() } } /** * [分享给微信好友或微信群] * @param {[Object]} opt 入参对象 * @example { thumbImage:'', title: '', webpageUrl: '' } */ async handleShareWeixinFriend(opt) { this.lock = true /* 异步操作锁 */ try { let result = await WeChat.shareToSession({ type: "news", ...opt, }); } catch (e) { console.error(e) } finally { this.lock = false this.close() } } |
我这里用到的是分享网页,更多分享功能参见
微信支付用到的是 WeChat.pay(opt)
方法
后端需要为我们提供一个支付接口 去调取微信支付的 “统一下单” 接口,然后返回下面这些东西:
1 2 3 4 5 6 7 8 9 | { appid: '', //应用id partnerid: '', // 商家向财付通申请的商家id prepayid: '', // 预支付订单 noncestr: '', // 随机串,防重发 timestamp: '', // 时间戳,防重发 package: '', // 商家根据财付通文档填写的数据和签名 sign: '' // 商家根据微信开放平台文档对数据做的签名 } |
注意:后端要严格区分大小写,这几个变量必须都小写。否则会报 “支付签名验证失败” 这类的错误
有了react-native-wechat
,微信支付其实也就调用一个方法的事情。类似支付宝支付的action
,下面是最原始的实现代码(建议把fetch
封装一下)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | export function weixinPay(opt) { return (dispatch) => { const uri = `http://${CONFIG.API_URI}/wx/pay`; /*支付接口*/ const headers = { ...CONFIG.HEADERS, 'Authorization': opt.token, }; /*发起支付请求*/ fetch(uri, { method: 'POST', headers: headers, body: JSON.stringify(opt.body)}) .then( (response) => { if (response.status === 200) { return response.json() } else { return { code: response.status} } }) .then( (data) => { if ( String(data.code) == '0') { /*打开微信进行支付*/ pay(data.result, opt.success, opt.fail) } else { /*预支付失败的后续操作*/ opt.error && opt.error(data.error.message) } }) } } async function pay(res, success, fail) { try { let result = await WeChat.pay({ partnerId: res.partnerid, /*商家向财付通申请的商家id*/ prepayId: res.prepayid, /*预支付订单*/ nonceStr: res.noncestr, /*随机串,防重发*/ timeStamp: res.timestamp, /*时间戳,防重发*/ package: res.package, /*商家根据财付通文档填写的数据和签名*/ sign: res.sign, /*商家根据微信开放平台文档对数据做的签名*/ }); /*支付成功的后续操作*/ success && success() } catch (error) { /*支付失败的后续操作*/ fail && fail( error === -2 ? "用户取消" : "订单支付失败") } } |
@欢迎关注我的 和