Wechat Miniprogram
Payment Flow
- Merchant retrieve OpenID using “wx.login’s code” and “code2session api”
- Merchant make API call to 2C2P to get the wx.requestPayment (prepay_id)
- Merchant Invoke wx.requestPayment in MiniProgram
- WeChat shall prompt customer to confirm payment
- Wechat shall display payment result to customer
- WeChat shall notify a notification from 2C2P regarding payment result
- 2C2P shall notify payment result to Merchant
Getting OpenID
- Merchant shall invoke “wx.login” in miniprogram to get “code”
Document: https://developers.weixin.qq.com/miniprogram/dev/api/open-api/login/wx.login.html - Merchant shall submit “code” to merchant’s backend to retrieve openID
Document: https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/login/auth.code2Session.html
Integration Guide
- Make SecurePay Payment
1.1) Information to make Wechat MiniProgram
- paymentChannel is
WCMINI
- miniProgramData show following. Required
appID
&openID
<miniProgramData>
<wechat>
<appID>{appid}</appID>
<openID>{openid}</openID>
</wechat>
</miniProgramData>
- You will receive the response back from 2C2P with response code “32”
- You will read the “miniProgramData/wechat” xml tag to receive the wx.requestPayment payload
<miniProgramData>
<wechat>
{"timeStamp":"","package":"","nonceStr":"","signType":"","paySign":""}
</wechat>
</miniProgramData>
Sample code show following
Environment
Please refer Demo & Live Endpoint.
Secure Pay API
Refer Payload Refer Payload Parameter Specification & API Parameter Specification
#region ALL Fields
string cardholderEmail = "", payCategoryID = "", userDefined1 = "", userDefined2 = "", userDefined3 = "", userDefined4 = "", userDefined5 = "", storeCard = "",
ippTransaction = "", installmentPeriod = "", interestType = "", recurring = "", invoicePrefix = "", recurringAmount = "", allowAccumulate = "", maxAccumulateAmt = "",
recurringInterval = "", recurringCount = "", chargeNextDate = "", promotion = "", request3DS = "", statementDescriptor = "", agentCode = "", channelCode = "", paymentExpiry = "", mobileNo = "", tokenizeWithoutAuthorization = "",
paymentChannel = "", storeCardUniqueID = "", panBank = "", userId = "", storeId = "", storeName = "", storeTerminalId = "", wxAppId = "", wxOpenId = "";
#endregion
// RETRIEVE merchantId, merchantSecretKey from your database
//Merchant Account Information
string merchantID = "JT01"; //Get MerchantID from 2c2p PGW Dashboard
string secretKey = "7jYcp4FxFdf0"; //Get SecretKey from 2c2p PGW Dashboard
//Product Information
string uniqueTransactionCode = "Invoice" + DateTime.Now.ToString ("yyMMddHHmmss");
string desc = "item 1";
string amt = "000000000001"; //12 digit format
string currencyCode = "702"; //Ref: http://en.wikipedia.org/wiki/ISO_4217
//Customer Information
string cardholderName = "John Doe";
string country = "SG";
//Payment Channel
paymentChannel = "WCMINI"; // Wechat App
string miniprogramData = "";
wxAppId = "wx0ecdd8f41c8ac9ab"; // app id
wxOpenId = paymentData.openId; // openid
miniprogramData = "<wechat>" +
"<appID>" + wxAppId + "</appID>" +
"<openID>" + wxOpenId + "</openID>" +
"</wechat>";
//Request Information
string timeStamp = DateTime.Now.ToString ("ddMMyyHHmmss");
string apiVersion = "9.9";
//Construct payment request message
string payloadXml = "<PaymentRequest>" +
"<timeStamp>" + timeStamp + "</timeStamp>" +
"<merchantID>" + merchantID + "</merchantID>" +
"<uniqueTransactionCode>" + uniqueTransactionCode + "</uniqueTransactionCode>" +
"<desc>" + HttpUtility.HtmlEncode (desc) + "</desc>" +
"<amt>" + amt + "</amt>" +
"<currencyCode>" + currencyCode + "</currencyCode>" +
"<panCountry>" + country + "</panCountry>" +
"<cardholderName>" + cardholderName + "</cardholderName>" +
"<paymentChannel>" + paymentChannel + "</paymentChannel>" +
"<miniProgramData>" +
miniprogramData +
"</miniProgramData>" +
"</PaymentRequest>";
string payload = Utility.Base64Encode (payloadXml); //Convert payload to base64
string hash = Utility.GetHMAC2 (payload, secretKey); //Calculate Hash Value
string xml = "<PaymentRequest>" +
"<version>" + apiVersion + "</version>" + //request version number (9.9)
"<payload>" + payload + "</payload>" + //request payload
"<signature>" + hash + "</signature>" + //signature
"</PaymentRequest>";
string data = Utility.Base64Encode (xml); //Convert payload to base64
data = "paymentRequest=" + HttpUtility.UrlEncode (data); //urlEncode data
string url = "https://demo2.2c2p.com/2C2PFrontEnd/SecurePayment/Payment.aspx";
var paymentResponse = Utility.PostRequest (url, data, Utility.PostContentType.FORM);
if (paymentResponse.Result) {
if (!string.IsNullOrEmpty (paymentResponse.ResultOutput)) {
string clearResult = Utility.Base64Decode (paymentResponse.ResultOutput);
XmlDocument xDoc = new XmlDocument ();
xDoc.LoadXml (clearResult);
string respPayload = (xDoc.SelectNodes ("//payload").Count > 0 ? xDoc.SelectSingleNode ("//payload").InnerText : "");
string respSign = (xDoc.SelectNodes ("//signature").Count > 0 ? xDoc.SelectSingleNode ("//signature").InnerText : "");
string respHash = Utility.GetHMAC2 (respPayload, secretKey); //Calculate Hash Value
respPayload = Utility.Base64Decode (respPayload);
if (respHash.Equals (respSign, StringComparison.OrdinalIgnoreCase)) {
XmlDocument xDocResponse = new XmlDocument ();
xDocResponse.LoadXml (respPayload);
string respCode = (xDocResponse.SelectNodes ("//respCode").Count > 0 ? xDocResponse.SelectSingleNode ("//respCode").InnerText : "");
if (respCode == "32") {
string wechatData = (xDocResponse.SelectNodes ("//miniProgramData//wechat").Count > 0 ? xDocResponse.SelectSingleNode ("//miniProgramData//wechat").InnerText : "");
return Json (wechatData);
} else {
return BadRequest ("Failed to get requestPayment");
}
} else {
return BadRequest ();
}
} else {
return BadRequest ("Empty response");
}
} else {
return BadRequest (paymentResponse.ErrorDetails);
}
Updated almost 3 years ago