|
|
|
@ -0,0 +1,282 @@
|
|
|
|
|
package au.com.royalpay.payment.manage.citypartner.core.impls;
|
|
|
|
|
|
|
|
|
|
import au.com.royalpay.payment.tools.exceptions.BadRequestException;
|
|
|
|
|
import au.com.royalpay.payment.tools.exceptions.ServerErrorException;
|
|
|
|
|
import cn.yixblog.platform.http.HttpRequestGenerator;
|
|
|
|
|
import cn.yixblog.platform.http.HttpRequestResult;
|
|
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
|
|
|
|
import org.apache.commons.codec.binary.Base64;
|
|
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
|
|
import org.apache.commons.lang3.RandomStringUtils;
|
|
|
|
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
|
|
|
|
import org.apache.commons.lang3.time.DateUtils;
|
|
|
|
|
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
|
|
|
|
import org.junit.Test;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
import org.springframework.boot.test.context.SpringBootTest;
|
|
|
|
|
import org.springframework.web.bind.annotation.RequestMethod;
|
|
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
import java.nio.charset.StandardCharsets;
|
|
|
|
|
import java.security.*;
|
|
|
|
|
import java.security.spec.InvalidKeySpecException;
|
|
|
|
|
import java.security.spec.PKCS8EncodedKeySpec;
|
|
|
|
|
import java.security.spec.X509EncodedKeySpec;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@SpringBootTest
|
|
|
|
|
public class GatewayApplicationMerchantDemoTest {
|
|
|
|
|
|
|
|
|
|
static String SHORTID = "NH6NR8J53M";
|
|
|
|
|
static String RPDEMOPUBKEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtBE+bgY1FHUOP/7PIDdRZH8BUkDJBpZkI5kh+ytJs7uLJY7LJMOG2HTkJv5SdzdsBBaJgGAHcIjZrsd6oRrcBohWmAxTN0p+vlQEwNd689mlOAObds23lXWtn+huDv8cjorC4Doy79grPni8SZYJocqs9qFpdaQLIZaGUIRTIE0eTSV2tZ3ry4l6kNdFLpkBvXW76iWC6CZcrfuGcgiJq438CmFeXrY5HQPjRZfq243fFjyMPmc9ZfGiwqJERCQlwmLtVcgWPTjkIEhpPt8bldV6kZ9ctSUJr+KyC827kHrn/YAFj5DJWqX4mXW84w1OUeQZQlPOpNvzojbMfiW60wIDAQAB";
|
|
|
|
|
static String SPDEMOPRIKEY = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdIiy3fFUrZx4X0aIU37PGzViqG03yRDprSk2tqhORnAiZL3sLNFsjmy2FR4+84bksp2VxIc+rMot+4iFIAmpK50t6qj2Fz7sOO5DMSN0pRN9flIqQ1RFKYnIQN+BymfJ9bXbMN2aN+sbfZzZRTAZPtJuES9JIrmUDi4NwNeqBSjhflUqlyYx3ejMx2CrxHAS+35W5fAK88e//9SQiMdKHzNPFl4vXtCMqTY7Mk7febLfsG0aaRVMM/QOeT57sszB3Wib3wUFi9xGsqdqLi0skAWc4QmOGOoue7uvieghFWZXETfFN/K3wSz5TzVS55ma2u3KOkn8/M4E7J96RHzAPAgMBAAECggEAet+ueA0RzM7mCVo0lH4Z5uvM2bhgS4Ju7Fc+Rv8oLkUFtEQcw7Y9TqqZ/g7np5wbYX/FI6J88jKkQqQxwk2hMNGNhG57jZfTfl217QlNaGgjBGrzsC3tR22UJHqNWRBpPwvKSgdIet4PhcMABrKcfNeOhPWFirBU7WC7d5OxvUdA3oCnZXZ7nGxgyX06actjb3GhIUybi4DJosCY3NkBsUXWLh45Kmm8IfJv29cd+VrIBn5i1+mMd6hECmiN03ToH9dc3o1aS4YGJirvkf1q1oiJJMT7exacuZiTrRfUh+NIemm8oaBYJj9PMcy5PEtS/ZyJe7jzDEnbV71i5dnkAQKBgQDhXej3o3KyvP9h/nwH/gifK/Urai0u/SB6CScb8c0xzHoQhomjNaaHHKX82j8zDYMvg7yNWHEo5WdCEcenvjO4OWkbhL9brBJnpN5QyfPtjijUh/8PFNKu/NP0PISkFjuAOp+LVgMRgrfQL/wu1/zp6jgsAXckauUIBNITZPTWrwKBgQCyffLy1Cc1tSovzXchty7TLU49IzNZQ3keMEy8MWw6YFS5PGUSEixtjvsAuzoYMg6w7F/LxK8jMfOcDPza1AJUQIByXPoZs4jm31j6EPjPYP+ocQ04Ji+OOcbR5TOlFamNMnjQNlTqpEmNYpQcKp8AOyGm0dSMHe7YUKqzaymUoQKBgQDNQ4aL/s/aIjAM5ge8E9FwgE4GY+eRc7Wf0TRQzHSTVeUbph44jAYH67z3RyTm7/i7TyZuKs6ua/sXfzA1BRUARzIHgWn1Kg19Xvmp5bcJeECSCufxqYqXHOpD+tboyOMa0Mo903JqAYA/22S6mbjeqJjO4+rLPZ0rJ5DbX0ltOwKBgA+3rYwaiHVfRZ69/g6W/eWUqL4TenMS0PiKkkdEJt6hGvTQz6methDTtWCkHAKDbe3ActMTt8RmoqgMMLvoTWgz4duwOknHGHgUFNa4ZeCFDx47Dknyet+QUOSsxTZ1SN/pIOBc2G9tFhkAJECytBumGVmCQrAv9pdPyyhPeHLhAoGATvtEmi3oYPQtoy8qDEhI8wCXrrKIZh2a7ahRjt8B056HZ26EjalKg2Yz+5WTRbS6Bgr8ZN+12wRl7CbjWyr+loOEsMTjAuJoxGDo9bm936IqvmwVlEdLkOoMoFnJY6OFiVqWmLIXHr56+z2ShryZVPc59gdLxNRA+ZJMF5kY27s=";
|
|
|
|
|
static String SPDEMOPUBKEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnSIst3xVK2ceF9GiFN+zxs1YqhtN8kQ6a0pNraoTkZwImS97CzRbI5sthUePvOG5LKdlcSHPqzKLfuIhSAJqSudLeqo9hc+7DjuQzEjdKUTfX5SKkNURSmJyEDfgcpnyfW12zDdmjfrG32c2UUwGT7SbhEvSSK5lA4uDcDXqgUo4X5VKpcmMd3ozMdgq8RwEvt+VuXwCvPHv//UkIjHSh8zTxZeL17QjKk2OzJO33my37BtGmkVTDP0Dnk+e7LMwd1om98FBYvcRrKnai4tLJAFnOEJjhjqLnu7r4noIRVmVxE3xTfyt8Es+U81UueZmtrtyjpJ/PzOBOyfekR8wDwIDAQAB";
|
|
|
|
|
/**
|
|
|
|
|
* The demo can run tests directly
|
|
|
|
|
*/
|
|
|
|
|
private static Provider securityProvider = new BouncyCastleProvider();
|
|
|
|
|
private Logger logger = LoggerFactory.getLogger(getClass());
|
|
|
|
|
|
|
|
|
|
private static PublicKey loadPublicKey(InputStream ins) {
|
|
|
|
|
try {
|
|
|
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
|
|
|
|
|
String line;
|
|
|
|
|
StringBuilder certBuffer = new StringBuilder();
|
|
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
if (line.startsWith("-")) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
certBuffer.append(line).append("\r");
|
|
|
|
|
}
|
|
|
|
|
return resolvePublic(Base64.decodeBase64(certBuffer.toString()));
|
|
|
|
|
} catch (IOException | InvalidKeySpecException e) {
|
|
|
|
|
throw new ServerErrorException(e);
|
|
|
|
|
} finally {
|
|
|
|
|
IOUtils.closeQuietly(ins);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static PublicKey resolvePublic(byte[] bytes) throws InvalidKeySpecException {
|
|
|
|
|
X509EncodedKeySpec x509 = new X509EncodedKeySpec(bytes);
|
|
|
|
|
try {
|
|
|
|
|
KeyFactory factory = KeyFactory.getInstance("RSA", securityProvider);
|
|
|
|
|
return factory.generatePublic(x509);
|
|
|
|
|
} catch (NoSuchAlgorithmException e) {
|
|
|
|
|
//Shall Never Happense
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static PrivateKey loadPrivateKey(InputStream ins) {
|
|
|
|
|
try {
|
|
|
|
|
BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
|
|
|
|
|
String line;
|
|
|
|
|
StringBuilder certBuffer = new StringBuilder();
|
|
|
|
|
while ((line = reader.readLine()) != null) {
|
|
|
|
|
if (line.startsWith("-")) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
certBuffer.append(line);
|
|
|
|
|
}
|
|
|
|
|
return resolvePrivate(Base64.decodeBase64(certBuffer.toString()));
|
|
|
|
|
} catch (IOException | InvalidKeySpecException e) {
|
|
|
|
|
throw new ServerErrorException(e);
|
|
|
|
|
} finally {
|
|
|
|
|
IOUtils.closeQuietly(ins);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static PrivateKey resolvePrivate(byte[] bytes) throws InvalidKeySpecException {
|
|
|
|
|
PKCS8EncodedKeySpec pkcs8 = new PKCS8EncodedKeySpec(bytes);
|
|
|
|
|
try {
|
|
|
|
|
KeyFactory factory = KeyFactory.getInstance("RSA", securityProvider);
|
|
|
|
|
return factory.generatePrivate(pkcs8);
|
|
|
|
|
} catch (NoSuchAlgorithmException e) {
|
|
|
|
|
//Shall Never happens
|
|
|
|
|
e.printStackTrace();
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void applicationMerchant() throws Exception {
|
|
|
|
|
JSONObject companyInfo = new JSONObject() {{
|
|
|
|
|
put("company_name", "CompanyLongName");
|
|
|
|
|
put("short_name", "CompanyShortName");
|
|
|
|
|
put("store_name", "StoreName");
|
|
|
|
|
put("business_name", null);
|
|
|
|
|
put("business_structure", "ASSOCIATION");
|
|
|
|
|
put("abn", "2332423");
|
|
|
|
|
put("acn", null);
|
|
|
|
|
put("company_phone", "0411120000");
|
|
|
|
|
put("logo_url", "https://file.royalpay.com.au/open/2018/11/01/1541059398731_7fJpTXCHagUGOHjc7NfvZIxEP28yMD.png");
|
|
|
|
|
}};
|
|
|
|
|
JSONObject contactInfo = new JSONObject() {{
|
|
|
|
|
put("contact_person", "Applicant name");
|
|
|
|
|
put("contact_phone", "0411120000");
|
|
|
|
|
put("contact_email", "anyemail@test.com");
|
|
|
|
|
put("contact_job", "General Manager");
|
|
|
|
|
put("address", "111 Bourke Street");
|
|
|
|
|
put("suburb", "Melbourne");
|
|
|
|
|
put("postcode", "3000");
|
|
|
|
|
put("state", "VIC");
|
|
|
|
|
put("country", "AUS");
|
|
|
|
|
put("registered_address", "111 Bourke Street");
|
|
|
|
|
put("registered_suburb", "Melbourne");
|
|
|
|
|
put("registered_postcode", "3000");
|
|
|
|
|
put("registered_state", "VIC");
|
|
|
|
|
put("timezone", "Australia/Melbourne"); //"AUSTRALIA_MELBOURNE" is illegal, just need to fill in the enumerated values
|
|
|
|
|
}};
|
|
|
|
|
JSONObject ClientLegalConfig = new JSONObject() {{
|
|
|
|
|
put("legal_representative_person", "Legal contact person name");
|
|
|
|
|
put("legal_representative_phone", "0411120001");
|
|
|
|
|
put("legal_representative_email", "legalcontactemail@test.com");
|
|
|
|
|
put("legal_representative_job", "Legal contact job title");
|
|
|
|
|
}};
|
|
|
|
|
JSONObject clientPayConfig = new JSONObject() {{
|
|
|
|
|
put("client_pay_type", "1"); //"1:The online payment" is illegal,just need to fill in the enumerated values
|
|
|
|
|
put("client_pay_desc", "101");//"101:PC Web" is illegal,just need to fill in the enumerated values
|
|
|
|
|
put("royalpay_industry", "70001");//"Supermarket" is illegal,just need to fill in the enumerated values
|
|
|
|
|
put("company_website", "www.anywebsite.com.au");
|
|
|
|
|
}};
|
|
|
|
|
JSONObject settleConfig = new JSONObject() {{
|
|
|
|
|
put("swift_code", "BKWAAU6P");
|
|
|
|
|
put("bsb_no", "063551");
|
|
|
|
|
put("account_no", "00000000");
|
|
|
|
|
put("account_name", "account name");
|
|
|
|
|
put("clean_days", 1);
|
|
|
|
|
put("wechat_rate", 2.5); //0 is not allowed
|
|
|
|
|
put("alipay_rate", 2.5); //0 is not allowed
|
|
|
|
|
put("alipay_online_rate", 2.5); //0 is not allowed
|
|
|
|
|
put("transaction_fee", 0);
|
|
|
|
|
put("active_time", DateFormatUtils.format(new Date(),"yyyy-MM-dd HH:mm:ss")); //Please format the date :'yyyy-MM-dd HH:mm:ss"'
|
|
|
|
|
put("expire_time", DateFormatUtils.format(DateUtils.addYears(new Date(), 1), "yyyy-MM-dd HH:mm:ss"));//Please format the date :'yyyy-MM-dd HH:mm:ss"'
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
JSONObject complianceInfo = new JSONObject() {{
|
|
|
|
|
put("id_type", "passport");//"passport:Passport" is illegal,just need to fill in the enumerated values
|
|
|
|
|
put("id_title", "Ultimate beneficiary owner");//"jobTitle" is illegal,Legal values:"Ultimate beneficiary owner"| "CEO"| "Director"| "General Manager"| "Other"
|
|
|
|
|
put("bank_statement", "https://file.royalpay.com.au/open/2018/11/01/1541059398731_7fJpTXCHagUGOHjc7NfvZIxEP28yMD.png");
|
|
|
|
|
put("certificate_of_registration", "https://file.royalpay.com.au/open/2018/11/01/1541059398731_7fJpTXCHagUGOHjc7NfvZIxEP28yMD.pn");
|
|
|
|
|
put("id_file", "https://file.royalpay.com.au/open/2018/11/01/1541059398731_7fJpTXCHagUGOHjc7NfvZIxEP28yMD.png");
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
JSONObject params = new JSONObject() {{
|
|
|
|
|
put("apply_id", "orgtestadmin3"); //username = spadmin or spgwadmin
|
|
|
|
|
put("company_info", companyInfo);
|
|
|
|
|
put("contact_info", contactInfo);
|
|
|
|
|
put("legal_info", ClientLegalConfig);
|
|
|
|
|
put("pay_info", clientPayConfig);
|
|
|
|
|
put("settle_info", settleConfig);
|
|
|
|
|
put("compliance_file_info", complianceInfo);
|
|
|
|
|
}};
|
|
|
|
|
String originUrl = "https://sandbox.royalpay.com.au/api/v1.0/org_gateway/partners/" + SHORTID + "/merchant/application";
|
|
|
|
|
String url = addSignUrl(originUrl, params, SPDEMOPRIKEY);
|
|
|
|
|
HttpRequestGenerator gen = new HttpRequestGenerator(url, RequestMethod.POST);
|
|
|
|
|
gen.setJSONEntity(params);
|
|
|
|
|
gen.setTimeout(10000);
|
|
|
|
|
HttpRequestResult result = gen.execute();
|
|
|
|
|
if (result.isSuccess()) {
|
|
|
|
|
JSONObject resultJson = result.getResponseContentJSONObj();
|
|
|
|
|
logger.debug("result info :{}", resultJson.toJSONString());
|
|
|
|
|
if (!signIsValid(resultJson)) {
|
|
|
|
|
throw new BadRequestException("Sign Invalid");
|
|
|
|
|
}
|
|
|
|
|
//todo save partner_code && credential_code
|
|
|
|
|
}else {
|
|
|
|
|
//todo error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean signIsValid(JSONObject jsonObject) {
|
|
|
|
|
JSONObject data = jsonObject.getJSONObject("data");
|
|
|
|
|
String sign = jsonObject.getString("sign");
|
|
|
|
|
return checkSign(JSONObject.toJSONBytes(data, SerializerFeature.MapSortField), sign, RPDEMOPUBKEY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void queryMerchantStatus() throws Exception{
|
|
|
|
|
String partnerCode = "PHQ3";
|
|
|
|
|
String originUrl = "https://sandbox.royalpay.com.au/api/v1.0/org_gateway/partners/" + SHORTID + "/merchant/" + partnerCode + "/status";
|
|
|
|
|
String url = addSignUrl(originUrl, null, SPDEMOPRIKEY);
|
|
|
|
|
HttpRequestGenerator gen = new HttpRequestGenerator(url, RequestMethod.GET);
|
|
|
|
|
HttpRequestResult result = gen.execute();
|
|
|
|
|
if (result.isSuccess()) {
|
|
|
|
|
JSONObject resultJson = result.getResponseContentJSONObj();
|
|
|
|
|
logger.debug("result info :{}", resultJson.toJSONString());
|
|
|
|
|
if (!signIsValid(resultJson)) {
|
|
|
|
|
throw new BadRequestException("Sign Invalid");
|
|
|
|
|
}
|
|
|
|
|
}else {
|
|
|
|
|
//todo error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Test
|
|
|
|
|
public void updateFile() throws Exception{
|
|
|
|
|
String originUrl = "https://sandbox.royalpay.com.au/api/v1.0/org_gateway/partners/" + SHORTID + "/attachment/files";
|
|
|
|
|
String url = addSignUrl(originUrl, null, SPDEMOPRIKEY);
|
|
|
|
|
File file = new File("/Users/1/Downloads/banner_eshop.jpg");
|
|
|
|
|
InputStream stream = new FileInputStream(file);
|
|
|
|
|
HttpRequestGenerator gen = new HttpRequestGenerator(url, RequestMethod.POST);
|
|
|
|
|
gen.setTimeout(10000);
|
|
|
|
|
gen.initFileEntity().attachFile("file", "banner_eshop.jpg", stream);
|
|
|
|
|
HttpRequestResult result = gen.execute();
|
|
|
|
|
if (result.isSuccess()) {
|
|
|
|
|
JSONObject resultJson = result.getResponseContentJSONObj();
|
|
|
|
|
logger.debug("result info :{}", resultJson.toJSONString());
|
|
|
|
|
if (!signIsValid(resultJson)) {
|
|
|
|
|
throw new BadRequestException("Sign Invalid");
|
|
|
|
|
}
|
|
|
|
|
}else {
|
|
|
|
|
//todo error
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String addSignUrl(String originUrl, JSONObject params, String priKey) {
|
|
|
|
|
if (params == null) {
|
|
|
|
|
params = new JSONObject();
|
|
|
|
|
}
|
|
|
|
|
String nonceStr = RandomStringUtils.random(15, true, true);
|
|
|
|
|
params.put("url", originUrl);
|
|
|
|
|
params.put("sign_type", "RSA2");
|
|
|
|
|
params.put("nonce_str", nonceStr);
|
|
|
|
|
String signStr = generateSign(JSONObject.toJSONBytes(params, SerializerFeature.MapSortField), priKey);
|
|
|
|
|
originUrl += ("?nonce_str=" + nonceStr);
|
|
|
|
|
originUrl += "&sign_type=RSA2";
|
|
|
|
|
originUrl += "&sign=" + signStr;
|
|
|
|
|
return originUrl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String generateSign(byte[] source, String privateKey) {
|
|
|
|
|
try {
|
|
|
|
|
PrivateKey priKey = loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes(StandardCharsets.UTF_8)));
|
|
|
|
|
Signature signature = Signature.getInstance("SHA256withRSA");
|
|
|
|
|
signature.initSign(priKey);
|
|
|
|
|
signature.update(source);
|
|
|
|
|
byte[] signed = signature.sign();
|
|
|
|
|
return Base64.encodeBase64URLSafeString(signed);
|
|
|
|
|
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
|
|
|
|
|
//shall never happen
|
|
|
|
|
throw new ServerErrorException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private boolean checkSign(byte[] source, String sign, String publicKey) {
|
|
|
|
|
try {
|
|
|
|
|
PublicKey pubKey = loadPublicKey(new ByteArrayInputStream(publicKey.getBytes(StandardCharsets.UTF_8)));
|
|
|
|
|
Signature signature = Signature.getInstance("SHA256withRSA");
|
|
|
|
|
signature.initVerify(pubKey);
|
|
|
|
|
signature.update(source);
|
|
|
|
|
return signature.verify(Base64.decodeBase64(sign));
|
|
|
|
|
} catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) {
|
|
|
|
|
//shall never happen
|
|
|
|
|
throw new ServerErrorException(e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|