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 研究微信开发一年多了,每个新接口,都会第一时间进行研究.微信支付开放很久,一直没机会接触到支付接口,等了好久终于从 ...
随机推荐
- linux 下 php 扩展
首先查看,php 原来安装的配置 /www/server/php/72/bin/php -i | grep configure (php 位置) 加上你的扩展 '--with-mcrypt' make ...
- Git的入门级玩法
作为一个还没有实际开发经验的程序员,对于版本控制多少有些陌生,我通常的做法就是项目名后面加数字标记版本,然后备注一个文档说明更新.据个人了解svn用的比较多,我也学习了一点,无非是本地下载一个服务器端 ...
- POJ 2960 S-Nim 博弈论 sg函数
http://poj.org/problem?id=2960 sg函数几乎是模板题. 调试代码的最大障碍仍然是手残在循环里打错变量名,是时候换个hydra产的机械臂了[超想要.jpg] #includ ...
- BZOJ 3790 神奇项链(manacher+DP+树状数组)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3790 [题目大意] 问最少用几个回文串可以构成给出串,重叠部分可以合并 [题解] 我们 ...
- 【数论】【二次剩余】【map】hdu6128 Inverse of sum
部分引用自:http://blog.csdn.net/v5zsq/article/details/77255048 所以假设方程 x^2+x+1=0 在模p意义下的解为d,则答案就是满足(ai/aj) ...
- 【带权并查集】poj1182 食物链
带权并查集,或者叫做种类并查集,经典题. http://blog.csdn.net/shuangde800/article/details/7974668 这份代码感觉是坠吼的. 我的代码是暴力分类讨 ...
- 【FFT卷积】BZOJ3527-力
[题目大意] [思路] 很好这很FFT…… 想了半天也没明白到底什么是卷积∑的上下界,我当初学的时候没说一定要从0开始啊quq 我还是背不出FFT的模板我要狗带了 我上面写的什么乱七八糟的,要什么数学 ...
- 【OpenJudge9275】【Usaco2009 Feb】【递推】Bullcow
Bullcow 总时间限制: 12000ms 单个测试点时间限制: 1000ms 内存限制: 131072kB [描述] 一年一度的展会要来临了,农民约翰想要把N(1 <= N <= 10 ...
- Word中插入英文格式的算法流程
如图上部分所示,需要序号自动编号,那么插入一个一行一列的的表格,然后点击编号,使得项目自动编号,编号一个就在后面输入一些内容,按enter后第二行开始自动编号,如果要缩进,不能按Tab,Tab自动创建 ...
- VHD命令
一.命令解说1.diskpart作用:运行分区管理2.Create vdisk file=D:\dpx\win7.Vhd type=fixed maximum=15000作用:在D盘的dpx文件夹里创 ...