文章目录
1、前置
1、案列采用java编写(其实什么写都一样,没啥区别)
2、主要是介绍paytabs支付的思路,具体代码倒不是很多
3、支付流程和前期博客介绍大致一致
4、会对一些可能出现的坑,或者说我碰到的坑进行标记
5、介绍一下后台管理界面paytabs的官方管理界面
2、WEB支付
我们先看官方链接:Create paypage API
我主要是基于这个API进行开发,所以本案列也是围绕这个进行。最后结尾会简单的介绍一下IOS和Android
进入这个页面我简单的看一下,我就把他理解成是一个web支付界面。这个API文档里面包含了请求,响应,验证付款(查询交易结果)
他这个下面还有STCpay我不是太懂这个,也没有怎么研究,这里我们就只看框框里面的这五个
1、Request
基于这个里面的参数标记的都是必传,我没有试过少一个参数会怎么样。
msg_lang:我填写的就是English
cms_with_version:填写java (这个没有具体的要求,按使用的语言进行填写就行)
amount :这个金额是需要注意的一点,如果货币是美元,那么该金额要大于 1.85
site_url:如果注册的时候没有注意,可以到这个地方取:Home ----->>> My Account ----->>> My Profile ----->>> Store Information ----->>> Site URL
secret_key: Home ----->>> Secret Key
HttpsUtils: 可以参考这边文章,重复代码就懒得贴了,传送门:https://blog.csdn.net/qq_38637558/article/details/78668349
package com.tomorrow.pay.impl;
import com.alibaba.fastjson.JSONObject;
import com.tomorrow.commons.util.HttpsUtils;
import org.apache.log4j.Logger;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* @author Tomorrow
* @date 2020/2/25 2:12
*/
public class TestPayTabs {
private static Logger logger = Logger.getLogger(TestPayTabs.class);
// 商家电子邮件ID
public static final String merchantEmail = "cm646236438@gmail.com";
// 密钥
public static final String merchantSecretKey = "7E3LS3yAwCse4LfGEaqLAUmVL8*****************************";
// API的站点的URL
public static final String siteUrl = "http://00.000.000.000";
// 付款页面请求地址
public static final String CreatePayTabsUrl = "https://www.paytabs.com/apiv2/create_pay_page";
public static JSONObject createPayPage(Map<String, Object> map) {
try {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("merchant_email=" + URLEncoder.encode(merchantEmail, "UTF-8"));
stringBuffer.append("&secret_key=" + URLEncoder.encode(merchantSecretKey, "UTF-8"));
stringBuffer.append("&site_url=" + URLEncoder.encode(siteUrl, "UTF-8"));
for (Map.Entry<String, Object> entry : map.entrySet()) {
if (entry.getValue() == null) {
stringBuffer.append("&" + entry.getKey().toString() + "=" + URLEncoder.encode("", "UTF-8"));
} else {
stringBuffer.append("&" + entry.getKey().toString() + "=" + URLEncoder.encode(entry.getValue().toString(), "UTF-8"));
}
}
Map<String, String> mapHead = new HashMap<>();
mapHead.put("Content-Type", "application/x-www-form-urlencoded");
String post = HttpsUtils.HttpsRequest(CreatePayTabsUrl, "POST", stringBuffer.toString(), mapHead);
JSONObject requestParams = JSONObject.parseObject(JSONObject.toJSON(post).toString());
if ("4012".equals(requestParams.getString("response_code"))) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("code", 200);
jsonObject.put("message", "生成成功");
jsonObject.put("data", requestParams);
return jsonObject;
}
}catch (Exception e) {
logger.error("*************************************");
logger.error(e);
logger.error("PayTabs下单失败: " + e.getMessage());
logger.error("*************************************");
}
return null;
}
public static void main(String[] args) {
Map<String, Object> map = new HashMap<>();
map.put("country", "CHN");
map.put("ip_customer", "127.0.0.1");
map.put("city", "China");
map.put("cms_with_version", "java");
map.put("cc_phone_number", "861");
map.put("discount", 0.0);
map.put("billing_address", "中国湖北省武汉市武昌区");
map.put("title", "产品测试");
map.put("msg_lang", "en");
map.put("country_shipping", "CHN");
map.put("ip_merchant", "00.000.000.000");
map.put("state_shipping", "wuhan");
map.put("cc_last_name", "Tom");
map.put("other_charges", 0.5);
map.put("return_url", "http://www.baidu.com");
map.put("currency", "USD");
map.put("state", "China");
map.put("cc_first_name", "Tomorrow");
map.put("email", "cm646236438@gmail.com");
map.put("amount", 2.5);
map.put("quantity", "2");
map.put("shipping_first_name", "Tomorrow");
map.put("unit_price", "1.00");
map.put("products_per_title", "产品测试");
map.put("postal_code_shipping", "430000");
map.put("shipping_last_name", "Tom");
map.put("phone_number", "13100000000");
map.put("postal_code", "430000");
map.put("city_shipping", "wuhan");
map.put("reference_no", "122333");
map.put("address_shipping", "中国湖北省武汉市武昌区");
JSONObject jsonObject = createPayPage(map);
System.out.println(jsonObject);
}
}
输出:
{
"code": 200,
"data": {
"result": "The Pay Page is created.",
"response_code": "4012",
"payment_url": "https://www.paytabs.com****************",
"p_id": 391323
},
"message": "生成成功"
}
payment_url:就是我们进行支付的界面,跳转到这个界面就行
这个地方p_id 我们是要保存的,因为后面我们查询订单的时候是会使用到的
3、付款
付款,我通过页面来请求payment_url返回的值
测试卡的地址:我们用4111111111111111这个就行,其余的也可以
红色框框内部的可以随意填写,我CVV(这个其实就是我们银行卡后面的那一串数字,有点像手写的那个,白色银联标识上面)填写就是卡号前几位,日期的话就选择时间往后就行。
4、验证交易
这个地方要提一下,因为web交易验证方式和APP交易验证方式是不一样的。两者有些区别,首先入参会不一样,第二个返回的金额类型也会不一样。
web的入参就是我上面提到的p_id
APP的入参我会在后面补充
先说一下两者的不同吧:
1、WEB验证交易入参以及出参:
2、APP验证交易入参以及出参:
web方式验证交易:
// 查询订单接口
public static final String QueryPayTabsUrl = "https://www.paytabs.com/apiv2/verify_payment";
public static JSONObject queryOrder(String pId) {
try {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("merchant_email=" + URLEncoder.encode(merchantEmail, "UTF-8"));
stringBuffer.append("&secret_key=" + URLEncoder.encode(merchantSecretKey, "UTF-8"));
stringBuffer.append("&payment_reference=" + URLEncoder.encode(pId, "UTF-8"));
Map<String, String> mapHead = new HashMap<>();
mapHead.put("Content-Type", "application/x-www-form-urlencoded");
String post = HttpsUtils.HttpsRequest(QueryPayTabsUrl, "POST", stringBuffer.toString(), mapHead);
JSONObject requestParams = JSONObject.parseObject(JSONObject.toJSON(post).toString());
JSONObject jsonObject = new JSONObject();
switch (requestParams.getString("response_code")) {
case "0":
jsonObject.put("code", 500);
jsonObject.put("message", "未支付");
break;
case "4002":
jsonObject.put("code", 500);
jsonObject.put("message", "无此订单号");
break;
case "0404":
jsonObject.put("code", 500);
jsonObject.put("message", "无此权限");
break;
case "400":
jsonObject.put("code", 500);
jsonObject.put("message", "无此交易");
break;
case "100":
jsonObject.put("code", 200);
jsonObject.put("message", "支付成功");
jsonObject.put("data", requestParams);
break;
default:
jsonObject.put("code", 500);
jsonObject.put("message", "查询订单失败");
}
return jsonObject;
}catch (Exception e) {
logger.error("*************************************");
logger.error(e);
logger.error("PayTabs查询失败: " + e.getMessage());
logger.error("*************************************");
}
return null;
}
public static void main(String[] args) {
JSONObject jsonObject = queryOrder("391323");
System.out.println(jsonObject);
}
输出:
{
"code": 200,
"data": {
"result": "The payment is completed successfully!",
"transaction_id": "434281",
"response_code": "100",
"amount": 2.5,
"currency": "USD",
"pt_invoice_id": "391323",
"reference_no": "122333"
},
"message": "支付成功"
}
5、申请退款
退款申请需要正式环境才可以进行调用成功,测试环境是不支持的,但是我们可以调通这个接口:文档
申请退款的入参:transaction_id , 这个是我们验证交易中返回的 transaction_id。这里不是p_id
// 退款订单接口
public static final String RefundPayTabsUrl = "https://www.paytabs.com/apiv2/refund_process";
public static JSONObject refundOrder(String refundAmount, String refundReason, String transactionId ) {
try {
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("merchant_email=" + URLEncoder.encode(merchantEmail, "UTF-8"));
stringBuffer.append("&secret_key=" + URLEncoder.encode(merchantSecretKey, "UTF-8"));
stringBuffer.append("&refund_amount=" + URLEncoder.encode(refundAmount, "UTF-8"));
stringBuffer.append("&refund_reason=" + URLEncoder.encode(refundReason, "UTF-8"));
stringBuffer.append("&transaction_id=" + URLEncoder.encode(transactionId, "UTF-8"));
Map<String, String> mapHead = new HashMap<>();
mapHead.put("Content-Type", "application/x-www-form-urlencoded");
String post = HttpsUtils.HttpsRequest(RefundPayTabsUrl, "POST", stringBuffer.toString(), mapHead);
JSONObject requestParams = JSONObject.parseObject(JSONObject.toJSON(post).toString());
JSONObject jsonObject = new JSONObject();
if ("4012".equals(requestParams.getString("response_code"))) {
jsonObject.put("code", 200);
jsonObject.put("message", "退款成功");
jsonObject.put("data", requestParams);
}
jsonObject.put("code", 500);
jsonObject.put("message", "退款失败");
jsonObject.put("data", requestParams);
return jsonObject;
}catch (Exception e) {
logger.error("*************************************");
logger.error(e);
logger.error("PayTabs下单失败: " + e.getMessage());
logger.error("*************************************");
}
return null;
}
public static void main(String[] args) {
JSONObject jsonObject = refundOrder("2.5", "测试退款", "434281");
System.out.println(jsonObject);
}
输出:
{
"code": 500,
"data": {
"result": "You don't have permissions to raise Refund request.. Because your account is . Refund API can only be used once your account is Active.",
"response_code": "4404"
},
"message": "退款失败"
}
6、IOS、Android 验证交易
首先我不会这个,就打字截图说说
验证交易请求地址 :https://www.paytabs.com/apiv2/verify_payment_transaction
卡名: :Test cards
1、Android:文档
1、我们这边的流程:先请求后端拿到一个订单ID,然后Android调用接口时使用 PaymentParams.ORDER_ID
2、然后SDK会响应返回 TRANSACTION_ID,通过这个后端会在进行订单的验证交易处理
2、IOS:文档
1、我们这边的流程:先请求后端拿到一个订单ID,然后Android调用接口时使用 Order ID
2、然后SDK会响应返回 Transaction ID,通过这个后端会在进行订单的验证交易处理
7:杂谈
1、感觉这个文档还是蛮容易懂的,提供的功能也蛮多的,后期有时间可以研究一下其余的接口
2、代码方面的到还好,主要是这个文档要读懂,至少自己需要的接口相关的文档需要懂,然后代码无非就那么几行,随便写写就OK了
3、 在查询订单,也就是验证交易的时候,我这边是做成的一个接口,通过订单类型进行区分,然后看请求哪个接口,这个时候对返回的金额就需要专门的处理一下,这个地方吃了亏的,哈哈哈哈!!!
4、如果是模拟/测试帐户,只能使用USD,AED或SAR货币来在模拟账户上获得成功的结果。在这个地方弄了个RMB卡了好久,哈哈哈哈!!!
5、然后到也没有什么了,难度…感觉一般吧。就这样吧!!!!!
提供一个群:807770565,欢迎各位进来尬聊