微信支付的集成
不管是你之前做没做过微信支付,或者是集成其他的一些第三方,都首先阅读官方文档,多读几遍,看看官方demo,问题都会迎刃而解。
一、首先介绍一下公司产品经理需要申请的一些东西以及服务端需要的配置
1.申请开发者资质
地址:https://open.weixin.qq.com/
使用公司管理者/高层帐号登录微信开放平台,进入“账号中心”,进行开发者资质认证,需要填写公司资料,包括但不限于,公司注册号,公司营业执照,公司对外办公电话,公司对公银行卡信息(卡号,发卡行)。审核时间为一周左右。
备注:因为从2015年10月1日起,国家实行三证(组织机构代码证,企业营业执照,税务登记证)合一,所以组织机构代码处填写-工商执照注册号,同样,组织机构代码证,上传-企业工商营业执照。
备注2:进行开发者资质认证需要支付300元人名币/年,只有具备开发者资质认证的开发者才能够使用app支付,授权登录等接口
。
2.申请APP_ID/APP_KEY
每个应用/游戏要调用微信的接口都需要有一个微信标志,这个唯一标志通常成为APP_ID或者APP_KEY,各开放平台差异不大
进入管理中心,创建移动应用,每个开发者具有10个应用的创建机会,好在创建的应用可以随时删除。已上线的应用就不建议手贱删除!!
申请appid需要填写应用信息:应用名称,包名,签名(keystore的md5值去分号小写),icon(28*28 & 108*108),app下载地址等信息,即可分配到一个appid。
备注:测试支付时,务必使用申请时填写的keystore文件签名,包名也需要核对清楚,必然无法调起支付,返回-1错误码
3.申请支付能力
在管理中心,查看需要集成支付能力的app,找到“微信支付”一栏,点击右侧“申请开通”,填写一些企业信息后等待审核,审核时间为一周左右,审核通过后,会得到一个企业商户号及密码,对公银行卡中将收到几分钱,进入商户平台,输入收到的金钱金额以验证。验证通过后即可开始集成支付调用。在这之前,调用支付接口是无法完成支付的。
4.
商户在微信开放平台申请开发应用后,微信开放平台会生成APP的唯一标识APPID。由于需要保证支付安全,需要在开放平台绑定商户应用包名和应用签名,设置好后才能正常发起支付。设置界面在【开放平台】中的栏目【管理中心 / 修改应用 / 修改开发信息】里面
应用包名:是在APP项目配置文件AndroidManifest.xml中声明的package值,例如DEMO中的package=”net.sourceforge.simcpux”。
应用签名:根据项目的应用包名和编译使用的keystore,可由签名工具生成一个32位的md5串,在调试的手机上安装签名工具后,运行可生成应用签名串,如图8.9所示,绿色串即应用签名。签名工具下载地址https://open.weixin.qq.com/zh_CN/htmledition/res/dev/download/sdk/Gen_Signature_Android.apk
5.支付流程图
商户系统和微信支付系统主要交互说明:
步骤1:用户在商户APP中选择商品,提交订单,选择微信支付。
步骤2:商户后台收到用户支付单,调用微信支付统一下单接口。参见
步骤3:统一下单接口返回正常的prepay_id,再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式为Sign=WXPay
步骤4:商户APP调起微信支付。
步骤5:商户后台接收支付通知。
步骤6:商户后台查询支付结果。
这里,移动端只需要第四步就ok了
二、移动端集成
在此,我们需要知道 APP_ID,需要提前准备
1.添加SDK
Android Studio环境下:已改用gradle形式,发布到jcenter( http://jcenter.bintray.com/),请开发者使用gradle来编译、更新微信SDK。
在build.gradle文件中,添加如下依赖即可:
dependencies {
compile ‘com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+’
}
或
dependencies {
compile ‘com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+’
}
(其中,前者包含统计功能)
eclipse环境下:需要下载 Android开发工具包
2.WXPayEntryActivity.java
这个页面是在你调起微信支付完成支付(或取消或失败)后,再回到你的App时会调用的一个页面,目录结构一定是下图:
示例代码(可以随意copy一个示例放进去,布局也随意,或者不加载布局):
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler,
OnClickListener {
private IWXAPI msgApi;
private String app_id = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//如果不需要布局。下面这一局可以删除
setContentView(R.layout.pay_result);
//你自己的APP_ID
app_id = SharedPreferencesUtil.getPrefString(SharedPreferencesKeys.WEIXIN_APP_ID, "");
regToWx();
findViews();
addEvents();
}
private void regToWx() {
msgApi = WXAPIFactory.createWXAPI(this, app_id, false);
msgApi.registerApp(app_id);
msgApi.handleIntent(getIntent(), this);
}
private void findViews() {
}
private void addEvents() {
}
@Override
public void onClick(View v) {
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
msgApi.handleIntent(intent, this);
}
@Override
public void onReq(BaseReq req) {
// TODO Auto-generated method stub
}
//这里做你的处理
@Override
public void onResp(BaseResp resp) {
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
if (resp.errCode == 0) {
Intent intent = new Intent(this, ChargeActivity.class);
intent.putExtra("type", "check");
startActivity(intent);
finish();
}
if (resp.errCode == -1) {
ToastUtils.toastShort("充值失败");
finish();
}
if (resp.errCode == -2) {
ToastUtils.toastShort("取消充值");
finish();
}
}
}
}
在AndroidManifest.xml中
添加权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
为之前的WXPayEntryActivity,声明
<!--微信支付-->
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/WX_theme"/>
<!--最后这个theme ,咱们会在常见问题中单独说明-->
这个类中的其余的回调方法,我们都不需要去操作
3.微信支付
微信SDK集成之后,准备工作也就做好了,接下来就是要写代码了。官方文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_12&index=2
(1).统一下单(服务端做)
为了更加安全,微信推荐统一下单是交给服务端人员来做的,当然也有一下服务端开发人员觉得麻烦,会推到客户端来做,这个时候千万别怂,一定要跟他讲。
(2).请求我们自己服务器的接口
在我们自己的APP中点击微信支付按钮后,我们首先要请求一个我们自己服务端的接口,这时服务端需要走统一下单的逻辑,然后将一些参数返回给我们。这里需要注意,严格来说的话,这个接口应该返回如下所有参数:
这七个参数是必须,当然可以是更多。
单独说明一下这个签名sign:
这个签名不是之前统一下单的签名,而是再按签名规范重新生成签名后,将数据传输给APP。参与签名的字段名为appid,partnerid,prepayid,noncestr,timestamp,package。注意:package的值格式为Sign=WXPay
(3).发起支付
//必须注册
IWXAPI mWxApi = WXAPIFactory.createWXAPI(mContext,WX_APPID, true);
mWxApi.registerApp(WX_APPID);
/**
* 请求自己的服务器得到返回的参数
*/
@Override
public void onGet(JSONObject jsonObject) {
if (mWxApi != null) {
PayReq req = new PayReq();
req.appId = WX_APPID;// 你自己的APPID
req.partnerId=jsonObject.getString("partnerid");// 微信支付分配的商户号
req.prepayId = jsonObject.getString("prepayid");// 预支付订单号,app服务器调用“统一下单”接口获取
req.nonceStr = jsonObject.getString("noncestr");// 随机字符串,不长于32位,服务器小哥会给咱生成
req.timeStamp = jsonObject.getString("timestamp");// 时间戳,app服务器小哥给出
req.packageValue = jsonObject.getString("package");// 固定值Sign=WXPay,可以直接写死,服务器返回的也是这个固定值
req.sign = jsonObject.getString("sign");// 签名
// 调用接口发起支付
mWxApi.sendReq(req);
}
}
(4) 支付结果回调
此时,不出意外会调起微信支付界面
WXPayEntryActivity类(包名或类名不一致会造成无法回调)中实现onResp函数,支付完成后,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。回调中errCode值列表:
如果返回支付成功,建议在查询一遍服务器,确认支付成功
三:取消支付,屏幕闪烁问题
就是在之前WXPayEntryActivity引用的theme
WXPayEntryActivity是一个空界面,如果普通的两个页面跳转,一个如果没有布局,也会出现闪屏的效果,最终锁定问题的所在: 两个页面跳转的出现闪屏,去除默认带的动画。
解决办法:去掉页面动画,以及改成背景透明
<style name="WX_theme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- 设置启动背景透明 -->
<item name="android:windowIsTranslucent">true</item>
<!-- 设置启动不要Title -->
<item name="android:windowNoTitle">true</item>
</style>
<!--充值取消白屏问题-->
<style name="Theme.Mike" parent="AppSplash">
<item name="android:windowAnimationStyle">@style/Animation</item>
</style>
<style name="Animation">
<item name="android:activityOpenEnterAnimation">@null</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@null</item>
<item name="android:taskOpenEnterAnimation">@null</item>
<item name="android:taskOpenExitAnimation">@null</item>
<item name="android:taskCloseEnterAnimation">@null</item>
<item name="android:taskCloseExitAnimation">@null</item>
<item name="android:taskToFrontEnterAnimation">@null</item>
<item name="android:taskToFrontExitAnimation">@null</item>
<item name="android:taskToBackEnterAnimation">@null</item>
<item name="android:taskToBackExitAnimation">@null</item>
</style>
其他返回-1 的 情况。自行google 或者baidu。总之呢,操作过程一定要仔细。