【干货】java集成paypal,含android代码,服务端代码
条评论支付流程
1. 前端选择商品,调用paypal支付
2. 支付完成,paypal会返回payment信息,将payment的id返回给自己服务端
3. 服务端根据paymentId,调paypal,查询支付是否完成
准备
前往
https://www.paypal.com/
注册商家账号前往
https://developer.paypal.com/
,使用刚注册的商家账号登录点击右上角名字,选择Dashboard
在左边的导航栏中点击 Sandbox 下的 Accounts
进入Acccouts界面后,可以看到系统有两个已经生成好的测试账号,但是我们不要用系统给的测试账号,自己创建两个,一个是商家账号,一个是个人账号
- 点击右上角的“Create Account”,创建测试用户
- 先创建一个“ PERSONAL”类型的用户,国家一定要选“China”,账户余额自己填写(邮箱地址可以随便写,自己好记就行)
- 接着创建一个“BUSINESS”类型的用户,国家一定要选“China”,账户余额自己填写 (邮箱地址可以随便写,自己好记就行)
- 创建好之后可以点击测试账号下的”Profile“,可以查看信息,如果没加载出来,刷新
- 用测试账号登录测试网站查看,注意!这跟paypal官网不同!不是同一个地址,在浏览器输入:
https://www.sandbox.paypal.com
在这里登陆测试账户
创建应用,生成用于测试的clientID 和 密钥
- 点击左边导航栏Dashboard下的My Apps & Credentials,创建一个Live账号
- 然后再到下边创建App
- 点击刚刚创建好的App,注意看到”ClientID“ 和”Secret“(Secret如果没显示,点击下面的show就会看到,点击后show变为hide)
start coding
Android`
添加依赖
`compile('com.paypal.sdk:paypal-android-sdk:2.15.1') { exclude group: 'io.card' }//禁止通过信用卡直接支付,如果不禁止可以直接去掉这一句`
强制在你的编译版本上执行编译操作(编译不过的时候才建议添加)
`<uses-sdk android:minSdkVersion="这里填写你需要的编译版本" tools:overrideLibrary="com.paypal.android.sdk.payments" />`
封装好的工具类
` import android.app.Activity; import android.content.Context; import android.content.Intent; import android.util.Log; import com.globalegrow.app.gearbest.network.HttpCallBack; import com.globalegrow.app.gearbest.widget.CustomToast; import com.paypal.android.sdk.payments.PayPalAuthorization; import com.paypal.android.sdk.payments.PayPalConfiguration; import com.paypal.android.sdk.payments.PayPalFuturePaymentActivity; import com.paypal.android.sdk.payments.PayPalItem; import com.paypal.android.sdk.payments.PayPalPayment; import com.paypal.android.sdk.payments.PayPalPaymentDetails; import com.paypal.android.sdk.payments.PayPalProfileSharingActivity; import com.paypal.android.sdk.payments.PayPalService; import com.paypal.android.sdk.payments.PaymentActivity; import com.paypal.android.sdk.payments.PaymentConfirmation; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.math.BigDecimal; /** * Create by Moosen on 09/11/2016 */ public class PayPalHelper { private static final String TAG = "PayPalHelper"; //配置何种支付环境,一般沙盒,正式 private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX; // note that these credentials will differ between live & sandbox environments. //你所注册的APP Id private static final String CONFIG_CLIENT_ID = ""; private static final int REQUEST_CODE_PAYMENT = 1; private static final int REQUEST_CODE_FUTURE_PAYMENT = 2; private static final int REQUEST_CODE_PROFILE_SHARING = 3; private static PayPalConfiguration config = new PayPalConfiguration() .environment(CONFIG_ENVIRONMENT) .clientId(CONFIG_CLIENT_ID); //以下配置是授权支付的时候用到的 // .merchantName("Example Merchant") // .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy")) // .merchantUserAgreementUri(Uri.parse("https://www.example.com/legal")); private static PayPalHelper payPalHelper; private PayPalHelper() { } public static PayPalHelper getInstance() { if (payPalHelper == null) { synchronized (PayPalHelper.class) { payPalHelper = new PayPalHelper(); } } return payPalHelper; } /** * 启动PayPal服务 * * @param context */ public void startPayPalService(Context context) { Intent intent = new Intent(context, PayPalService.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config); context.startService(intent); } /** * 停止PayPal服务 sdfsdfsdssaaass * * @param context */ public void stopPayPalService(Context context) { context.stopService(new Intent(context, PayPalService.class)); } /** * 开始执行支付操作 * * @param context */ public void doPayPalPay(Context context) { /* * PAYMENT_INTENT_SALE will cause the payment to complete immediately. * Change PAYMENT_INTENT_SALE to * - PAYMENT_INTENT_AUTHORIZE to only authorize payment and capture funds later. * - PAYMENT_INTENT_ORDER to create a payment for authorization and capture * later via calls from your server. * * Also, to include additional payment details and an item list, see getStuffToBuy() below. */ PayPalPayment thingToBuy = getStuffToBuy(PayPalPayment.PAYMENT_INTENT_SALE); /* * See getStuffToBuy(..) for examples of some available payment options. */ Intent intent = new Intent(context, PaymentActivity.class); // send the same configuration for restart resiliency intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config); intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy); ((Activity) context).startActivityForResult(intent, REQUEST_CODE_PAYMENT); } /* * This method shows use of optional payment details and item list. * * 直接给PP创建支付的信息,支付对象实体信息 */ private PayPalPayment getStuffToBuy(String paymentIntent) { //--- include an item list, payment amount details //具体的产品信息列表 PayPalItem[] items = { new PayPalItem("sample item #1", 2, new BigDecimal("0.50"), "USD", "sku-12345678"), new PayPalItem("free sample item #2", 1, new BigDecimal("0.00"), "USD", "sku-zero-price"), new PayPalItem("sample item #3 with a longer name", 6, new BigDecimal("0.99"), "USD", "sku-33333") }; BigDecimal subtotal = PayPalItem.getItemTotal(items); BigDecimal shipping = new BigDecimal("0.21"); BigDecimal tax = new BigDecimal("0.67"); PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails(shipping, subtotal, tax); BigDecimal amount = subtotal.add(shipping).add(tax); PayPalPayment payment = new PayPalPayment(amount, "USD", "sample item", paymentIntent); payment.items(items).paymentDetails(paymentDetails); //--- set other optional fields like invoice_number, custom field, and soft_descriptor payment.custom("This is text that will be associated with the payment that the app can use."); return payment; } /** * 处理支付之后的结果 * * @param context * @param requestCode * @param resultCode * @param data */ public void confirmPayResult(final Context context, int requestCode, int resultCode, Intent data, final DoResult doResult) { if (requestCode == REQUEST_CODE_PAYMENT) { if (resultCode == Activity.RESULT_OK) { PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION); if (confirm != null) { try { Log.i(TAG, confirm.toJSONObject().toString(4)); Log.i(TAG, confirm.getPayment().toJSONObject().toString(4)); /** * TODO: send 'confirm' (and possibly confirm.getPayment() to your server for verification * or consent completion. * See https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/ * for more details. * * For sample mobile backend interactions, see * https://github.com/paypal/rest-api-sdk-python/tree/master/samples/mobile_backend */ // displayResultText("PaymentConfirmation info received from PayPal"); // 这里直接跟服务器确认支付结果,支付结果确认后回调处理结果 JSONObject jsonObject = confirm.toJSONObject(); if (jsonObject != null) { JSONObject response = jsonObject.optJSONObject("response"); if (response != null) { String id = response.optString("id"); try { CartManager.getInstance().confirmPayPalPayPrice(context, id, new HttpCallBack<String>() { @Override public void onSuccess(String responseString) { if (responseString != null) { try { JSONObject jsonObject = new JSONObject(responseString); if (jsonObject != null) { int resultcode = jsonObject.optInt("_resultcode"); String msg = jsonObject.optString("_msg"); if (200 == resultcode) { doResult.confirmSuccess(); Log.i(TAG, "dddddddd"); } else { Log.i(TAG, "ssssssss"); CustomToast.getInstance(context).showToast(msg); doResult.confirmNetWorkError(); } CustomToast.getInstance(context).showToast(msg); } } catch (JSONException e) { e.printStackTrace(); doResult.confirmNetWorkError(); } } } @Override public void onFailure(IOException e) { Log.i(TAG, "aaaaaaaa"); doResult.confirmNetWorkError(); } }); } catch (Exception e) { e.printStackTrace(); doResult.confirmNetWorkError(); } } } } catch (JSONException e) { Log.e(TAG, "an extremely unlikely failure occurred: ", e); doResult.confirmNetWorkError(); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i(TAG, "The user canceled."); doResult.customerCanceled(); } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) { doResult.invalidPaymentConfiguration(); Log.i( TAG, "An invalid Payment or PayPalConfiguration was submitted. Please see the docs."); } } else if (requestCode == REQUEST_CODE_FUTURE_PAYMENT) { if (resultCode == Activity.RESULT_OK) { PayPalAuthorization auth = data.getParcelableExtra(PayPalFuturePaymentActivity.EXTRA_RESULT_AUTHORIZATION); if (auth != null) { try { doResult.confirmFuturePayment(); Log.i("FuturePaymentExample", auth.toJSONObject().toString(4)); String authorization_code = auth.getAuthorizationCode(); Log.i("FuturePaymentExample", authorization_code); // sendAuthorizationToServer(auth); // displayResultText("Future Payment code received from PayPal"); } catch (JSONException e) { doResult.confirmNetWorkError(); Log.e("FuturePaymentExample", "an extremely unlikely failure occurred: ", e); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i("FuturePaymentExample", "The user canceled."); doResult.customerCanceled(); } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) { doResult.invalidPaymentConfiguration(); Log.i( "FuturePaymentExample", "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs."); } } else if (requestCode == REQUEST_CODE_PROFILE_SHARING) { if (resultCode == Activity.RESULT_OK) { PayPalAuthorization auth = data.getParcelableExtra(PayPalProfileSharingActivity.EXTRA_RESULT_AUTHORIZATION); if (auth != null) { try { Log.i("ProfileSharingExample", auth.toJSONObject().toString(4)); String authorization_code = auth.getAuthorizationCode(); Log.i("ProfileSharingExample", authorization_code); // sendAuthorizationToServer(auth); // displayResultText("Profile Sharing code received from PayPal"); } catch (JSONException e) { Log.e("ProfileSharingExample", "an extremely unlikely failure occurred: ", e); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i("ProfileSharingExample", "The user canceled."); } else if (resultCode == PayPalFuturePaymentActivity.RESULT_EXTRAS_INVALID) { Log.i( "ProfileSharingExample", "Probably the attempt to previously start the PayPalService had an invalid PayPalConfiguration. Please see the docs."); } } } /** * c处理完结果之后回调 */ public interface DoResult { //与服务确认支付成功 void confirmSuccess(); //网络异常或者json返回有问题 void confirmNetWorkError(); //用户取消支付 void customerCanceled(); //授权支付 void confirmFuturePayment(); //订单支付验证无效 void invalidPaymentConfiguration(); } } `
在你需要调起支付的页面配置支付环境(或者在基类配置相应的支付环境)
` //配置何种支付环境,一般沙盒,正式 private static final String CONFIG_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX; // note that these credentials will differ between live & sandbox environments. //你所注册的APP Id private static final String CONFIG_CLIENT_ID = "你所注册的CLient Id"; private static final int REQUEST_CODE_PAYMENT = 1; private static final int REQUEST_CODE_FUTURE_PAYMENT = 2; private static final int REQUEST_CODE_PROFILE_SHARING = 3; private static PayPalConfiguration config = new PayPalConfiguration() .environment(CONFIG_ENVIRONMENT) .clientId(CONFIG_CLIENT_ID); //以下配置是授权支付的时候用到的 //.merchantName("Example Merchant") // .merchantPrivacyPolicyUri(Uri.parse("https://www.example.com/privacy")) //.merchantUserAgreementUri(Uri.parse("https://www.example.com/legal")); `
在类的onCreate方法里面调起支付服务
` Intent intent = new Intent(this, PayPalService.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config); startService(intent); `
创建支付实体,在需要调起支付的地方调起支付
` public void onBuyPressed(View pressed) { //创建支付对象,用于传过去给PayPal服务器进行收款 PayPalPayment thingToBuy = getThingToBuy(PayPalPayment.PAYMENT_INTENT_SALE); Intent intent = new Intent(SampleActivity.this, PaymentActivity.class); intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, config); intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingToBuy); //这里直接调起PayPal的sdk进行付款操作 startActivityForResult(intent, REQUEST_CODE_PAYMENT); } //这里只传一个总价格或者单个产品的信息收款情况 private PayPalPayment getThingToBuy(String paymentIntent) { return new PayPalPayment(new BigDecimal("0.01"), "USD", "sample item", paymentIntent); } //这里是购买一系列产品创建购买对象 private PayPalPayment getStuffToBuy(String paymentIntent) { PayPalItem[] items = { new PayPalItem("sample item #1", 2, new BigDecimal("87.50"), "USD", "sku-12345678"), new PayPalItem("free sample item #2", 1, new BigDecimal("0.00"), "USD", "sku-zero-price"), new PayPalItem("sample item #3 with a longer name", 6, new BigDecimal("37.99"), "USD", "sku-33333") }; BigDecimal subtotal = PayPalItem.getItemTotal(items); BigDecimal shipping = new BigDecimal("7.21"); BigDecimal tax = new BigDecimal("4.67"); PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails(shipping, subtotal, tax); BigDecimal amount = subtotal.add(shipping).add(tax); PayPalPayment payment = new PayPalPayment(amount, "USD", "sample item", paymentIntent); payment.items(items).paymentDetails(paymentDetails); //--- set other optional fields like invoice_number, custom field, and soft_descriptor payment.custom("This is text that will be associated with the payment that the app can use."); return payment; } `
在类的onActivityResult 里进行回调结果的处理
` if (resultCode == Activity.RESULT_OK) { PaymentConfirmation confirm = data.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION); if (confirm != null) { try { Log.i(TAG, confirm.toJSONObject().toString(4)); Log.i(TAG, confirm.getPayment().toJSONObject().toString(4)); //这里可以把PayPal带回来的json数据传给服务器以确认你的款项是否收到或者收全 //可以直接把 confirm.toJSONObject() 这个带给服务器, //得到服务器返回的结果,你就可以跳转成功页面或者做相应的处理了 } catch (JSONException e) { Log.e(TAG, "an extremely unlikely failure occurred: ", e); } } } else if (resultCode == Activity.RESULT_CANCELED) { Log.i(TAG, "The user canceled."); } else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) { Log.i( TAG, "An invalid Payment or PayPalConfiguration was submitted. Please see the docs."); } }
`
在类的onDestroy 注销服务
` stopService(new Intent(this, PayPalService.class)); `
服务端,根据前端给的paymentId,判断是否完成付款
`
package com.net.pay.paypal.service;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.net.crud.dao.RechargeMapper;
@Service
public class PayPalVerifyPayment {
private static final String TOKEN_URL = "https://api.sandbox.paypal.com/v1/oauth2/token";
private static final String PAYMENT_DETAIL = "https://api.sandbox.paypal.com/v1/payments/payment/";
private static final String clientId = "clientId";
private static final String secret = "secret";
/**
* 获取token
* 了解更多:https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
* @return
*/
private String getAccessToken(){
try{
URL url = new URL(TOKEN_URL);
String authorization = clientId+":"+secret;
authorization = Base64.encodeBase64String(authorization.getBytes());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");// 提交模式
//设置请求头header
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Accept-Language", "en_US");
conn.setRequestProperty("Authorization", "Basic "+authorization);
// conn.setConnectTimeout(10000);//连接超时 单位毫秒
// conn.setReadTimeout(2000);//读取超时 单位毫秒
conn.setDoOutput(true);// 是否输入参数
String params = "grant_type=client_credentials";
conn.getOutputStream().write(params.getBytes());// 输入参数
InputStreamReader inStream = new InputStreamReader(conn.getInputStream());
BufferedReader reader = new BufferedReader(inStream);
StringBuilder result = new StringBuilder();
String lineTxt = null;
while((lineTxt = reader.readLine()) != null){
result.append(lineTxt);
}
reader.close();
String accessTokey = JSONObject.fromObject(result.toString()).optString("access_token");
System.out.println("getAccessToken:"+accessTokey);
return accessTokey;
}catch(Exception err){
err.printStackTrace();
}
return null;
}
/**
* 获取支付详情
* 了解更多:https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
* @param paymentId 支付ID,来自于用户客户端
* @return
*/
public String getPaymentDetails(String paymentId){
try{
URL url = new URL(PAYMENT_DETAIL+paymentId);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");// 提交模式
//设置请求头header
conn.setRequestProperty("Accept", "application/json");
conn.setRequestProperty("Authorization", "Bearer "+getAccessToken());
// conn.setConnectTimeout(10000);//连接超时 单位毫秒
// conn.setReadTimeout(2000);//读取超时 单位毫秒
InputStreamReader inStream = new InputStreamReader(conn.getInputStream());
BufferedReader reader = new BufferedReader(inStream);
StringBuilder result = new StringBuilder();
String lineTxt = null;
while((lineTxt = reader.readLine()) != null){
result.append(lineTxt);
}
reader.close();
return result.toString();
}catch(Exception err){
err.printStackTrace();
}
return null;
}
/**
* 获取支付详情
* 了解更多:https://developer.paypal.com/webapps/developer/docs/integration/mobile/verify-mobile-payment/
* @param paymentId 支付ID,来自于用户客户端
* @return
*/
public boolean verifyPayment(String paymentId) throws Exception {
String str = getPaymentDetails(paymentId);
System.out.println(str);
JSONObject detail = JSONObject.fromObject(str);
//校验订单是否完成
if("approved".equals(detail.optString("state"))){
JSONObject transactions = detail.optJSONArray("transactions").optJSONObject(0);
JSONObject amount = transactions.optJSONObject("amount");
JSONArray relatedResources = transactions.optJSONArray("related_resources");
//从数据库查询支付总金额与Paypal校验支付总金额
double total = 0;
System.out.println("amount.optDouble('total'):"+amount.optDouble("total"));
if( total != amount.optDouble("total") ){
return false;
}
//校验交易货币类型
String currency = "USD";
if( !currency.equals(amount.optString("currency")) ){
return false;
}
//校验每个子订单是否完成
for (int i = 0,j = relatedResources.size(); i < j; i++) {
JSONObject sale = relatedResources.optJSONObject(i).optJSONObject("sale");
if(sale!=null){
if( !"completed".equals(sale.optString("state")) ){
System.out.println("子订单未完成,订单状态:"+sale.optString("state"));
}
}
}
return true;
}
return false;
}
public static void main(String[] args) {
PayPalVerifyPayment payment = new PayPalVerifyPayment();
boolean success = false;
try {
success = payment.verifyPayment("PAY-9MTXXXXXXXXXXXXXXXXXMI");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(success ? "支付完成" : "支付校验失败");
}
}
`
- 本文链接:https://www.ofcoder.com/2018/06/09/integrate/paypal/
- 版权声明:Copyright © 并发笔记 - ofcoder.com. Author by far.
分享