一文帶你瞭解移動支付

前言

相信作app的童鞋都知道,咱們app 確定離不開移動支付的,而咱們常用的支付通常就是微信支付,支付寶支付這2個。
而題主最近恰好離職,也比較閒,恰好總結了以前作過的支付DEMO,整合了微信支付,支付寶支付,銀聯支付,貝寶支付,整合成一個demo,也算是一個經驗總結吧。
java

醜醜的界面
醜醜的界面

github地址:github.com/LinHuanTanL…android

正文

項目結構介紹:

最基礎的項目目錄結構
最基礎的項目目錄結構

其中網絡請求咱們使用了okhttputils,解析JSON用了gsongit

配置類介紹:

咱們全部須要的配置都寫在配置類裏面,這個類也在咱們項目中扮演着很重要的角色,固然,爲了避嫌,咱們BASE_URL以及一些配置文件作了xxxxx處理,你們能夠替換成大家本身的key而後再運行。代碼以下:程序員

/** * @author Ly * @date 2017/10/24 * 配置類 */

public class AppConf {
    /** * BaseUrl */
    private static final String BASE_URL = "https://app.globalxxx.com";

    /** * 微信配置文件 */
    public interface WechatConf {
        String APP_ID = "xxxxxxxab57ab288";
        String APP_SECRET = "xxxxxxxx1269874371fc75a79a";
    }

    /** * 貝寶的配置文件 */
    public interface PayPalConf {
        /** * 沙盒環境 */
        String CONFIG_CLIENT_ID_SANDBOX = "xxxxlZPMz2PN3C8akROwHZjDnzmRDGdxt965BkkvVfF8cUlzRU8a2AALVYCPMSc9uwqyJY5";
        /** * 正式環境 */
        String CONFIG_CLIENT_ID_LIVE = "xxxxEiCmYlq83H73jHejGw8r-hyaiL0WbueHIUbOLtSEV_Vfh8rkU4aawFknGQZhA";
    }

    /** * 銀行卡配置環境 */
    public interface CardConf {
        /** * 銀聯支付 配置信息 * * @return 01 沙盒環境 00 正式環境 */
        String SANDBOX = "01", FORMAL = "00";

    }

    /** * 接口配置文件 */
    public interface NetConf {
        /** * 登陸信息 */
        String LOGIN = BASE_URL + "/user/login.do";
        /** * 微信支付信息 */
        String WECHAT_PAY_INFO = BASE_URL + "/user/pay/weChatRecharge.do";
        /** * 支付寶支付信息 */
        String ALI_PAY_INFO = BASE_URL + "/user/pay/alipayRecharge.do";

        /** * 貝寶支付信息 */
        String PAYPAL_PAY_INFO = BASE_URL + "/user/pay/getPayPalOrderId.do";
        /** * 驗證paypal支付狀態 */
        String PAYPAL_SYN_ORDER = BASE_URL + "/user/pay/synPaypalOrder.do";
        /** * 銀聯支付 獲取tn */
        String CARD_PAY_INFO = "http://101.231.204.84:8091/sim/getacptn";
    }
}複製代碼

微信支付:

微信支付如今已經能夠支持依賴導入了。github

  1. 在build.gradle 寫入依賴:
    compile 'com.tencent.mm.opensdk:wechat-sdk-android-without-mta:+'複製代碼
  2. 在清單文件中寫入權限:
    ``` xmljson




3. 在後臺配置的包名下新建wxapi包,而且新建一個類,命名爲*WXPayEntryActivity*,實現*IWXAPIEventHandler*接口,其中咱們須要注意的是:假設項目包名爲 *com.ly.PayDemo*,那麼這個類的路徑就應該是*com.ly.PayDemo.wxapi.WXPayEntryActivity*,包名,路徑都不能夠錯,不然沒法進入回調頁面!而且記得在AndroidManifest.xml進行註冊。
``` xml
  <!--微信支付成功回調的頁面-->
        <activity
            android:name=".wxapi.WXPayEntryActivity"
            android:exported="true"
            android:launchMode="singleTop"/>
        <!--end of 微信支付-->複製代碼
  1. 真正進行微信支付,首先咱們看下咱們的支付類,相信你們能夠看出邏輯:

微信支付頁面
微信支付頁面

/** * @author Ly * @date 2017/10/24 * 微信支付界面 */

public class WeChatPayActivity extends AppCompatActivity implements View.OnClickListener {


    private TextView mTvWechatPay, mTvWechatIsSupport;


    /** * 微信支付 */
    private IWXAPI api;

    private String token;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_wechat_pay);
        Bundle bundle = getIntent().getBundleExtra("extra");
        if (bundle != null) {
            token = bundle.getString("token");
        }
        initView();
    }

    private void initView() {
        mTvWechatPay = (TextView) findViewById(R.id.tv_wechat_pay);
        mTvWechatIsSupport = (TextView) findViewById(R.id.tv_wechat_is_support);
        mTvWechatPay.setOnClickListener(this);
        mTvWechatIsSupport.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_wechat_pay:
                doGetWechatPayInfo();
                break;
            case R.id.tv_wechat_is_support:
                isPaySupported();
                break;
            default:
                break;
        }
    }

    /** * 獲取微信訂單 */
    private void doGetWechatPayInfo() {
        OkHttpUtils.post()
                .url(AppConf.NetConf.WECHAT_PAY_INFO)
                .addParams("accessToken", token)
                .addParams("wRechargeMoney", "0.01")
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        WechatPayInfo wechatPayInfo = new Gson().fromJson(response, WechatPayInfo.class);
                        Log.e("xxx", wechatPayInfo.toString());
                        WXPay(wechatPayInfo.getData().getAppid(),
                                wechatPayInfo.getData().getPartnerid(),
                                wechatPayInfo.getData().getPrepayid(),
                                wechatPayInfo.getData().getTimestamp(),
                                wechatPayInfo.getData().getNoncestr(),
                                wechatPayInfo.getData().getPaySign());
                    }
                });
    }

    /** * 微信支付 */
    private void WXPay(String appId, String partnerId, String prepayId, String timeStamp, String nonceStr, String paySign) {
        api = WXAPIFactory.createWXAPI(this, null);
        api.registerApp(AppConf.WechatConf.APP_ID);
        PayReq req = new PayReq();
        req.appId = appId;
        req.partnerId = partnerId;
        req.prepayId = prepayId;
        req.nonceStr = nonceStr;
        req.timeStamp = timeStamp;
        req.packageValue = "Sign=WXPay";
        req.sign = paySign;
        api.sendReq(req);
    }

    /** * 檢測微信版本是否支持支付 */
    private boolean isPaySupported() {
        if (api == null) {
            api = WXAPIFactory.createWXAPI(this, null);
            api.registerApp(AppConf.WechatConf.APP_ID);
        }
        boolean isPaySupported;
        isPaySupported = api.getWXAppSupportAPI() >= Build.PAY_SUPPORTED_SDK_INT;
        if (!isPaySupported) {
            Toast.makeText(this, "您的微信版本不支持支付", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "您的微信版本支持支付", Toast.LENGTH_SHORT).show();
        }
        return isPaySupported;
    }

    public static void toWechatActivity(Activity activity, String token) {
        Intent intent = new Intent(activity, WeChatPayActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("token", token);
        intent.putExtra("extra", bundle);
        activity.startActivity(intent);
    }
}複製代碼

咱們能夠看到,其實就分爲2個方法:api

  • isPaySupported 檢測是否有微信客戶端以及是否該客戶端支持微信支付
  • doGetWechatPayInfo 從服務器獲取訂單信息,在callback裏面吊起微信支付。
  1. 值得一提的是,咱們要如何接受支付的回調,那就是要靠咱們以前大費周章寫的WXPayEntryActivity:
    ``` java
    @Override
    public void onResp(BaseResp resp) {
    Log.e("", "onPayFinish, errCode = " + resp.errCode);
     int code = resp.errCode;
     switch (code) {
         case 0://支付成功後的界面
             Toast.makeText(this, "支付成功", Toast.LENGTH_SHORT).show();
             finish();
             break;
         case -1:
             Toast.makeText(this, "簽名錯誤、未註冊APPID、項目設置APPID不正確、註冊的APPID與設置的不匹配、您的微信帳號異常等", Toast.LENGTH_SHORT).show();
             finish();
             break;
         case -2://用戶取消支付後的界面
             Toast.makeText(this, "用戶取消", Toast.LENGTH_SHORT).show();
             finish();
             break;
         default:
             break;
     }複製代碼
    }
在這裏咱們能夠處理下這個頁面,而若是咱們不須要這個頁面而又必須靠這個頁面去接受回調,有個小技巧,咱們能夠把這個頁面1dp,或者是修改theme爲dialog。


### 支付寶支付:
1. 導入JAR:
支付寶的話暫時沒有依賴方法,咱們須要手動導入jar包:
![支付寶的jar包](http://upload-images.jianshu.io/upload_images/1924616-7a1a9ad258b7c0f8.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
2. 配置清單文件:
 須要配置的權限爲:
``` xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />複製代碼

其實與微信支付是同樣的,因此咱們不贅述。
可是咱們要配置2個activity:bash

<!--支付寶支付-->
        <activity android:name="com.alipay.sdk.app.H5PayActivity" android:configChanges="orientation|keyboardHidden|navigation|screenSize" android:exported="false" android:screenOrientation="behind" android:windowSoftInputMode="adjustResize|stateHidden">
        </activity>
        <activity android:name="com.alipay.sdk.app.H5AuthActivity" android:configChanges="orientation|keyboardHidden|navigation" android:exported="false" android:screenOrientation="behind" android:windowSoftInputMode="adjustResize|stateHidden">
        </activity>

        <!--end of 支付寶支付-->複製代碼
  1. 咱們看下支付寶支付的類:
    ``` java

/**服務器

  • @author Ly
  • @date 2017/10/24
  • 支付寶支付
    */

public class AliPayActivity extends AppCompatActivity {
private Button mBtAliPay;微信

private String token;
/**
 * 支付寶支付
 */
private static final int SDK_PAY_FLAG = 1;


@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
    @Override
    @SuppressWarnings("unused")
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case SDK_PAY_FLAG: {
                AliPayResult payResult = new AliPayResult((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")) {
                    Toast.makeText(AliPayActivity.this, "支付成功", Toast.LENGTH_SHORT).show();
                } else {
                    // 判斷resultStatus 爲非"9000"則表明可能支付失敗
                    // "8000"表明支付結果由於支付渠道緣由或者系統緣由還在等待支付結果確認,最終交易是否成功以服務端異步通知爲準(小几率狀態)
                    if (TextUtils.equals(resultStatus, "8000")) {
                        Toast.makeText(AliPayActivity.this, "支付結果確認中", Toast.LENGTH_SHORT).show();

                    } else {
                        // 其餘值就能夠判斷爲支付失敗,包括用戶主動取消支付,或者系統返回的錯誤
                        Toast.makeText(AliPayActivity.this, "支付失敗", Toast.LENGTH_SHORT).show();

                    }
                }
                break;
            }
            default:
                break;
        }
    }
};

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_ali_pay);
    Bundle bundle = getIntent().getBundleExtra("extra");
    if (bundle != null) {
        token = bundle.getString("token");
    }
    initView();
}

private void initView() {
    mBtAliPay = (Button) findViewById(R.id.bt_ali_pay);
    mBtAliPay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            doGetAliPayInfo();
        }
    });
}


/**
 * 獲取支付寶信息
 */
private void doGetAliPayInfo() {
    OkHttpUtils.post().url(AppConf.NetConf.ALI_PAY_INFO)
            .addParams("accessToken", token)
            .addParams("aRechargeMoney", "0.01")
            .build()
            .execute(new StringCallback() {
                @Override
                public void onError(Call call, Exception e, int id) {
                    e.printStackTrace();
                }

                @Override
                public void onResponse(String response, int id) {
                    AliPayInfo aliPayInfo = new Gson().fromJson(response, AliPayInfo.class);
                    aliPay(aliPayInfo.getData().getOrderStr());
                }
            });
}

/**
 * 調用SDK支付
 */
public void aliPay(final String payInfo) {
    Runnable payRunnable = new Runnable() {
        @Override
        public void run() {
            // 構造PayTask 對象
            PayTask alipay = new PayTask(AliPayActivity.this);
            // 調用支付接口,獲取支付結果
            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();
}

public static void toAliPayAcitivity(Activity activity, String token) {
    Intent intent = new Intent(activity, AliPayActivity.class);
    Bundle bundle = new Bundle();
    bundle.putString("token", token);
    intent.putExtra("extra", bundle);
    activity.startActivity(intent);
}複製代碼

}

其實咱們這個類中只有一個重要的方法:
* **doGetAliPayInfo** 從服務器獲取咱們的訂單信息。
獲取到了信息後,咱們經過調用支付寶的支付api吊起支付:
```java
 /**
     * 調用SDK支付
     */
    public void aliPay(final String payInfo) {
        Runnable payRunnable = new Runnable() {
            @Override
            public void run() {
                // 構造PayTask 對象
                PayTask alipay = new PayTask(AliPayActivity.this);
                // 調用支付接口,獲取支付結果
                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();
    }複製代碼

而吊起了支付後,支付結果咱們能夠在handler中看到,固然!涉及到支付的,咱們app本地所謂「支付成功」,"支付失敗"都是不靠譜的,最靠譜的仍是得靠服務器那邊的回調。

銀聯支付

  1. 導入JAR以及SO
    銀聯的導入相對比較麻煩,須要導入JAR,SO,還有BIN文件
    銀聯支付的配置
    銀聯支付的配置

    由於咱們的so是放在libs下面的,而且咱們只導入3個cpu類型,因此咱們須要在build.gradle文件作以下配置:
    defaultConfig下配置ndk:
    ``` xml
    ndk {
    //選擇要添加的對應cpu類型的.so庫。
         abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
         // 還能夠添加 'x86', 'x86_64', 'mips', 'mips64'
     }複製代碼
在*android*下配置:
```xml
  sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }複製代碼

至此導入完成。

  1. 咱們仍舊須要在清單文件進行配置:
    ``` xml

    <uses-library
        android:name="org.simalliance.openmobileapi"
        android:required="false"/>
    
    <activity
        android:name="com.unionpay.uppay.PayActivity"
        android:configChanges="orientation|keyboardHidden"
        android:excludeFromRecents="true"
        android:label="@string/app_name"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize"/>
    
    <activity
        android:name="com.unionpay.UPPayWapActivity"
        android:configChanges="orientation|keyboardHidden"
        android:screenOrientation="portrait"
        android:windowSoftInputMode="adjustResize"/>
    <!--end of 銀聯支付-->複製代碼
3. 咱們照舊看下銀聯支付的類;
```java

/**
 * @author Ly
 * @date 2017/10/24
 * 銀行卡支付界面
 */

public class CardPayActivity extends AppCompatActivity {

    private Button mBtCardPay;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_card);
        initView();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (data == null) {
            return;
        }

        String msg = "";
        /*
         * 支付控件返回字符串:success、fail、cancel 分別表明支付成功,支付失敗,支付取消
         */
        String str = data.getExtras().getString("pay_result");
        if (str.equalsIgnoreCase("success")) {

            // 若是想對結果數據驗籤,可以使用下面這段代碼,但建議不驗籤,直接去商戶後臺查詢交易結果
            // result_data結構見c)result_data參數說明
            if (data.hasExtra("result_data")) {
                String result = data.getExtras().getString("result_data");
                try {
                    JSONObject resultJson = new JSONObject(result);
                    String sign = resultJson.getString("sign");
                    String dataOrg = resultJson.getString("data");
                    // 此處的verify建議送去商戶後臺作驗籤
                    // 如要放在手機端驗,則代碼必須支持更新證書
                    boolean ret = verify(dataOrg, sign, AppConf.CardConf.SANDBOX);
                    if (ret) {
                        // 驗籤成功,顯示支付結果
                        msg = "支付成功!";
                    } else {
                        // 驗籤失敗
                        msg = "支付失敗!";
                    }
                } catch (JSONException e) {
                }
            }
            // 結果result_data爲成功時,去商戶後臺查詢一下再展現成功
            msg = "支付成功!";
        } else if (str.equalsIgnoreCase("fail")) {
            msg = "支付失敗!";
        } else if (str.equalsIgnoreCase("cancel")) {
            msg = "用戶取消了支付";
        }

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("支付結果通知");
        builder.setMessage(msg);
        builder.setInverseBackgroundForced(true);
        builder.setNegativeButton("肯定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.dismiss();
            }
        });
        builder.create().show();
    }

    private boolean verify(String dataOrg, String sign, String sandbox) {
        return true;
    }

    private void initView() {
        mBtCardPay = (Button) findViewById(R.id.bt_card_pay);
        mBtCardPay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doGetCardPayInfo();
            }
        });
    }

    /**
     * 獲取銀聯支付的信息
     */
    private void doGetCardPayInfo() {
        OkHttpUtils.get()
                .url(AppConf.NetConf.CARD_PAY_INFO)
                .build().execute(new StringCallback() {
            @Override
            public void onError(Call call, Exception e, int id) {
                e.printStackTrace();
            }

            @Override
            public void onResponse(String response, int id) {
                Log.e("xxxx", response);
                UPPayAssistEx.startPay(CardPayActivity.this, null, null, response, AppConf.CardConf.SANDBOX);
            }
        });
    }


    public static void toCardPayActivity(Activity activity) {
        Intent intent = new Intent(activity, CardPayActivity.class);
        activity.startActivity(intent);
    }
}複製代碼

其實我不說各位看官也知道了,這個類裏面的方法也很少,就一個:

  • doGetCardPayInfo 獲取服務器上的訂單信息

獲取到了訂單信息後,咱們調用支付的方法:

UPPayAssistEx.startPay(CardPayActivity.this, null, null, response, AppConf.CardConf.SANDBOX);複製代碼

這裏咱們注意AppConf.CardConf.SANDBOX,這裏使用的是沙盒模式,對前文的配置類還有印象的話,應該記得我使用的是沙盒的模式,包括獲取tn訂單信息,也都是沙盒的;固然,這個之後能夠替換成app本身的服務器接口。

paypal支付

相信各位看官對這個支付應該是陌生的吧,
能夠查看下:www.paypal-biz.com/,這個是用在以前的某個…

  1. 導入

貝寶導入
貝寶導入

  1. 配置
    ``` xml

    <service
         android:name="com.paypal.android.sdk.payments.PayPalService"
         android:exported="false" />
    
     <activity android:name="com.paypal.android.sdk.payments.PaymentActivity" />
     <activity android:name="com.paypal.android.sdk.payments.LoginActivity" />
     <activity android:name="com.paypal.android.sdk.payments.PaymentMethodActivity" />
     <activity android:name="com.paypal.android.sdk.payments.PaymentConfirmActivity" />
     <activity
         android:name="io.card.payment.CardIOActivity"
         android:configChanges="keyboardHidden|orientation" />
     <activity android:name="io.card.payment.DataEntryActivity" />
    
     <!--end of paypal-->複製代碼
貝寶的支付確實是比較麻煩,不止須要導入6個activity,還須要咱們導入一個service。
3. 看下咱們的支付類:
``` java

/**
 * @author Ly
 * @date 2017/10/24
 */

public class PayPalPayActivity extends AppCompatActivity {

    private Button mBtPaypalPay;


    private String token;

    /**
     * 你在PalPay建立的測試應用客戶端ID
     */
    private static final String CONFIG_CLIENT_ID = AppConf.PayPalConf.CONFIG_CLIENT_ID_LIVE;
    /**
     * 沙盒測試(ENVIRONMENT_SANDBOX),生產環境(ENVIRONMENT_PRODUCTION)
     */
    private static PayPalConfiguration config = new PayPalConfiguration()
            .environment(PayPalConfiguration.ENVIRONMENT_PRODUCTION)
            .clientId(CONFIG_CLIENT_ID);
    /**
     * 用於後臺檢驗的paymentId
     */
    private String paymentId = null;

    @Override

    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_paypal);
        startPayPalSer();
        Bundle bundle = getIntent().getBundleExtra("extra");
        if (bundle != null) {
            token = bundle.getString("token");
        }
        initView();
    }

    private void initView() {
        mBtPaypalPay = (Button) findViewById(R.id.bt_paypal_pay);
        mBtPaypalPay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                doGetPaypalPayInfo();
            }
        });
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        //中止PayPalService服務
        stopService(new Intent(this, PayPalService.class));
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {
            PaymentConfirmation confirm1 = data
                    .getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
            String paymentId;
            try {
                paymentId = confirm1.toJSONObject().getJSONObject("response")
                        .getString("id");
                String paymentClient = confirm1.getPayment().toJSONObject()
                        .toString();
                doSynPaypalOrderStatus(paymentId);
                Log.e("onActivityResult-----", "paymentId: " + paymentId + ", payment_json: "
                        + paymentClient);
            } catch (JSONException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } else if (resultCode == Activity.RESULT_CANCELED) {
            Log.i("paymentExample", "The user canceled.");
        } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
            Log.i("paymentExample", "An invalid Payment or PayPalConfiguration was submitted. Please see the docs.");
        }
    }

    /**
     * 啓動paypal服務
     */
    private void startPayPalSer() {
        //啓動PayPalService服務
        Intent intent = new Intent(this, PayPalService.class);
        intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config);
        startService(intent);
    }

    /**
     * 獲取貝寶的支付信息
     */
    private void doGetPaypalPayInfo() {
        OkHttpUtils.post()
                .url(AppConf.NetConf.PAYPAL_PAY_INFO)
                .addParams("accessToken", token)
                .addParams("rechangeUSD", "0.01")
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        PaypalInfoBean paypalInfoBean = new Gson().fromJson(response, PaypalInfoBean.class);
                        Log.e("xxx", paypalInfoBean.toString());
                        paymentId = paypalInfoBean.getData().getOrderId();
                        // PAYMENT_INTENT_SALE 意思是支付當即完成
                        // 修改 PAYMENT_INTENT_SALE 爲 PAYMENT_INTENT_AUTHORIZE to only authorize payment and
                        // capture funds later.
                        PayPalPayment payment = new PayPalPayment(new BigDecimal(paypalInfoBean.getData().getRechangeUSD()), "USD", "充值支付",
                                PayPalPayment.PAYMENT_INTENT_SALE);
                        com.paypal.android.sdk.payments.PayPalItem[] payPalItems =
                                {new PayPalItem(paymentId,
                                        1,
                                        new BigDecimal(paypalInfoBean.getData().getRechangeUSD()),
                                        "USD",
                                        paymentId)};
                        // Total amount
                        BigDecimal subtotal = PayPalItem.getItemTotal(payPalItems);
                        // If you have shipping cost, add it here
                        BigDecimal shipping = new BigDecimal("0.0");
                        // If you have tax, add it here
                        BigDecimal tax = new BigDecimal("0.0");
                        PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails(
                                shipping, subtotal, tax);
                        payment.items(payPalItems).paymentDetails(paymentDetails);
                        Intent intent = new Intent(PayPalPayActivity.this, PaymentActivity.class);
                        intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment);
                        startActivityForResult(intent, 0);
                    }
                });
    }

    /**
     * 校驗貝寶
     *
     * @param paymentId
     */
    private void doSynPaypalOrderStatus(String paymentId) {
        OkHttpUtils.post()
                .url(AppConf.NetConf.PAYPAL_SYN_ORDER)
                .addParams("accessToken", token)
                .addParams("paymentId", paymentId)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        Log.e("貝寶校驗---", response);
                    }
                });
    }

    public static void toPayPalPayActivity(Activity activity, String token) {
        Intent intent = new Intent(activity, PayPalPayActivity.class);
        Bundle bundle = new Bundle();
        bundle.putString("token", token);
        intent.putExtra("extra", bundle);
        activity.startActivity(intent);
    }
}複製代碼

相信各位看官也會以爲,這個類...繁瑣了多!行,咱們慢慢解釋,有一些注意事項:

  • 在oncreate()須要啓動一個service,而在ondestory()咱們須要stop
  • 爲了區分訂單信息,咱們拿到後臺返回的信息後,還須要本身憑藉一段標識信息傳遞給服務器(這個是咱們服務器本身的需求,不是每一個app都須要)
    ``` java
    PaypalInfoBean paypalInfoBean = new Gson().fromJson(response, PaypalInfoBean.class);
    Log.e("xxx", paypalInfoBean.toString());
                      paymentId = paypalInfoBean.getData().getOrderId();
                      // PAYMENT_INTENT_SALE 意思是支付當即完成
                      // 修改 PAYMENT_INTENT_SALE 爲 PAYMENT_INTENT_AUTHORIZE to only authorize payment and
                      // capture funds later.
                      PayPalPayment payment = new PayPalPayment(new BigDecimal(paypalInfoBean.getData().getRechangeUSD()), "USD", "充值支付",
                              PayPalPayment.PAYMENT_INTENT_SALE);
                      com.paypal.android.sdk.payments.PayPalItem[] payPalItems =
                              {new PayPalItem(paymentId,
                                      1,
                                      new BigDecimal(paypalInfoBean.getData().getRechangeUSD()),
                                      "USD",
                                      paymentId)};
                      // Total amount
                      BigDecimal subtotal = PayPalItem.getItemTotal(payPalItems);
                      // If you have shipping cost, add it here
                      BigDecimal shipping = new BigDecimal("0.0");
                      // If you have tax, add it here
                      BigDecimal tax = new BigDecimal("0.0");
                      PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails(
                              shipping, subtotal, tax);
                      payment.items(payPalItems).paymentDetails(paymentDetails);
                      Intent intent = new Intent(PayPalPayActivity.this, PaymentActivity.class);
                      intent.putExtra(PaymentActivity.EXTRA_PAYMENT, payment);
                      startActivityForResult(intent, 0);複製代碼

```

  • 拿到支付結果後,咱們須要請求服務器接口進行校驗,其實至關於驗籤(這個也是咱們服務器的需求,不是每一個app都須要的)
    參考方法: doSynPaypalOrderStatus

結尾

其實咱們看了4個支付方案,有沒有以爲有什麼共同點呢:
拿取訂單信息 ---> 吊起支付 ----> 支付後接受callback(視具體狀況是否須要驗籤)

總結

額,好像也沒什麼好說的,上着班偷偷摸摸寫的,算了,繼續打代碼去。
AND
各位程序猿/媛 節日快樂

AND 毒奶一波

眼淚嘩啦啦地流
眼淚嘩啦啦地流

祝:諸君與我早日成爲程序員

相關文章
相關標籤/搜索