[web3j]java使用web3j调用以太坊私链上的智能合约

/ 21,767评论 / 75341阅读 / 10点赞

环境


web3j命令行工具

* 这个工具可以帮我们把合约生成为一个java类,供我们实现java调用智能合约。

* github项目链接


安装4.5.5以上的新版本(4.9)


安装4.5.5以及之前的旧版本

此时的目录结构
web3j_home=/usr/local/sbin/web3j
PATH=$web3j_home/bin:$PATH
export PATH

在Maven中导入web3j

<dependency>
  <groupId>org.web3j</groupId>
  <artifactId>core</artifactId>
  <version>4.9.0</version>
</dependency>
<dependency>
  <groupId>org.web3j</groupId>
  <artifactId>core</artifactId>
  <version>4.9.0-android</version>
</dependency>

生成测试文件(java智能合约封装器)

准备sol,abi和bin文件

// SPDX-License-Identifier: SimPL-2.0
pragma solidity >=0.4.0 <=0.7.0;

contract HelloWorld {
    uint count = 2022;
    
    function setCount(uint in_count) public
    {
        count = in_count;
    }

    function GetCount()public view returns(uint)
    {
        return count;
    }
}

使用web3j把智能合约生成java类

web3j generate solidity -a hello.abi -b hello.bin -o ./web_hello -p com.coolight.hello

修改web3j自动生成的java类

    //web3j自动生成的函数
    public RemoteFunctionCall<TransactionReceipt> GetCount() {
        final Function function = new Function(
                FUNC_GETCOUNT, 
                Arrays.<Type>asList(), 
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }
    //增加的函数
    public RemoteFunctionCall<BigInteger> GetCountReturn() {
        final Function function = new Function(
                FUNC_GETCOUNT,
                Collections.emptyList(),
                Arrays.asList(new TypeReference<Uint256>(){}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }
    //web3j自动生成的函数
    public RemoteFunctionCall<TransactionReceipt> getUserEvent(String user_name) 
    {
        final Function function = new Function(
                FUNC_GETUSEREVENT,
                Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(user_name)),
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

    //增加的函数
    public RemoteFunctionCall<String> getUserEventReturn(String user_name) {
        final Function function = new Function(
                FUNC_GETUSEREVENT,
                Arrays.asList(new org.web3j.abi.datatypes.Utf8String(user_name)),
                Arrays.asList(new TypeReference<Utf8String>(){}));
        return  executeRemoteCallSingleValueReturn(function, String.class);
    }
    //web3j自动生成的函数
    public RemoteFunctionCall<TransactionReceipt> getUserLen(String user_name) {
        final Function function = new Function(
                FUNC_GETUSERLEN,
                Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(user_name)),
                Collections.<TypeReference<?>>emptyList());
        return  executeRemoteCallTransaction(function);
    }

    //增加的函数
    public RemoteFunctionCall<BigInteger> getUserLenReturn(String user_name) {
        final Function function = new Function(
                FUNC_GETUSERLEN,
                Arrays.asList(new org.web3j.abi.datatypes.Utf8String(user_name)),
                Arrays.asList(new TypeReference<Uint256>(){}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.RemoteFunctionCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;

/**
 * <p>Auto generated code.
 * <p><strong>Do not modify!</strong>
 * <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
 * or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the 
 * <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
 *
 * <p>Generated with web3j version 4.5.5.
 */
@SuppressWarnings("rawtypes")
public class Hello extends Contract {
    private static final String BINARY = "{\n"
            + "\t\"linkReferences\": {},\n"
            + "\t\"object\": \"60806040526107e660005534801561001657600080fd5b5060c7806100256000396000f3fe6080604052348015600f57600080fd5b506004361060325760003560e01c80630ab93971146037578063d14e62b8146053575b600080fd5b603d607e565b6040518082815260200191505060405180910390f35b607c60048036036020811015606757600080fd5b81019080803590602001909291905050506087565b005b60008054905090565b806000819055505056fea26469706673582212205f4a89ec8a6affc1a5970dfedafa55c57435fd83a7635cd22b59193fcb6e42e964736f6c63430007000033\",\n"
            + "\t\"opcodes\": \"PUSH1 0x80 PUSH1 0x40 MSTORE PUSH2 0x7E6 PUSH1 0x0 SSTORE CALLVALUE DUP1 ISZERO PUSH2 0x16 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xC7 DUP1 PUSH2 0x25 PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN INVALID PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x4 CALLDATASIZE LT PUSH1 0x32 JUMPI PUSH1 0x0 CALLDATALOAD PUSH1 0xE0 SHR DUP1 PUSH4 0xAB93971 EQ PUSH1 0x37 JUMPI DUP1 PUSH4 0xD14E62B8 EQ PUSH1 0x53 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x3D PUSH1 0x7E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x7C PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x20 DUP2 LT ISZERO PUSH1 0x67 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0x87 JUMP JUMPDEST STOP JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 POP SWAP1 JUMP JUMPDEST DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP JUMP INVALID LOG2 PUSH5 0x6970667358 0x22 SLT KECCAK256 0x5F 0x4A DUP10 0xEC DUP11 PUSH11 0xFFC1A5970DFEDAFA55C574 CALLDATALOAD REVERT DUP4 0xA7 PUSH4 0x5CD22B59 NOT EXTCODEHASH 0xCB PUSH15 0x42E964736F6C634300070000330000 \",\n"
            + "\t\"sourceMap\": \"75:231:0:-:0;;;115:4;102:17;;75:231;;;;;;;;;;;;;;;;\"\n"
            + "}\n";

    public static final String FUNC_GETCOUNT = "GetCount";

    public static final String FUNC_SETCOUNT = "setCount";

    @Deprecated
    protected Hello(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    protected Hello(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        super(BINARY, contractAddress, web3j, credentials, contractGasProvider);
    }

    @Deprecated
    protected Hello(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    protected Hello(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        super(BINARY, contractAddress, web3j, transactionManager, contractGasProvider);
    }

    public RemoteFunctionCall<TransactionReceipt> GetCount() {
        final Function function = new Function(
                FUNC_GETCOUNT, 
                Arrays.<Type>asList(), 
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

    // 新增获取返回值方法
    public RemoteFunctionCall<BigInteger> GetCountReturn() {
        final Function function = new Function(
                FUNC_GETCOUNT, 
                Collections.emptyList(),
                Arrays.asList(new TypeReference<Uint256>(){}));
        return executeRemoteCallSingleValueReturn(function, BigInteger.class);
    }

    public RemoteFunctionCall<TransactionReceipt> setCount(BigInteger in_count) {
        final Function function = new Function(
                FUNC_SETCOUNT, 
                Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(in_count)), 
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

    @Deprecated
    public static Hello load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return new Hello(contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    @Deprecated
    public static Hello load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return new Hello(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    public static Hello load(String contractAddress, Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        return new Hello(contractAddress, web3j, credentials, contractGasProvider);
    }

    public static Hello load(String contractAddress, Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        return new Hello(contractAddress, web3j, transactionManager, contractGasProvider);
    }

    public static RemoteCall<Hello> deploy(Web3j web3j, Credentials credentials, ContractGasProvider contractGasProvider) {
        return deployRemoteCall(Hello.class, web3j, credentials, contractGasProvider, BINARY, "");
    }

    @Deprecated
    public static RemoteCall<Hello> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return deployRemoteCall(Hello.class, web3j, credentials, gasPrice, gasLimit, BINARY, "");
    }

    public static RemoteCall<Hello> deploy(Web3j web3j, TransactionManager transactionManager, ContractGasProvider contractGasProvider) {
        return deployRemoteCall(Hello.class, web3j, transactionManager, contractGasProvider, BINARY, "");
    }

    @Deprecated
    public static RemoteCall<Hello> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return deployRemoteCall(Hello.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "");
    }
}

测试调用智能合约

import java.math.BigInteger;

import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.admin.Admin;
import org.web3j.protocol.admin.methods.response.PersonalUnlockAccount;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGetBalance;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.RawTransactionManager;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

public class App
{
   // 1 - 智能合约地址
   private static String contractAddress = "0x62f7ca98490B199857ccDf9e68C218DEf5000d50";

    //燃料消耗
    private static final BigInteger gasPrice = new BigInteger("100000");

    //消耗限制
    private static final BigInteger gasLimit = new BigInteger("300000");

    //2 - 私链ID
    private static final long chainId = 7;


   // main method
   public static void main(String[] args) {

        //3 - 私钥的文件名
        String fileName = "UTC--2022-01-22T14-43-04.829667987Z--7cbad9dbed1f3ef418de1f0c6412cfec197c7751";
        try{
        // 4 - 加载 web3j - 这里需要修改为你要连接的节点链接
       Web3j web3 = Web3j.build(new HttpService("http://localhost:8545/"));

        // 5 - 加载账号 - 第一个String是密码,第二个是私钥的文件路径
       Credentials credentials = WalletUtils.loadCredentials("123456", "/home/0Acoolight/geth/rungeth/data/keystore/" + fileName);
       // 6 - 加载合约
       Hello contract = Hello.load(
           contractAddress, web3,
           new RawTransactionManager(web3, credentials, chainId),
           new StaticGasProvider(gasPrice, gasLimit)
       );
       // say hello
       System.out.println("Welcome coolight - " + credentials.getAddress());
       // 7 - 调用智能合约
           BigInteger currentValue;
           // 获取Count的值 - 调用GetCountReturn() 相当于合约中的GetCount()
           currentValue = contract.GetCountReturn().send();
           System.out.println(currentValue);
           // 修改Count的值 - 调用setCount()
           contract.setCount(new BigInteger("1")).send();
           // 获取Count的值
           currentValue = contract.GetCountReturn().send();
           System.out.println(currentValue);
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

本文所用文件打包

如果显示需要登录,请刷新页面或点击此处下载

常见问题


常见数据类型所在包

  1. RobertInpup说道:

    where can i buy clomid no prescription: order generic clomid prices – how to get generic clomid tablets

  2. Тут можно преобрести сейф взломостойкий взломостойкие сейфы

  3. Jugabet_jmml说道:

    Jugabet casino [url=http://www.superogorod.ucoz.org/forum/2-2293-1]Jugabet casino[/url] .

  4. Danielplent说道:

    https://clomidonpharm.com/# where buy clomid no prescription

  5. RobertInpup说道:

    ciprofloxacin generic price: buy cipro no rx – ciprofloxacin

  6. Shaneuncog说道:

    Please let me know if you’re looking for a article writer for your blog. You have some really great posts and I believe I would be a good asset. If you ever want to take some of the load off, I’d love to write some material for your blog in exchange for a link back to mine. Please shoot me an e-mail if interested. Thank you!
    фильмы онлайн бесплатно

  7. Danielplent说道:

    https://cipharmdelivery.com/# where to buy cipro online

  8. Jugabet_dwml说道:

    Jugabet bonos [url=https://aqvakr.forum24.ru/?1-7-0-00011967-000-0-0-1734608905]Jugabet bonos[/url] .

  9. Тут можно преобрести cейф взломостойкий взломостойкие сейфы для дома

  10. onexbet_pfsa说道:

    Самый популярный букмекер onexbet, присоединяйтесь и выигрывайте|Профессиональные прогнозы от onexbet, большие деньги ждут вас|Безопасные ставки с onexbet, играйте честно и безопасно|Приятные сюрпризы от onexbet, участвуйте в акциях и выигрывайте|Играйте в казино онлайн на onexbet, наслаждайтесь игрой в любое время суток|Надежный сервис onexbet, получите свои деньги моментально|Легальное онлайн казино onexbet, ваша безопасность – важнее всего|Онлайн трансляции спортивных событий на onexbet, ставьте деньги и наслаждайтесь игрой|Больше выгодных предложений на onexbet, получите возможность выиграть дополнительные призы|Азартные игры с живыми дилерами на onexbet, получайте эмоции и азарт вместе с onexbet|Следите за результатами на onexbet, получайте прибыль от своих прогнозов|Делайте выгодные прогнозы и зарабатывайте, выигрывайте больше и чаще|Непревзойденная возможность заработать деньги, играйте и побеждайте с onexbet|Ваш комфорт – наш приоритет, гарантия качественного обслуживания|Сделайте ставки с комфортом и удовольствием, новый уровень игрового опыта|Большие джекпоты на onexbet, не упустите возможность стать богаче|Получайте прибыль от своих прогнозов, играть и выигрывать стало проще|Увеличьте свои шансы на победу с onexbet, ваш выигрыш – наша главная задача|Больше выигрышей с onexbet, делайте прогнозы и получайте прибыль|Профессиональная букмекерская контора onex
    one x bet download apk one x bet download apk .

  11. onexbet_absa说道:

    Большие выигрыши с onexbet, присоединяйтесь и выигрывайте|Больше шансов на победу с onexbet, большие деньги ждут вас|Защитите свои деньги с onexbet, не рискуйте сомнительными сайтами|Больше шансов на успех с onexbet, не упустите возможность удвоить свой выигрыш|Играйте в казино онлайн на onexbet, наслаждайтесь игрой в любое время суток|Беспрецедентный уровень обслуживания на onexbet, важны ваш комфорт и удобство|Законные ставки на onexbet, играйте честно и законно|Смотрите спорт в прямом эфире на onexbet, выигрывайте, не выходя из дома|Больше выгодных предложений на onexbet, не упустите шанс стать богаче|Играйте с живыми дилерами на onexbet, ощутите атмосферу настоящего казино|Большой выбор спортивных событий на onexbet, получайте прибыль от своих прогнозов|Делайте выгодные прогнозы и зарабатывайте, получайте прибыль без лишних затрат|Непревзойденная возможность заработать деньги, делайте ставки с выгодой и уверенностью|Онлайн поддержка пользователей на onexbet, наши специалисты помогут вам 24/7|Сделайте ставки с комфортом и удовольствием, новый уровень игрового опыта|Играйте и выигрывайте крупные суммы, ваша удача ждет вас в онлайн казино|Зарабатывайте на ставках с onexbet, новый уровень заработка|Увеличьте свои шансы на победу с onexbet, ваш выигрыш – наша главная задача|Больше выигрышей с onexbet, больше денег с onexbet|Профессиональная букмекерская контора onex
    download onexbet apk https://arxbetdslps.com/ .

  12. onexbet_yasa说道:

    Самый популярный букмекер onexbet, присоединяйтесь и выигрывайте|Успешные ставки на спорт с onexbet, большие деньги ждут вас|Защитите свои деньги с onexbet, играйте честно и безопасно|Больше шансов на успех с onexbet, получите дополнительные ставки бесплатно|Играйте в казино онлайн на onexbet, наслаждайтесь игрой в любое время суток|Надежный сервис onexbet, играйте без задержек и проблем|Соблюдайте законодательство с onexbet, играйте честно и законно|Не упустите шанс следить за любимыми матчами, прогнозируйте и побеждайте онлайн|Участвуйте в уникальных акциях onexbet, бонусы и подарки ждут вас|Азартные игры с живыми дилерами на onexbet, новый уровень азарта в онлайн казино|Следите за результатами на onexbet, получайте прибыль от своих прогнозов|Заработайте на ставках с onexbet, выигрывайте больше и чаще|Лучшие коэффициенты и выигрыши на onexbet, играйте и побеждайте с onexbet|Онлайн поддержка пользователей на onexbet, не оставляйте вопросов без ответа|Сделайте ставки с комфортом и удовольствием, играйте без стресса и неудобств|Увеличьте свои шансы на миллион с onexbet, ставьте и получайте крупные выигрыши|Получайте прибыль от своих прогнозов, играть и выигрывать стало проще|Персональный коэффициент успеха на onexbet, получайте индивидуальные предложения и бонусы|Больше выигрышей с onexbet, успешные ставки – это реально|Профессиональная букмекерская контора onex
    download one x bet https://arxbetdslps.com/ .

  13. Тут можно преобрести сейф пожаровзломостойкие купить сейфы офисные взломостойкие

  14. Danielplent说道:

    http://cipharmdelivery.com/# ciprofloxacin order online

  15. KennethCex说道:

    can you buy amoxicillin over the counter AmoxStar amoxicillin discount coupon

  16. SamuelDarse说道:

    order amoxicillin online: amoxicillin without rx – amoxicillin where to get

  17. RobertInpup说道:

    amoxicillin 500mg pill: AmoxStar – amoxicillin in india

  18. Здесь можно купить домашний сейф в москве сейф домашний

  19. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов honor рядом, можете посмотреть на сайте: ремонт телефонов honor
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  20. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов honor рядом, можете посмотреть на сайте: ремонт телефонов honor цены
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  21. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов honor цены, можете посмотреть на сайте: ремонт телефонов honor сервис
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  22. SamuelDarse说道:

    amoxicillin 500mg capsules price: Amox Star – where to buy amoxicillin

  23. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов infinix цены, можете посмотреть на сайте: ремонт телефонов infinix адреса
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  24. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов honor адреса, можете посмотреть на сайте: ремонт телефонов honor рядом
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  25. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов infinix адреса, можете посмотреть на сайте: ремонт телефонов infinix в москве
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  26. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов honor адреса, можете посмотреть на сайте: срочный ремонт телефонов honor
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  27. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов infinix адреса, можете посмотреть на сайте: ремонт телефонов infinix в москве
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  28. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов honor в москве, можете посмотреть на сайте: ремонт телефонов honor адреса
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  29. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов infinix, можете посмотреть на сайте: срочный ремонт телефонов infinix
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  30. Здесь можно купит сейф для дома сейф для дома москва

  31. Предлагаем услуги профессиональных инженеров офицальной мастерской.
    Еслли вы искали ремонт телефонов infinix цены, можете посмотреть на сайте: ремонт телефонов infinix
    Наши мастера оперативно устранят неисправности вашего устройства в сервисе или с выездом на дом!

  32. SamuelDarse说道:

    amoxicillin price without insurance: amoxicillin 500 coupon – where can i buy amoxicillin online

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注