Android微信支付V3版
由于公司需求做微信APP支付,在集成过程中也遇到各种问题,比如说签名错误,body编码必须为UTF-8、APP端无法调用支付页面直接到支付结果页面、结果为null,code=-1等等;
1、签名错误问题,首先得确保APPID、商户ID、api密钥正确,其次就是编码问题了,Java文件得是UTF-8的,再有就是接下来代码里注释的。
2、body编码必须为UTF-8的问题,改body编码后报签名错误,唉!各种无奈,于是想到是不是跟开发环境编码有关,换了台电脑,居然成了。(这是我的办法,不一定适用大家)
3、APP端无法调用支付页面直接到支付结果页面,支付结果:null,code=-1,这个问题官方(http://kf.qq.com/faq/140225MveaUz150413eimyiQ.html)给的解决方法是:
开放平台配置的报名和应用签名是否一致:(android);确认是否使用正式的keystore打包apk并安装调试;(android);提交订单部分需要在服务器端完成。
所以,调试微信支付要么申请一个debug.keystore版的,要么使用正式的keystore打包apk并安装调试。
接下来给大家分享我的结果,我是从服务段获取的prepay_id:
服务端:WXPaynewBiz.java
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import org.apache.commons.httpclient.NameValuePair; import com.jing.lang.MD5Util;
public class WXPaynewBiz {
/** APP_ID 应用从官方网站申请到的合法appId */
public static final String WX_APP_ID = "APP_ID";
/** 商户号 */
public static final String WX_PARTNER_ID = "商户号";
/** 接口链接 */
public static final String url="https://api.mch.weixin.qq.com/pay/unifiedorder";
/** 商户平台和开发平台约定的API密钥,在商户平台设置 */
public static final String key="API密钥"; public void submitOrder(double realPayPrice, int tradeType, String ip) {
int realpayPrice=(int)(realPayPrice*100);
List<NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new NameValuePair("appid", WX_APP_ID));
nvps.add(new NameValuePair("body", "商品描述"));
nvps.add(new NameValuePair("mch_id", WX_PARTNER_ID));
nvps.add(new NameValuePair("nonce_str", UUID.randomUUID().toString().replace("-", "")));
nvps.add(new NameValuePair("notify_url", "回调通知地址"));
nvps.add(new NameValuePair("out_trade_no", "86"));
nvps.add(new NameValuePair("spbill_create_ip", ip));
nvps.add(new NameValuePair("total_fee",realpayPrice+"" ));
nvps.add(new NameValuePair("trade_type", "APP"));
StringBuffer sb=new StringBuffer(); for (NameValuePair nvp : nvps) {
sb.append(nvp.getName()+"="+nvp.getValue()+"&");
}
String signA=sb.toString();
String stringSignTemp=signA+"key="+key ;
System.out.println(signA);
System.out.println(stringSignTemp);
String sign=MD5Util.getMD5String(stringSignTemp).toUpperCase();
System.out.println(sign);
nvps.add(new NameValuePair("sign", sign));
try {
// 最关键的一步,我们要把最终发送的数据字符转为字节后,再使用“ISO8859-1”进行编码,得到“ISO8859-1”的字符串,否则有可能有“签名错误”的问题
byte[] buf = Util.httpPost(url, new String(toXml(nvps).getBytes(),"ISO8859-1"));
String content = new String(buf);
System.out.println(content);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
} private String toXml(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
sb.append("<?xml version='1.0' encoding='UTF-8'?><xml>");
for (int i = 0; i < params.size(); i++) {
sb.append("<"+params.get(i).getName()+">"); sb.append(params.get(i).getValue());
sb.append("</"+params.get(i).getName()+">");
}
sb.append("</xml>");
System.out.println(sb.toString());
return sb.toString();
}
public static void main(String[] args) {
WXPaynewBiz wx=new WXPaynewBiz();
wx.submitOrder(10.00, 1, "127.0.0.1");
}
}
Android端,android端是根据官方给的Demo做的:
一、在自己的项目的包路径中实现WXPayEntryActivity类,即添加 .wxapi.WXPayEntryActivity,在WXPayEntryActivity类中实现onResp函数,支付完成后,微信APP会返回到商户APP并回调onResp函数,开发者需要在该函数中接收通知,判断返回错误码,如果支付成功则去后台查询支付结果再展示用户实际支付结果。注意一定不能以客户端返回作为用户支付的结果,应以服务器端的接收的支付通知或查询API返回的结果为准。代码示例如下:
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.os.Bundle; import com.tencent.mm.sdk.constants.ConstantsAPI;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.sdk.openapi.WXAPIFactory; public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler { private IWXAPI api; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.pay_result);
api = WXAPIFactory.createWXAPI(this, Constants.WX_APP_ID);
api.handleIntent(getIntent(), this);
} @Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
api.handleIntent(intent, this);
} @Override
public void onReq(BaseReq req) {
} @Override
public void onResp(BaseResp resp) {
if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
int code = resp.errCode;
String msg = "";
switch (code) {
case 0:
msg = "支付成功!";
break;
case -1:
msg = "支付失败!";
break;
case -2:
msg = "您取消了支付!";
break; default:
msg = "支付失败!";
break;
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.app_tip);
builder.setMessage(msg);
builder.setNegativeButton("确定", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
WXPayEntryActivity.this.finish();
}
});
builder.show();
}
}
}
二、在APP项目配置文件AndroidManifest.xml中配置WXPayEntryActivity,代码如下:
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
三、看官方demo还有一个AppRegister.java文件,具体不知道什么作用,我也给配置了,代码如下:
import com.tencent.mm.sdk.openapi.IWXAPI;
import com.tencent.mm.sdk.openapi.WXAPIFactory; import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent; public class AppRegister extends BroadcastReceiver { @Override
public void onReceive(Context context, Intent intent) {
final IWXAPI msgApi = WXAPIFactory.createWXAPI(context, null); // 将该app注册到微信
msgApi.registerApp(Constants.WX_APP_ID);
}
}
<receiver
android:name=".wxpay.AppRegister">
<intent-filter>
<action android:name="com.tencent.mm.plugin.openapi.Intent.ACTION_REFRESH_WXAPP" />
</intent-filter>
</receiver>
四、在项目包名下添加微信客户端回调函数类 .wxapi.WXEntryActivity,并添加AndroidManifest.xml配置:代码如下:
import android.content.Intent;
import android.widget.Toast;
import cn.sharesdk.wechat.utils.WXAppExtendObject;
import cn.sharesdk.wechat.utils.WXMediaMessage;
import cn.sharesdk.wechat.utils.WechatHandlerActivity; /** 微信客户端回调activity示例 */
public class WXEntryActivity extends WechatHandlerActivity { /**
* 处理微信发出的向第三方应用请求app message
* <p>
* 在微信客户端中的聊天页面有“添加工具”,可以将本应用的图标添加到其中
* 此后点击图标,下面的代码会被执行。Demo仅仅只是打开自己而已,但你可
* 做点其他的事情,包括根本不打开任何页面
*/
public void onGetMessageFromWXReq(WXMediaMessage msg) {
Intent iLaunchMyself = getPackageManager().getLaunchIntentForPackage(getPackageName());
startActivity(iLaunchMyself);
} /**
* 处理微信向第三方应用发起的消息
* <p>
* 此处用来接收从微信发送过来的消息,比方说本demo在wechatpage里面分享
* 应用时可以不分享应用文件,而分享一段应用的自定义信息。接受方的微信
* 客户端会通过这个方法,将这个信息发送回接收方手机上的本demo中,当作
* 回调。
* <p>
* 本Demo只是将信息展示出来,但你可做点其他的事情,而不仅仅只是Toast
*/
public void onShowMessageFromWXReq(WXMediaMessage msg) {
if (msg != null && msg.mediaObject != null
&& (msg.mediaObject instanceof WXAppExtendObject)) {
WXAppExtendObject obj = (WXAppExtendObject) msg.mediaObject;
Toast.makeText(this, obj.extInfo, Toast.LENGTH_SHORT).show();
}
} }
<activity
android:name=".wxapi.WXEntryActivity"
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="keyboardHidden|orientation|screenSize"
android:exported="true"
android:screenOrientation="portrait" />
五、最后做我们的发起微信支付的页面,主要代码如下(主要还是官方Demo里的),另外还要在发起微信支付的Activity标签中添加属性<data android:scheme="appid"/>:
private PayReq req;
private StringBuffer sb; /**
* 微信支付临时订单的prepay_id
*/
private void getWXPrepayId(){
//从服务器获取,代码略……
//获取成功后
sendPayReq(prepayId);
} /**
* 调用微信支付页面
*/
private void sendPayReq(String prepayId){
genPayReq(prepayId);
WXapi.registerApp(Constants.WX_APP_ID);
WXapi.sendReq(req);
try {
Thread.sleep(1000*3);
} catch (InterruptedException e) {
e.printStackTrace();
}
closeProDialog();
this.finish();
} /**
* 生成签名参数
*/
private void genPayReq(String prepayId) {
req.appId = Constants.WX_APP_ID;
req.partnerId = Constants.WX_PARTNER_ID;
req.prepayId = prepayId;
req.packageValue = "Sign=WXPay";
req.nonceStr = genNonceStr();
req.timeStamp = String.valueOf(genTimeStamp()); List<NameValuePair> signParams = new LinkedList<NameValuePair>();
signParams.add(new BasicNameValuePair("appid", req.appId));
signParams.add(new BasicNameValuePair("noncestr", req.nonceStr));
signParams.add(new BasicNameValuePair("package", req.packageValue));
signParams.add(new BasicNameValuePair("partnerid", req.partnerId));
signParams.add(new BasicNameValuePair("prepayid", req.prepayId));
signParams.add(new BasicNameValuePair("timestamp", req.timeStamp));
req.sign = genAppSign(signParams);
sb.append("sign\n"+req.sign+"\n\n");
} /**
* 随机数
* @return
*/
private String genNonceStr() {
Random random = new Random();
return MD5Util.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
} /**
* 时间戳
* @return
*/
private long genTimeStamp() {
return System.currentTimeMillis() / 1000;
} /**
* 获取签名
* @param params
* @return
*/
private String genAppSign(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder(); for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).getName());
sb.append('=');
sb.append(params.get(i).getValue());
sb.append('&');
}
sb.append("key=");
sb.append(Constants.WX_API_SECRET);
this.sb.append("sign str\n"+sb.toString()+"\n\n");
String appSign = MD5Util.getMessageDigest(sb.toString().getBytes()).toUpperCase(Locale.CHINA);
return appSign;
}
<activity android:name=".OrderFormPayActivity" >
<data android:scheme="自己的appid"/>
</activity>
到此就差不多了,主要还是的注意下编码格式,希望对各位有帮助,谢谢!
附官方demo:wechat_sdk_sample_android_v3_pay.zip
Android微信支付V3版的更多相关文章
- jsapi微信支付v3版
请看清楚你的微信支付是v2还是v3.在这里整理的是v3的,v2的同学请忽略! 前期准备须要用的是商户证书,用的是p12的.设置api密钥(在微信商户端中设置),还须要在微信公众号中设置jsapi授权文 ...
- 微信支付 V3版
本人小菜鸟一仅仅.为了自我学习和交流PHP(jquery,linux,lamp,shell,javascript,server)等一系列的知识,小菜鸟创建了一个群.希望光临本博客的人能够进来交流. 寻 ...
- 微信支付v3接口的 官方 Java SDK
啰嗦几句:微信支付v3版接口麻烦吗?在对接微信支付v3接口时,本来是一件很简单的事情,其实微信支付v3接口并不是很复杂,但是微信团队的管理很混乱,给我们开发者带来了巨大的麻烦. 微信支付v3版接口对接 ...
- 微信支付开发(1) JS API支付V3版(转)
http://www.cnblogs.com/txw1958/p/wxpayv3-jsapi.html 本文介绍微信支付下的jsapi实现流程 前言 微信支付现在分为v2版和v3版,2014年9月10 ...
- 微信支付java版V3验证数据合法性
[TOC] 1. 微信支付java版V3验证数据合法性 概要:使用微信支付接口时,微信会返回或回调给商户XML数据,开发者需要验证微信返回的数据是否合法. 特别提醒:商户系统对于支付结果通知的内容一定 ...
- 到处都是坑的微信支付V3之 微信支付回调页面
据上次 到处都是坑的微信支付V3 后很多园友在被虐了千百遍后终于跳转到了亲切的微信支付界面,但输入密码支付后却不知道怎么处理了,接下来补上支付后的处理流程. 1. html中根据前台支付后反馈信息成功 ...
- 到处都是坑的微信支付V3
业务需要一个在微信上能付款的功能,于是乎想到了最普遍的支付宝,坑爹的是T与A是水火不容啊,默默的还是接微信支付吧,没想到从此掉进了连环坑…… 网上写微信支付接口的还是很多,PHP官方有(鄙视源码作者, ...
- 微信支付v3开发(5) 扫码并输入金额支付
关键字:微信支付 微信支付v3 动态native支付 统一支付 Native支付 prepay_id 作者:方倍工作室 本文介绍微信支付下的扫描二维码并输入自定义金额的支付的开发过程. 注意 微信支付 ...
- 坑爹的微信支付v3,其实没有那么坑
http://www.cnblogs.com/zskbll/p/wxpay.html 研究微信开发一年多了,每个新接口,都会第一时间进行研究.微信支付开放很久,一直没机会接触到支付接口,等了好久终于从 ...
随机推荐
- Windows 下使用 mingw+msys 交叉编译 Android Unity Mono
对于没有升级到 Unity5.4的用户,发布安卓版本都会有对 C# 脚本进行加密的需求,我们项目在裸奔了很长时间后,决定开始做这件事. 网上查看了很多资料,我很希望直接在 windows 下编译而不去 ...
- 洛谷—— P1598 垂直柱状图
P1598 垂直柱状图 题目描述 写一个程序从输入文件中去读取四行大写字母(全都是大写的,每行不超过72个字符),然后用柱状图输出每个字符在输入文件中出现的次数.严格地按照输出样例来安排你的输出格式. ...
- 【BFS】Tester Program
[poj1024]Tester Program Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 2760 Accepted ...
- [CODECHEF]TREECNT2
题意:一棵带边权的树,边权可单边修改,问初始时和每次修改后有多少条路径$\gcd=1$ 首先考虑用反演求答案,设$f(n)$为路径$\gcd=n$的路径条数,$g(n)$为路径$\gcd$是$n$倍数 ...
- canvas之arcTo
arc与arcTo,从名字都能看出来相似.arcTo也是画曲线的方法,而且他画出的曲线也是正圆的一段弧线.但他的参数和arc简直是不共戴天~ ctx.arcTo(x1,y1,x2,y2,radius) ...
- 配置友盟最新SDK遇到的问题
编译报错 Undefined symbols for architecture i386:原因:i386是代表模拟器,显示i386错误说明静态库不支持模拟器,只支持真机.友盟最新SDK可能不支持模拟 ...
- Web API使用记录系列(二)HelpPage优化与WebApiTestClient
继续使用记录的第二节,HelpPage的优化与测试工具WebApiTestClient的使用. 之前没怎么整理博客,都是记录一下笔记,真正好好整理发现没想像的那么简单.不管怎么说还是培养下写博客的习惯 ...
- VirtualBox的网络配置,Host Only+NAT方式
其实网络这类相关的文章很多,我只是想结合自己的实际情况,把我的经验写下来,给那些需要的人们吧. 主机:windows xp 虚拟机:ubuntu 10.10 Virtualbox:4.0.2 虚拟机在 ...
- Toad 常用快捷键
F9 执行全部sql Ctrl_Enter 执行当前sql Ctrl+T 补全table_name ...
- mysql 碎片清理
在MySQL中,我们经常会使用VARCHAR.TEXT.BLOB等可变长度的文本数据类型.不过,当我们使用这些数据类型之后,我们就不得不做一些额外的工作——MySQL数据表碎片整理. 那么,为什么在使 ...