위 챗 결제 의 공중번호 지불(자바 실현)
본 고 는 공중 번호 지불 의 실현 절 차 를 소개 하고 자 한다.즉,위 챗 사용자 가 공중 번호 에서 링크 를 클릭 하여 상품 h5 페이지 에 들 어가 고 상품 을 선택 한 후에 지불 단 추 를 클릭 한 후에 위 챗 결제 페이지 를 팝 업 하고 지불 비밀 번 호 를 입력 하 며 지불 에 성공 한 후에 모든 상품 페이지 로 넘 어 가 는 전체 과정 이다.위 챗 스 캔 결 제 는 후속 글 을 참조 하 시기 바 랍 니 다.
1.우선,상 가 는 위 챗 공중 번호,위 챗 상점 번호 와 위 챗 결제 권한 을 신청 해 야 합 니 다.개발 과정 에서 공중 번호 와 상점 플랫폼 을 참조 하여 다음 과 같은 매개 변 수 를 제공 해 야 한다.
① appid:공중 번호 id,위 챗 공중 번호 C 개발 C 기본 설정 에 로그 인하 여 얻 을 수 있 습 니 다.
② mch_id:수금 업 체 상점 번호;
③ APP_SECRET:제3자 유일한 증빙 비밀번호;
④ key:수금 업 체 백 엔 드 를 설정 하고 위 챗 업 체 플랫폼 C 계 정 에 로그 인하 여 C 안전 설정 Capi 안전,32 비트 key 값 을 설정 합 니 다.
2.위 챗 공식 번호 에 로그 인하 여 관련 설정 을 개발 합 니 다.
① 사용자 기본 정보 획득(주로 openid)권한 설정:위 챗 퍼 블 릭 플랫폼 C 개발 C 인터페이스 권한 C 웹 페이지 권한 부여 C 웹 페이지 권한 부여 도 메 인 이름(IP 주 소 를 받 지 않 고 ICP 등록 검증 을 통 해 http 없 음):
② 지불 테스트 디 렉 터 리 및 테스트 화이트 리스트 설정:위 챗 공식 플랫폼 C 위 챗 결제 C 개발 설정,테스트 권한 수여 디 렉 터 리 는 마지막 단계 까지 구체 적 으로 설정 합 니 다.
3.사용자 openid 를 가 져 옵 니 다.OpenID 는 공중 번호 1 대 1 로 해당 하 는 사용자 신분 의 표지 입 니 다.
① 위 챗 홈 페이지 는 사용자 정보 문 서 를 얻 을 수 있 는 권한 을 부여 한다.https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/functions/userinfo.html.문서 패키지 url 에 따라 사용자 가 위 챗 에서 이 링크 를 클릭 하여 openid 등 기본 정 보 를 얻 도록 유도 합 니 다.
② 사용자 가 url 을 클릭 하도록 유도 합 니 다(예 를 들 어 공중 번호 로 이 링크 를 푸 시 합 니 다).형식 은 다음 과 같 습 니 다.
https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
각 매개 변 수 는 교체 해 야 합 니 다.의 미 는 다음 과 같 습 니 다.
REDIRECT_URI:URL 을 바 꾸 면 상품 목록 페이지 나 상품 페이지 로 이동 할 수 있 습 니 다.사용자 권한 이 성공 하면 이 URL 이 가리 키 는 페이지 로 이동 합 니 다.
scope:snsapi_base 와 snsapiuserinfo 두 가지,snsapibase 사용자 에 게 침묵 권한 부여,snsapiuserinfo 는 사용자 가 인증 확인 을 해 야 더 많은 사용자 정 보 를 얻 을 수 있 습 니 다.본문 은 후 자 를 선택한다.
state:방향 을 바 꾼 후 이 인 자 를 가 져 옵 니 다.
③ 사용자 가 권한 을 수 여 받 은 후에 방향 을 바 꾸 는 페이지 는 code 인 자 를 얻 습 니 다(사용자 가 권한 을 수 여 받 지 못 하면 방향 을 바 꾼 후에 code 인 자 를 가 져 오지 않 고 state 파라미터 redirect 만 가 져 옵 니 다.uri?state=STATE),공식 적 으로 code 매개 변수 에 대한 설명 은 다음 과 같다.
code 교환 accesstoken 의 어음 은 사용자 권한 수여 에 따 른 code 가 다 릅 니 다.code 는 한 번 만 사용 할 수 있 고 5 분 동안 자동 으로 만 료 되 지 않 습 니 다.
페이지 에 대응 하 는 controller 에서
String code = getPara("code");
을 통 해 code 인 자 를 가 져 옵 니 다.④ contoller 에서 WxPayUtil 의 방법 을 동시에 이용 하여 위 챗 인 터 페 이 스 를 호출 하여 현재 사용자 openid 를 가 져 오고 이 openid 를 session 에 저장 합 니 다.
setSessionAttr("openid", (WxPayUtil.getOpenIdByCode(code)).get("openid"));
4,사용자 선택 상품 클릭 지불,업 체 제공 h5 페이지 확인 지불 대응 controller 에서 통일 주문 을 획득 prepayid(여기 서 주의 하 셔 야 합 니 다.주문 금액 은 단위 로 전환 합 니 다).아래 의 공식 문서 주 소 를 통일 하 는 것 은 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 이다.
// , xml, return_code , prepay_id
String prePayInfoXml = WxPayUtil.unifiedOrder("WxPay", userOrder.getStr("orderNo"), (entity.getBigDecimal("orderMoney").multiply(new BigDecimal(100))).intValue(), WxPayUtil.getIpAddr(getRequest()), getSessionAttr("openid").toString());
// prepay_id map,map
map = WxPayUtil.getPayMap(prePayInfoXml);
// map,
map.put("orderNo",userOrder.getStr("orderNo"));
5.전단 에서 이전 맵 을 획득 한 후 위 챗 으로 JSPI 를 지불 합 니 다.전단 js 코드 는 다음 과 같 습 니 다.
<script type="text/javascript">
function payPublic(){
Common.AjaxSubmitBind("saveForm",function(){
saveIndex=Common.Loading(" ");
},function(data){
prepay_id = data.prepay_id;
paySign = data.paySign;
appId = data.appId;
timeStamp = data.timeStamp;
nonceStr = data.nonceStr;
packageStr = data.packageStr;
signType = data.signType;
orderNo = data.orderNo;
callpay();
},function(errMsg,errCode){
Common.Alert(errMsg);
});
}
var prepay_id;
var paySign;
var appId;
var timeStamp;
var nonceStr;
var packageStr;
var signType;
var orderNo;
function onBridgeReady(){
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId" : appId, // ,
"timeStamp" : timeStamp, // , 1970
"nonceStr" : nonceStr , //
"package" : packageStr,
"signType" : signType, // :
"paySign" : paySign //
},
function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
alert(" ");
window.location.href="${base}/test/paySuccess" rel="external nofollow" ;
}
if (res.err_msg == "get_brand_wcpay_request:cancel") {
alert(" ");
window.location.href="${base}/test/cancel" rel="external nofollow" ;
}
if (res.err_msg == "get_brand_wcpay_request:fail") {
alert(" ");
window.location.href="${base}/test/fail" rel="external nofollow" ;
}
}
);
}
function callpay(){
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();
}
}
</script>
6.사용자 가 결 제 를 완성 하고 백 스테이지 에서 위 챗 결제 의 리 턴 을 기다 리 며 결제 성공 후 작업 을 합 니 다.① 사용자 가 비밀 번 호 를 입력 하여 결제 완료.백 엔 드 리 셋 주소(아래 목록 에 설 정 된 notify 통일url)위 챗 결제 결 과 를 받 아 결제 결 과 를 판단 하고 이에 대응 하 는 작업 을 한다.
public void notify(){
System.out.print(" ");
HttpServletRequest request = getRequest();
String resXml = WxPayUtil.getNotifyResult(request);
// , (SUCCESS), , 8
renderText(resXml, "text/xml");
}
관련 도구 및 상수 류 는 다음 과 같 습 니 다.① WxPayUtil 류(결제 도구 류):
public class WxPayUtil {
private static Logger logger = Logger.getLogger(WxPayUtil.class);
/**
* code openid
* @param code
* @return
* @throws IOException
*/
public static Map<String,Object> getOpenIdByCode(String code) throws IOException {
// access_token
HttpPost httppost = new HttpPost("https://api.weixin.qq.com/sns/oauth2/access_token");
//
String reqEntityStr = "appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";
reqEntityStr = reqEntityStr.replace("APPID", WxPayConstants.APPID);
reqEntityStr = reqEntityStr.replace("SECRET", WxPayConstants.APP_SECRET);
reqEntityStr = reqEntityStr.replace("CODE", code);
StringEntity reqEntity = new StringEntity(reqEntityStr);
//
httppost.setEntity(reqEntity);
//
CloseableHttpClient httpclient = HttpClients.createDefault();
//
CloseableHttpResponse response = httpclient.execute(httppost);
//
String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
// openid
JSONObject jsonObject = new JSONObject(strResult);
Map<String,Object> map = new HashMap<String,Object>();
map.put("openid",jsonObject.get("openid"));
map.put("access_token",jsonObject.get("access_token"));
map.put("refresh_token",jsonObject.get("refresh_token"));
return map;
}
/**
*
* @param body
* @param out_trade_no
* @param total_fee
* @param IP
* @param notify_url
* @param openid
* @return
* @throws IOException
*/
public static String unifiedOrder(String body,String out_trade_no,Integer total_fee,String IP,String openid)throws IOException {
//
HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/pay/unifiedorder");
String nonce_str = getNonceStr().toUpperCase();//
// , ASCII
String sign = "appid=" + WxPayConstants.APPID +
"&body=" + body +
"&mch_id=" + WxPayConstants.MCH_ID +
"&nonce_str=" + nonce_str +
"¬ify_url=" + WxPayConstants.NOTIFY_URL +
"&openid=" + openid +
"&out_trade_no=" + out_trade_no +
"&spbill_create_ip=" + IP +
"&total_fee=" + total_fee.toString() +
"&trade_type=" + WxPayConstants.TRADE_TYPE_JS +
"&key=" + WxPayConstants.KEY;// MD5 , ascii
sign = ToolMD5.MD5Encode(sign,"").toUpperCase();
// openid XML
StringBuilder sb = new StringBuilder("");
sb.append("<xml>");
setXmlKV(sb,"appid",WxPayConstants.APPID);
setXmlKV(sb,"body",body);
setXmlKV(sb,"mch_id",WxPayConstants.MCH_ID);
setXmlKV(sb,"nonce_str",nonce_str);
setXmlKV(sb,"notify_url",WxPayConstants.NOTIFY_URL);
setXmlKV(sb,"openid",openid);
setXmlKV(sb,"out_trade_no",out_trade_no);
setXmlKV(sb,"spbill_create_ip",IP);
setXmlKV(sb,"total_fee",total_fee.toString());
setXmlKV(sb,"trade_type",WxPayConstants.TRADE_TYPE_JS);
setXmlKV(sb,"sign",sign);
sb.append("</xml>");
System.out.println(" :" + sb);
StringEntity reqEntity = new StringEntity(new String (sb.toString().getBytes("UTF-8"),"ISO8859-1"));//
httppost.setEntity(reqEntity);
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(httppost);
String strResult = EntityUtils.toString(response.getEntity(), Charset.forName("utf-8"));
System.out.println(" xml:" + strResult);
return strResult;
}
/**
* id map( )
* @param prePayInfoXml
* @return
*/
public static Map<String,Object> getPayMap(String prePayInfoXml){
Map<String,Object> map = new HashMap<String,Object>();
String prepay_id = getXmlPara(prePayInfoXml,"prepay_id");// xml prepay_id
String timeStamp = String.valueOf((System.currentTimeMillis()/1000));//1970
String nonceStr = getNonceStr().toUpperCase();//
String packageStr = "prepay_id=" + prepay_id;
String signType = "MD5";
String paySign =
"appId=" + WxPayConstants.APPID +
"&nonceStr=" + nonceStr +
"&package=prepay_id=" + prepay_id +
"&signType=" + signType +
"&timeStamp=" + timeStamp +
"&key="+ WxPayConstants.KEY;// ASCII
paySign = ToolMD5.MD5Encode(paySign,"").toUpperCase();// MD5
map.put("appId",WxPayConstants.APPID);
map.put("timeStamp",timeStamp);
map.put("nonceStr",nonceStr);
map.put("packageStr",packageStr);
map.put("signType",signType);
map.put("paySign",paySign);
map.put("prepay_id",prepay_id);
return map;
}
/**
* ,
* @param request
* @return
*/
public static String getNotifyResult(HttpServletRequest request){
String inputLine;
String notifyXml = "";
String resXml = "";
try {
while ((inputLine = request.getReader().readLine()) != null){
notifyXml += inputLine;
}
request.getReader().close();
} catch (Exception e) {
logger.debug("xml :" + e);
e.printStackTrace();
}
System.out.println(" xml:" + notifyXml);
logger.debug(" :");
logger.debug(notifyXml);
if(ToolString.isEmpty(notifyXml)){
logger.debug("xml :");
}
String appid = getXmlPara(notifyXml,"appid");;
String bank_type = getXmlPara(notifyXml,"bank_type");
String cash_fee = getXmlPara(notifyXml,"cash_fee");
String fee_type = getXmlPara(notifyXml,"fee_type");
String is_subscribe = getXmlPara(notifyXml,"is_subscribe");
String mch_id = getXmlPara(notifyXml,"mch_id");
String nonce_str = getXmlPara(notifyXml,"nonce_str");
String openid = getXmlPara(notifyXml,"openid");
String out_trade_no = getXmlPara(notifyXml,"out_trade_no");
String result_code = getXmlPara(notifyXml,"result_code");
String return_code = getXmlPara(notifyXml,"return_code");
String sign = getXmlPara(notifyXml,"sign");
String time_end = getXmlPara(notifyXml,"time_end");
String total_fee = getXmlPara(notifyXml,"total_fee");
String trade_type = getXmlPara(notifyXml,"trade_type");
String transaction_id = getXmlPara(notifyXml,"transaction_id");
// xml
String localSign =
"appid=" + appid +
"&bank_type=" + bank_type +
"&cash_fee=" + cash_fee +
"&fee_type=" + fee_type +
"&is_subscribe=" + is_subscribe +
"&mch_id=" + mch_id +
"&nonce_str=" + nonce_str +
"&openid=" + openid +
"&out_trade_no=" + out_trade_no +
"&result_code=" + result_code +
"&return_code=" + return_code +
"&time_end=" + time_end +
"&total_fee=" + total_fee +
"&trade_type=" + trade_type +
"&transaction_id=" + transaction_id +
"&key=" + WxPayConstants.KEY;// ASCII
localSign = ToolMD5.MD5Encode(localSign,"").toUpperCase();// MD5
System.out.println(" :" + localSign);
logger.debug(" :" + localSign);
logger.debug(" :" + sign);
// ||
if(!sign.equals(localSign) || !"SUCCESS".equals(result_code) || !"SUCCESS".equals(return_code)){
System.out.println(" ");
logger.error(" ");
resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[FAIL]]></return_msg>" + "</xml> ";
}else{
System.out.println(" ");
logger.debug(" ,out_trade_no( ) :" + out_trade_no);
resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
}
return resXml;
}
/**
* 32
* @return
*/
public static String getNonceStr(){
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
StringBuilder sb = new StringBuilder();
Random rd = new Random();
for(int i = 0 ; i < 32 ; i ++ ){
sb.append(str.charAt(rd.nextInt(str.length())));
}
return sb.toString();
}
/**
* XML
* @param sb
* @param Key
* @param value
* @return
*/
public static StringBuilder setXmlKV(StringBuilder sb,String Key,String value){
sb.append("<");
sb.append(Key);
sb.append(">");
sb.append(value);
sb.append("</");
sb.append(Key);
sb.append(">");
return sb;
}
/**
* XML para
* @param xml
* @param para
* @return
*/
public static String getXmlPara(String xml,String para){
int start = xml.indexOf("<"+para+">");
int end = xml.indexOf("</"+para+">");
if(start < 0 && end < 0){
return null;
}
return xml.substring(start + ("<"+para+">").length(),end).replace("<![CDATA[","").replace("]]>","");
}
/**
* ip
* @param request
* @return
*/
public static String getIpAddr(HttpServletRequest request) {
InetAddress addr = null;
try {
addr = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
return request.getRemoteAddr();
}
byte[] ipAddr = addr.getAddress();
String ipAddrStr = "";
for (int i = 0; i < ipAddr.length; i++) {
if (i > 0) {
ipAddrStr += ".";
}
ipAddrStr += ipAddr[i] & 0xFF;
}
return ipAddrStr;
}
}
② 상수 류(사업 자 정보 에 따라 설정):
public class WxPayConstants {
// ID
public static String APPID = "";
//
public static String APP_SECRET = "";
// ID
public static String MCH_ID = "";
// - - -api , 32 key
public static String KEY = "";
//
public static String TRADE_TYPE_JS = "JSAPI";
// url
public static String NOTIFY_URL = "";
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.