android 集成微信支付(已模拟统一下单)
微信支付和支付宝支付是我们现在覆盖电商爆炸app的一个必备功能,那么微信支付是怎么实现的呢?我们今天理一下步骤。我是在h5调android原生接口,所以android端就实现了一个微信支付接口,但是思路是一致的。我这里模拟统一下单主要是可以走一个完成的支付流程,实际开发中模拟统一下单是你后台人员负责这个接口,后台需要打通订单系统,你只需要调用后台接口返回预支付id,然后在调用支付接口即可。
首先看一下整体支付效果截图
再来说下流程,流程是传入所需要的10大参数,调用统一下单接口,获取到预支付id,然后在调用支付接口,最后微信回调即整过流程完成。
所以先去阅读以下微信app支付开发文档是很有必要的。链接是https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
在查看以下API列表也是很有必要的,链接是https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
一、微信开放平台
创建应用,获取appid,平台上填写签名需要注意一下,必须一致,如果是release的话那么后期测试的时候就release包测试,不过很不方便,所以在测试期间一般直接用debug版本的包,方便测试。
二、微信商户平台
获取得到商户号并在商户平台配置API密钥(生成预支付订单号需要)
三、代码整体目录展示(android项目)
四、代码
1、build.gradle集成:
// 微信支付包
compile 'com.tencent.mm.opensdk:wechat-sdk-android-with-mta:+'
// xml和对象互转
compile group: 'com.thoughtworks.xstream', name: 'xstream', version: '1.3.1'
2、AndroidManifest.xml 加入注册antivity和权限
(1)activity
<!--微信支付注册-->
<activity
android:name=".wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
(2)权限
<uses-permission android:name="android.permission.INTERNET" />
3、JavaScriptUtils类: js调用android入口,也是程序入口处
public static PrepayIdInfo bean = null;
/**
* 微信支付
*/
@JavascriptInterface
public void wxPayClient(String shoppingDesc, String orderNo, int totalMoney) {
// 请求统一下单服务 生成预支付Id
OrederSendInfo sendInfo = new OrederSendInfo(Config.APP_ID,Config.MCH_ID,new WXPayUtils().genNonceStr(),shoppingDesc,orderNo,String.valueOf(totalMoney),"127.0.0.1","http://www.weixin.qq.com/wxpay/pay.php","APP");
NetWorkFactory.UnfiedOrder(sendInfo, new NetWorkFactory.Listerner() {
@Override
public void Success(String data) {
// data是xml,从xml里面获取prepay_id
XStream xStream = new XStream();
xStream.alias("xml", PrepayIdInfo.class);
bean = (PrepayIdInfo) xStream.fromXML(data);
System.out.println(bean.toString());
// 调用微信支付
new WXPayUtils().Pay(bean.getPrepay_id());
}
@Override
public void Faiulre(String data) {
}
});
}
4、OrederSendInfo类
package com.iwiteks.PalmarTourism.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 统一下单信息
* Created by xmg on 2016/12/5.
*/
@XStreamAlias("xml")
public class OrederSendInfo {
// 应用ID appid
// 商户号 mch_id
// 随机字符串 nonce_str 随机数生成算法
// 商品描述 body 鹅豆-旅游
// 商户订单号 out_trade_no 32个字符内
// 总金额 total_fee 单位:分
// 终端IP spbill_create_ip
// 通知地址 notify_url
// 交易类型 trade_type APP
// 签名 sign 签名生成算法
private String appid;
private String mch_id;
private String nonce_str;
private String body;
private String out_trade_no;
private String total_fee;
private String spbill_create_ip;
private String notify_url;
private String trade_type;
private String sign;
public OrederSendInfo(String appid, String mch_id, String nonce_str, String body, String out_trade_no, String total_fee, String spbill_create_ip, String notify_url, String trade_type) {
this.appid = appid;
this.mch_id = mch_id;
this.nonce_str = nonce_str;
this.body = body;
this.out_trade_no = out_trade_no;
this.total_fee = total_fee;
this.spbill_create_ip = spbill_create_ip;
this.notify_url = notify_url;
this.trade_type = trade_type;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getTotal_fee() {
return total_fee;
}
public void setTotal_fee(String total_fee) {
this.total_fee = total_fee;
}
public String getSpbill_create_ip() {
return spbill_create_ip;
}
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
//注意排序规则ASCII排序(一般按照A-Z,a-z)就行
@Override
public String toString() {
return "appid=" + appid + '&' +
"body=" + body + '&' +
"mch_id=" + mch_id + '&' +
"nonce_str=" + nonce_str + '&' +
"notify_url=" + notify_url + '&' +
"out_trade_no=" + out_trade_no + '&' +
"spbill_create_ip=" + spbill_create_ip + '&' +
"total_fee=" + total_fee + '&' +
"trade_type=" + trade_type + '&';
}
}
5、Config类:
package com.iwiteks.PalmarTourism.common;
/**
* 微信配置类
*/
public class Config {
// 嗨黔东南商户号
public static final String MCH_ID = "xxxxx";
// 嗨黔东南API密钥
public static final String API_KEY = "xxxxxxxx";
//微信统一下单接口
public static final String UNIFIED_ORDER ="https://api.mch.weixin.qq.com/pay/unifiedorder";
// 嗨黔东南appId
public static final String APP_ID = "xxxxxx";
//设置估计有问题
public static final String APP_SERECET = "xxxxxx";
}
6、WXPayUtils微信工具类,签名、时间戳、支付方法都封装在里面了
package com.iwiteks.PalmarTourism.util;
import android.widget.Toast;
import com.iwiteks.PalmarTourism.application.MyApp;
import com.iwiteks.PalmarTourism.bean.OrederSendInfo;
import com.iwiteks.PalmarTourism.common.Config;
import com.tencent.mm.opensdk.modelpay.PayReq;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
/**
* 微信支付工具类
* Created by spirits on 2017/7/5.
*/
public class WXPayUtils {
private static IWXAPI iwxapi;
public static IWXAPI getWXAPI(){
if (iwxapi == null){
//通过WXAPIFactory创建IWAPI实例
iwxapi = WXAPIFactory.createWXAPI(MyApp.getContext(), null);
//将应用的appid注册到微信
iwxapi.registerApp(Config.APP_ID);
}
return iwxapi;
}
//生成随机字符串
public static String genNonceStr() {
Random random = new Random();
return MD5.getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
}
//获得时间戳
private static long genTimeStamp() {
return System.currentTimeMillis() / 1000;
}
//生成预支付随机签名
public static String genSign(OrederSendInfo info) {
StringBuffer sb = new StringBuffer(info.toString());
if (Config.API_KEY.equals("")){
Toast.makeText(MyApp.getContext(),"APP_ID为空",Toast.LENGTH_LONG).show();
}
//拼接密钥
sb.append("key=");
sb.append(Config.API_KEY);
String appSign = MD5.getMessageDigest(sb.toString().getBytes());
return appSign;
}
//生成支付随机签名
private static String genAppSign(List<OkHttpUtils.Param> params){
StringBuilder sb = new StringBuilder();
for (int i = 0; i < params.size(); i++) {
sb.append(params.get(i).key);
sb.append('=');
sb.append(params.get(i).value);
sb.append('&');
}
//拼接密钥
sb.append("key=");
sb.append(Config.API_KEY);
String appSign = MD5.getMessageDigest(sb.toString().getBytes());
return appSign.toUpperCase();
}
//生成支付参数
private static void genPayReq(String prepayid, PayReq req) {
req.appId = Config.APP_ID;
req.partnerId = Config.MCH_ID;
req.prepayId = prepayid;
req.packageValue = "Sign=" + prepayid;
req.nonceStr = genNonceStr();
req.timeStamp = String.valueOf(genTimeStamp());
List<OkHttpUtils.Param> signParams = new LinkedList<OkHttpUtils.Param>();
signParams.add(new OkHttpUtils.Param("appid", req.appId));
signParams.add(new OkHttpUtils.Param("noncestr", req.nonceStr));
signParams.add(new OkHttpUtils.Param("package", req.packageValue));
signParams.add(new OkHttpUtils.Param("partnerid", req.partnerId));
signParams.add(new OkHttpUtils.Param("prepayid", req.prepayId));
signParams.add(new OkHttpUtils.Param("timestamp", req.timeStamp));
req.sign = genAppSign(signParams);
}
public static void Pay(String prepayid){
if (judgeCanGo()){
PayReq req = new PayReq();
genPayReq(prepayid,req);
iwxapi.registerApp(Config.APP_ID);
iwxapi.sendReq(req);
}
}
private static boolean judgeCanGo(){
getWXAPI();
if (!iwxapi.isWXAppInstalled()) {
Toast.makeText(MyApp.getContext(), "请先安装微信应用", Toast.LENGTH_SHORT).show();
return false;
} else if (!iwxapi.isWXAppSupportAPI()) {
Toast.makeText(MyApp.getContext(), "请先更新微信应用", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
}
7、NetWorkFactory统一下单类
package com.iwiteks.PalmarTourism.util;
import com.iwiteks.PalmarTourism.bean.OrederSendInfo;
import com.iwiteks.PalmarTourism.common.Config;
import com.thoughtworks.xstream.XStream;
/**
* 微信支付统一下单类
* Created by spirits on 2018/8/8.
*/
public class NetWorkFactory {
public interface Listerner {
void Success(String data);
void Faiulre(String data);
}
/**
* 本地模拟 统一下单 生成微信预支付Id 这一步放在服务器端生成
* @param orederSendInfo
* @param listerner
*/
public static void UnfiedOrder(OrederSendInfo orederSendInfo, final Listerner listerner) {
//生成sign签名
String sign = WXPayUtils.genSign(orederSendInfo);
//生成所需参数,为xml格式
orederSendInfo.setSign(sign.toUpperCase());
XStream xstream = new XStream();
xstream.alias("xml", OrederSendInfo.class);
final String xml = xstream.toXML(orederSendInfo).replaceAll("__","_");
//调起接口,获取预支付ID
OkHttpUtils.ResultCallback<String> resultCallback = new OkHttpUtils.ResultCallback<String>() {
@Override
public void onSuccess(String response) {
String data = response;
data = data.replaceAll("<!\\[CDATA\\[","").replaceAll("]]>","");
listerner.Success(data);
}
@Override
public void onFailure(Exception e) {
listerner.Faiulre(e.toString());
}
};
OkHttpUtils.post(Config.UNIFIED_ORDER, resultCallback, xml);
}
}
8、支付实体类:PrepayIdInfo
package com.iwiteks.PalmarTourism.bean;
import com.thoughtworks.xstream.annotations.XStreamAlias;
/**
* 预支付订单信息
* Created by xmg on 2016/12/6.
*/
@XStreamAlias("xml")
public class PrepayIdInfo {
private String return_code;
private String return_msg;
private String appid;
private String mch_id;
private String nonce_str;
private String sign;
private String result_code;
private String prepay_id;
private String trade_type;
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getPrepay_id() {
return prepay_id;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
@Override
public String toString() {
return "PrepayIdInfo{" +
"return_code='" + return_code + '\'' +
", return_msg='" + return_msg + '\'' +
", appid='" + appid + '\'' +
", mch_id='" + mch_id + '\'' +
", nonce_str='" + nonce_str + '\'' +
", sign='" + sign + '\'' +
", result_code='" + result_code + '\'' +
", prepay_id='" + prepay_id + '\'' +
", trade_type='" + trade_type + '\'' +
'}';
}
}
9、MyApp获取上下文类
package com.iwiteks.PalmarTourism.application;
import android.app.Application;
import android.content.Context;
/**
* 创建于 09/03/2018 19:41
*
* @author xukai
* 类说明:全局Application
* 所属公司:贵州中测
*/
public class MyApp extends Application {
public static Context sContext;//全局的Context对象
public static Context getContext(){
return sContext;
}
@Override
public void onCreate() {
super.onCreate();
sContext = getApplicationContext();
}
}
10、网络请求类OkHttpUtils
package com.iwiteks.PalmarTourism.util;
import android.os.Handler;
import android.os.Looper;
import com.google.gson.Gson;
import com.google.gson.internal.$Gson$Types;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
* By zhaoyi
* Description : OkHttp网络连接封装工具类 解析用的是Gson 记得添加Gson依赖 或者jar包
*/
public class OkHttpUtils {
private static final String TAG = "OkHttpUtils";
private static OkHttpUtils mInstance;
private OkHttpClient mOkHttpClient;
private Handler mDelivery;
private Gson mGson;
private OkHttpUtils() {
mOkHttpClient = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.build();
mGson = new Gson();
mDelivery = new Handler(Looper.getMainLooper());
}
private synchronized static OkHttpUtils getmInstance() {
if (mInstance == null) {
mInstance = new OkHttpUtils();
}
return mInstance;
}
private void getRequest(String url, final ResultCallback callback) {
final Request request = new Request.Builder().url(url).build();
deliveryResult(callback, request);
}
private void postRequest(String url, final ResultCallback callback, List<Param> params) {
Request request = buildPostRequest(url, params);
deliveryResult(callback, request);
}
private void postRequest(String url, final ResultCallback callback,String xml) {
Request request = buildPostRequest(url, xml);
deliveryResult(callback, request);
}
/**
* 处理结果
* @param callback
* @param request
*/
private void deliveryResult(final ResultCallback callback, Request request) {
mOkHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
sendFailCallback(callback, e);
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try {
String str = response.body().string();
if (callback.mType == String.class) {
/**
* 返回字符串
*/
sendSuccessCallBack(callback, str);
} else {
/**
* 这里处理解析返回对象
*/
Object object = mGson.fromJson(str, callback.mType);
sendSuccessCallBack(callback, object);
}
} catch (final Exception e) {
// LogUtils.e(TAG, "convert json failure", e);
sendFailCallback(callback, e);
}
}
});
}
private void sendFailCallback(final ResultCallback callback, final Exception e) {
mDelivery.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onFailure(e);
}
}
});
}
private void sendSuccessCallBack(final ResultCallback callback, final Object obj) {
mDelivery.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onSuccess(obj);
}
}
});
}
private Request buildPostRequest(String url, List<Param> params) {
FormBody.Builder builder= new FormBody.Builder();
for (Param param : params) {
builder.add(param.key, param.value);
}
RequestBody requestBody = builder.build();
return new Request.Builder().url(url).post(requestBody).build();
}
private Request buildPostRequest(String url, String xml) {
MediaType MEDIA_TYPE_TEXT = MediaType.parse("text/xml");
RequestBody requestBody = RequestBody.create(MEDIA_TYPE_TEXT,xml);
return new Request.Builder().url(url).post(requestBody).build();
}
/**********************对外接口************************/
/**
* get请求
* @param url 请求url
* @param callback 请求回调
*/
public static void get(String url, ResultCallback callback) {
getmInstance().getRequest(url, callback);
}
/**
* post请求
* @param url 请求url
* @param callback 请求回调
* @param params 请求参数
*/
public static void post(String url, final ResultCallback callback, List<Param> params) {
getmInstance().postRequest(url, callback, params);
}
public static void post(String url, final ResultCallback callback, String xml) {
getmInstance().postRequest(url, callback, xml);
}
/**
* http请求回调类,回调方法在UI线程中执行
* @param <T>
*/
public static abstract class ResultCallback<T> {
Type mType;
public ResultCallback(){
mType = getSuperclassTypeParameter(getClass());
}
static Type getSuperclassTypeParameter(Class<?> subclass) {
Type superclass = subclass.getGenericSuperclass();
if (superclass instanceof Class) {
throw new RuntimeException("Missing type parameter.");
}
ParameterizedType parameterized = (ParameterizedType) superclass;
return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
}
/**
* 请求成功回调
* @param response
*/
public abstract void onSuccess(T response);
/**
* 请求失败回调
* @param e
*/
public abstract void onFailure(Exception e);
}
/**
* post请求参数类 这里可以根据项目抽取成泛型
*/
public static class Param {
String key;
String value;
public Param() {
}
public Param(String key, String value) {
this.key = key;
this.value = value;
}
}
}
11、MD5加密工具类
package com.iwiteks.PalmarTourism.util;
import java.security.MessageDigest;
public class MD5 {
private MD5() {}
public final static String getMessageDigest(byte[] buffer) {
char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
try {
MessageDigest mdTemp = MessageDigest.getInstance("MD5");
mdTemp.update(buffer);
byte[] md = mdTemp.digest();
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str);
} catch (Exception e) {
return null;
}
}
}
12、WXPayEntryActivity,微信回调类
package com.iwiteks.PalmarTourism.wxapi;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Message;
import com.iwiteks.PalmarTourism.common.Config;
import com.iwiteks.PalmarTourism.util.JavaScriptUtils;
import com.tencent.mm.opensdk.constants.ConstantsAPI;
import com.tencent.mm.opensdk.modelbase.BaseReq;
import com.tencent.mm.opensdk.modelbase.BaseResp;
import com.tencent.mm.opensdk.openapi.IWXAPI;
import com.tencent.mm.opensdk.openapi.IWXAPIEventHandler;
import com.tencent.mm.opensdk.openapi.WXAPIFactory;
/**
* Created by zhaoyi on 2018/8/7.
*/
public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler {
private IWXAPI api;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
api = WXAPIFactory.createWXAPI(this, Config.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 baseReq) {
}
@Override
public void onResp(BaseResp baseResp) {
if (baseResp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
if (baseResp.errCode == 0) {
Toast.makeText(this, "支付成功", Toast.LENGTH_LONG).show();
} else if (baseResp.errCode == -1){
Toast.makeText(this, "支付失败", Toast.LENGTH_LONG).show();
} else if (baseResp.errCode == -2) {
Toast.makeText(this, "取消支付", Toast.LENGTH_LONG).show();
}
finish();
}
}
}
13、h5前端调用实例new_file.html
<!DOCTYPE html>
<input>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<meta charset="UTF-8">
<title>fghdf</title>
<script type="text/javascript">
function wbShare(){
alert('111')
window.android.wbShare("标题","好玩","https://blog.csdn.net/u013144287/article/list/","http://p2pblz7ar.bkt.clouddn.com/152541667562405b9d120-d2d0-4419-9b5a-47c91045a599.jpg")
}
function QQShare() {
alert('222')
window.android.qqShare("11","22","https://blog.csdn.net/u013144287/article/list/","http://p0w4yb0aj.bkt.clouddn.com/background_my.jpg",0)
}
function _Native_qqShare(result) {
alert(result)
}
function _Native_weiboShare(result) {
alert(result)
}
function getLanguage() {
alert(111)
alert(window.android.getLanguage())
}
function speechSynthesizerVoice() {
alert(111)
window.android.speechSynthesizerVoice('我是小嗨,科大讯飞,让世界聆听您的声音')
}
function _Native_speechComplete(result) {
alert(result)
}
function openPage(){
window.android.openPage('http://cs.114utrip.com/trainsearch/toTrain.shtml')
}
function position() {
alert('111')
window.android.getPositioning()
}
function _Native_location(result) {
alert(result)
}
function setLightStatusBar() {
alert('222')
window.android.setWStatusBarColor("black")
}
function wbLogin() {
alert('111')
window.android.wbLogin()
}
function _Native_weiboLogin(result) {
alert(JSON.stringify(result))
}
function wbShare() {
alert('222')
window.android.wbShare('标题','文本','https://blog.csdn.net/u013144287/article/list/','https://avatar.csdn.net/3/1/D/3_u013144287.jpg')
}
function _Native_weiboShare(result) {
alert(result)
}
function wxPayClient() {
alert('微信支付客户端签名')
window.android.wxPayClient("未来生鲜视觉体验", "1415659990", 888)
}
function _Native_weixinPay(result) {
alert("支付结果" + result)
}
</script>
</head>
<body>
<br>
<br>
<br>
<button onclick="QQShare()">
QQ分享
</button>
<button onclick="wbShare()">
微博分享
</button>
<button onclick="getLanguage()">
系统设置语言
</button>
<button onclick="speechSynthesizerVoice()">
文字转语音
</button>
<button onclick="openPage()">
打开新页面
</button>
<button onclick="position()">
定位
</button>
<button onclick="setLightStatusBar()">
设置黑色
</button>
<button onclick="wbLogin()">
微博登录
</button>
<button onclick="wbShare()">
微博分享
</button>
<button onclick="wxPayClient()">微信支付</button>
</body>
</html>
需要注意的就是统一下单和支付接口调用的时候签名,和怎么发起请求支付接口的,类里面方法已经写得差不多了,注重思路,场景可能不太一样。但是走完了一个完整的流程。