Java实现JsApi方式的微信支付

要使用JsApi进行微信支付,首先要从微信获得一个prepay_id,然后通过调用微信的jsapi完成支付,JS API的返回结果get_brand_wcpay_request:ok仅在用户成功完成支付时返回。由于前端交互复杂,get_brand_wcpay_request:cancel或者get_brand_wcpay_request:fail可以统一处理为用户遇到错误或者主动放弃,不必细化区分。示例代码如下:

function onBridgeReady(){
   WeixinJSBridge.invoke(
     'getBrandWCPayRequest', {
       "appId" : "wx2421b1c4370ec43b",	 //公众号名称,由商户传入	 
       "timeStamp":" 1395712654",		 //时间戳,自1970年以来的秒数	 
       "nonceStr" : "e61463f8efa94090b1f366cccfbbb444", //随机串	 
       "package" : "u802345jgfjsdfgsdg888",	 
       "signType" : "MD5",		 //微信签名方式:	 
       "paySign" : "70EA570631E4BB79628FBCA90534C63FF7FADD89" //微信签名 
     },
     function(res){	 
       if(res.err_msg == "get_brand_wcpay_request:ok" ) {}	 // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回	ok,但并不保证它绝对可靠。 
     }
   ); 
}
if (typeof WeixinJSBridge == "undefined"){
   if( document.addEventListener ){
     document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
   }else if (document.attachEvent){
     document.attachEvent('WeixinJSBridgeReady', onBridgeReady); 
     document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
   }
}else{
   onBridgeReady();
}

以上传入的参数package,即为prepay_id

详细文档见: https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7

下面讲的是获得参数来调用jsapi

我们调用JSAPI时,必须获得用户的openid,(trade_type=JSAPI,openid为必填参数。)

首先定义一个请求的对象:

package com.unstoppedable.protocol;
import com.unstoppedable.common.Configure;
import com.unstoppedable.common.HttpService;
import com.unstoppedable.common.RandomStringGenerator;
import com.unstoppedable.common.Signature;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
public class UnifiedOrderReqData {
  private String appid;
  private String mch_id;
  private String device_info;
  private String nonce_str;
  private String sign;
  private String body;
  private String detail;
  private String attach;
  private String out_trade_no;
  private String fee_type;
  private int total_fee;
  private String spbill_create_ip;
  private String time_start;
  private String time_expire;
  private String goods_tag;
  private String notify_url;
  private String trade_type;
  private String product_id;
  private String limit_pay;
  private String openid;
  private UnifiedOrderReqData(UnifiedOrderReqDataBuilder builder) {
    this.appid = builder.appid;
    this.mch_id = builder.mch_id;
    this.device_info = builder.device_info;
    this.nonce_str = RandomStringGenerator.getRandomStringByLength(32);
    this.body = builder.body;
    this.detail = builder.detail;
    this.attach = builder.attach;
    this.out_trade_no = builder.out_trade_no;
    this.fee_type = builder.fee_type;
    this.total_fee = builder.total_fee;
    this.spbill_create_ip = builder.spbill_create_ip;
    this.time_start = builder.time_start;
    this.time_expire = builder.time_expire;
    this.goods_tag = builder.goods_tag;
    this.notify_url = builder.notify_url;
    this.trade_type = builder.trade_type;
    this.product_id = builder.product_id;
    this.limit_pay = builder.limit_pay;
    this.openid = builder.openid;
    this.sign = Signature.getSign(toMap());
  }
  public void setAppid(String appid) {
    this.appid = appid;
  }
  public void setMch_id(String mch_id) {
    this.mch_id = mch_id;
  }
  public void setDevice_info(String device_info) {
    this.device_info = device_info;
  }
  public void setNonce_str(String nonce_str) {
    this.nonce_str = nonce_str;
  }
  public void setSign(String sign) {
    this.sign = sign;
  }
  public void setBody(String body) {
    this.body = body;
  }
  public void setDetail(String detail) {
    this.detail = detail;
  }
  public void setAttach(String attach) {
    this.attach = attach;
  }
  public void setOut_trade_no(String out_trade_no) {
    this.out_trade_no = out_trade_no;
  }
  public void setFee_type(String fee_type) {
    this.fee_type = fee_type;
  }
  public void setTotal_fee(int total_fee) {
    this.total_fee = total_fee;
  }
  public void setSpbill_create_ip(String spbill_create_ip) {
    this.spbill_create_ip = spbill_create_ip;
  }
  public void setTime_start(String time_start) {
    this.time_start = time_start;
  }
  public void setTime_expire(String time_expire) {
    this.time_expire = time_expire;
  }
  public void setGoods_tag(String goods_tag) {
    this.goods_tag = goods_tag;
  }
  public void setNotify_url(String notify_url) {
    this.notify_url = notify_url;
  }
  public void setTrade_type(String trade_type) {
    this.trade_type = trade_type;
  }
  public void setProduct_id(String product_id) {
    this.product_id = product_id;
  }
  public void setLimit_pay(String limit_pay) {
    this.limit_pay = limit_pay;
  }
  public void setOpenid(String openid) {
    this.openid = openid;
  }
  public Map<String, Object> toMap() {
    Map<String, Object> map = new HashMap<String, Object>();
    Field[] fields = this.getClass().getDeclaredFields();
    for (Field field : fields) {
      Object obj;
      try {
        obj = field.get(this);
        if (obj != null) {
          map.put(field.getName(), obj);
        }
      } catch (IllegalArgumentException e) {
        e.printStackTrace();
      } catch (IllegalAccessException e) {
        e.printStackTrace();
      }
    }
    return map;
  }
  public static class UnifiedOrderReqDataBuilder {
    private String appid;
    private String mch_id;
    private String device_info;
    private String body;
    private String detail;
    private String attach;
    private String out_trade_no;
    private String fee_type;
    private int total_fee;
    private String spbill_create_ip;
    private String time_start;
    private String time_expire;
    private String goods_tag;
    private String notify_url;
    private String trade_type;
    private String product_id;
    private String limit_pay;
    private String openid;
    public UnifiedOrderReqDataBuilder(String appid, String mch_id, String body, String out_trade_no, Integer total_fee,
                      String spbill_create_ip, String notify_url, String trade_type) {
      if (appid == null) {
        throw new IllegalArgumentException("传入参数appid不能为null");
      }
      if (mch_id == null) {
        throw new IllegalArgumentException("传入参数mch_id不能为null");
      }
      if (body == null) {
        throw new IllegalArgumentException("传入参数body不能为null");
      }
      if (out_trade_no == null) {
        throw new IllegalArgumentException("传入参数out_trade_no不能为null");
      }
      if (total_fee == null) {
        throw new IllegalArgumentException("传入参数total_fee不能为null");
      }
      if (spbill_create_ip == null) {
        throw new IllegalArgumentException("传入参数spbill_create_ip不能为null");
      }
      if (notify_url == null) {
        throw new IllegalArgumentException("传入参数notify_url不能为null");
      }
      if (trade_type == null) {
        throw new IllegalArgumentException("传入参数trade_type不能为null");
      }
      this.appid = appid;
      this.mch_id = mch_id;
      this.body = body;
      this.out_trade_no = out_trade_no;
      this.total_fee = total_fee;
      this.spbill_create_ip = spbill_create_ip;
      this.notify_url = notify_url;
      this.trade_type = trade_type;
    }
    public UnifiedOrderReqDataBuilder setDevice_info(String device_info) {
      this.device_info = device_info;
      return this;
    }
    public UnifiedOrderReqDataBuilder setDetail(String detail) {
      this.detail = detail;
      return this;
    }
    public UnifiedOrderReqDataBuilder setAttach(String attach) {
      this.attach = attach;
      return this;
    }
    public UnifiedOrderReqDataBuilder setFee_type(String fee_type) {
      this.fee_type = fee_type;
      return this;
    }
    public UnifiedOrderReqDataBuilder setTime_start(String time_start) {
      this.time_start = time_start;
      return this;
    }
    public UnifiedOrderReqDataBuilder setTime_expire(String time_expire) {
      this.time_expire = time_expire;
      return this;
    }
    public UnifiedOrderReqDataBuilder setGoods_tag(String goods_tag) {
      this.goods_tag = goods_tag;
      return this;
    }
    public UnifiedOrderReqDataBuilder setProduct_id(String product_id) {
      this.product_id = product_id;
      return this;
    }
    public UnifiedOrderReqDataBuilder setLimit_pay(String limit_pay) {
      this.limit_pay = limit_pay;
      return this;
    }
    public UnifiedOrderReqDataBuilder setOpenid(String openid) {
      this.openid = openid;
      return this;
    }
    public UnifiedOrderReqData build() {
      if("JSAPI".equals(this.trade_type) && this.openid == null) {
        throw new IllegalArgumentException("当传入trade_type为JSAPI时,openid为必填参数");
      }
      if("NATIVE".equals(this.trade_type) && this.product_id == null) {
        throw new IllegalArgumentException("当传入trade_type为NATIVE时,product_id为必填参数");
      }
      return new UnifiedOrderReqData(this);
    }
  }
}

因为有些参数为必填,有些参数为选填。而且sign要等所有参数传入之后才能计算的出,所以这里用了builder模式。关于builder模式。关于每个参数的定义,参考说明文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1

我们选用httpclient进行网络传输。

package com.unstoppedable.common;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.KeyStore;
/**
 * Created by hupeng on 2015/7/28.
 */
public class HttpService {
    private static Log logger = LogFactory.getLog(HttpService.class);
    private static CloseableHttpClient httpClient = buildHttpClient();
    //连接超时时间,默认10秒
    private static int socketTimeout = 5000;
    //传输超时时间,默认30秒
    private static int connectTimeout = 5000;
    private static int requestTimeout = 5000;
    public static CloseableHttpClient buildHttpClient() {
  try {
      KeyStore keyStore = KeyStore.getInstance("PKCS12");
      FileInputStream instream = new FileInputStream(new File(Configure.getCertLocalPath()));//加载本地的证书进行https加密传输
      try {
    keyStore.load(instream, Configure.getCertPassword().toCharArray());//设置证书密码
      } finally {
    instream.close();
      }
      // Trust own CA and all self-signed certs
      SSLContext sslcontext = SSLContexts.custom()
        .loadKeyMaterial(keyStore, Configure.getCertPassword().toCharArray())
        .build();
      // Allow TLSv1 protocol only
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
        sslcontext,
        new String[]{"TLSv1"},
        null,
        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
      RequestConfig requestConfig = RequestConfig.custom()
        .setConnectTimeout(connectTimeout)
        .setConnectionRequestTimeout(requestTimeout)
        .setSocketTimeout(socketTimeout).build();
      httpClient = HttpClients.custom()
        .setDefaultRequestConfig(requestConfig)
        .setSSLSocketFactory(sslsf)
        .build();
      return httpClient;
  } catch (Exception e) {
      throw new RuntimeException("error create httpclient......", e);
  }
    }
    public static String doGet(String requestUrl) throws Exception {
  HttpGet httpget = new HttpGet(requestUrl);
  try {
      logger.debug("Executing request " + httpget.getRequestLine());
      // Create a custom response handler
      ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
    @Override
    public String handleResponse(
      final HttpResponse response) throws ClientProtocolException, IOException {
        int status = response.getStatusLine().getStatusCode();
        if (status >= 200 && status < 300) {
      HttpEntity entity = response.getEntity();
      return entity != null ? EntityUtils.toString(entity) : null;
        } else {
      throw new ClientProtocolException("Unexpected response status: " + status);
        }
    }
      };
      return httpClient.execute(httpget, responseHandler);
  } finally {
      httpget.releaseConnection();
  }
    }
    public static String doPost(String url, Object object2Xml) {
  String result = null;
  HttpPost httpPost = new HttpPost(url);
  //解决XStream对出现双下划线的bug
  XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
  //将要提交给API的数据对象转换成XML格式数据Post给API
  String postDataXML = xStreamForRequestPostData.toXML(object2Xml);
  logger.info("API,POST过去的数据是:");
  logger.info(postDataXML);
  //得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
  StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
  httpPost.addHeader("Content-Type", "text/xml");
  httpPost.setEntity(postEntity);
  //设置请求器的配置
  logger.info("executing request" + httpPost.getRequestLine());
  try {
      HttpResponse response = httpClient.execute(httpPost);
      HttpEntity entity = response.getEntity();
      result = EntityUtils.toString(entity, "UTF-8");
  } catch (ConnectionPoolTimeoutException e) {
      logger.error("http get throw ConnectionPoolTimeoutException(wait time out)", e);
  } catch (ConnectTimeoutException e) {
      logger.error("http get throw ConnectTimeoutException", e);
  } catch (SocketTimeoutException e) {
      logger.error("http get throw SocketTimeoutException", e);
  } catch (Exception e) {
      logger.error("http get throw Exception", e);
  } finally {
      httpPost.abort();
  }
  return result;
    }
}

然后是我们的总入口:

package com.unstoppedable.service;
import com.unstoppedable.common.Configure;
import com.unstoppedable.common.HttpService;
import com.unstoppedable.common.XMLParser;
import com.unstoppedable.protocol.UnifiedOrderReqData;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.util.Map;
/**
 * Created by hupeng on 2015/7/28.
 */
public class WxPayApi {
  public static Map<String,Object> UnifiedOrder(UnifiedOrderReqData reqData) throws IOException, SAXException, ParserConfigurationException {
    String res  = HttpService.doPost(Configure.UNIFIED_ORDER_API, reqData);
    return XMLParser.getMapFromXML(res);
  }
  public static void main(String[] args) throws Exception {
    UnifiedOrderReqData reqData = new UnifiedOrderReqData.UnifiedOrderReqDataBuilder("appid", "mch_id", "body", "out_trade_no", 1, "spbill_create_ip", "notify_url", "JSAPI").setOpenid("openid").build();
    System.out.println(UnifiedOrder(reqData));
  }
}

返回的xml为:

<xml>
  <return_code><![CDATA[SUCCESS]]></return_code>
  <return_msg><![CDATA[OK]]></return_msg>
  <appid><![CDATA[wx2421b1c4370ec43b]]></appid>
  <mch_id><![CDATA[10000100]]></mch_id>
  <nonce_str><![CDATA[IITRi8Iabbblz1Jc]]></nonce_str>
  <sign><![CDATA[7921E432F65EB8ED0CE9755F0E86D72F]]></sign>
  <result_code><![CDATA[SUCCESS]]></result_code>
  <prepay_id><![CDATA[wx201411101639507cbf6ffd8b0779950874]]></prepay_id>
  <trade_type><![CDATA[JSAPI]]></trade_type>
</xml>

return_code 和result_code都为SUCCESS的时候会返回我们需要的prepay_id。。。

然后在jsapi中使用他就可以了。。

代码托管在https://github.com/hupengcool/wxpay_jsapi ,欢迎指正


转载于:http://www.tuicool.com/articles/rmQRrm7

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Java实现微信支付需要使用微信支付 SDK。您可以在微信支付官方网站上下载最新版本的 SDK,并在您的 Java 项目中使用它。 使用微信支付 SDK 的具体步骤如下: 1. 注册微信支付商户并获取商户 ID 和密钥。 2. 下载并导入微信支付 SDK。 3. 创建支付订单并获取支付二维码。 4. 使用扫码支付或者 JSAPI 支付接口调用微信支付。 5. 接收微信支付的异步通知并进行订单状态的更新。 有关微信支付的更多信息,您可以参考微信支付官方文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 希望这些信息对您有帮助! ### 回答2: 要实现微信支付功能,可以使用Java编程语言结合微信支付开放平台提供的API来实现。 首先,需要在微信支付开放平台注册并创建一个应用,获取到应用的AppID、商户号、AppSecret等信息。 接下来,在Java项目中引入微信支付SDK,可以使用第三方库,如"wechatpay-api"来简化开发流程。然后,通过使用SDK提供的相关方法,可以实现以下功能: 1. 获取access_token:通过获取 access_token 接口,获取微信支付接口调用凭证,用于后续接口调用的身份验证。 2. 统一下单:使用统一下单接口,将用户提交的支付信息传给微信支付平台,生成预支付订单,并返回预付款二维码链接或者支付ID。 3. 生成支付链接或二维码:将预付款二维码链接或支付ID返回给前端,通过生成支付链接或者二维码的方式,提供给用户进行支付。 4. 微信支付回调:在用户支付成功后,微信支付平台会异步调用开发者设置的支付结果通知地址,向该地址发送支付结果信息。开发者需要在接收到回调时,验证回调的合法性,并及时处理支付结果。 5. 查询订单状态:通过订单查询接口,可以查询用户支付订单的当前状态,如支付成功、支付失败等。 6. 退款:使用退款接口,可以实现订单退款操作,退还用户支付的金额。 以上是使用Java实现微信支付的基本步骤。在具体实现过程中,还需注意接口调用的参数传递、异常处理、数据加密等问题。为确保支付安全,建议使用HTTPS协议进行数据传输,并加强对接口的签名验证。 ### 回答3: Java 实现微信支付可以通过微信支付开放平台提供的开发工具包来完成。首先,需要在微信支付开放平台注册一个开发者账号,并创建一个应用获取对应的应用ID和应用密钥。 接下来,可以使用Java语言进行开发。首先,需要引入微信支付Java SDK,例如官方提供的weixin-java-pay SDK。通过在项目的pom.xml文件中添加相关依赖,即可将SDK集成到项目中。 然后,通过在代码中进行配置,将应用ID和应用密钥等信息设置到SDK中。可以使用SDK提供的配置类进行设置,例如WxPayConfig。 接下来,可以使用SDK提供的API进行微信支付的相关操作。例如,使用SDK提供的统一下单API可以生成一个支付链接,通过该链接用户可以进行支付操作。可以通过创建对应的请求对象,并调用SDK提供的发送请求的方法来实现。 支付结果通知可以使用SDK提供的回调接口来处理,当支付完成后,微信支付平台会向预先设置的回调URL发送通知。可以在代码中编写对应的处理逻辑,接收并解析微信支付平台发送的通知,校验数据的正确性,并进行相应的业务处理。 最后,可以使用SDK提供的查询订单API来查询订单的支付结果。可以根据订单号或其他查询条件,调用SDK提供的查询订单接口来获取订单的最新支付状态。 通过以上步骤,就可以使用Java实现微信支付功能。需要注意的是,开发过程中需要仔细阅读微信支付开放平台提供的文档和SDK的使用指南,并按照实际需求进行相关配置和操作。同时,为了确保支付过程的安全性,建议使用SSL证书进行加密传输。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值