安卓 集成微信支付和支付宝
最近比较闲,公司项目更换后台,于是自己来研究微信支付和支付宝支付,把自己学习的过程写下来,以备以后查看。
注:要集成微信支付和支付宝功能,必须要有以下几个配置信息,而这写信息需要公司去微信支付和支付宝开放平台申请并提供给开发者,当然自己也可以去申请,这里作者用的是公司提供的,这里不纠结这些过程。获得这些信息以后
将配置信息放到一个静态类中,以共统一使用,但是处于安全考虑,微信与支付宝推荐这些数据放到服务器,这里作者把他们都放在前端,整个过程都是前端处理,实际开发尽量预处理订单生成放到后端处理。
- public class ParameterConfig {
- public static final String GANHOST = "http://101.226.197.11"; //服务器地址ip(根据自己替换)
- /**
- * 微信
- */
- <span style="white-space:pre"> </span> //appid
- public static final String WX_APP_ID = "";// 自己填写自己项目的
- // 商户号
- public static final String WX_MCH_ID = "";// 自己填写自己项目的
- // API**,在商户平台设置
- public static final String WX_API_KEY = "";// 自己填写自己项目的
- //服务器回调接口
- public static final String WX_notifyUrl = GANHOST+"/service/orderComplete";// 用于微信支付成功的回调(按自己需求填写)
- /**
- * 支付宝
- */
- // 商户PID
- public static final String PARTNER = "";//自己填写自己项目的
- // 商户收款账号
- public static final String SELLER = "";//自己填写自己项目的
- // 商户私钥,pkcs8格式
- public static final String RSA_PRIVATE = "";//自己填写自己项目的
- public static final String aliPay_notifyURL = GANHOST+"/service/alipay/orderComplete";//支付宝支付成功的回调
- }
1.首先需要导入微信jar包,从开放平台可以下载到,加入到libs目录即可
2.配置manifest
a.用户权限
<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"/>
b.activity配置,这里com.gan.mypay改成自己的包名(如果自己包名与src下的package 名不一样,这里要的是在manifest中配置的名称,同样需要在src建立以自己包名为路劲的package,一定确保有这个activity)这个activity是微信支付结果要回调的activty
<!-- 微信支付 -->
<activity
android:name="com.gan.mypay.wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
<!-- 微信支付 -->
<activity
android:name="com.gan.mypay.wxapi.WXPayEntryActivity"
android:exported="true"
android:launchMode="singleTop"/>
<!-- 微信支付 -->
2.支付宝支付的集成前提条件
1.首先需要导入微信jar包,从开放平台可以下载到,加入到libs目录即可
2.配置manifest
a.用户权限
<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"/>
b.activity配置这里必须要这么配置
<!-- 支付宝 -->
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
</activity>
<activity
android:name="com.alipay.sdk.auth.AuthActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
</activity>
<!-- 支付宝 -->
<activity
android:name="com.alipay.sdk.app.H5PayActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
</activity>
<activity
android:name="com.alipay.sdk.auth.AuthActivity"
android:configChanges="orientation|keyboardHidden|navigation"
android:exported="false"
android:screenOrientation="behind" >
</activity>
<!-- 支付宝 -->
3.代码集成
1.首先要有个商品页面MainActivity,用来手机收集商品信息,这里需要后台交互生成订单,我偷懒就直接在页面生成了假订单
MainActivity.java(这里用了xutils的注入)
- @ContentView(R.layout.activity_main)
- public class MainActivity extends Activity {
- private Goods goods;
- private String username;
- private String mobile;
- private String adress;
- private int count;
- @ViewInject(R.id.product_ordsubmit_username)
- private TextView usernameTV;
- @ViewInject(R.id.product_ordsubmit_phone)
- private TextView phoneTV;
- @ViewInject(R.id.product_ordsubmit_adress)
- private TextView adressTV;
- @ViewInject(R.id.product_ordsubmit_desc)
- private TextView descTV;
- @ViewInject(R.id.product_ordsubmit_price)
- private TextView priceTV;
- @ViewInject(R.id.product_ordsubmit_intg)
- private TextView intgTV;
- @ViewInject(R.id.product_ordsubmit_count1)
- private TextView countTV1;
- @ViewInject(R.id.product_ordsubmit_count)
- private TextView countTV;
- @ViewInject(R.id.product_ordsubmit_intgtotal1)
- private TextView intgtotal1TV;
- @ViewInject(R.id.product_ordsubmit_intgtotal2)
- private TextView intgtotal2TV;
- @ViewInject(R.id.product_ordsubmit_pricetotal1)
- private TextView pricetotal1TV;
- @ViewInject(R.id.product_ordsubmit_pricetotal2)
- private TextView pricetotal2TV;
- @ViewInject(R.id.product_ordsubmit_counttotal)
- private TextView counttotalTV;
- @ViewInject(R.id.product_ordsubmit_ok)
- private Button okBtn;
- @ViewInject(R.id.product_ordsubmit_say_et)
- private TextView sayEt;
- @ViewInject(R.id.product_ordsubmit_img)
- private ImageView img;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ViewUtils.inject(this);
- goods = new Goods();
- goods.costprice=100;
- goods.productid=692356222;
- goods.producttypeid=11;
- goods.productname="测试商品";
- goods.discountprice=0.01;
- goods.productdescription="商品描述";
- goods.companydesc="测试商户简单描述";
- goods.comanyadress="商户地址未知";
- goods.companyname="测试商户";
- goods.score=1;
- goods.status=1;
- goods.stock=300;
- count=1;
- initData();
- initView();
- }
- private void initData() {
- username ="客户名称";
- mobile = "13800380038";
- adress="客户地址";
- }
- private void initView() {
- usernameTV.setText("收货人:"+username);
- phoneTV.setText(mobile+"");
- adressTV.setText(adress);
- descTV.setText(goods.productdescription);
- priceTV.setText("¥"+goods.discountprice);
- intgTV.setText("积分:"+goods.score);
- countTV1.setText("X"+count);
- countTV.setText(count+"");
- intgtotal1TV.setText("共得到"+count*goods.score+"积分");
- intgtotal2TV.setText("积分:"+count*goods.score);
- counttotalTV.setText("共"+count+"件");
- pricetotal1TV.setText("¥"+Arith.mul(goods.discountprice, count));
- pricetotal2TV.setText("¥"+Arith.mul(goods.discountprice, count));
- //ImageLoader.getInstance().displayImage(goods.pic1, img);
- }
- /**
- * 增加数量
- * @param v
- */
- @OnClick(R.id.product_ordsubmit_count_add)
- public void add(View v) {
- count++;
- countTV1.setText("X"+count);
- countTV.setText(count+"");
- intgtotal1TV.setText("共得到"+count*goods.score+"积分");
- intgtotal2TV.setText("积分:"+count*goods.score);
- counttotalTV.setText("共"+count+"件");
- pricetotal1TV.setText("¥"+Arith.mul(goods.discountprice, count));
- pricetotal2TV.setText("¥"+Arith.mul(goods.discountprice, count));
- }
- /**
- * 减少数量
- * @param v
- */
- @OnClick(R.id.product_ordsubmit_count_sub)
- public void sub(View v) {
- if (count>1) {
- count--;
- countTV1.setText("X"+count);
- countTV.setText(count+"");
- intgtotal1TV.setText("共得到"+count*goods.score+"积分");
- intgtotal2TV.setText("积分:"+count*goods.score);
- counttotalTV.setText("共"+count+"件");
- pricetotal1TV.setText("¥"+Arith.mul(goods.discountprice, count));
- pricetotal2TV.setText("¥"+Arith.mul(goods.discountprice, count));
- }
- }
- /**
- * 提交订单
- * @param v
- */
- @OnClick(R.id.product_ordsubmit_ok)
- public void submit(View v) {
- final OrderInfo orderInfo=new OrderInfo();
- orderInfo.userid=13752;
- orderInfo.areacode=23;
- orderInfo.buildno="10";
- orderInfo.roomno="1001";
- orderInfo.producttypeid=goods.producttypeid;
- orderInfo.productid=goods.productid;
- orderInfo.amount=goods.discountprice;//单价
- orderInfo.account=count;//数量
- orderInfo.totalamount=Arith.mul(goods.discountprice, count);
- //double offsetamount;//抵扣金额
- orderInfo.score=count*goods.score;
- //int assessitem;//评价项
- //int assesslevel;//评价级别
- //String assesscontent;//评价内容
- //long payid=;//支付编号
- orderInfo.status=2;//支付状态待付款
- orderInfo.type=11;//日用品
- orderInfo.usermemo =sayEt.getText().toString();//业主备注
- orderInfo.address =adress;
- orderInfo.productname =goods.productname;//
- orderInfo.desccontext =goods.productdescription;//
- orderInfo.outtradeno=System.currentTimeMillis()+""+orderInfo.userid;
- orderInfo.merchantid=goods.companyid;
- submitorder(orderInfo);
- }
- /**
- * 订单提交成功,进入付款界面
- * @param orderInfo
- * @return
- */
- private void submitorder(OrderInfo orderInfo) {
- Intent intent=new Intent(this, SelectPayTypeActivity.class);
- intent.putExtra("data", orderInfo);
- startActivity(intent);
- }
- }
- <span style="white-space:pre"> </span>activty_main.xml
- <pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <ScrollView
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:background="@color/igray"
- android:layout_weight="1"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="15dp"
- android:paddingRight="15dp"
- android:paddingTop="10dp"
- android:paddingBottom="10dp"
- android:orientation="vertical"
- android:background="@color/white"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- >
- <TextView
- android:id="@+id/product_ordsubmit_username"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:textSize="14sp"
- android:gravity="center_vertical"
- android:textColor="@color/black"
- android:text="收货人:"
- />
- <TextView
- android:id="@+id/product_ordsubmit_phone"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:textSize="14sp"
- android:gravity="center_vertical|right"
- android:textColor="@color/igray_et"
- android:text="13862325641"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- >
- <TextView android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="14sp"
- android:gravity="center_vertical"
- android:textColor="@color/igray_et"
- android:text="收货地址:"
- />
- <TextView
- android:id="@+id/product_ordsubmit_adress"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:textSize="14sp"
- android:textColor="@color/igray_et"
- android:drawableRight="@drawable/next"
- android:text="上海市徐汇区浦北路中星城15号"
- />
- </LinearLayout>
- </LinearLayout>
- <View android:layout_width="match_parent"
- android:layout_height="5dp"
- android:background="@color/igray"/>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:background="@color/white"
- android:paddingLeft="15dp"
- android:paddingRight="15dp"
- android:orientation="vertical"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- >
- <ImageView
- android:id="@+id/product_ordsubmit_img"
- android:layout_width="100dp"
- android:layout_height="100dp"
- android:scaleType="centerCrop"
- android:src="@drawable/user_head" />
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- >
- <TextView
- android:id="@+id/product_ordsubmit_desc"
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1"
- android:textSize="14sp"
- android:text="商品描述"
- android:layout_margin="10dp"
- android:textColor="@color/black"/>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- >
- <TextView
- android:id="@+id/product_ordsubmit_price"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="¥49"
- android:textSize="18sp"
- android:textColor="@color/Orange"
- android:layout_margin="5dp"
- />
- <TextView
- android:id="@+id/product_ordsubmit_intg"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="积分:2"
- android:textSize="14sp"
- android:layout_margin="5dp"
- android:textColor="@color/igray_et"
- />
- <View android:layout_width="0dp"
- android:layout_height="0dp"
- android:layout_weight="1"/>
- <TextView
- android:id="@+id/product_ordsubmit_count1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="X2"
- android:textSize="14sp"
- android:layout_margin="5dp"
- android:textColor="@color/igray_et"
- />
- </LinearLayout>
- </LinearLayout>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="5dp"
- android:gravity="center_vertical"
- android:paddingBottom="5dp"
- >
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="购买数量"
- android:textColor="@color/black"
- android:textSize="14sp"
- />
- <View android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
- <ImageView
- android:id="@+id/product_ordsubmit_count_sub"
- android:layout_width="25dp"
- android:layout_height="25dp"
- android:src="@drawable/sub_orange"/>
- <TextView
- android:id="@+id/product_ordsubmit_count"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="3"
- android:textColor="@color/black"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:textSize="18sp"
- />
- <ImageView
- android:id="@+id/product_ordsubmit_count_add"
- android:layout_width="25dp"
- android:layout_height="25dp"
- android:src="@drawable/add_orange"/>
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="5dp"
- android:focusableInTouchMode="true"
- android:gravity="center_vertical"
- android:paddingBottom="5dp"
- >
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="业主留言:"
- android:textColor="@color/black"
- android:textSize="14sp"
- />
- <EditText
- android:id="@+id/product_ordsubmit_say_et"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:hint="选填,可以填你对卖家一致达成的要求"
- android:textColor="@color/igray_et"
- android:layout_marginLeft="10dp"
- android:singleLine="true"
- android:layout_marginRight="10dp"
- android:textSize="14sp"
- />
- </LinearLayout>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingTop="5dp"
- android:gravity="center_vertical"
- android:paddingBottom="5dp"
- >
- <TextView
- android:id="@+id/product_ordsubmit_intgtotal1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="共得到6积分"
- android:textColor="@color/igray_et"
- android:textSize="14sp"
- />
- <View android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
- <TextView
- android:id="@+id/product_ordsubmit_counttotal"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="14sp"
- android:textColor="@color/black"
- android:text="共3件"/>
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="合计:"
- android:textColor="@color/black"
- android:layout_marginLeft="10dp"
- android:textSize="14sp"
- />
- <TextView
- android:id="@+id/product_ordsubmit_pricetotal1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="18sp"
- android:textColor="@color/Orange"
- android:text="¥127"/>
- </LinearLayout>
- </LinearLayout>
- </LinearLayout>
- </ScrollView>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="44dp"
- android:paddingLeft="15dp"
- android:paddingRight="15dp"
- android:paddingTop="5dp"
- android:paddingBottom="5dp"
- android:gravity="right|center_vertical"
- android:background="@color/white">
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="合计:"
- android:textColor="@color/black"
- android:textSize="14sp"
- />
- <TextView
- android:id="@+id/product_ordsubmit_pricetotal2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="14sp"
- android:textColor="@color/Orange"
- android:text="¥127"/>
- <TextView
- android:id="@+id/product_ordsubmit_intgtotal2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="积分:6"
- android:textColor="@color/igray_et"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:textSize="12sp"
- />
- <Button
- android:id="@+id/product_ordsubmit_ok"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@drawable/shape_btn_oval_orange_bg2"
- android:text="确认"/>
- </LinearLayout>
- </LinearLayout>
2.在mainactivty中点击确认按钮调用支付方式选择页面SelectPayTypeActivity,用来发起支付选择
- SelectPayTypeActivity.java
- <pre name="code" class="java">@ContentView(R.layout.activity_select_pay_type)
- public class SelectPayTypeActivity extends Activity {
- @ViewInject(R.id.paytype_of_weixin_ck)
- private CheckBox weixinCK;
- @ViewInject(R.id.paytype_of_zhifubao_ck)
- private CheckBox zhifubaoCK;
- @ViewInject(R.id.last_pay_count_tv)
- private TextView payCountTv;
- private OrderInfo orderInfo;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- ViewUtils.inject(this);
- initData();
- initView();
- }
- private void initView() {
- payCountTv.setText("¥"+orderInfo.totalamount);
- }
- private void initData() {
- orderInfo=(OrderInfo) getIntent().getSerializableExtra("data");
- }
- @Override
- protected void onNewIntent(Intent intent) {
- super.onNewIntent(intent);
- int code=intent.getIntExtra("result", 1);
- switch (code) {
- case 0://表示成功
- finish();
- break;
- case -1://表示失败
- finish();
- break;
- case -2:////表示取消
- finish();
- break;
- case 1://未知不做处理
- break;
- default:
- break;
- }
- }
- @OnClick(R.id.paytype_of_weixin)
- public void wx(View v) {
- if (zhifubaoCK.isChecked()) {
- zhifubaoCK.setChecked(false);
- }
- if (!weixinCK.isChecked()) {
- weixinCK.setChecked(true);
- }
- }
- @OnClick(R.id.paytype_of_zhifubao)
- public void zfb(View v) {
- if (weixinCK.isChecked()) {
- weixinCK.setChecked(false);
- }
- if (!zhifubaoCK.isChecked()) {
- zhifubaoCK.setChecked(true);
- }
- }
- @OnClick(R.id.paytype_of_weixin_ck)
- public void wxck(View v) {
- if (zhifubaoCK.isChecked()) {
- zhifubaoCK.setChecked(false);
- }
- if (!weixinCK.isChecked()) {
- weixinCK.setChecked(true);
- }
- }
- @OnClick(R.id.paytype_of_zhifubao_ck)
- public void zfbck(View v) {
- if (weixinCK.isChecked()) {
- weixinCK.setChecked(false);
- }
- if (!zhifubaoCK.isChecked()) {
- zhifubaoCK.setChecked(true);
- }
- }
- @OnClick(R.id.btn_pay_submit)
- public void paysubmit(View v) {
- if (weixinCK.isChecked()) {
- if (!isWeixinAvilible(this)) {
- Toast.makeText(this, "请先安装微信或者选择其他支付方式",0).show();
- return;
- }
- //微信支付
- payByWX(handler,orderInfo);
- }else{
- if (!isZfbAvilible(this)) {
- Toast.makeText(this, "请先安支付宝或者选择其他支付方式",0).show();
- return;
- }
- //支付宝支付
- payByzfb(handler,orderInfo);
- }
- }
- Handler handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case 9000://支付宝支付成功
- Intent it;
- finish();
- break;
- case 8000://支付宝支付失败
- finish();
- break;
- default:
- break;
- }
- }
- };
- /**
- * 调用支付宝支付
- * @param handler
- * @param order
- */
- private void payByzfb(Handler handler, OrderInfo order) {
- AlipayUtil alipay=new AlipayUtil(this,order,handler);
- }
- /**
- * 调用微信支付
- * @param handler
- * @param orderInfo2
- */
- private void payByWX(Handler handler, OrderInfo order) {
- WXpayUtil wxpay=new WXpayUtil(this,order);
- }
- /**
- * 检查微信是否存在
- * @param context
- * @return
- */
- public boolean isWeixinAvilible(Context context) {
- PackageManager packageManager = context.getPackageManager();// 获取packagemanager
- List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);// 获取所有已安装程序的包信息
- if (pinfo != null) {
- for (int i = 0; i < pinfo.size(); i++) {
- String pn = pinfo.get(i).packageName;
- System.out.println(pinfo.get(i).packageName);
- if (pn.equals("com.tencent.mm")) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * 检查支付包是否存在
- * @param context
- * @return
- */
- private boolean isZfbAvilible(Context context) {
- PackageManager packageManager = context.getPackageManager();// 获取packagemanager
- List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);// 获取所有已安装程序的包信息
- if (pinfo != null) {
- for (int i = 0; i < pinfo.size(); i++) {
- String pn = pinfo.get(i).packageName;
- System.out.println(pinfo.get(i).packageName);
- if (pn.equals("com.alipay.android.app")) {
- return true;
- }
- }
- }
- return false;
- }
- }
- <pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@color/white"
- android:orientation="vertical" >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="10dp"
- android:gravity="center_vertical"
- >
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:textSize="18sp"
- android:textColor="@color/black"
- android:text="需支付:"/>
- <TextView
- android:id="@+id/last_pay_count_tv"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:textSize="22sp"
- android:textColor="@color/Orange"
- android:text="¥152"/>
- </LinearLayout>
- <View android:layout_width="match_parent"
- android:layout_height="5dp"
- android:background="@color/igray"/>
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:paddingLeft="10dp"
- android:paddingRight="10dp"
- android:paddingBottom="10dp"
- >
- <LinearLayout
- android:id="@+id/paytype_of_weixin"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="10dp"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- >
- <ImageView android:layout_width="44dp"
- android:layout_height="44dp"
- android:src="@drawable/icon64_wx"/>
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="微信支付"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:textSize="20sp"
- />
- <View android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
- <CheckBox
- android:id="@+id/paytype_of_weixin_ck"
- android:layout_width="wrap_content"
- android:checked="true"
- android:layout_height="wrap_content"
- android:focusable="false"
- />
- </LinearLayout>
- <View
- android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="@color/igray"/>
- <LinearLayout
- android:id="@+id/paytype_of_zhifubao"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:padding="10dp"
- android:orientation="horizontal"
- android:gravity="center_vertical"
- >
- <ImageView android:layout_width="44dp"
- android:layout_height="44dp"
- android:src="@drawable/zfb_icon_120"/>
- <TextView android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="支付宝"
- android:layout_marginLeft="10dp"
- android:layout_marginRight="10dp"
- android:textSize="20sp"
- />
- <View android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
- <CheckBox
- android:id="@+id/paytype_of_zhifubao_ck"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="false"
- />
- </LinearLayout>
- <View android:layout_width="match_parent"
- android:layout_height="1dp"
- android:background="@color/igray"/>
- <RelativeLayout android:layout_width="match_parent"
- android:layout_height="match_parent"
- >
- <Button
- android:id="@+id/btn_pay_submit"
- android:layout_width="match_parent"
- android:layout_height="40dp"
- android:text="支付"
- android:textColor="@color/white"
- android:layout_marginBottom="10dp"
- android:layout_marginLeft="40dp"
- android:layout_marginRight="40dp"
- android:layout_alignParentBottom="true"
- android:background="@drawable/shape_btn_oval_orange_bg2"
- />
- </RelativeLayout>
- </LinearLayout>
- </LinearLayout>
3.根据支付方式调用对应工具类微信(WXpayUtil),支付宝(AlipayUtil)
WXpayUtil.java- public class WXpayUtil {
- private IWXAPI api;
- private OrderInfo order;
- private Context context;
- private PayReq req;
- private Map<String,String> resultunifiedorder;
- private static final String TAG = "ewuye.online.SelectPayTypeActivity";
- public WXpayUtil(Context mcontext,OrderInfo order){
- //初始化微信支付
- this.order=order;
- this.context=mcontext;
- if (TextUtils.isEmpty(ParameterConfig.WX_APP_ID) || TextUtils.isEmpty(ParameterConfig.WX_MCH_ID) || TextUtils.isEmpty(ParameterConfig.WX_API_KEY)) {
- new AlertDialog.Builder(context).setTitle("警告").setMessage("需要配置WX_APP_ID | WX_MCH_ID| WX_API_KEY\n请到ParameterConfig.java里配置")
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialoginterface, int i) {
- //
- ((Activity)context).finish();
- }
- }).show();
- return;
- }
- api = WXAPIFactory.createWXAPI(context, null);
- req = new PayReq();
- //生成prepay_id
- GetPrepayIdTask getPrepayId = new GetPrepayIdTask();
- getPrepayId.execute();
- }
- /**
- * 用于获取
- * @author 95
- *
- */
- private class GetPrepayIdTask extends AsyncTask<Void, Void, Map<String,String>> {
- private ProgressDialog dialog;
- @Override
- protected void onPreExecute() {
- dialog = ProgressDialog.show(context, "提示", "正在获取预支付订单...");
- }
- @Override
- protected void onPostExecute(Map<String,String> result) {
- if (dialog != null) {
- dialog.dismiss();
- }
- resultunifiedorder=result;
- genPayReq();
- }
- @Override
- protected void onCancelled() {
- super.onCancelled();
- }
- @Override
- protected Map<String,String> doInBackground(Void... params) {
- String url = String.format("https://api.mch.weixin.qq.com/pay/unifiedorder");
- String entity = genProductArgs();
- Log.e("orion",entity);
- byte[] buf = httpPost(url, entity);
- String content = new String(buf);
- Log.e("orion", content);
- Map<String,String> xml=decodeXml(content);
- return xml;
- }
- }
- private void genPayReq() {
- req.appId = ParameterConfig.WX_APP_ID;
- req.partnerId = ParameterConfig.WX_MCH_ID;
- req.prepayId = resultunifiedorder.get("prepay_id");
- req.packageValue = "prepay_id="+resultunifiedorder.get("prepay_id");
- 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);
- Log.e("orion", signParams.toString());
- sendPayReq();
- }
- private void sendPayReq() {
- api.registerApp(ParameterConfig.WX_APP_ID);
- api.sendReq(req);
- }
- private String genProductArgs() {
- StringBuffer xml = new StringBuffer();
- try {
- String nonceStr = genNonceStr();
- xml.append("</xml>");
- List<NameValuePair> packageParams = new LinkedList<NameValuePair>();
- packageParams.add(new BasicNameValuePair("appid", ParameterConfig.WX_APP_ID));
- packageParams.add(new BasicNameValuePair("body", order.productname));
- packageParams.add(new BasicNameValuePair("mch_id", ParameterConfig.WX_MCH_ID));
- packageParams.add(new BasicNameValuePair("nonce_str", nonceStr));
- packageParams.add(new BasicNameValuePair("notify_url", ParameterConfig.WX_notifyUrl));
- packageParams.add(new BasicNameValuePair("out_trade_no",genOutTradNo()));
- packageParams.add(new BasicNameValuePair("spbill_create_ip","127.0.0.1"));
- packageParams.add(new BasicNameValuePair("total_fee", (int)(order.totalamount*100)+""));
- packageParams.add(new BasicNameValuePair("trade_type", "APP"));
- String sign = genPackageSign(packageParams);
- packageParams.add(new BasicNameValuePair("sign", sign));
- String xmlstring =toXml(packageParams);
- return new String(xmlstring.toString().getBytes(), "ISO8859-1");
- //return xmlstring;
- } catch (Exception e) {
- Log.e(TAG, "genProductArgs fail, ex = " + e.getMessage());
- return null;
- }
- }
- 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(ParameterConfig.WX_API_KEY);
- String appSign = getMessageDigest(sb.toString().getBytes());
- Log.e("orion",appSign);
- return appSign;
- }
- private HttpClient getNewHttpClient() {
- try {
- KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
- trustStore.load(null, null);
- SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
- sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
- HttpParams params = new BasicHttpParams();
- HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
- HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);
- SchemeRegistry registry = new SchemeRegistry();
- registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
- registry.register(new Scheme("https", sf, 443));
- ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);
- return new DefaultHttpClient(ccm, params);
- } catch (Exception e) {
- return new DefaultHttpClient();
- }
- }
- private class SSLSocketFactoryEx extends SSLSocketFactory {
- SSLContext sslContext = SSLContext.getInstance("TLS");
- public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
- super(truststore);
- TrustManager tm = new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
- @Override
- public void checkClientTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
- }
- @Override
- public void checkServerTrusted(X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {
- }
- };
- sslContext.init(null, new TrustManager[] { tm }, null);
- }
- @Override
- public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
- return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
- }
- @Override
- public Socket createSocket() throws IOException {
- return sslContext.getSocketFactory().createSocket();
- }
- }
- public byte[] httpPost(String url, String entity) {
- if (url == null || url.length() == 0) {
- Log.e(TAG, "httpPost, url is null");
- return null;
- }
- HttpClient httpClient = getNewHttpClient();
- HttpPost httpPost = new HttpPost(url);
- try {
- httpPost.setEntity(new StringEntity(entity));
- httpPost.setHeader("Accept", "application/json");
- httpPost.setHeader("Content-type", "application/json");
- HttpResponse resp = httpClient.execute(httpPost);
- if (resp.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
- Log.e(TAG, "httpGet fail, status code = " + resp.getStatusLine().getStatusCode());
- return null;
- }
- return EntityUtils.toByteArray(resp.getEntity());
- } catch (Exception e) {
- Log.e(TAG, "httpPost exception, e = " + e.getMessage());
- e.printStackTrace();
- return null;
- }
- }
- private String genOutTradNo() {
- Random random = new Random();
- return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
- }
- public Map<String,String> decodeXml(String content) {
- try {
- Map<String, String> xml = new HashMap<String, String>();
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(new StringReader(content));
- int event = parser.getEventType();
- while (event != XmlPullParser.END_DOCUMENT) {
- String nodeName=parser.getName();
- switch (event) {
- case XmlPullParser.START_DOCUMENT:
- break;
- case XmlPullParser.START_TAG:
- if("xml".equals(nodeName)==false){
- //实例化student对象
- xml.put(nodeName,parser.nextText());
- }
- break;
- case XmlPullParser.END_TAG:
- break;
- }
- event = parser.next();
- }
- return xml;
- } catch (Exception e) {
- Log.e("orion",e.toString());
- }
- return null;
- }
- private String genNonceStr() {
- Random random = new Random();
- return getMessageDigest(String.valueOf(random.nextInt(10000)).getBytes());
- }
- private long genTimeStamp() {
- return System.currentTimeMillis() / 1000;
- }
- public 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;
- }
- }
- /**
- 生成签名
- */
- private String genPackageSign(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(ParameterConfig.WX_API_KEY);
- String packageSign = getMessageDigest(sb.toString().getBytes()).toUpperCase();
- Log.e("orion",packageSign);
- return packageSign;
- }
- private String toXml(List<NameValuePair> params) {
- StringBuilder sb = new StringBuilder();
- sb.append("<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>");
- Log.e("orion",sb.toString());
- return sb.toString();
- }
- }
- public class AlipayUtil {
- private Activity context;
- private OrderInfo order;
- private Handler mhandler;
- private static final int SDK_PAY_FLAG = 1;
- public AlipayUtil(Activity context, OrderInfo order,Handler mhandler) {
- this.context=context;
- this.order=order;
- this.mhandler=mhandler;
- pay();
- }
- private void pay() {
- //判断是否注册商户到支付宝
- if (TextUtils.isEmpty(ParameterConfig.PARTNER) || TextUtils.isEmpty(ParameterConfig.RSA_PRIVATE) || TextUtils.isEmpty(ParameterConfig.SELLER)) {
- new AlertDialog.Builder(context).setTitle("警告").setMessage("需要配置PARTNER | RSA_PRIVATE| SELLER\n请到ParameterConfig.java里配置")
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialoginterface, int i) {
- //
- ((Activity)context).finish();
- }
- }).show();
- return;
- }
- String orderInfo = getOrderInfo(order);
- /**
- * 特别注意,这里的签名逻辑需要放在服务端,切勿将私钥泄露在代码中!
- */
- String sign = sign(orderInfo);
- try {
- /**
- * 仅需对sign 做URL编码
- */
- sign = URLEncoder.encode(sign, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- /**
- * 完整的符合支付宝参数规范的订单信息
- */
- final String payInfo = orderInfo + "&sign=\"" + sign + "\"&" + getSignType();
- Runnable payRunnable = new Runnable() {
- @Override
- public void run() {
- // 构造PayTask 对象
- PayTask alipay = new PayTask(context);
- // 调用支付接口,获取支付结果
- String result = alipay.pay(payInfo, true);
- Message msg = new Message();
- msg.what = SDK_PAY_FLAG;
- msg.obj = result;
- mHandler.sendMessage(msg);
- }
- };
- // 必须异步调用
- Thread payThread = new Thread(payRunnable);
- payThread.start();
- }
- @SuppressLint("HandlerLeak")
- private Handler mHandler = new Handler() {
- @SuppressWarnings("unused")
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case SDK_PAY_FLAG: {
- PayResult payResult = new PayResult((String) msg.obj);
- /**
- * 同步返回的结果必须放置到服务端进行验证(验证的规则请看https://doc.open.alipay.com/doc2/
- * detail.htm?spm=0.0.0.0.xdvAU6&treeId=59&articleId=103665&
- * docType=1) 建议商户依赖异步通知
- */
- String resultInfo = payResult.getResult();// 同步返回需要验证的信息
- String resultStatus = payResult.getResultStatus();
- // 判断resultStatus 为“9000”则代表支付成功,具体状态码代表含义可参考接口文档
- if (TextUtils.equals(resultStatus, "9000")) {
- mhandler.sendEmptyMessage(9000);
- //Toast.makeText(context, "支付成功", Toast.LENGTH_SHORT).show();
- } else {
- // 判断resultStatus 为非"9000"则代表可能支付失败
- // "8000"代表支付结果因为支付渠道原因或者系统原因还在等待支付结果确认,最终交易是否成功以服务端异步通知为准(小概率状态)
- if (TextUtils.equals(resultStatus, "8000")) {
- Toast.makeText(context, "支付结果确认中", Toast.LENGTH_SHORT).show();
- } else {
- // 其他值就可以判断为支付失败,包括用户主动取消支付,或者系统返回的错误
- Toast.makeText(context, "支付宝支付失败", Toast.LENGTH_SHORT).show();
- }
- mhandler.sendEmptyMessage(8000);
- }
- break;
- }
- default:
- break;
- }
- };
- };
- /**
- * create the order info. 创建订单信息
- *
- */
- private String getOrderInfo(OrderInfo order) {
- // 签约合作者身份ID
- String orderInfo = "partner=" + "\"" + ParameterConfig.PARTNER + "\"";
- // 签约卖家支付宝账号
- orderInfo += "&seller_id=" + "\"" +ParameterConfig.SELLER + "\"";
- // 商户网站唯一订单号
- orderInfo += "&out_trade_no=" + "\"" + order.outtradeno + "\"";
- // 商品名称
- orderInfo += "&subject=" + "\"" + order.productname + "\"";
- // 商品详情
- orderInfo += "&body=" + "\"" + order.desccontext + "\"";
- // 商品金额
- orderInfo += "&total_fee=" + "\"" + order.totalamount + "\"";
- // 服务器异步通知页面路径
- orderInfo += "¬ify_url=" + "\"" + ParameterConfig.aliPay_notifyURL + "\"";
- // 服务接口名称, 固定值
- orderInfo += "&service=\"mobile.securitypay.pay\"";
- // 支付类型, 固定值
- orderInfo += "&payment_type=\"1\"";
- // 参数编码, 固定值
- orderInfo += "&_input_charset=\"utf-8\"";
- // 设置未付款交易的超时时间
- // 默认30分钟,一旦超时,该笔交易就会自动被关闭。
- // 取值范围:1m~15d。
- // m-分钟,h-小时,d-天,1c-当天(无论交易何时创建,都在0点关闭)。
- // 该参数数值不接受小数点,如1.5h,可转换为90m。
- orderInfo += "&it_b_pay=\"30m\"";
- // extern_token为经过快登授权获取到的alipay_open_id,带上此参数用户将使用授权的账户进行支付
- // orderInfo += "&extern_token=" + "\"" + extern_token + "\"";
- // 支付宝处理完请求后,当前页面跳转到商户指定页面的路径,可空
- orderInfo += "&return_url=\"m.alipay.com\"";
- // 调用银行卡支付,需配置此参数,参与签名, 固定值 (需要签约《无线银行卡快捷支付》才能使用)
- // orderInfo += "&paymethod=\"expressGateway\"";
- return orderInfo;
- }
- /**
- * sign the order info. 对订单信息进行签名
- *
- * @param content
- * 待签名订单信息
- */
- private String sign(String content) {
- return SignUtils.sign(content, ParameterConfig.RSA_PRIVATE);
- }
- /**
- * get the sign type we use. 获取签名方式
- *
- */
- private String getSignType() {
- return "sign_type=\"RSA\"";
- }
- }
- 微信的回调actvity
- package com.gan.mypay.wxapi;
- import com.gan.mypay.ParameterConfig;
- import com.gan.mypay.R;
- import com.gan.mypay.SelectPayTypeActivity;
- 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;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.content.Intent;
- import android.os.Bundle;
- import android.util.Log;
- import android.widget.Toast;
- public class WXPayEntryActivity extends Activity implements IWXAPIEventHandler{
- private static final String TAG = "MicroMsg.SDKSample.WXPayEntryActivity";
- private IWXAPI api;
- // private TextView reulttv;
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.wx_pay_result);
- api = WXAPIFactory.createWXAPI(this, ParameterConfig.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) {
- Log.d(TAG, "onPayFinish, errCode = " + resp.errCode);
- if (resp.getType() == ConstantsAPI.COMMAND_PAY_BY_WX) {
- AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setTitle("提示");
- //builder.setMessage(getString(R.string.pay_result_callback_msg, String.valueOf(resp.errCode)));
- builder.show();
- Intent intent;
- int code = resp.errCode;
- switch (code) {
- case 0:
- Toast.makeText(this, "支付成功",0).show();
- intent=new Intent(this,SelectPayTypeActivity.class);
- intent.putExtra("result", 0);
- startActivity(intent);
- finish();
- break;
- case -1:
- Toast.makeText(this, "支付失败",0).show();
- intent=new Intent(this,SelectPayTypeActivity.class);
- intent.putExtra("result", -1);
- startActivity(intent);
- finish();
- break;
- case -2:
- Toast.makeText(this, "支付取消",0).show();
- intent=new Intent(this,SelectPayTypeActivity.class);
- intent.putExtra("result", -2);
- startActivity(intent);
- finish();
- break;
- default:
- break;
- }
- }
- }
- }
相关推荐
- 目前聚合支付的发展现状如何? 目前聚合支付市场规模如何?有哪些比较好的玩家?云收呗API怎么样?竞争态势怎样用支付宝和微信都可以扫的聚合支付API码云收呗其原理是什么?
- 纸币要被取代了!难道是支付宝和微信?或许结果令你大吃一惊!
- 支付宝和微信支付程序-附源码下载
- H5移动支付java demo,包含支付宝和微信,便宜了5元,可项目使用,可学习使用...
- 1月16日科技资讯|微信付费阅读支付宝可用,iOS抽成30%;苹果安卓充电器或统一;UOS 20发布
- 才发现!微信、QQ和支付宝还有这么好用的翻译功能,一键轻松翻译
- uCharts图表免费开源,支持微信小程序图表,支付宝小程序图表,百度小程序图表,头条小程序图表,H5图表,IOS图表,安卓图表
- 超详细的Android APP 集成 PayPal 境外支付 信用卡 借记卡 支付,支付宝 微信海外 境外支付
- Xcode8 集成微信/支付宝sdk步骤及错误
- ionic 支付宝和微信支付在ionic中的使用,及注意事项
- springboot版本的微信支付和支付宝支付
- 解决XCode编译异常clang: error: linker command failed with exit code 1